From 28bdc5cb7f34300e24063fc19bfa7c81909e49e5 Mon Sep 17 00:00:00 2001 From: SimpleLove520 <1960997571@qq.com> Date: Wed, 24 Jan 2024 20:28:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=B8=BF=E8=92=99?= =?UTF-8?q?=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 2 + sqflite/CHANGELOG.md | 7 +- sqflite/analysis_options.yaml | 3 +- sqflite/doc/opening_asset_db.md | 4 +- sqflite/doc/troubleshooting.md | 46 - sqflite/example/analysis_options.yaml | 3 +- .../example/lib/database/database_impl.dart | 30 +- sqflite/example/lib/database/database_io.dart | 6 +- sqflite/example/lib/exp_test_page.dart | 4 +- sqflite/example/lib/main.dart | 44 +- sqflite/example/lib/open_test_page.dart | 192 +-- sqflite/example/lib/raw_test_page.dart | 1269 ++++++++--------- sqflite/example/lib/test_page.dart | 2 +- sqflite/example/pubspec.yaml | 4 +- sqflite/ios/sqflite.podspec | 5 +- sqflite/lib/src/factory_impl.dart | 32 +- sqflite/lib/src/sqflite_impl.dart | 3 +- sqflite/ohos/.hvigor/cache/file-cache.json | 1 + sqflite/ohos/.hvigor/cache/task-cache.json | 1 + .../.hvigor/outputs/logs/details/details.json | 16 + sqflite/ohos/.hvigor/outputs/sync/output.json | 39 + sqflite/ohos/.hvigor/report/report.json | 308 ++++ sqflite/ohos/AppScope/app.json5 | 24 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes sqflite/ohos/build-profile.json5 | 42 + sqflite/ohos/dependencies/hvigor-2.3.0-s.tgz | 3 + sqflite/ohos/dependencies/hvigor-3.0.9-s.tgz | 3 + .../hvigor-ohos-arkui-x-plugin-2.1.7-s.tgz | 3 + .../hvigor-ohos-plugin-2.3.0-s.tgz | 3 + .../hvigor-ohos-plugin-3.0.9-s.tgz | 3 + sqflite/ohos/dependencies/rollup.tgz | 3 + sqflite/ohos/hvigor/hvigor-config.json5 | 26 + sqflite/ohos/hvigor/hvigor-wrapper.js | 2 + sqflite/ohos/hvigorfile.ts | 2 + sqflite/ohos/hvigorw | 61 + sqflite/ohos/hvigorw.bat | 77 + sqflite/ohos/oh-package-lock.json5 | 13 + sqflite/ohos/oh-package.json5 | 27 + .../oh_modules/@ohos/hypium/CHANGELOG.md | 45 + .../oh_modules/@ohos/hypium/README.md | 219 +++ .../oh_modules/@ohos/hypium/index.d.ts | 136 ++ .../oh_modules/@ohos/hypium/index.ets | 92 ++ .../oh_modules/@ohos/hypium/index.js | 92 ++ .../oh_modules/@ohos/hypium/oh-package.json5 | 11 + .../@ohos/hypium/src/main/Constant.js | 47 + .../oh_modules/@ohos/hypium/src/main/core.js | 159 +++ .../oh_modules/@ohos/hypium/src/main/event.js | 94 ++ .../@ohos/hypium/src/main/interface.js | 44 + .../src/main/module/assert/ExpectExtend.js | 85 ++ .../src/main/module/assert/assertClose.js | 41 + .../src/main/module/assert/assertContain.js | 35 + .../src/main/module/assert/assertFail.js | 23 + .../src/main/module/assert/assertFalse.js | 23 + .../main/module/assert/assertInstanceOf.js | 29 + .../src/main/module/assert/assertLarger.js | 23 + .../main/module/assert/assertLargerOrEqual.js | 23 + .../src/main/module/assert/assertLess.js | 23 + .../main/module/assert/assertLessOrEqual.js | 23 + .../src/main/module/assert/assertNaN.js | 23 + .../main/module/assert/assertNegUnlimited.js | 23 + .../src/main/module/assert/assertNull.js | 23 + .../main/module/assert/assertPosUnlimited.js | 23 + .../module/assert/assertPromiseIsPending.js | 42 + .../module/assert/assertPromiseIsRejected.js | 40 + .../assert/assertPromiseIsRejectedWith.js | 57 + .../assertPromiseIsRejectedWithError.js | 103 ++ .../module/assert/assertPromiseIsResolved.js | 45 + .../assert/assertPromiseIsResolvedWith.js | 59 + .../main/module/assert/assertThrowError.js | 44 + .../src/main/module/assert/assertUndefined.js | 23 + .../module/assert/deepEquals/DeepTypeUtils.js | 138 ++ .../assert/deepEquals/assertDeepEquals.js | 311 ++++ .../src/main/module/assert/isPromiseLike.js | 32 + .../src/main/module/config/DataDriver.js | 116 ++ .../hypium/src/main/module/config/Filter.js | 81 ++ .../src/main/module/config/configService.js | 292 ++++ .../hypium/src/main/module/kit/SysTestKit.js | 88 ++ .../src/main/module/mock/ArgumentMatchers.js | 122 ++ .../src/main/module/mock/ExtendInterface.js | 57 + .../hypium/src/main/module/mock/MockKit.js | 256 ++++ .../src/main/module/mock/VerificationMode.js | 49 + .../hypium/src/main/module/report/OhReport.js | 148 ++ .../src/main/module/report/ReportExtend.js | 137 ++ .../@ohos/hypium/src/main/service.js | 929 ++++++++++++ sqflite/ohos/sqflite/build-profile.json5 | 24 + sqflite/ohos/sqflite/hvigorfile.ts | 2 + sqflite/ohos/sqflite/index.ets | 17 + .../ohos/sqflite/libs/flutter_embedding.har | Bin 0 -> 84259 bytes sqflite/ohos/sqflite/oh-package.json5 | 25 + .../@ohos/flutter_ohos/build-profile.json5 | 26 + .../@ohos/flutter_ohos/hvigorfile.ts | 17 + .../oh_modules/@ohos/flutter_ohos/index.ets | 18 + .../@ohos/flutter_ohos/oh-package.json5 | 27 + .../src/main/cpp/types/libflutter/index.d.ets | 89 ++ .../cpp/types/libflutter/index_actual.d.ets | 267 ++++ .../cpp/types/libflutter/oh-package.json5 | 21 + .../src/main/ets/FlutterInjector.ets | 49 + .../main/ets/app/FlutterPluginRegistry.ets | 47 + .../main/ets/component/FlutterComponent.ets | 32 + .../ets/embedding/engine/FlutterEngine.ets | 277 ++++ .../embedding/engine/FlutterEngineCache.ets | 64 + .../FlutterEngineConnectionRegistry.ets | 281 ++++ .../embedding/engine/FlutterEngineGroup.ets | 184 +++ .../engine/FlutterEngineGroupCache.ets | 42 + .../main/ets/embedding/engine/FlutterNapi.ets | 362 +++++ .../engine/FlutterOverlaySurface.ets | 27 + .../ets/embedding/engine/FlutterShellArgs.ets | 86 ++ .../embedding/engine/dart/DartExecutor.ets | 379 +++++ .../embedding/engine/dart/DartMessenger.ets | 288 ++++ .../engine/dart/PlatformMessageHandler.ets | 22 + .../engine/loader/ApplicationInfoLoader.ets | 24 + .../engine/loader/FlutterApplicationInfo.ets | 55 + .../embedding/engine/loader/FlutterLoader.ets | 219 +++ .../mutatorsstack/FlutterMutatorView.ets | 135 ++ .../mutatorsstack/FlutterMutatorsStack.ets | 136 ++ .../engine/plugins/FlutterPlugin.ets | 125 ++ .../engine/plugins/PluginRegistry.ets | 73 + .../engine/plugins/ability/AbilityAware.ets | 75 + .../plugins/ability/AbilityControlSurface.ets | 27 + .../plugins/ability/AbilityPluginBinding.ets | 84 ++ .../renderer/FlutterUiDisplayListener.ets | 20 + .../systemchannels/AccessibilityChannel.ets | 119 ++ .../engine/systemchannels/KeyEventChannel.ets | 75 + .../systemchannels/LifecycleChannel.ets | 105 ++ .../systemchannels/LocalizationChannel.ets | 71 + .../systemchannels/MouseCursorChannel.ets | 85 ++ .../systemchannels/NavigationChannel.ets | 62 + .../engine/systemchannels/PlatformChannel.ets | 505 +++++++ .../systemchannels/PlatformViewsChannel.ets | 551 +++++++ .../systemchannels/RestorationChannel.ets | 175 +++ .../engine/systemchannels/SettingsChannel.ets | 89 ++ .../engine/systemchannels/SystemChannel.ets | 37 + .../engine/systemchannels/TestChannel.ets | 38 + .../systemchannels/TextInputChannel.ets | 372 +++++ .../embedding/ohos/ExclusiveAppComponent.ets | 32 + .../ets/embedding/ohos/FlutterAbility.ets | 419 ++++++ .../embedding/ohos/FlutterAbilityDelegate.ets | 457 ++++++ .../ohos/FlutterAbilityLaunchConfigs.ets | 46 + .../ohos/FlutterEngineConfigurator.ets | 23 + .../embedding/ohos/FlutterEngineProvider.ets | 21 + .../main/ets/embedding/ohos/FlutterPage.ets | 43 + .../ets/embedding/ohos/OhosTouchProcessor.ets | 58 + .../src/main/ets/embedding/ohos/Settings.ets | 35 + .../ets/embedding/ohos/TouchEventTracker.ets | 87 ++ ...owInfoRepositoryCallbackAdapterWrapper.ets | 23 + .../src/main/ets/plugin/PlatformPlugin.ets | 301 ++++ .../ets/plugin/common/BasicMessageChannel.ets | 171 +++ .../main/ets/plugin/common/BinaryCodec.ets | 49 + .../ets/plugin/common/BinaryMessenger.ets | 158 ++ .../main/ets/plugin/common/EventChannel.ets | 263 ++++ .../ets/plugin/common/FlutterException.ets | 28 + .../ets/plugin/common/JSONMessageCodec.ets | 52 + .../ets/plugin/common/JSONMethodCodec.ets | 97 ++ .../main/ets/plugin/common/MessageCodec.ets | 30 + .../src/main/ets/plugin/common/MethodCall.ets | 59 + .../main/ets/plugin/common/MethodChannel.ets | 217 +++ .../main/ets/plugin/common/MethodCodec.ets | 87 ++ .../main/ets/plugin/common/PluginRegistry.ets | 14 + .../plugin/common/StandardMessageCodec.ets | 331 +++++ .../ets/plugin/common/StandardMethodCodec.ets | 116 ++ .../main/ets/plugin/common/StringCodec.ets | 42 + .../plugin/editing/ListenableEditingState.ets | 263 ++++ .../ets/plugin/editing/TextEditingDelta.ets | 61 + .../ets/plugin/editing/TextInputPlugin.ets | 264 ++++ .../localization/LocalizationPlugin.ets | 68 + .../ets/plugin/mouse/MouseCursorPlugin.ets | 129 ++ .../platform/AccessibilityEventsDelegate.ets | 38 + .../plugin/platform/PlatformOverlayView.ets | 28 + .../main/ets/plugin/platform/PlatformView.ets | 80 ++ .../plugin/platform/PlatformViewFactory.ets | 44 + .../plugin/platform/PlatformViewRegistry.ets | 32 + .../platform/PlatformViewRegistryImpl.ets | 40 + .../plugin/platform/PlatformViewWrapper.ets | 94 ++ .../PlatformViewsAccessibilityDelegate.ets | 43 + .../platform/PlatformViewsController.ets | 505 +++++++ .../plugin/platform/RootDvModelManager.ets | 72 + .../src/main/ets/util/ByteBuffer.ets | 818 +++++++++++ .../flutter_ohos/src/main/ets/util/Log.ets | 122 ++ .../src/main/ets/util/MessageChannelUtils.ets | 25 + .../src/main/ets/util/PathUtils.ets | 46 + .../src/main/ets/util/StringUtils.ets | 39 + .../src/main/ets/util/ToolUtils.ets | 24 + .../src/main/ets/util/TraceSection.ets | 39 + .../src/main/ets/view/AccessibilityBridge.ets | 45 + .../main/ets/view/DynamicView/dynamicView.ets | 272 ++++ .../ets/view/DynamicView/dynamicViewJson.ets | 68 + .../ets/view/FlutterCallbackInformation.ets | 39 + .../src/main/ets/view/FlutterNativeView.ets | 137 ++ .../src/main/ets/view/FlutterRunArguments.ets | 20 + .../src/main/ets/view/FlutterView.ets | 18 + .../src/main/ets/view/TextureRegistry.ets | 36 + .../@ohos/flutter_ohos/src/main/module.json | 20 + .../io/flutter/plugins/sqflite/Messages.ets | 422 ++++++ .../flutter/plugins/sqflite/SqflitePlugin.ets | 454 ++++++ .../io/flutter/plugins/sqflite/constant.ets | 79 + .../plugins/sqflite/sqflite_helper.ets | 939 ++++++++++++ .../io/flutter/plugins/sqflite/sql_helper.ets | 216 +++ .../ets/io/flutter/plugins/sqflite/tools.ets | 13 + sqflite/ohos/sqflite/src/main/module.json5 | 24 + .../main/resources/base/element/string.json | 8 + .../main/resources/en_US/element/string.json | 8 + .../main/resources/zh_CN/element/string.json | 8 + sqflite/ohos/sqflite/src/test/List.test.ets | 19 + .../ohos/sqflite/src/test/LocalUnit.test.ets | 47 + sqflite/pubspec.yaml | 19 +- sqflite/test/sqlite_api_test.dart | 4 - sqflite/test/src_mixin_test.dart | 11 - sqflite/tripartite/sqflite_common/.gitignore | 19 + .../tripartite/sqflite_common/CHANGELOG.md | 69 + sqflite/tripartite/sqflite_common/LICENSE | 25 + sqflite/tripartite/sqflite_common/README.md | 15 + .../sqflite_common/analysis_options.yaml | 112 ++ .../doc/method_call_protocol.md | 110 ++ .../sqflite_common/example/main.dart | 5 + .../sqflite_common/lib/sqflite.dart | 114 ++ .../sqflite_common/lib/sqflite_dev.dart | 28 + .../sqflite_common/lib/sqflite_logger.dart | 22 + .../tripartite/sqflite_common/lib/sql.dart | 6 + .../sqflite_common/lib/sqlite_api.dart | 588 ++++++++ .../sqflite_common/lib/src/arg_utils.dart | 29 + .../sqflite_common/lib/src/batch.dart | 190 +++ .../lib/src/collection_utils.dart | 217 +++ .../sqflite_common/lib/src/compat.dart | 66 + .../sqflite_common/lib/src/constant.dart | 182 +++ .../sqflite_common/lib/src/cursor.dart | 36 + .../sqflite_common/lib/src/database.dart | 132 ++ .../lib/src/database_mixin.dart | 927 ++++++++++++ .../sqflite_common/lib/src/dev_utils.dart | 12 + .../sqflite_common/lib/src/env_utils.dart | 23 + .../sqflite_common/lib/src/exception.dart | 193 +++ .../sqflite_common/lib/src/factory.dart | 35 + .../sqflite_common/lib/src/factory_mixin.dart | 273 ++++ .../sqflite_common/lib/src/internals.dart | 26 + .../sqflite_common/lib/src/log_level.dart | 1 + .../lib/src/logger/sqflite_logger.dart | 880 ++++++++++++ .../sqflite_common/lib/src/method_call.dart | 33 + .../sqflite_common/lib/src/mixin.dart | 5 + .../lib/src/mixin/constant.dart | 1 + .../lib/src/mixin/dev_utils.dart | 2 + .../sqflite_common/lib/src/mixin/factory.dart | 38 + .../lib/src/mixin/import_mixin.dart | 45 + .../sqflite_common/lib/src/open_options.dart | 48 + .../sqflite_common/lib/src/path_utils.dart | 21 + .../lib/src/platform/platform.dart | 22 + .../lib/src/platform/platform_io.dart | 23 + .../lib/src/platform/platform_web.dart | 9 + .../lib/src/sqflite_database_factory.dart | 57 + .../sqflite_common/lib/src/sqflite_debug.dart | 27 + .../lib/src/sqflite_import.dart | 32 + .../sqflite_common/lib/src/sql_builder.dart | 597 ++++++++ .../sqflite_common/lib/src/sql_command.dart | 32 + .../sqflite_common/lib/src/transaction.dart | 49 + .../sqflite_common/lib/src/utils.dart | 64 + .../sqflite_common/lib/src/value_utils.dart | 66 + .../sqflite_common/lib/utils/utils.dart | 60 + .../tripartite/sqflite_common/pubspec.yaml | 22 + .../test/import_mixin_test.dart | 37 + .../sqflite_common/test/list_mixin_test.dart | 74 + .../sqflite_common/test/path_utils_test.dart | 22 + .../test/sqflite_batch_test.dart | 74 + .../test/sqflite_debug_test.dart | 39 + .../sqflite_common/test/sqflite_dev_test.dart | 39 + .../test/sqflite_exception_test.dart | 162 +++ .../test/sqflite_impl_test.dart | 121 ++ .../test/sqflite_logger_test.dart | 74 + .../test/sqflite_not_initialized_test.dart | 9 + .../test/sqflite_open_test.dart | 87 ++ .../sqflite_common/test/sqflite_sql_test.dart | 298 ++++ .../test/sqflite_transaction_test.dart | 110 ++ .../sqflite_common/test/sql_builder_test.dart | 188 +++ .../sqflite_common/test/sql_test.dart | 18 + .../sqflite_common/test/sqlite_api_test.dart | 29 + .../test/src_mixin_factory_test.dart | 33 + .../sqflite_common/test/src_mixin_test.dart | 805 +++++++++++ .../sqflite_common/test/test_scenario.dart | 73 + .../sqflite_common/test/utils_test.dart | 96 ++ 277 files changed, 28874 insertions(+), 940 deletions(-) create mode 100644 .gitattributes create mode 100644 sqflite/ohos/.hvigor/cache/file-cache.json create mode 100644 sqflite/ohos/.hvigor/cache/task-cache.json create mode 100644 sqflite/ohos/.hvigor/outputs/logs/details/details.json create mode 100644 sqflite/ohos/.hvigor/outputs/sync/output.json create mode 100644 sqflite/ohos/.hvigor/report/report.json create mode 100644 sqflite/ohos/AppScope/app.json5 create mode 100644 sqflite/ohos/AppScope/resources/base/element/string.json create mode 100644 sqflite/ohos/AppScope/resources/base/media/app_icon.png create mode 100644 sqflite/ohos/build-profile.json5 create mode 100644 sqflite/ohos/dependencies/hvigor-2.3.0-s.tgz create mode 100644 sqflite/ohos/dependencies/hvigor-3.0.9-s.tgz create mode 100644 sqflite/ohos/dependencies/hvigor-ohos-arkui-x-plugin-2.1.7-s.tgz create mode 100644 sqflite/ohos/dependencies/hvigor-ohos-plugin-2.3.0-s.tgz create mode 100644 sqflite/ohos/dependencies/hvigor-ohos-plugin-3.0.9-s.tgz create mode 100644 sqflite/ohos/dependencies/rollup.tgz create mode 100644 sqflite/ohos/hvigor/hvigor-config.json5 create mode 100644 sqflite/ohos/hvigor/hvigor-wrapper.js create mode 100644 sqflite/ohos/hvigorfile.ts create mode 100644 sqflite/ohos/hvigorw create mode 100644 sqflite/ohos/hvigorw.bat create mode 100644 sqflite/ohos/oh-package-lock.json5 create mode 100644 sqflite/ohos/oh-package.json5 create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/CHANGELOG.md create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/README.md create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.ets create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/oh-package.json5 create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/Constant.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/core.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/event.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/interface.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/Filter.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/configService.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js create mode 100644 sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/service.js create mode 100644 sqflite/ohos/sqflite/build-profile.json5 create mode 100644 sqflite/ohos/sqflite/hvigorfile.ts create mode 100644 sqflite/ohos/sqflite/index.ets create mode 100644 sqflite/ohos/sqflite/libs/flutter_embedding.har create mode 100644 sqflite/ohos/sqflite/oh-package.json5 create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/build-profile.json5 create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/hvigorfile.ts create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/index.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/oh-package.json5 create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/index.d.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/index_actual.d.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/oh-package.json5 create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/FlutterInjector.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/app/FlutterPluginRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/component/FlutterComponent.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineCache.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroupCache.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterOverlaySurface.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterShellArgs.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartMessenger.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/PlatformMessageHandler.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterApplicationInfo.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterLoader.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorsStack.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/PluginRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityControlSurface.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterUiDisplayListener.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/KeyEventChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LifecycleChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LocalizationChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/MouseCursorChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/NavigationChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SettingsChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SystemChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TestChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/ExclusiveAppComponent.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbility.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityDelegate.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityLaunchConfigs.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineConfigurator.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineProvider.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterPage.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/OhosTouchProcessor.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/Settings.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventTracker.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapper.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/PlatformPlugin.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/PluginRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StringCodec.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/ListenableEditingState.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextEditingDelta.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/localization/LocalizationPlugin.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/mouse/MouseCursorPlugin.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformOverlayView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistryImpl.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsAccessibilityDelegate.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ByteBuffer.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/MessageChannelUtils.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/PathUtils.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/StringUtils.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ToolUtils.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/TraceSection.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/AccessibilityBridge.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterCallbackInformation.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterNativeView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterRunArguments.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterView.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/TextureRegistry.ets create mode 100644 sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/module.json create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/constant.ets create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sql_helper.ets create mode 100644 sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/tools.ets create mode 100644 sqflite/ohos/sqflite/src/main/module.json5 create mode 100644 sqflite/ohos/sqflite/src/main/resources/base/element/string.json create mode 100644 sqflite/ohos/sqflite/src/main/resources/en_US/element/string.json create mode 100644 sqflite/ohos/sqflite/src/main/resources/zh_CN/element/string.json create mode 100644 sqflite/ohos/sqflite/src/test/List.test.ets create mode 100644 sqflite/ohos/sqflite/src/test/LocalUnit.test.ets create mode 100644 sqflite/tripartite/sqflite_common/.gitignore create mode 100644 sqflite/tripartite/sqflite_common/CHANGELOG.md create mode 100644 sqflite/tripartite/sqflite_common/LICENSE create mode 100644 sqflite/tripartite/sqflite_common/README.md create mode 100644 sqflite/tripartite/sqflite_common/analysis_options.yaml create mode 100644 sqflite/tripartite/sqflite_common/doc/method_call_protocol.md create mode 100644 sqflite/tripartite/sqflite_common/example/main.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/sqflite.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/sqflite_dev.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/sqflite_logger.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/sql.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/sqlite_api.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/arg_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/batch.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/collection_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/compat.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/constant.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/cursor.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/database.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/database_mixin.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/dev_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/env_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/exception.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/factory.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/factory_mixin.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/internals.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/log_level.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/logger/sqflite_logger.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/method_call.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/mixin.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/mixin/constant.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/mixin/dev_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/mixin/factory.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/mixin/import_mixin.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/open_options.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/path_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/platform/platform.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/platform/platform_io.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/platform/platform_web.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/sqflite_database_factory.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/sqflite_debug.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/sqflite_import.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/sql_builder.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/sql_command.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/transaction.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/src/value_utils.dart create mode 100644 sqflite/tripartite/sqflite_common/lib/utils/utils.dart create mode 100644 sqflite/tripartite/sqflite_common/pubspec.yaml create mode 100644 sqflite/tripartite/sqflite_common/test/import_mixin_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/list_mixin_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/path_utils_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_batch_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_debug_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_dev_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_exception_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_impl_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_logger_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_not_initialized_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_open_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_sql_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqflite_transaction_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sql_builder_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sql_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/sqlite_api_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/src_mixin_factory_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/src_mixin_test.dart create mode 100644 sqflite/tripartite/sqflite_common/test/test_scenario.dart create mode 100644 sqflite/tripartite/sqflite_common/test/utils_test.dart diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..56522a8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*[[:space:]].tgz filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text diff --git a/sqflite/CHANGELOG.md b/sqflite/CHANGELOG.md index db89ca7..c999b72 100644 --- a/sqflite/CHANGELOG.md +++ b/sqflite/CHANGELOG.md @@ -1,13 +1,8 @@ -## 2.3.0 - -* Dart 3 only - -## 2.2.8+4 +## 2.2.8+3 * Android: Adds a namespace for compatibility with AGP 8.0. * Android: Use compile SDK 33 * Export global sqflite API -* iOS set minimum deployment target to 11.0 ## 2.2.7 diff --git a/sqflite/analysis_options.yaml b/sqflite/analysis_options.yaml index 7773ddc..74f78c9 100644 --- a/sqflite/analysis_options.yaml +++ b/sqflite/analysis_options.yaml @@ -43,7 +43,8 @@ linter: - directives_ordering - empty_catches - hash_and_equals - - collection_methods_unrelated_type + - iterable_contains_unrelated_type + - list_remove_unrelated_type - no_adjacent_strings_in_list - no_duplicate_case_values - non_constant_identifier_names diff --git a/sqflite/doc/opening_asset_db.md b/sqflite/doc/opening_asset_db.md index 2f8cad6..7166de9 100644 --- a/sqflite/doc/opening_asset_db.md +++ b/sqflite/doc/opening_asset_db.md @@ -51,7 +51,7 @@ if (!exists) { } catch (_) {} // Copy from asset - ByteData data = await rootBundle.load(url.join("assets", "example.db")); + ByteData data = await rootBundle.load(join("assets", "example.db")); List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); @@ -87,7 +87,7 @@ try { } catch (_) {} // Copy from asset -ByteData data = await rootBundle.load(url.join("assets", "example.db")); +ByteData data = await rootBundle.load(join("assets", "example.db")); List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await new File(path).writeAsBytes(bytes, flush: true); diff --git a/sqflite/doc/troubleshooting.md b/sqflite/doc/troubleshooting.md index 8beee03..a609879 100644 --- a/sqflite/doc/troubleshooting.md +++ b/sqflite/doc/troubleshooting.md @@ -204,52 +204,6 @@ end Since Flutter templates change over time for new sdk, you might sometimes try to delete the ios folder and re-create your project. -### XCode 14 support - -You might likely get the following error: - -``` -Error (Xcode): File not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a -``` - -See: https://developer.apple.com/forums/thread/728021 - -Xcode 14 only supports building for a deployment target of iOS 11. - -Here as well you need to enforce the deployment target until I find a better way -as the FMDB dependency is no longer actively maintained. - -In your application Podfile inside the post_install section where you have this in the -app template: - -``` -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end -``` - -you need to have -(11 is used here, but you might want to specify a higher platform): - -``` -post_install do |installer| - - installer.generated_projects.each do |project| - project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' - end - end - end - - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end -``` - ### Module 'FMDB' not found Since v2.2.1-1, you might encounter `Module 'FMDB' not found` on old projects. diff --git a/sqflite/example/analysis_options.yaml b/sqflite/example/analysis_options.yaml index 2be3bca..2abbd7f 100644 --- a/sqflite/example/analysis_options.yaml +++ b/sqflite/example/analysis_options.yaml @@ -43,7 +43,8 @@ linter: - directives_ordering - empty_catches - hash_and_equals - - collection_methods_unrelated_type + - iterable_contains_unrelated_type + - list_remove_unrelated_type - no_adjacent_strings_in_list - no_duplicate_case_values - non_constant_identifier_names diff --git a/sqflite/example/lib/database/database_impl.dart b/sqflite/example/lib/database/database_impl.dart index ab9c3a0..a4992dc 100644 --- a/sqflite/example/lib/database/database_impl.dart +++ b/sqflite/example/lib/database/database_impl.dart @@ -16,15 +16,13 @@ abstract class PlatformHandler { } /// Write the db file directly to the file system - Future writeFileAsBytes(String path, List bytes, - {bool flush = false}); + Future writeFileAsBytes(String path, List bytes, {bool flush = false}); /// Read a file as bytes Future readFileAsBytes(String path); /// Write a file as a string - Future writeFileAsString(String path, String text, - {bool flush = false}); + Future writeFileAsString(String path, String text, {bool flush = false}); /// Read a file as a string Future readFileAsString(String path); @@ -47,41 +45,33 @@ abstract class PlatformHandler { // --- /// delete the db, create the folder and returnes its path -Future initDeleteDb(String dbName) => - platformHandler.initDeleteDb(dbName); +Future initDeleteDb(String dbName) => platformHandler.initDeleteDb(dbName); /// Write the db file directly to the file system -Future writeFileAsBytes(String path, List bytes, - {bool flush = false}) => +Future writeFileAsBytes(String path, List bytes, {bool flush = false}) => platformHandler.writeFileAsBytes(path, bytes, flush: flush); /// Read a file as bytes -Future readFileAsBytes(String path) => - platformHandler.readFileAsBytes(path); +Future readFileAsBytes(String path) => platformHandler.readFileAsBytes(path); /// Write a file as a string -Future writeFileAsString(String path, String text, - {bool flush = false}) => +Future writeFileAsString(String path, String text, {bool flush = false}) => platformHandler.writeFileAsString(path, text, flush: flush); /// Read a file as a string -Future readFileAsString(String path) => - platformHandler.readFileAsString(path); +Future readFileAsString(String path) => platformHandler.readFileAsString(path); /// Check if a path exists. Future pathExists(String path) => platformHandler.pathExists(path); /// Recursively create a directory -Future createDirectory(String path) => - platformHandler.createDirectory(path); +Future createDirectory(String path) => platformHandler.createDirectory(path); /// Recursively delete a directory -Future deleteDirectory(String path) => - platformHandler.deleteDirectory(path); +Future deleteDirectory(String path) => platformHandler.deleteDirectory(path); /// Check if a directory exists -Future existsDirectory(String path) => - platformHandler.existsDirectory(path); +Future existsDirectory(String path) => platformHandler.existsDirectory(path); PlatformHandler? _platformHandler; diff --git a/sqflite/example/lib/database/database_io.dart b/sqflite/example/lib/database/database_io.dart index 58592dd..a050dab 100644 --- a/sqflite/example/lib/database/database_io.dart +++ b/sqflite/example/lib/database/database_io.dart @@ -31,8 +31,7 @@ class _PlatformHandlerIo extends PlatformHandler { /// Write the db file directly to the file system @override - Future writeFileAsBytes(String path, List bytes, - {bool flush = false}) async { + Future writeFileAsBytes(String path, List bytes, {bool flush = false}) async { await File(path).writeAsBytes(bytes, flush: flush); } @@ -44,8 +43,7 @@ class _PlatformHandlerIo extends PlatformHandler { /// Write a file as a string @override - Future writeFileAsString(String path, String text, - {bool flush = false}) async { + Future writeFileAsString(String path, String text, {bool flush = false}) async { await File(path).writeAsString(text, flush: true); } diff --git a/sqflite/example/lib/exp_test_page.dart b/sqflite/example/lib/exp_test_page.dart index ca5087e..d67ce66 100644 --- a/sqflite/example/lib/exp_test_page.dart +++ b/sqflite/example/lib/exp_test_page.dart @@ -345,10 +345,10 @@ class ExpTestPage extends TestPage { await deleteDatabase(path); // Copy from asset - final data = await rootBundle.load(url.join('assets', 'issue_64.db')); + final data = await rootBundle.load(join('assets', 'issue_64.db')); final bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - await databaseFactory.writeDatabaseBytes(path, bytes); + await writeFileAsBytes(path, bytes); // open the database final db = await openDatabase(path); diff --git a/sqflite/example/lib/main.dart b/sqflite/example/lib/main.dart index 01783fe..08b9f8b 100644 --- a/sqflite/example/lib/main.dart +++ b/sqflite/example/lib/main.dart @@ -110,28 +110,16 @@ class _SqfliteExampleAppState extends State { class MyHomePage extends StatefulWidget { /// App home menu page. MyHomePage({Key? key, this.title}) : super(key: key) { - _items.add( - MainItem('Raw tests', 'Raw SQLite operations', route: testRawRoute)); - _items.add(MainItem('Open tests', 'Open onCreate/onUpgrade/onDowngrade', - route: testOpenRoute)); - _items - .add(MainItem('Type tests', 'Test value types', route: testTypeRoute)); - _items.add(MainItem('Batch tests', 'Test batch operations', - route: testBatchRoute)); - _items.add( - MainItem('Slow tests', 'Lengthy operations', route: testSlowRoute)); - _items.add(MainItem( - 'Todo database example', 'Simple Todo-like database usage example', - route: testTodoRoute)); - _items.add(MainItem('Exp tests', 'Experimental and various tests', - route: testExpRoute)); - _items.add(MainItem('Exception tests', 'Tests that trigger exceptions', - route: testExceptionRoute)); - _items.add(MainItem('Manual tests', 'Tests that requires manual execution', - route: testManualRoute)); - _items.add(MainItem('Deprecated test', - 'Keeping some old tests for deprecated functionalities', - route: testDeprecatedRoute)); + _items.add(MainItem('Raw tests', 'Raw SQLite operations', route: testRawRoute)); + _items.add(MainItem('Open tests', 'Open onCreate/onUpgrade/onDowngrade', route: testOpenRoute)); + _items.add(MainItem('Type tests', 'Test value types', route: testTypeRoute)); + _items.add(MainItem('Batch tests', 'Test batch operations', route: testBatchRoute)); + _items.add(MainItem('Slow tests', 'Lengthy operations', route: testSlowRoute)); + _items.add(MainItem('Todo database example', 'Simple Todo-like database usage example', route: testTodoRoute)); + _items.add(MainItem('Exp tests', 'Experimental and various tests', route: testExpRoute)); + _items.add(MainItem('Exception tests', 'Tests that trigger exceptions', route: testExceptionRoute)); + _items.add(MainItem('Manual tests', 'Tests that requires manual execution', route: testManualRoute)); + _items.add(MainItem('Deprecated test', 'Keeping some old tests for deprecated functionalities', route: testDeprecatedRoute)); // Uncomment to view all logs //Sqflite.devSetDebugModeOn(true); @@ -154,8 +142,7 @@ String? get debugAutoStartRouteName => _debugAutoStartRouteName; /// Deprecated to avoid calls @Deprecated('Deb only') -set debugAutoStartRouteName(String? routeName) => - _debugAutoStartRouteName = routeName; +set debugAutoStartRouteName(String? routeName) => _debugAutoStartRouteName = routeName; class _MyHomePageState extends State { int get _itemCount => widget._items.length; @@ -172,8 +159,7 @@ class _MyHomePageState extends State { // await Navigator.of(context).pushNamed(testExpRoute); // await Navigator.of(context).pushNamed(testRawRoute); - final future = - Navigator.of(context).pushNamed(debugAutoStartRouteName!); + final future = Navigator.of(context).pushNamed(debugAutoStartRouteName!); // ignore: deprecated_member_use_from_same_package debugAutoStartRouteName = null; await future; @@ -187,11 +173,9 @@ class _MyHomePageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Center( - child: Text('Sqflite demo', textAlign: TextAlign.center)), + title: const Center(child: Text('Sqflite demo', textAlign: TextAlign.center)), ), - body: - ListView.builder(itemBuilder: _itemBuilder, itemCount: _itemCount)); + body: ListView.builder(itemBuilder: _itemBuilder, itemCount: _itemCount)); } //new Center(child: new Text('Running on: $_platformVersion\n')), diff --git a/sqflite/example/lib/open_test_page.dart b/sqflite/example/lib/open_test_page.dart index 89592fb..e43de7f 100644 --- a/sqflite/example/lib/open_test_page.dart +++ b/sqflite/example/lib/open_test_page.dart @@ -24,9 +24,7 @@ class OpenCallbacks { onConfigure = (Database db) { // devPrint('onConfigure'); //verify(!onConfigureCalled, 'onConfigure must be called once'); - expect(onConfigureCalled, false, - reason: - 'onConfigure already called'); // onConfigure must be called once + expect(onConfigureCalled, false, reason: 'onConfigure already called'); // onConfigure must be called once onConfigureCalled = true; }; @@ -206,8 +204,7 @@ class OpenTestPage extends TestPage { final path = await initDeleteDb('open_test2.db'); var onCreate = false; var onCreateTransaction = false; - final db = await openDatabase(path, version: 1, - onCreate: (Database db, int version) async { + final db = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { expect(version, 1); onCreate = true; @@ -227,17 +224,14 @@ class OpenTestPage extends TestPage { final path = await initDeleteDb('open_simple_on_create.db'); expect(await isDatabase(path), isFalse); - final db = - await openDatabase(path, version: 1, onCreate: (db, version) async { + final db = await openDatabase(path, version: 1, onCreate: (db, version) async { final batch = db.batch(); batch.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, text NAME)'); await batch.commit(); }); try { - expect( - await db.rawInsert('INSERT INTO Test (text) VALUES (?)', ['test']), - 1); + expect(await db.rawInsert('INSERT INTO Test (text) VALUES (?)', ['test']), 1); final result = await db.query('Test'); final expected = [ {'id': 1, 'text': 'test'} @@ -265,21 +259,18 @@ class OpenTestPage extends TestPage { // await Sqflite.devSetDebugModeOn(true); var onUpgrade = false; final path = await initDeleteDb('open_on_upgrade.db'); - var database = await openDatabase(path, version: 1, - onCreate: (Database db, int version) async { + var database = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { await db.execute('CREATE TABLE Test(id INTEGER PRIMARY KEY)'); }); try { - await database - .insert('Test', {'id': 1, 'name': 'test'}); + await database.insert('Test', {'id': 1, 'name': 'test'}); fail('should fail'); } on DatabaseException catch (e) { print(e); } expect(await database.getVersion(), 1); await database.close(); - database = await openDatabase(path, version: 2, - onUpgrade: (Database db, int oldVersion, int newVersion) async { + database = await openDatabase(path, version: 2, onUpgrade: (Database db, int oldVersion, int newVersion) async { expect(oldVersion, 1); expect(newVersion, 2); await db.execute('ALTER TABLE Test ADD name TEXT'); @@ -288,10 +279,7 @@ class OpenTestPage extends TestPage { verify(onUpgrade); expect(await database.getVersion(), 2); try { - expect( - await database - .insert('Test', {'id': 1, 'name': 'test'}), - 1); + expect(await database.insert('Test', {'id': 1, 'name': 'test'}), 1); } finally { await database.close(); } @@ -300,8 +288,7 @@ class OpenTestPage extends TestPage { test('Open onDowngrade', () async { // await Sqflite.devSetDebugModeOn(true); final path = await initDeleteDb('open_on_downgrade.db'); - var database = await openDatabase(path, version: 2, - onCreate: (Database db, int version) async { + var database = await openDatabase(path, version: 2, onCreate: (Database db, int version) async { await db.execute('CREATE TABLE Test(id INTEGER PRIMARY KEY)'); }, onDowngrade: (Database db, int oldVersion, int newVersion) async { verify(false, 'should not be called'); @@ -310,8 +297,7 @@ class OpenTestPage extends TestPage { await database.close(); var onDowngrade = false; - database = await openDatabase(path, version: 1, - onDowngrade: (Database db, int oldVersion, int newVersion) async { + database = await openDatabase(path, version: 1, onDowngrade: (Database db, int oldVersion, int newVersion) async { expect(oldVersion, 2); expect(newVersion, 1); await db.execute('ALTER TABLE Test ADD name TEXT'); @@ -325,8 +311,10 @@ class OpenTestPage extends TestPage { test('Open bad path', () async { try { - await openDatabase('/invalid_path'); - fail(); + // await openDatabase('/invalid_path'); + final db = await openDatabase('my_path/my_db.db'); + print('db的值:$db'); + // fail(); } on DatabaseException catch (e) { verify(e.isOpenFailedError()); } @@ -345,11 +333,11 @@ class OpenTestPage extends TestPage { await createDirectory(path); } catch (_) {} -// Copy from asset to a database file. - final data = await rootBundle.load(url.join('assets', 'example.db')); - final bytes = - data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - await databaseFactory.writeDatabaseBytes(path, bytes); + // Copy from asset + final data = await rootBundle.load(join('assets', 'example.db')); + final List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + // Write and flush the bytes written + await writeFileAsBytes(path, bytes, flush: true); // open the database final db = await openDatabase(path); @@ -387,8 +375,7 @@ class OpenTestPage extends TestPage { // await Sqflite.devSetDebugModeOn(false); final path = await initDeleteDb('open_on_downgrade_delete.db'); - var database = await openDatabase(path, version: 3, - onCreate: (Database db, int version) async { + var database = await openDatabase(path, version: 3, onCreate: (Database db, int version) async { await db.execute('CREATE TABLE Test(id INTEGER PRIMARY KEY)'); }); await database.close(); @@ -399,8 +386,7 @@ class OpenTestPage extends TestPage { var onConfiguredOnce = false; // onConfigure will be called twice here // since the database is re-opened var onConfigured = false; - database = - await openDatabase(path, version: 2, onConfigure: (Database db) { + database = await openDatabase(path, version: 2, onConfigure: (Database db) { // Must not be configured nor created yet verify(!onConfigured); verify(!onCreated); @@ -429,8 +415,7 @@ class OpenTestPage extends TestPage { onCreated = false; onOpened = false; - database = await openDatabase(path, version: 2, - onCreate: (Database db, int version) { + database = await openDatabase(path, version: 2, onCreate: (Database db, int version) { expect(false, 'should not be called'); }, onOpen: (Database db) { onOpened = true; @@ -524,14 +509,8 @@ class OpenTestPage extends TestPage { await batch.commit(); } - final db = await openDatabase(path, - version: 1, - onConfigure: onConfigure, - onCreate: onCreate, - onOpen: onOpen); - expect( - Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), - 2); + final db = await openDatabase(path, version: 1, onConfigure: onConfigure, onCreate: onCreate, onOpen: onOpen); + expect(Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), 2); await db.close(); }); @@ -549,16 +528,12 @@ class OpenTestPage extends TestPage { } var db = await openDatabase(path, version: 1, onCreate: onCreate); - expect( - Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), - 1); + expect(Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), 1); await db.close(); db = await openReadOnlyDatabase(path); - expect( - Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), - 1); + expect(Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM Test')), 1); try { await db.rawInsert('INSERT INTO Test(value) VALUES(?)', ['value1']); @@ -592,8 +567,7 @@ class OpenTestPage extends TestPage { { Future onCreate(Database db, int version) async { // Database is created, delete the table - await db.execute( - 'CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)'); + await db.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, value TEXT)'); } Future onUpgrade(Database db, int oldVersion, int newVersion) async { @@ -603,10 +577,7 @@ class OpenTestPage extends TestPage { // Special callback used for onDowngrade here to recreate the database final db = await openDatabase(path, - version: 1, - onCreate: onCreate, - onUpgrade: onUpgrade, - onDowngrade: onDatabaseDowngradeDelete); + version: 1, onCreate: onCreate, onUpgrade: onUpgrade, onDowngrade: onDatabaseDowngradeDelete); await db.close(); } @@ -642,9 +613,8 @@ class OpenTestPage extends TestPage { print('Creating new copy from asset'); // Copy from asset - final data = await rootBundle.load(url.join('assets', 'example.db')); - final bytes = - data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + final data = await rootBundle.load(join('assets', 'example.db')); + final bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); await writeFileAsBytes(path, bytes); // open the database @@ -676,12 +646,9 @@ class OpenTestPage extends TestPage { final path = await initDeleteDb('instances_test.db'); Database? db1, db2, db3; try { - db1 = await databaseFactory.openDatabase(path, - options: OpenDatabaseOptions(singleInstance: false)); - db2 = await databaseFactory.openDatabase(path, - options: OpenDatabaseOptions(singleInstance: true)); - db3 = await databaseFactory.openDatabase(path, - options: OpenDatabaseOptions(singleInstance: true)); + db1 = await databaseFactory.openDatabase(path, options: OpenDatabaseOptions(singleInstance: false)); + db2 = await databaseFactory.openDatabase(path, options: OpenDatabaseOptions(singleInstance: true)); + db3 = await databaseFactory.openDatabase(path, options: OpenDatabaseOptions(singleInstance: true)); expect(db1, isNot(db2)); expect(db2, db3); } finally { @@ -705,13 +672,11 @@ class OpenTestPage extends TestPage { }); test('In memory database', () async { - const inMemoryPath = - inMemoryDatabasePath; // tried null without success, as it crashes on Android + const inMemoryPath = inMemoryDatabasePath; // tried null without success, as it crashes on Android const path = inMemoryPath; var db = await openDatabase(path); - await db - .execute('CREATE TABLE IF NOT EXISTS Test(id INTEGER PRIMARY KEY)'); + await db.execute('CREATE TABLE IF NOT EXISTS Test(id INTEGER PRIMARY KEY)'); await db.insert('Test', {'id': 1}); expect(await db.query('Test'), [ {'id': 1} @@ -734,8 +699,7 @@ class OpenTestPage extends TestPage { final path = await initDeleteDb('not_in_memory.db'); var db = await openDatabase(path); - await db - .execute('CREATE TABLE IF NOT EXISTS Test(id INTEGER PRIMARY KEY)'); + await db.execute('CREATE TABLE IF NOT EXISTS Test(id INTEGER PRIMARY KEY)'); await db.insert('Test', {'id': 1}); expect(await db.query('Test'), [ {'id': 1} @@ -766,8 +730,7 @@ class OpenTestPage extends TestPage { test('open in sub sub directory', () async { // await Sqflite.devSetDebugModeOn(true); final databasesPath = await factory.getDatabasesPath(); - final path = - join(databasesPath, 'sub2_that_should_not_exists', 'sub_sub'); + final path = join(databasesPath, 'sub2_that_should_not_exists', 'sub_sub'); try { await deleteDirectory(path); } catch (_) {} @@ -784,18 +747,15 @@ class OpenTestPage extends TestPage { const path = 'open_close_open_no_wait.db'; final factory = databaseFactory; await factory.deleteDatabase(path); - final db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + final db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); try { expect(await db.getVersion(), 1); // close no wait unawaited(db.close()); - final db2 = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + final db2 = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); print('$db, $db2'); verify(db != db2); - verify((db as SqfliteDatabaseMixin).id != - (db2 as SqfliteDatabaseMixin).id); + verify((db as SqfliteDatabaseMixin).id != (db2 as SqfliteDatabaseMixin).id); expect(await db2.getVersion(), 1); } finally { await db.close(); @@ -806,15 +766,13 @@ class OpenTestPage extends TestPage { const path = 'test_close_in_transaction.db'; final factory = databaseFactory; await factory.deleteDatabase(path); - var db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + var db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); try { //await db.getVersion(); await db.execute('BEGIN IMMEDIATE'); await db.close(); - db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); } finally { await db.close(); } @@ -825,27 +783,21 @@ class OpenTestPage extends TestPage { const path = 'test_open_in_transaction.db'; final factory = databaseFactory; await factory.deleteDatabase(path); - var db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + var db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); try { //await db.getVersion(); await db.execute('BEGIN IMMEDIATE'); // Trick to make sure we don't reuse the same instance during open - (factory as SqfliteDatabaseFactoryMixin) - .databaseOpenHelpers - .remove(db.path); + (factory as SqfliteDatabaseFactoryMixin).databaseOpenHelpers.remove(db.path); - final db2 = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + final db2 = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); print('after open'); verify(db != db2); - expect( - (db as SqfliteDatabaseMixin).id, (db2 as SqfliteDatabaseMixin).id); + expect((db as SqfliteDatabaseMixin).id, (db2 as SqfliteDatabaseMixin).id); //await db.getVersion(); //await db.execute('ROLLBACK'); - db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); expect(db, db2); } finally { await db.close(); @@ -856,8 +808,7 @@ class OpenTestPage extends TestPage { // Kind of corruption simulation // await Sqflite.devSetDebugModeOn(true); final factory = databaseFactory; - final path = - join(await factory.getDatabasesPath(), 'test_non_sqlite_file.db'); + final path = join(await factory.getDatabasesPath(), 'test_non_sqlite_file.db'); await factory.deleteDatabase(path); // Write dummy content @@ -869,8 +820,7 @@ class OpenTestPage extends TestPage { { late Database db; try { - db = await factory.openDatabase(path, - options: OpenDatabaseOptions(readOnly: true)); + db = await factory.openDatabase(path, options: OpenDatabaseOptions(readOnly: true)); } catch (e) { print('open error'); } @@ -891,8 +841,7 @@ class OpenTestPage extends TestPage { expect((await readFileAsBytes(path)).length, lessThan(minExpectedSize)); var db = await factory.openDatabase(path); - var versionShouldFail = - !supportsCompatMode || platform.isIOS || platform.isMacOS; + var versionShouldFail = !supportsCompatMode || platform.isIOS || platform.isMacOS; if (versionShouldFail) { // On iOS it fails try { @@ -909,14 +858,12 @@ class OpenTestPage extends TestPage { if (versionShouldFail) { // On iOS it fails try { - db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); } catch (e) { print('getVersion error'); } } else { - db = await factory.openDatabase(path, - options: OpenDatabaseOptions(version: 1)); + db = await factory.openDatabase(path, options: OpenDatabaseOptions(version: 1)); // On Android the database is re-created await db.getVersion(); } @@ -924,42 +871,9 @@ class OpenTestPage extends TestPage { if (platform.isAndroid) { // Content has changed, it is a big file now! - expect( - (await readFileAsBytes(path)).length, greaterThan(minExpectedSize)); + expect((await readFileAsBytes(path)).length, greaterThan(minExpectedSize)); } }); - test('Read/write bytes', () async { - var path = await initDeleteDb('database_read_bytes.db'); - var writtenPath = await initDeleteDb('database_written_bytes.db'); - var db = await factory.openDatabase(path, - options: OpenDatabaseOptions( - version: 1, - onCreate: (db, version) async { - await db.execute( - 'CREATE TABLE Test(id INTEGER PRIMARY KEY, value TEXT)'); - })); - var textValue = 'value_to_read'; - await db.insert('Test', {'id': 1, 'value': textValue}); - expect(await db.query('Test'), [ - {'id': 1, 'value': textValue} - ]); - await db.close(); - var bytes = await factory.readDatabaseBytes(path); - //expect(bytes.length, 8192); - expect(bytes.sublist(0, 4), [ - 83, - 81, - 76, - 105, - ]); - - await factory.writeDatabaseBytes(writtenPath, bytes); - db = await factory.openDatabase(writtenPath); - expect(await db.query('Test'), [ - {'id': 1, 'value': textValue} - ]); - await db.close(); - }); } } diff --git a/sqflite/example/lib/raw_test_page.dart b/sqflite/example/lib/raw_test_page.dart index c2954f5..941b6aa 100644 --- a/sqflite/example/lib/raw_test_page.dart +++ b/sqflite/example/lib/raw_test_page.dart @@ -21,11 +21,8 @@ class RawTestPage extends TestPage { final path = await initDeleteDb('raw_simple.db'); final db = await openDatabase(path); try { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - expect( - await db.rawInsert('INSERT INTO Test (name) VALUES (?)', ['test']), - 1); + await db.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + expect(await db.rawInsert('INSERT INTO Test (name) VALUES (?)', ['test']), 1); final result = await db.query('Test'); final expected = [ @@ -37,636 +34,636 @@ class RawTestPage extends TestPage { } }); - test('Sqlite version', () async { - final db = await openDatabase(inMemoryDatabasePath); - final results = await db.rawQuery('select sqlite_version()'); - print('sqlite version: ${results.first.values.first}'); - await db.close(); - }); - - test('Options', () async { - // Sqflite.devSetDebugModeOn(true); - - final path = await initDeleteDb('raw_query_format.db'); - final db = await openDatabase(path); - try { - final batch = db.batch(); - - batch.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - batch.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); - batch.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 2']); - await batch.commit(); - - var sql = 'SELECT id, name FROM Test'; - // ignore: deprecated_member_use - var resultSet = await db.devInvokeSqlMethod('query', sql); - var expectedResultSetMap = { - 'columns': ['id', 'name'], - 'rows': [ - [1, 'item 1'], - [2, 'item 2'] - ] - }; - print('result as r/c $resultSet'); - expect(resultSet, expectedResultSetMap); - - // empty - sql = 'SELECT id, name FROM Test WHERE id=1234'; - // ignore: deprecated_member_use - resultSet = await db.devInvokeSqlMethod('query', sql); - expectedResultSetMap = {}; - print('result as r/c $resultSet'); - try { - // This might be just for compatibility - expect(resultSet, expectedResultSetMap); - } catch (e) { - // Allow empty result - expectedResultSetMap = { - 'columns': ['id', 'name'], - 'rows': [] - }; - expect(resultSet, expectedResultSetMap); - } - } finally { - await db.close(); - } - }); - - test('Transaction', () async { - //Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('simple_transaction.db'); - final db = await openDatabase(path); - try { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - - Future testItem(int i) async { - await db.transaction((txn) async { - final count = Sqflite.firstIntValue( - await txn.rawQuery('SELECT COUNT(*) FROM Test'))!; - await Future.delayed(const Duration(milliseconds: 40)); - await txn - .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item $i']); - //print(await db.query('SELECT COUNT(*) FROM Test')); - final afterCount = Sqflite.firstIntValue( - await txn.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count + 1, afterCount); - }); - } - - final futures = []; - for (var i = 0; i < 4; i++) { - futures.add(testItem(i)); - } - await Future.wait(futures); - } finally { - await db.close(); - } - }); - - test('Concurrency 1', () async { - // Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('simple_concurrency_1.db'); - final db = await openDatabase(path); - try { - final step1 = Completer(); - final step2 = Completer(); - final step3 = Completer(); - - Future action1() async { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - step1.complete(); - - await step2.future; - try { - await db - .rawQuery('SELECT COUNT(*) FROM Test') - .timeout(const Duration(seconds: 1)); - throw 'should fail'; - } catch (e) { - expect(e is TimeoutException, true); - } - - step3.complete(); - } - - Future action2() async { - await db.transaction((txn) async { - // Wait for table being created; - await step1.future; - await txn - .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); - step2.complete(); - - await step3.future; - - final count = Sqflite.firstIntValue( - await txn.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count, 1); - }); - } - - final future1 = action1(); - final future2 = action2(); - - await Future.wait([future1, future2]); - - final count = Sqflite.firstIntValue( - await db.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count, 1); - } finally { - await db.close(); - } - }); - - test('Concurrency 2', () async { - // Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('simple_concurrency_2.db'); - final db = await openDatabase(path); - try { - final step1 = Completer(); - final step2 = Completer(); - final step3 = Completer(); - - Future action1() async { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - step1.complete(); - - await step2.future; - try { - await db - .rawQuery('SELECT COUNT(*) FROM Test') - .timeout(const Duration(seconds: 1)); - throw 'should fail'; - } catch (e) { - expect(e is TimeoutException, true); - } - - step3.complete(); - } - - Future action2() async { - // This is the change from concurrency 1 - // Wait for table being created; - await step1.future; - - await db.transaction((txn) async { - // Wait for table being created; - await txn - .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); - step2.complete(); - - await step3.future; - - final count = Sqflite.firstIntValue( - await txn.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count, 1); - }); - } - - final future1 = action1(); - final future2 = action2(); - - await Future.wait([future1, future2]); - - final count = Sqflite.firstIntValue( - await db.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count, 1); - } finally { - await db.close(); - } - }); - - test('Transaction recursive', () async { - final path = await initDeleteDb('transaction_recursive.db'); - final db = await openDatabase(path); - try { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - - // insert then fails to make sure the transaction is cancelled - await db.transaction((txn) async { - await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); - - await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 2']); - }); - final afterCount = Sqflite.firstIntValue( - await db.rawQuery('SELECT COUNT(*) FROM Test')); - expect(afterCount, 2); - } finally { - await db.close(); - } - }); - - test('Transaction open twice', () async { - //Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('transaction_open_twice.db'); - final db = await openDatabase(path); - Database? db2; - try { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - - db2 = await openDatabase(path); - - await db.transaction((txn) async { - await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item']); - final afterCount = Sqflite.firstIntValue( - await txn.rawQuery('SELECT COUNT(*) FROM Test')); - expect(afterCount, 1); - - /* - // this is not working on Android - int db2AfterCount = - Sqflite.firstIntValue(await db2.rawQuery('SELECT COUNT(*) FROM Test')); - assert(db2AfterCount == 0); - */ - }); - final db2AfterCount = Sqflite.firstIntValue( - await db2.rawQuery('SELECT COUNT(*) FROM Test')); - expect(db2AfterCount, 1); - - final afterCount = Sqflite.firstIntValue( - await db.rawQuery('SELECT COUNT(*) FROM Test')); - expect(afterCount, 1); - } finally { - await db.close(); - await db2?.close(); - } - }); - - if (supportsCompatMode) { - test('Debug mode (log)', () async { - //await Sqflite.devSetDebugModeOn(false); - final path = await initDeleteDb('debug_mode.db'); - final db = await openDatabase(path); - try { - // ignore: deprecated_member_use - final debugModeOn = await Sqflite.getDebugModeOn(); - // ignore: deprecated_member_use - await Sqflite.setDebugModeOn(true); - await db.setVersion(1); - // ignore: deprecated_member_use - await Sqflite.setDebugModeOn(false); - // this message should not appear - await db.setVersion(2); - // ignore: deprecated_member_use - await Sqflite.setDebugModeOn(true); - await db.setVersion(3); - // restore - // ignore: deprecated_member_use - await Sqflite.setDebugModeOn(debugModeOn); - } finally { - await db.close(); - } - }); - } - - test('Demo', () async { - // await Sqflite.devSetDebugModeOn(); - final path = await initDeleteDb('simple_demo.db'); - final database = await openDatabase(path); - try { - //int version = await database.update('PRAGMA user_version'); - //print('version: ${await database.update('PRAGMA user_version')}'); - print('version: ${await database.rawQuery('PRAGMA user_version')}'); - - //print('drop: ${await database.update('DROP TABLE IF EXISTS Test')}'); - await database.execute('DROP TABLE IF EXISTS Test'); - - print('dropped'); - await database.execute( - 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); - print('table created'); - var id = await database.rawInsert( - // This does not work using ffi - // 'INSERT INTO Test(name, value, num) VALUES("some name",1234,?)', - // [456.789]); - 'INSERT INTO Test(name, value, num) VALUES(?,1234,?)', - ['some name', 456.789]); - print('inserted1: $id'); - id = await database.rawInsert( - 'INSERT INTO Test(name, value) VALUES(?, ?)', - ['another name', 12345678]); - print('inserted2: $id'); - var count = await database.rawUpdate( - 'UPDATE Test SET name = ?, value = ? WHERE name = ?', - ['updated name', '9876', 'some name']); - print('updated: $count'); - expect(count, 1); - var list = await database.rawQuery('SELECT * FROM Test'); - var expectedList = [ - {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, - {'name': 'another name', 'id': 2, 'value': 12345678, 'num': null} - ]; - - print('list: ${json.encode(list)}'); - print('expected $expectedList'); - expect(list, expectedList); - - count = await database - .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); - print('deleted: $count'); - expect(count, 1); - list = await database.rawQuery('SELECT * FROM Test'); - expectedList = [ - {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, - ]; - - print('list: ${json.encode(list)}'); - print('expected $expectedList'); - expect(list, expectedList); - } finally { - await database.close(); - } - }); - - test('Demo clean', () async { - // Get a location - final databasesPath = await getDatabasesPath(); - - // Make sure the directory exists - try { - if (!kIsWeb) { - // ignore: avoid_slow_async_io - if (!await io.Directory(databasesPath).exists()) { - await io.Directory(databasesPath).create(recursive: true); - } - } - } catch (_) {} - - final path = join(databasesPath, 'demo.db'); - - // Delete the database - await deleteDatabase(path); - - // open the database - final database = await openDatabase(path, version: 1, - onCreate: (Database db, int version) async { - // When creating the db, create the table - await db.execute( - 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); - }); - - // Insert some records in a transaction - await database.transaction((txn) async { - final id1 = await txn.rawInsert( - // 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)'); This does not work using ffi - 'INSERT INTO Test(name, value, num) VALUES(?, 1234, 456.789)', - ['some name']); - print('inserted1: $id1'); - final id2 = await txn.rawInsert( - 'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)', - ['another name', 12345678, 3.1416]); - print('inserted2: $id2'); - }); - - // Update some record - var count = await database.rawUpdate( - 'UPDATE Test SET name = ?, value = ? WHERE name = ?', - ['updated name', '9876', 'some name']); - print('updated: $count'); - - // Get the records - final list = await database.rawQuery('SELECT * FROM Test'); - final expectedList = [ - {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, - {'name': 'another name', 'id': 2, 'value': 12345678, 'num': 3.1416} - ]; - print(list); - print(expectedList); - //assert(const DeepCollectionEquality().equals(list, expectedList)); - expect(list, expectedList); - - // Count the records - count = (Sqflite.firstIntValue( - await database.rawQuery('SELECT COUNT(*) FROM Test')))!; - expect(count, 2); - - // Delete a record - count = await database - .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); - expect(count, 1); - - // Close the database - await database.close(); - }); - - test('Open twice', () async { - // Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('open_twice.db'); - final db = await openDatabase(path); - Database? db2; - try { - await db - .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); - db2 = await openReadOnlyDatabase(path); - - final count = Sqflite.firstIntValue( - await db2.rawQuery('SELECT COUNT(*) FROM Test')); - expect(count, 0); - } finally { - await db.close(); - await db2?.close(); - } - }); - - test('text primary key', () async { - // Sqflite.devSetDebugModeOn(true); - final path = await initDeleteDb('text_primary_key.db'); - final db = await openDatabase(path); - try { - // This table has no primary key however sqlite generates an hidden row id - await db.execute('CREATE TABLE Test (name TEXT PRIMARY KEY)'); - var id = await db.insert('Test', {'name': 'test'}); - expect(id, 1); - id = await db.insert('Test', {'name': 'other'}); - expect(id, 2); - // row id is not retrieve by default - var list = await db.query('Test'); - expect(list, [ - {'name': 'test'}, - {'name': 'other'} - ]); - list = await db.query('Test', columns: ['name', 'rowid']); - expect(list, [ - {'name': 'test', 'rowid': 1}, - {'name': 'other', 'rowid': 2} - ]); - } finally { - await db.close(); - } - }); - - test('Without rowid', () async { - // Sqflite.devSetDebugModeOn(true); - // this fails on iOS - - late Database db; - try { - final path = await initDeleteDb('without_rowid.db'); - db = await openDatabase(path); - // This table has no primary key and we ask sqlite not to generate - // a rowid - await db - .execute('CREATE TABLE Test (name TEXT PRIMARY KEY) WITHOUT ROWID'); - var id = await db.insert('Test', {'name': 'test'}); - - // it seems to always return 1 on Android, 0 on iOS..., 0 using ffi - var rowIdAlways0 = - (!supportsCompatMode || (platform.isIOS || platform.isMacOS)); - - if (rowIdAlways0) { - expect(id, 0); - } else { - expect(id, 1); - } - id = await db.insert('Test', {'name': 'other'}); - // it seems to always return 1 - if (rowIdAlways0) { - expect(id, 0); - } else { - expect(id, 1); - } - - // Insert conflict - // Only tested on Android for now... - try { - id = await db.insert('Test', {'name': 'other'}); - } on DatabaseException catch (e) { - // Test.name (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)) sql 'INSERT INTO Test (name) VALUES (?)' args [other] running without rowid - expect(e.getResultCode(), 1555); - } - - // notice the order is based on the primary key - final list = await db.query('Test'); - expect(list, [ - {'name': 'other'}, - {'name': 'test'} - ]); - } finally { - await db.close(); - } - }); - - test('Reference query', () async { - final path = await initDeleteDb('reference_query.db'); - final db = await openDatabase(path); - try { - final batch = db.batch(); - - batch.execute('CREATE TABLE Other (id INTEGER PRIMARY KEY, name TEXT)'); - batch.execute( - 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, other REFERENCES Other(id))'); - batch.rawInsert('INSERT INTO Other (name) VALUES (?)', ['other 1']); - batch.rawInsert( - 'INSERT INTO Test (other, name) VALUES (?, ?)', [1, 'item 2']); - await batch.commit(); - - var result = await db.query('Test', - columns: ['other', 'name'], where: 'other = 1'); - print(result); - expect(result, [ - {'other': 1, 'name': 'item 2'} - ]); - result = await db.query('Test', - columns: ['other', 'name'], where: 'other = ?', whereArgs: [1]); - print(result); - expect(result, [ - {'other': 1, 'name': 'item 2'} - ]); - } finally { - await db.close(); - } - }); - - test('Binding null (fails on Android)', () async { - final db = await openDatabase(inMemoryDatabasePath); - try { - for (var value in [null, 2]) { - expect( - firstIntValue(await db.rawQuery( - 'SELECT CASE WHEN 0 = 1 THEN 1 ELSE ? END', [value])), - value); - } - } finally { - await db.close(); - } - }); - - test('Query by page', () async { - // await databaseFactory.debugSetLogLevel(sqfliteLogLevelVerbose); - - //final path = await initDeleteDb('query_by_page.db'); - //final db = await openDatabase(path); - final db = await openDatabase(inMemoryDatabasePath); - try { - await db.execute(''' - CREATE TABLE test ( - id INTEGER PRIMARY KEY - )'''); - await db.insert('test', {'id': 1}); - await db.insert('test', {'id': 2}); - await db.insert('test', {'id': 3}); - var resultsList = []; - - // Use a cursor - var cursor = - await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 2); - resultsList.clear(); - var results = >[]; - while (await cursor.moveNext()) { - results.add(cursor.current); - } - expect(results, [ - {'id': 1}, - {'id': 2}, - {'id': 3} - ]); - - // Multiple cursors a cursor - var cursor1 = - await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 2); - var cursor2 = - await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 1); - await cursor1.moveNext(); - expect(cursor1.current.values, [1]); - await cursor2.moveNext(); - await cursor2.moveNext(); - expect(cursor2.current.values, [2]); - await cursor1.moveNext(); - expect(cursor1.current.values, [2]); - await cursor1.close(); - await cursor1.close(); // ok to call twice - try { - cursor1.current.values; - fail('should fail get current'); - } on StateError catch (_) {} - await cursor2.moveNext(); - expect(cursor2.current.values, [3]); - expect(await cursor2.moveNext(), isFalse); - expect(await cursor1.moveNext(), isFalse); - try { - cursor2.current.values; - fail('should fail get current'); - } on StateError catch (_) {} - - // No data - cursor = await db.rawQueryCursor('SELECT * FROM test WHERE id > ?', [3], - bufferSize: 2); - expect(await cursor.moveNext(), isFalse); - - // Matching page size - cursor = await db.rawQueryCursor('SELECT * FROM test WHERE id > ?', [1], - bufferSize: 2); - expect(await cursor.moveNext(), isTrue); - expect(await cursor.moveNext(), isTrue); - expect(await cursor.moveNext(), isFalse); - } finally { - await db.close(); - } - }); + // test('Sqlite version', () async { + // final db = await openDatabase(inMemoryDatabasePath); + // final results = await db.rawQuery('select sqlite_version()'); + // print('sqlite version: ${results.first.values.first}'); + // await db.close(); + // }); + + // test('Options', () async { + // // Sqflite.devSetDebugModeOn(true); + + // final path = await initDeleteDb('raw_query_format.db'); + // final db = await openDatabase(path); + // try { + // final batch = db.batch(); + + // batch.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + // batch.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); + // batch.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 2']); + // await batch.commit(); + + // var sql = 'SELECT id, name FROM Test'; + // // ignore: deprecated_member_use + // var resultSet = await db.devInvokeSqlMethod('query', sql); + // var expectedResultSetMap = { + // 'columns': ['id', 'name'], + // 'rows': [ + // [1, 'item 1'], + // [2, 'item 2'] + // ] + // }; + // print('result as r/c $resultSet'); + // expect(resultSet, expectedResultSetMap); + + // // empty + // sql = 'SELECT id, name FROM Test WHERE id=1234'; + // // ignore: deprecated_member_use + // resultSet = await db.devInvokeSqlMethod('query', sql); + // expectedResultSetMap = {}; + // print('result as r/c $resultSet'); + // try { + // // This might be just for compatibility + // expect(resultSet, expectedResultSetMap); + // } catch (e) { + // // Allow empty result + // expectedResultSetMap = { + // 'columns': ['id', 'name'], + // 'rows': [] + // }; + // expect(resultSet, expectedResultSetMap); + // } + // } finally { + // await db.close(); + // } + // }); + + // test('Transaction', () async { + // //Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('simple_transaction.db'); + // final db = await openDatabase(path); + // try { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + + // Future testItem(int i) async { + // await db.transaction((txn) async { + // final count = Sqflite.firstIntValue( + // await txn.rawQuery('SELECT COUNT(*) FROM Test'))!; + // await Future.delayed(const Duration(milliseconds: 40)); + // await txn + // .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item $i']); + // //print(await db.query('SELECT COUNT(*) FROM Test')); + // final afterCount = Sqflite.firstIntValue( + // await txn.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count + 1, afterCount); + // }); + // } + + // final futures = []; + // for (var i = 0; i < 4; i++) { + // futures.add(testItem(i)); + // } + // await Future.wait(futures); + // } finally { + // await db.close(); + // } + // }); + + // test('Concurrency 1', () async { + // // Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('simple_concurrency_1.db'); + // final db = await openDatabase(path); + // try { + // final step1 = Completer(); + // final step2 = Completer(); + // final step3 = Completer(); + + // Future action1() async { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + // step1.complete(); + + // await step2.future; + // try { + // await db + // .rawQuery('SELECT COUNT(*) FROM Test') + // .timeout(const Duration(seconds: 1)); + // throw 'should fail'; + // } catch (e) { + // expect(e is TimeoutException, true); + // } + + // step3.complete(); + // } + + // Future action2() async { + // await db.transaction((txn) async { + // // Wait for table being created; + // await step1.future; + // await txn + // .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); + // step2.complete(); + + // await step3.future; + + // final count = Sqflite.firstIntValue( + // await txn.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count, 1); + // }); + // } + + // final future1 = action1(); + // final future2 = action2(); + + // await Future.wait([future1, future2]); + + // final count = Sqflite.firstIntValue( + // await db.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count, 1); + // } finally { + // await db.close(); + // } + // }); + + // test('Concurrency 2', () async { + // // Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('simple_concurrency_2.db'); + // final db = await openDatabase(path); + // try { + // final step1 = Completer(); + // final step2 = Completer(); + // final step3 = Completer(); + + // Future action1() async { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + // step1.complete(); + + // await step2.future; + // try { + // await db + // .rawQuery('SELECT COUNT(*) FROM Test') + // .timeout(const Duration(seconds: 1)); + // throw 'should fail'; + // } catch (e) { + // expect(e is TimeoutException, true); + // } + + // step3.complete(); + // } + + // Future action2() async { + // // This is the change from concurrency 1 + // // Wait for table being created; + // await step1.future; + + // await db.transaction((txn) async { + // // Wait for table being created; + // await txn + // .rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); + // step2.complete(); + + // await step3.future; + + // final count = Sqflite.firstIntValue( + // await txn.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count, 1); + // }); + // } + + // final future1 = action1(); + // final future2 = action2(); + + // await Future.wait([future1, future2]); + + // final count = Sqflite.firstIntValue( + // await db.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count, 1); + // } finally { + // await db.close(); + // } + // }); + + // test('Transaction recursive', () async { + // final path = await initDeleteDb('transaction_recursive.db'); + // final db = await openDatabase(path); + // try { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + + // // insert then fails to make sure the transaction is cancelled + // await db.transaction((txn) async { + // await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 1']); + + // await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item 2']); + // }); + // final afterCount = Sqflite.firstIntValue( + // await db.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(afterCount, 2); + // } finally { + // await db.close(); + // } + // }); + + // test('Transaction open twice', () async { + // //Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('transaction_open_twice.db'); + // final db = await openDatabase(path); + // Database? db2; + // try { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + + // db2 = await openDatabase(path); + + // await db.transaction((txn) async { + // await txn.rawInsert('INSERT INTO Test (name) VALUES (?)', ['item']); + // final afterCount = Sqflite.firstIntValue( + // await txn.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(afterCount, 1); + + // /* + // // this is not working on Android + // int db2AfterCount = + // Sqflite.firstIntValue(await db2.rawQuery('SELECT COUNT(*) FROM Test')); + // assert(db2AfterCount == 0); + // */ + // }); + // final db2AfterCount = Sqflite.firstIntValue( + // await db2.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(db2AfterCount, 1); + + // final afterCount = Sqflite.firstIntValue( + // await db.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(afterCount, 1); + // } finally { + // await db.close(); + // await db2?.close(); + // } + // }); + + // if (supportsCompatMode) { + // test('Debug mode (log)', () async { + // //await Sqflite.devSetDebugModeOn(false); + // final path = await initDeleteDb('debug_mode.db'); + // final db = await openDatabase(path); + // try { + // // ignore: deprecated_member_use + // final debugModeOn = await Sqflite.getDebugModeOn(); + // // ignore: deprecated_member_use + // await Sqflite.setDebugModeOn(true); + // await db.setVersion(1); + // // ignore: deprecated_member_use + // await Sqflite.setDebugModeOn(false); + // // this message should not appear + // await db.setVersion(2); + // // ignore: deprecated_member_use + // await Sqflite.setDebugModeOn(true); + // await db.setVersion(3); + // // restore + // // ignore: deprecated_member_use + // await Sqflite.setDebugModeOn(debugModeOn); + // } finally { + // await db.close(); + // } + // }); + // } + + // test('Demo', () async { + // // await Sqflite.devSetDebugModeOn(); + // final path = await initDeleteDb('simple_demo.db'); + // final database = await openDatabase(path); + // try { + // //int version = await database.update('PRAGMA user_version'); + // //print('version: ${await database.update('PRAGMA user_version')}'); + // print('version: ${await database.rawQuery('PRAGMA user_version')}'); + + // //print('drop: ${await database.update('DROP TABLE IF EXISTS Test')}'); + // await database.execute('DROP TABLE IF EXISTS Test'); + + // print('dropped'); + // await database.execute( + // 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); + // print('table created'); + // var id = await database.rawInsert( + // // This does not work using ffi + // // 'INSERT INTO Test(name, value, num) VALUES("some name",1234,?)', + // // [456.789]); + // 'INSERT INTO Test(name, value, num) VALUES(?,1234,?)', + // ['some name', 456.789]); + // print('inserted1: $id'); + // id = await database.rawInsert( + // 'INSERT INTO Test(name, value) VALUES(?, ?)', + // ['another name', 12345678]); + // print('inserted2: $id'); + // var count = await database.rawUpdate( + // 'UPDATE Test SET name = ?, value = ? WHERE name = ?', + // ['updated name', '9876', 'some name']); + // print('updated: $count'); + // expect(count, 1); + // var list = await database.rawQuery('SELECT * FROM Test'); + // var expectedList = [ + // {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, + // {'name': 'another name', 'id': 2, 'value': 12345678, 'num': null} + // ]; + + // print('list: ${json.encode(list)}'); + // print('expected $expectedList'); + // expect(list, expectedList); + + // count = await database + // .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); + // print('deleted: $count'); + // expect(count, 1); + // list = await database.rawQuery('SELECT * FROM Test'); + // expectedList = [ + // {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, + // ]; + + // print('list: ${json.encode(list)}'); + // print('expected $expectedList'); + // expect(list, expectedList); + // } finally { + // await database.close(); + // } + // }); + + // test('Demo clean', () async { + // // Get a location + // final databasesPath = await getDatabasesPath(); + + // // Make sure the directory exists + // try { + // if (!kIsWeb) { + // // ignore: avoid_slow_async_io + // if (!await io.Directory(databasesPath).exists()) { + // await io.Directory(databasesPath).create(recursive: true); + // } + // } + // } catch (_) {} + + // final path = join(databasesPath, 'demo.db'); + + // // Delete the database + // await deleteDatabase(path); + + // // open the database + // final database = await openDatabase(path, version: 1, + // onCreate: (Database db, int version) async { + // // When creating the db, create the table + // await db.execute( + // 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); + // }); + + // // Insert some records in a transaction + // await database.transaction((txn) async { + // final id1 = await txn.rawInsert( + // // 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)'); This does not work using ffi + // 'INSERT INTO Test(name, value, num) VALUES(?, 1234, 456.789)', + // ['some name']); + // print('inserted1: $id1'); + // final id2 = await txn.rawInsert( + // 'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)', + // ['another name', 12345678, 3.1416]); + // print('inserted2: $id2'); + // }); + + // // Update some record + // var count = await database.rawUpdate( + // 'UPDATE Test SET name = ?, value = ? WHERE name = ?', + // ['updated name', '9876', 'some name']); + // print('updated: $count'); + + // // Get the records + // final list = await database.rawQuery('SELECT * FROM Test'); + // final expectedList = [ + // {'name': 'updated name', 'id': 1, 'value': 9876, 'num': 456.789}, + // {'name': 'another name', 'id': 2, 'value': 12345678, 'num': 3.1416} + // ]; + // print(list); + // print(expectedList); + // //assert(const DeepCollectionEquality().equals(list, expectedList)); + // expect(list, expectedList); + + // // Count the records + // count = (Sqflite.firstIntValue( + // await database.rawQuery('SELECT COUNT(*) FROM Test')))!; + // expect(count, 2); + + // // Delete a record + // count = await database + // .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); + // expect(count, 1); + + // // Close the database + // await database.close(); + // }); + + // test('Open twice', () async { + // // Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('open_twice.db'); + // final db = await openDatabase(path); + // Database? db2; + // try { + // await db + // .execute('CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)'); + // db2 = await openReadOnlyDatabase(path); + + // final count = Sqflite.firstIntValue( + // await db2.rawQuery('SELECT COUNT(*) FROM Test')); + // expect(count, 0); + // } finally { + // await db.close(); + // await db2?.close(); + // } + // }); + + // test('text primary key', () async { + // // Sqflite.devSetDebugModeOn(true); + // final path = await initDeleteDb('text_primary_key.db'); + // final db = await openDatabase(path); + // try { + // // This table has no primary key however sqlite generates an hidden row id + // await db.execute('CREATE TABLE Test (name TEXT PRIMARY KEY)'); + // var id = await db.insert('Test', {'name': 'test'}); + // expect(id, 1); + // id = await db.insert('Test', {'name': 'other'}); + // expect(id, 2); + // // row id is not retrieve by default + // var list = await db.query('Test'); + // expect(list, [ + // {'name': 'test'}, + // {'name': 'other'} + // ]); + // list = await db.query('Test', columns: ['name', 'rowid']); + // expect(list, [ + // {'name': 'test', 'rowid': 1}, + // {'name': 'other', 'rowid': 2} + // ]); + // } finally { + // await db.close(); + // } + // }); + + // test('Without rowid', () async { + // // Sqflite.devSetDebugModeOn(true); + // // this fails on iOS + + // late Database db; + // try { + // final path = await initDeleteDb('without_rowid.db'); + // db = await openDatabase(path); + // // This table has no primary key and we ask sqlite not to generate + // // a rowid + // await db + // .execute('CREATE TABLE Test (name TEXT PRIMARY KEY) WITHOUT ROWID'); + // var id = await db.insert('Test', {'name': 'test'}); + + // // it seems to always return 1 on Android, 0 on iOS..., 0 using ffi + // var rowIdAlways0 = + // (!supportsCompatMode || (platform.isIOS || platform.isMacOS)); + + // if (rowIdAlways0) { + // expect(id, 0); + // } else { + // expect(id, 1); + // } + // id = await db.insert('Test', {'name': 'other'}); + // // it seems to always return 1 + // if (rowIdAlways0) { + // expect(id, 0); + // } else { + // expect(id, 1); + // } + + // // Insert conflict + // // Only tested on Android for now... + // try { + // id = await db.insert('Test', {'name': 'other'}); + // } on DatabaseException catch (e) { + // // Test.name (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)) sql 'INSERT INTO Test (name) VALUES (?)' args [other] running without rowid + // expect(e.getResultCode(), 1555); + // } + + // // notice the order is based on the primary key + // final list = await db.query('Test'); + // expect(list, [ + // {'name': 'other'}, + // {'name': 'test'} + // ]); + // } finally { + // await db.close(); + // } + // }); + + // test('Reference query', () async { + // final path = await initDeleteDb('reference_query.db'); + // final db = await openDatabase(path); + // try { + // final batch = db.batch(); + + // batch.execute('CREATE TABLE Other (id INTEGER PRIMARY KEY, name TEXT)'); + // batch.execute( + // 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, other REFERENCES Other(id))'); + // batch.rawInsert('INSERT INTO Other (name) VALUES (?)', ['other 1']); + // batch.rawInsert( + // 'INSERT INTO Test (other, name) VALUES (?, ?)', [1, 'item 2']); + // await batch.commit(); + + // var result = await db.query('Test', + // columns: ['other', 'name'], where: 'other = 1'); + // print(result); + // expect(result, [ + // {'other': 1, 'name': 'item 2'} + // ]); + // result = await db.query('Test', + // columns: ['other', 'name'], where: 'other = ?', whereArgs: [1]); + // print(result); + // expect(result, [ + // {'other': 1, 'name': 'item 2'} + // ]); + // } finally { + // await db.close(); + // } + // }); + + // test('Binding null (fails on Android)', () async { + // final db = await openDatabase(inMemoryDatabasePath); + // try { + // for (var value in [null, 2]) { + // expect( + // firstIntValue(await db.rawQuery( + // 'SELECT CASE WHEN 0 = 1 THEN 1 ELSE ? END', [value])), + // value); + // } + // } finally { + // await db.close(); + // } + // }); + + // test('Query by page', () async { + // // await databaseFactory.debugSetLogLevel(sqfliteLogLevelVerbose); + + // //final path = await initDeleteDb('query_by_page.db'); + // //final db = await openDatabase(path); + // final db = await openDatabase(inMemoryDatabasePath); + // try { + // await db.execute(''' + // CREATE TABLE test ( + // id INTEGER PRIMARY KEY + // )'''); + // await db.insert('test', {'id': 1}); + // await db.insert('test', {'id': 2}); + // await db.insert('test', {'id': 3}); + // var resultsList = []; + + // // Use a cursor + // var cursor = + // await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 2); + // resultsList.clear(); + // var results = >[]; + // while (await cursor.moveNext()) { + // results.add(cursor.current); + // } + // expect(results, [ + // {'id': 1}, + // {'id': 2}, + // {'id': 3} + // ]); + + // // Multiple cursors a cursor + // var cursor1 = + // await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 2); + // var cursor2 = + // await db.rawQueryCursor('SELECT * FROM test', null, bufferSize: 1); + // await cursor1.moveNext(); + // expect(cursor1.current.values, [1]); + // await cursor2.moveNext(); + // await cursor2.moveNext(); + // expect(cursor2.current.values, [2]); + // await cursor1.moveNext(); + // expect(cursor1.current.values, [2]); + // await cursor1.close(); + // await cursor1.close(); // ok to call twice + // try { + // cursor1.current.values; + // fail('should fail get current'); + // } on StateError catch (_) {} + // await cursor2.moveNext(); + // expect(cursor2.current.values, [3]); + // expect(await cursor2.moveNext(), isFalse); + // expect(await cursor1.moveNext(), isFalse); + // try { + // cursor2.current.values; + // fail('should fail get current'); + // } on StateError catch (_) {} + + // // No data + // cursor = await db.rawQueryCursor('SELECT * FROM test WHERE id > ?', [3], + // bufferSize: 2); + // expect(await cursor.moveNext(), isFalse); + + // // Matching page size + // cursor = await db.rawQueryCursor('SELECT * FROM test WHERE id > ?', [1], + // bufferSize: 2); + // expect(await cursor.moveNext(), isTrue); + // expect(await cursor.moveNext(), isTrue); + // expect(await cursor.moveNext(), isFalse); + // } finally { + // await db.close(); + // } + // }); } } diff --git a/sqflite/example/lib/test_page.dart b/sqflite/example/lib/test_page.dart index 2bda08d..0964716 100644 --- a/sqflite/example/lib/test_page.dart +++ b/sqflite/example/lib/test_page.dart @@ -70,7 +70,7 @@ bool? verify(bool? condition, [String? message]) { } /// Group. -abstract mixin class Group { +abstract class Group { /// List of tests. List get tests; diff --git a/sqflite/example/pubspec.yaml b/sqflite/example/pubspec.yaml index 51827cf..79f3ebe 100644 --- a/sqflite/example/pubspec.yaml +++ b/sqflite/example/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: none version: '0.4.0' environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=2.18.0 <4.0.0' dependencies: path: any @@ -50,4 +50,4 @@ dependency_overrides: sqflite: path: ../ sqflite_common: - path: ../../sqflite_common + path: ../tripartite/sqflite_common \ No newline at end of file diff --git a/sqflite/ios/sqflite.podspec b/sqflite/ios/sqflite.podspec index 16f0501..c6b968e 100644 --- a/sqflite/ios/sqflite.podspec +++ b/sqflite/ios/sqflite.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'sqflite' - s.version = '0.0.3' + s.version = '0.0.2' s.summary = 'SQLite plugin.' s.description = <<-DESC Accss SQLite database. @@ -17,8 +17,7 @@ Accss SQLite database. s.dependency 'Flutter' s.dependency 'FMDB', '>= 2.7.5' - s.platform = :ios, '11.0' - s.ios.deployment_target = '11.0' + s.platform = :ios, '9.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } end diff --git a/sqflite/lib/src/factory_impl.dart b/sqflite/lib/src/factory_impl.dart index e0bbe21..49e2270 100644 --- a/sqflite/lib/src/factory_impl.dart +++ b/sqflite/lib/src/factory_impl.dart @@ -6,32 +6,25 @@ import 'package:sqflite/src/exception_impl.dart' as impl; import 'package:sqflite/src/sqflite_impl.dart' as impl; import 'package:sqflite/src/sqflite_import.dart'; import 'package:sqflite_common/sqflite.dart' as sqflite_common; -// ignore: implementation_imports -import 'package:sqflite_common/src/mixin/platform.dart'; - import 'dev_utils.dart'; // ignore: unused_import /// sqflite Default factory @visibleForTesting SqfliteDatabaseFactory get sqfliteDatabaseFactory => // ignore: invalid_use_of_visible_for_testing_member - (databaseFactoryOrNull ?? databaseFactorySqflitePlugin) - as SqfliteDatabaseFactory; + (databaseFactoryOrNull ?? databaseFactorySqflitePlugin) as SqfliteDatabaseFactory; -final SqfliteDatabaseFactory _databaseFactorySqflitePlugin = - SqfliteDatabaseFactoryImpl(); +final SqfliteDatabaseFactory _databaseFactorySqflitePlugin = SqfliteDatabaseFactoryImpl(); /// Default factory that uses the plugin. -DatabaseFactory get databaseFactorySqflitePlugin => - _databaseFactorySqflitePlugin; +DatabaseFactory get databaseFactorySqflitePlugin => _databaseFactorySqflitePlugin; /// Default factory that uses the plugin. final sqfliteDatabaseFactoryDefault = _databaseFactorySqflitePlugin; /// Change the default factory. test only. @visibleForTesting -set sqfliteDatabaseFactory(SqfliteDatabaseFactory? databaseFactory) => - sqflite_common.databaseFactory = databaseFactory; +set sqfliteDatabaseFactory(SqfliteDatabaseFactory? databaseFactory) => sqflite_common.databaseFactory = databaseFactory; /// Factory implementation class SqfliteDatabaseFactoryImpl with SqfliteDatabaseFactoryMixin { @@ -40,14 +33,11 @@ class SqfliteDatabaseFactoryImpl with SqfliteDatabaseFactoryMixin { static const _debugInternals = false; @override - Future wrapDatabaseException(Future Function() action) => - impl.wrapDatabaseException(action); + Future wrapDatabaseException(Future Function() action) => impl.wrapDatabaseException(action); @override Future invokeMethod(String method, [Object? arguments]) => - !_debugInternals - ? impl.invokeMethod(method, arguments) - : _invokeMethodWithLog(method, arguments); + !_debugInternals ? impl.invokeMethod(method, arguments) : _invokeMethodWithLog(method, arguments); Future _invokeMethodWithLog(String method, [Object? arguments]) async { // ignore: avoid_print @@ -57,14 +47,4 @@ class SqfliteDatabaseFactoryImpl with SqfliteDatabaseFactoryMixin { print('<- $result'); return result; } - - @override - Future readDatabaseBytes(String path) async { - return await platform.databaseFileSystem.readDatabaseBytes(path); - } - - @override - Future writeDatabaseBytes(String path, Uint8List bytes) async { - await platform.databaseFileSystem.writeDatabaseBytes(path, bytes); - } } diff --git a/sqflite/lib/src/sqflite_impl.dart b/sqflite/lib/src/sqflite_impl.dart index de1b051..9baf7f3 100644 --- a/sqflite/lib/src/sqflite_impl.dart +++ b/sqflite/lib/src/sqflite_impl.dart @@ -12,5 +12,4 @@ const MethodChannel channel = MethodChannel(channelName); const supportsConcurrency = false; /// Invoke a native method -Future invokeMethod(String method, [Object? arguments]) async => - await channel.invokeMethod(method, arguments) as T; +Future invokeMethod(String method, [Object? arguments]) async => await channel.invokeMethod(method, arguments) as T; diff --git a/sqflite/ohos/.hvigor/cache/file-cache.json b/sqflite/ohos/.hvigor/cache/file-cache.json new file mode 100644 index 0000000..3d2de4d --- /dev/null +++ b/sqflite/ohos/.hvigor/cache/file-cache.json @@ -0,0 +1 @@ +{"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\AppScope\\app.json5":{"hashValue":"08fc0c1cb05d3261806ebb63e4714bac","name":"app.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\AppScope\\app.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":875,"lastModifiedTime":1706059631374}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\module.json5":{"hashValue":"e1023c7c6717335313fe49e930dd5ae0","name":"module.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\module.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":785,"lastModifiedTime":1706059631524}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\oh-package.json5":{"hashValue":"e16f6cf494828bc7c0aa74c69f614ca5","name":"oh-package.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\oh-package.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":922,"lastModifiedTime":1706059631522}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default\\module.json":{"hashValue":"9ec0158bb31dc6e972a74673f5e99f40","name":"module.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default\\module.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":395,"lastModifiedTime":1706084761934}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets":{"hashValue":"2b00464badb6d6c698553adbb3771ef9","name":"ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e03c6dd526771fffbc93d2fd6bb77c6f","name":"io","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"80c7a8ae8aae48b4a2cf3276de9417d8","name":"flutter","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"02e58910ce276f959cb2e9ebb66eed09","name":"plugins","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e435b76f2d4c81f6d8afcfca619c179f","name":"sqflite","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"14844d1b9ee1fe908bb826062bbd5746","name":"constant.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\constant.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":3688,"lastModifiedTime":1706063438578}},{"hashValue":"2914c1433d84cc9a790fffeff8456dab","name":"Messages.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\Messages.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":16458,"lastModifiedTime":1706059631523}},{"hashValue":"8a00cba3203155178fb63abb8859ebfe","name":"sqflite_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sqflite_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":38720,"lastModifiedTime":1706084837870}},{"hashValue":"f125b24a36b06b8b146afe6a97113ffe","name":"SqflitePlugin.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\SqflitePlugin.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":18191,"lastModifiedTime":1706084156443}},{"hashValue":"8369f358c1b0e17eb29db65ba1d5c20d","name":"sql_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sql_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":8232,"lastModifiedTime":1706084805952}},{"hashValue":"3dfa4d7122cd9ea5dc95e53abbde4606","name":"tools.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\tools.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":411,"lastModifiedTime":1706067315976}}]}]}]}]}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\loader_out\\default\\ets":{"hashValue":"","name":"emptyroot","path":"","type":"unknown","isSymbolicLink":false,"children":[]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\process_profile\\default\\module.json":{"hashValue":"8708fae7f796bca08fd5263aea8bc401","name":"module.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\process_profile\\default\\module.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":480,"lastModifiedTime":1706084762749}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resConfig.json":{"hashValue":"c763be3e45afbcef276327a1204a3efc","name":"resConfig.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resConfig.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":826,"lastModifiedTime":1706084762752}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\libs":{"hashValue":"f5ba89696ccaa77b8b52cf0cbb5d0671","name":"libs","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\libs","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"56708f1c716704056554857e9821e096","name":"flutter_embedding.har","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\libs\\flutter_embedding.har","type":"file","isSymbolicLink":false,"fileMetaData":{"size":84259,"lastModifiedTime":1706059631521}}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\libs\\default":{"hashValue":"","name":"default","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\libs\\default","type":"directory","isSymbolicLink":false,"children":[]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources":{"hashValue":"2a08f3fd80934e41ce42e4ae61c075a9","name":"resources","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"6d6db0f209385c8198b6c934ddb5e0e8","name":"base","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"1ab34f3e4c3d41f31f9334b422c0e388","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"078e1ff91516d2008fc8bb1e38b5406d","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631524}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"en_US","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"zh_CN","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default":{"hashValue":"1a917d0b6327f3a2b1d2e8d2f80bf2c0","name":"default","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"afeaa89fe450010f8b20538457432f92","name":"ids_map","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ids_map","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"57bb4dc4efea8e9078570b14d8c28825","name":"id_defined.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ids_map\\id_defined.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":148,"lastModifiedTime":1706084764868}}]},{"hashValue":"887ba34b1ac75ecc4d03e06492444b26","name":"module.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\module.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":641,"lastModifiedTime":1706084764867}},{"hashValue":"c763be3e45afbcef276327a1204a3efc","name":"resConfig.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resConfig.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":826,"lastModifiedTime":1706084762752}},{"hashValue":"7b5b8d29037eb2bc91698b5742a59ce3","name":"resources.index","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resources.index","type":"file","isSymbolicLink":false,"fileMetaData":{"size":396,"lastModifiedTime":1706084764868}},{"hashValue":"9b952ab620271ba35152dde2e2382a5f","name":"ResourceTable.txt","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ResourceTable.txt","type":"file","isSymbolicLink":false,"fileMetaData":{"size":27,"lastModifiedTime":1706084764867}}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default\\ResourceTable.h":{"hashValue":"50c6ac3d27fad616b62c9d0be15592ee","name":"ResourceTable.h","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default\\ResourceTable.h","type":"file","isSymbolicLink":false,"fileMetaData":{"size":750,"lastModifiedTime":1706084764866}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default":{"hashValue":"bc8c85335f93baaad1b41ccf91b2c2ff","name":"default","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"50c6ac3d27fad616b62c9d0be15592ee","name":"ResourceTable.h","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default\\ResourceTable.h","type":"file","isSymbolicLink":false,"fileMetaData":{"size":750,"lastModifiedTime":1706084764866}}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default":{"hashValue":"d5c29615da1bf0bbf1b608f8dbc24289","name":"default","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"9ec0158bb31dc6e972a74673f5e99f40","name":"module.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default\\module.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":395,"lastModifiedTime":1706084761934}}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite":{"hashValue":"faa13fe2720afa4cd4c37f24bb69395d","name":"sqflite","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"442d6433a235efd06499a9e9262aab59","name":"hvigorfile.ts","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\hvigorfile.ts","type":"file","isSymbolicLink":false,"fileMetaData":{"size":160,"lastModifiedTime":1706059631520}},{"hashValue":"eeb6a76d4824c895309239615477c3e8","name":"index.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\index.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":769,"lastModifiedTime":1706059631521}},{"hashValue":"e16f6cf494828bc7c0aa74c69f614ca5","name":"oh-package.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\oh-package.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":922,"lastModifiedTime":1706059631522}},{"hashValue":"a2a27fb788a43a3962e1b63323ff0fe4","name":"src","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"c58a27dd04a7f0a3ebedef8fc90df4e2","name":"main","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"2b00464badb6d6c698553adbb3771ef9","name":"ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e03c6dd526771fffbc93d2fd6bb77c6f","name":"io","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"80c7a8ae8aae48b4a2cf3276de9417d8","name":"flutter","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"02e58910ce276f959cb2e9ebb66eed09","name":"plugins","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e435b76f2d4c81f6d8afcfca619c179f","name":"sqflite","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"14844d1b9ee1fe908bb826062bbd5746","name":"constant.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\constant.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":3688,"lastModifiedTime":1706063438578}},{"hashValue":"2914c1433d84cc9a790fffeff8456dab","name":"Messages.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\Messages.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":16458,"lastModifiedTime":1706059631523}},{"hashValue":"8a00cba3203155178fb63abb8859ebfe","name":"sqflite_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sqflite_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":38720,"lastModifiedTime":1706084837870}},{"hashValue":"f125b24a36b06b8b146afe6a97113ffe","name":"SqflitePlugin.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\SqflitePlugin.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":18191,"lastModifiedTime":1706084156443}},{"hashValue":"8369f358c1b0e17eb29db65ba1d5c20d","name":"sql_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sql_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":8232,"lastModifiedTime":1706084805952}},{"hashValue":"3dfa4d7122cd9ea5dc95e53abbde4606","name":"tools.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\tools.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":411,"lastModifiedTime":1706067315976}}]}]}]}]}]},{"hashValue":"e1023c7c6717335313fe49e930dd5ae0","name":"module.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\module.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":785,"lastModifiedTime":1706059631524}},{"hashValue":"2a08f3fd80934e41ce42e4ae61c075a9","name":"resources","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"6d6db0f209385c8198b6c934ddb5e0e8","name":"base","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"1ab34f3e4c3d41f31f9334b422c0e388","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"078e1ff91516d2008fc8bb1e38b5406d","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\base\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631524}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"en_US","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\en_US\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"zh_CN","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources\\zh_CN\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]}]}]},{"hashValue":"2737923ce501059afe068a9a2e38ae12","name":"test","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\test","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"baada0d2cca88b04416c72d11f322b89","name":"List.test.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\test\\List.test.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":762,"lastModifiedTime":1706059631526}},{"hashValue":"fbd6fef4ab95bd7a07e5e193f64e04db","name":"LocalUnit.test.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\test\\LocalUnit.test.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":2346,"lastModifiedTime":1706059631526}}]}]}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ResourceTable.txt":{"hashValue":"9b952ab620271ba35152dde2e2382a5f","name":"ResourceTable.txt","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ResourceTable.txt","type":"file","isSymbolicLink":false,"fileMetaData":{"size":27,"lastModifiedTime":1706084764867}},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar":{"hashValue":"020b62e35af28e1319cf220224432027","name":"default@PackageHar","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"192a6b5475c10e53b54066829df5ccda","name":"build-profile.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\build-profile.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":773,"lastModifiedTime":1706059631520}},{"hashValue":"442d6433a235efd06499a9e9262aab59","name":"hvigorfile.ts","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\hvigorfile.ts","type":"file","isSymbolicLink":false,"fileMetaData":{"size":160,"lastModifiedTime":1706059631520}},{"hashValue":"eeb6a76d4824c895309239615477c3e8","name":"index.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\index.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":769,"lastModifiedTime":1706059631521}},{"hashValue":"","name":"libs","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\libs","type":"directory","isSymbolicLink":false,"children":[]},{"hashValue":"e16f6cf494828bc7c0aa74c69f614ca5","name":"oh-package.json5","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\oh-package.json5","type":"file","isSymbolicLink":false,"fileMetaData":{"size":922,"lastModifiedTime":1706059631522}},{"hashValue":"9b952ab620271ba35152dde2e2382a5f","name":"ResourceTable.txt","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\ResourceTable.txt","type":"file","isSymbolicLink":false,"fileMetaData":{"size":27,"lastModifiedTime":1706084764867}},{"hashValue":"66687ea8010a7bffb5f75ae64021f912","name":"src","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"ef32c299ba1ef7d53f87b00cd1dade9b","name":"main","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"2b00464badb6d6c698553adbb3771ef9","name":"ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e03c6dd526771fffbc93d2fd6bb77c6f","name":"io","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"80c7a8ae8aae48b4a2cf3276de9417d8","name":"flutter","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"02e58910ce276f959cb2e9ebb66eed09","name":"plugins","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"e435b76f2d4c81f6d8afcfca619c179f","name":"sqflite","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"14844d1b9ee1fe908bb826062bbd5746","name":"constant.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\constant.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":3688,"lastModifiedTime":1706063438578}},{"hashValue":"2914c1433d84cc9a790fffeff8456dab","name":"Messages.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\Messages.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":16458,"lastModifiedTime":1706059631523}},{"hashValue":"8a00cba3203155178fb63abb8859ebfe","name":"sqflite_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sqflite_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":38720,"lastModifiedTime":1706084837870}},{"hashValue":"f125b24a36b06b8b146afe6a97113ffe","name":"SqflitePlugin.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\SqflitePlugin.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":18191,"lastModifiedTime":1706084156443}},{"hashValue":"8369f358c1b0e17eb29db65ba1d5c20d","name":"sql_helper.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\sql_helper.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":8232,"lastModifiedTime":1706084805952}},{"hashValue":"3dfa4d7122cd9ea5dc95e53abbde4606","name":"tools.ets","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\ets\\io\\flutter\\plugins\\sqflite\\tools.ets","type":"file","isSymbolicLink":false,"fileMetaData":{"size":411,"lastModifiedTime":1706067315976}}]}]}]}]}]},{"hashValue":"9ec0158bb31dc6e972a74673f5e99f40","name":"module.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\module.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":395,"lastModifiedTime":1706084761934}},{"hashValue":"2a08f3fd80934e41ce42e4ae61c075a9","name":"resources","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"6d6db0f209385c8198b6c934ddb5e0e8","name":"base","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\base","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"1ab34f3e4c3d41f31f9334b422c0e388","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\base\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"078e1ff91516d2008fc8bb1e38b5406d","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\base\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631524}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"en_US","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\en_US","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\en_US\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\en_US\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]},{"hashValue":"4cd2a58a352a73bc35c607a310826569","name":"zh_CN","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\zh_CN","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"83e13a67bf37f25c7691c33c9d4cd0f0","name":"element","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\zh_CN\\element","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"884083f93b10f4498b79067c4f5fe057","name":"string.json","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar\\src\\main\\resources\\zh_CN\\element\\string.json","type":"file","isSymbolicLink":false,"fileMetaData":{"size":108,"lastModifiedTime":1706059631525}}]}]}]}]}]}]},"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\outputs\\default":{"hashValue":"1549567cdb9e156e5ba529427fd190f3","name":"default","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\outputs\\default","type":"directory","isSymbolicLink":false,"children":[{"hashValue":"051e36df92cfb456fe3e46a57af49d89","name":"sqflite.har","path":"E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\outputs\\default\\sqflite.har","type":"file","isSymbolicLink":false,"fileMetaData":{"size":16671,"lastModifiedTime":1706084858103}}]}} \ No newline at end of file diff --git a/sqflite/ohos/.hvigor/cache/task-cache.json b/sqflite/ohos/.hvigor/cache/task-cache.json new file mode 100644 index 0000000..62e79ea --- /dev/null +++ b/sqflite/ohos/.hvigor/cache/task-cache.json @@ -0,0 +1 @@ +{":ohos:sqflite:default@PreBuild":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"0b5d05294fdf4e78e8482ef53eb64ac0\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"e7f94a9422a8bc317a7d90b58efcb5f6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"apiType\",\"_value\":\"stageMode\",\"_valueType\":\"string\",\"_hash\":\"699c7565645ea3ea8c88551a4926a3d5\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"codeType\",\"_value\":true,\"_valueType\":\"boolean\",\"_hash\":\"d6dcf21a9f078b661283507536e57ce8\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"compatibleApiVersion\",\"_value\":10,\"_valueType\":\"number\",\"_hash\":\"f08ac304243ae5663f2ea14e1973c253\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"compileApiVersion\",\"_value\":10,\"_valueType\":\"number\",\"_hash\":\"4fdb2d89c4c44dbf8c5dffe16d03220b\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"customTypes\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"970a2695bffac1c5a4fa283dc36050e3\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"deviceType\",\"_value\":[\"default\",\"tablet\"],\"_valueType\":\"object\",\"_hash\":\"3f44547af15457ff8e1ec09282ca9922\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"isSupportOhpmProj\",\"_value\":true,\"_valueType\":\"boolean\",\"_hash\":\"f3a249d7e3f751316e931b8a08b074b4\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"profileModuleName\",\"_value\":\"sqflite\",\"_valueType\":\"string\",\"_hash\":\"cc764aa319e2ba6b464ea7ceeb9f1bb6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"sdkToolchainsComponentVersion\",\"_value\":\"4.0.0.40\",\"_valueType\":\"string\",\"_hash\":\"9822dc2efe3bc5434b273057d46ed8e2\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"targetStatusCode\",\"_value\":2,\"_valueType\":\"number\",\"_hash\":\"5a9255c0f4ee50904a9349ebafca8369\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@PreBuild","_key":":ohos:sqflite:default@PreBuild","_executionId":":ohos:sqflite:default@PreBuild:1706084761836","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\AppScope\\app.json5",{"isDirectory":false,"fileSnapShotHashValue":"08fc0c1cb05d3261806ebb63e4714bac"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\module.json5",{"isDirectory":false,"fileSnapShotHashValue":"e1023c7c6717335313fe49e930dd5ae0"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\oh-package.json5",{"fileSnapShotHashValue":"e16f6cf494828bc7c0aa74c69f614ca5"}]]},"_outputFiles":{"dataType":"Map","value":[]}},":ohos:sqflite:default@MergeProfile":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"0b5d05294fdf4e78e8482ef53eb64ac0\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"e7f94a9422a8bc317a7d90b58efcb5f6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"asanEnable\",\"_value\":false,\"_valueType\":\"boolean\",\"_hash\":\"bc2129ba20a21b7e5234139ede1b4d7b\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"buildRoot\",\"_value\":\"build\",\"_valueType\":\"string\",\"_hash\":\"4c2dd7bb7507f74001ec27f2936db7f9\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"compatibleSdkVersion\",\"_value\":10,\"_valueType\":\"number\",\"_hash\":\"8ca3e69374439355c4f1b77ba4fb3435\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"isDebug\",\"_value\":true,\"_valueType\":\"boolean\",\"_hash\":\"edbf05a2d2be2c385e75d9565a48d419\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"isHarModule\",\"_value\":true,\"_valueType\":\"boolean\",\"_hash\":\"02f77a1e25718bf2a5689a57185f47f6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"multiProjects\",\"_value\":false,\"_valueType\":\"boolean\",\"_hash\":\"555604752defc243b4e4c55d1549fc06\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"releaseType\",\"_value\":\"Release\",\"_valueType\":\"string\",\"_hash\":\"bbcabdda034e97584f8c36f85b3ec517\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"targetSdkVersion\",\"_value\":10,\"_valueType\":\"number\",\"_hash\":\"68a4d173dd33897f0e74ffeae724b180\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@MergeProfile","_key":":ohos:sqflite:default@MergeProfile","_executionId":":ohos:sqflite:default@MergeProfile:1706084761929","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\AppScope\\app.json5",{"fileSnapShotHashValue":"08fc0c1cb05d3261806ebb63e4714bac"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\module.json5",{"fileSnapShotHashValue":"e1023c7c6717335313fe49e930dd5ae0"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default\\module.json",{"fileSnapShotHashValue":"9ec0158bb31dc6e972a74673f5e99f40"}]]}},":ohos:sqflite:default@LintArkTS":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"customTypes\",\"_value\":\"\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@LintArkTS","_key":":ohos:sqflite:default@LintArkTS","_executionId":":ohos:sqflite:default@LintArkTS:1706084843915","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\ets",{"isDirectory":true,"fileSnapShotHashValue":"2b00464badb6d6c698553adbb3771ef9"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\loader_out\\default\\ets",{"isDirectory":true,"fileSnapShotHashValue":""}]]}},":ohos:sqflite:default@ProcessProfile":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"0b5d05294fdf4e78e8482ef53eb64ac0\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"e7f94a9422a8bc317a7d90b58efcb5f6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"arkEnable\",\"_value\":true,\"_valueType\":\"boolean\",\"_hash\":\"750b4bda198545a67903dfb3f6a00a95\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"compileMode\",\"_value\":\"esmodule\",\"_valueType\":\"string\",\"_hash\":\"dacafc8e0b77a950178a0b4d142dc32c\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"dependency\",\"_value\":\"[]\",\"_valueType\":\"string\",\"_hash\":\"ac54f3d4ced2d4c1d666d40e4f7c454a\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"deviceTypes\",\"_value\":[\"default\",\"tablet\"],\"_valueType\":\"object\",\"_hash\":\"0342e19985c07130618d063695ce1f7c\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@ProcessProfile","_key":":ohos:sqflite:default@ProcessProfile","_executionId":":ohos:sqflite:default@ProcessProfile:1706084761972","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default\\module.json",{"fileSnapShotHashValue":"9ec0158bb31dc6e972a74673f5e99f40"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\process_profile\\default\\module.json",{"fileSnapShotHashValue":"8708fae7f796bca08fd5263aea8bc401"}]]}},":ohos:sqflite:default@ProcessResource":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"0b5d05294fdf4e78e8482ef53eb64ac0\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"e7f94a9422a8bc317a7d90b58efcb5f6\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"resConfigJsonContent\",\"_value\":\"{\\\"configPath\\\":\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\build\\\\\\\\default\\\\\\\\intermediates\\\\\\\\process_profile\\\\\\\\default\\\\\\\\module.json\\\",\\\"packageName\\\":\\\"io.flutter.plugins.sqflite\\\",\\\"output\\\":\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\build\\\\\\\\default\\\\\\\\intermediates\\\\\\\\res\\\\\\\\default\\\",\\\"moduleNames\\\":\\\"sqflite\\\",\\\"ResourceTable\\\":[\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\build\\\\\\\\default\\\\\\\\generated\\\\\\\\r\\\\\\\\default\\\\\\\\ResourceTable.h\\\"],\\\"moduleResources\\\":[\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\src\\\\\\\\main\\\\\\\\resources\\\"],\\\"dependencies\\\":[],\\\"iconCheck\\\":false,\\\"ids\\\":\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\build\\\\\\\\default\\\\\\\\intermediates\\\\\\\\res\\\\\\\\default\\\\\\\\ids_map\\\",\\\"definedIds\\\":\\\"E:\\\\\\\\work\\\\\\\\dev\\\\\\\\sqflite\\\\\\\\sqflite_ohos\\\\\\\\ohos\\\\\\\\sqflite\\\\\\\\build\\\\\\\\default\\\\\\\\intermediates\\\\\\\\res\\\\\\\\default\\\\\\\\ids_map\\\\\\\\id_defined.json\\\"}\",\"_valueType\":\"string\",\"_hash\":\"3e08a541b1ae5877370094d990df2998\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@ProcessResource","_key":":ohos:sqflite:default@ProcessResource","_executionId":":ohos:sqflite:default@ProcessResource:1706084762750","_inputFiles":{"dataType":"Map","value":[]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resConfig.json",{"isDirectory":false,"fileSnapShotHashValue":"c763be3e45afbcef276327a1204a3efc"}]]}},":ohos:sqflite:default@ProcessLibs":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"0b5d05294fdf4e78e8482ef53eb64ac0\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"e7f94a9422a8bc317a7d90b58efcb5f6\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@ProcessLibs","_key":":ohos:sqflite:default@ProcessLibs","_executionId":":ohos:sqflite:default@ProcessLibs:1706084762752","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\libs",{"isDirectory":true,"fileSnapShotHashValue":"f5ba89696ccaa77b8b52cf0cbb5d0671"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\libs\\default",{"isDirectory":true,"fileSnapShotHashValue":""}]]}},":ohos:sqflite:default@CompileResource":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"C:\\\\Users\\\\zblicq\\\\AppData\\\\Local\\\\Huawei\\\\Sdk\\\\openharmony\\\\10\\\\toolchains\\\\restool.exe,-l,E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\build\\\\default\\\\intermediates\\\\res\\\\default\\\\resConfig.json\",\"_valueType\":\"string\",\"_hash\":\"e7447aba3ccc014983986674fe0a441f\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"\",\"_valueType\":\"string\",\"_hash\":\"cdcdc2ec8062ca9ec1de46dbf2bbc053\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"C:\\\\Users\\\\zblicq\\\\AppData\\\\Local\\\\Huawei\\\\Sdk\\\\openharmony\\\\10\\\\toolchains\\\\restool.exe\",\"_valueType\":\"string\",\"_hash\":\"d7036cae244f45620e0792ecb179d0f8\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"TARGET_CONFIG\",\"_value\":\"{\\\"name\\\":\\\"default\\\"}\",\"_valueType\":\"string\",\"_hash\":\"ebe85c5c20c0e5d9e03bc5dc7135f953\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@CompileResource","_key":":ohos:sqflite:default@CompileResource","_executionId":":ohos:sqflite:default@CompileResource:1706084762758","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources",{"fileSnapShotHashValue":"2a08f3fd80934e41ce42e4ae61c075a9"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\process_profile\\default\\module.json",{"isDirectory":false,"fileSnapShotHashValue":"8708fae7f796bca08fd5263aea8bc401"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resConfig.json",{"isDirectory":false,"fileSnapShotHashValue":"c763be3e45afbcef276327a1204a3efc"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default",{"isDirectory":true,"fileSnapShotHashValue":"1a917d0b6327f3a2b1d2e8d2f80bf2c0"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default\\ResourceTable.h",{"isDirectory":false,"fileSnapShotHashValue":"50c6ac3d27fad616b62c9d0be15592ee"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\generated\\r\\default",{"isDirectory":true,"fileSnapShotHashValue":"bc8c85335f93baaad1b41ccf91b2c2ff"}]]}},":ohos:sqflite:default@PackageHar":{"_inputs":[{"dataType":"ValueEntry","value":"{\"_name\":\"hasNativeOption\",\"_value\":false,\"_valueType\":\"boolean\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"needCppTypes\",\"_value\":false,\"_valueType\":\"boolean\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"harModuleJson\",\"_value\":\"E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\build\\\\default\\\\cache\\\\default\\\\default@PackageHar\\\\src\\\\main\\\\module.json5\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"isOhpmProject\",\"_value\":true,\"_valueType\":\"boolean\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"artifactType\",\"_value\":\"original\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_COMMAND\",\"_value\":\"C:\\\\Program Files\\\\nodejs\\\\npm.cmd,pack\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_TOOLCHAIN\",\"_value\":\"\",\"_valueType\":\"string\"}"},{"dataType":"ValueEntry","value":"{\"_name\":\"BUILTIN_TASK_ENV\",\"_value\":\"cwd:E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\build\\\\default\\\\cache\\\\default\\\\default@PackageHar;\",\"_valueType\":\"string\"}"}],"_successful":true,"_projectName":"ohos","_moduleName":"sqflite","_taskName":"default@PackageHar","_key":":ohos:sqflite:default@PackageHar","_executionId":":ohos:sqflite:default@PackageHar:1706084858014","_inputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\merge_profile\\default",{"isDirectory":true,"fileSnapShotHashValue":"d5c29615da1bf0bbf1b608f8dbc24289"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite",{"isDirectory":true,"test":{"dataType":"RegExp","value":"^(?!E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\libs|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\build|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\node_modules|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\oh_modules|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\.cxx|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\.previewer|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\.hvigor|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\.gitignore|E:\\\\work\\\\dev\\\\sqflite\\\\sqflite_ohos\\\\ohos\\\\sqflite\\\\.ohpmignore).*"},"fileSnapShotHashValue":"faa13fe2720afa4cd4c37f24bb69395d"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\libs\\default",{"isDirectory":true,"fileSnapShotHashValue":""}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\ResourceTable.txt",{"isDirectory":false,"fileSnapShotHashValue":"9b952ab620271ba35152dde2e2382a5f"}]]},"_outputFiles":{"dataType":"Map","value":[["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@PackageHar",{"isDirectory":true,"fileSnapShotHashValue":"020b62e35af28e1319cf220224432027"}],["E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\outputs\\default",{"isDirectory":true,"fileSnapShotHashValue":"1549567cdb9e156e5ba529427fd190f3"}]]}}} \ No newline at end of file diff --git a/sqflite/ohos/.hvigor/outputs/logs/details/details.json b/sqflite/ohos/.hvigor/outputs/logs/details/details.json new file mode 100644 index 0000000..9dcc913 --- /dev/null +++ b/sqflite/ohos/.hvigor/outputs/logs/details/details.json @@ -0,0 +1,16 @@ +{ + "totalTime": 14836247400, + "moduleNum": 1, + "taskTime": { + "compileArkTS": 0, + "buildArkTS": 0, + "compileJS": 0, + "buildJS": 0, + "compileResource": 0, + "packageHap": 0, + "signHap": 0 + }, + "isIncremental": true, + "hasIncremental": true, + "isParallel": true +} \ No newline at end of file diff --git a/sqflite/ohos/.hvigor/outputs/sync/output.json b/sqflite/ohos/.hvigor/outputs/sync/output.json new file mode 100644 index 0000000..5813105 --- /dev/null +++ b/sqflite/ohos/.hvigor/outputs/sync/output.json @@ -0,0 +1,39 @@ +{ + "ohos-module-sqflite": { + "SELECT_TARGET": "default", + "MODULE_BUILD_DIR": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build", + "TARGETS": { + "default": { + "SOURCE_ROOT": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main", + "RESOURCES_PATH": [ + "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\src\\main\\resources" + ], + "BUILD_PATH": { + "OUTPUT_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\outputs\\default", + "INTERMEDIA_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates", + "JS_ASSETS_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\loader_out\\default", + "JS_LITE_ASSETS_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\loader_out_lite\\default", + "RES_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default", + "RES_PROFILE_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\res\\default\\resources\\base\\profile", + "ETS_SUPER_VISUAL_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@CompileArkTS\\esmodule", + "JS_SUPER_VISUAL_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\cache\\default\\default@CompileJS\\jsbundle", + "WORKER_LOADER": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\loader\\default\\loader.json", + "MANIFEST_JSON": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\manifest\\default", + "OUTPUT_METADATA_JSON": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\sqflite\\build\\default\\intermediates\\hap_metadata\\default\\output_metadata.json" + }, + "BUILD_OPTION": { + "debuggable": true + } + } + } + }, + "ohos-project": { + "SELECT_PRODUCT_NAME": "default", + "MODULE_BUILD_DIR": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\build", + "BUNDLE_NAME": "io.flutter.plugins.sqflite", + "BUILD_PATH": { + "OUTPUT_PATH": "E:\\work\\dev\\sqflite\\sqflite_ohos\\ohos\\build\\outputs\\default" + } + }, + "version": 1 +} \ No newline at end of file diff --git a/sqflite/ohos/.hvigor/report/report.json b/sqflite/ohos/.hvigor/report/report.json new file mode 100644 index 0000000..4d64efa --- /dev/null +++ b/sqflite/ohos/.hvigor/report/report.json @@ -0,0 +1,308 @@ +{ + "version": "1.0", + "workLog": [ + { + "type": "work", + "time": "[2024-01-24T16:27:38.007]", + "workerId": 0, + "content": "[2024-01-24T16:27:38.007] > hvigor \u001b[32m\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets:50:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets:64:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets:78:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets:92:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets:106:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:72:12\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:74:120\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:135:71\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:135:137\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:136:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:140:58\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:140:111\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:141:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:186:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets:195:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets:21:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets:24:45\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets:38:73\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets:41:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ToolUtils.ets:21:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:29:9\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:31:37\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:36:26\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:40:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:40:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:52:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets:52:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets:52:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets:64:78\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets:77:92\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets:86:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets:21:12\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets:23:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:63:67\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:67:28\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:73:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:98:43\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:98:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:155:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:159:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:159:50\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:164:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:220:36\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:234:56\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:238:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:241:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:244:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:247:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:250:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:253:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:257:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:261:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:265:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:275:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:285:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:295:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:300:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:304:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:309:30\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:309:40\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:313:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets:323:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets:60:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets:67:78\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets:80:92\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets:94:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets:60:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets:142:21\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets:153:66\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets:199:27\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets:203:72\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets:34:26\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets:41:40\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:38:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:52:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:53:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:64:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:68:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:68:80\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:72:92\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:76:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:80:13\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:81:18\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:83:13\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:84:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:85:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets:86:37\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets:222:9\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets:282:22\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets:85:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets:88:11\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets:115:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets:116:9\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets:130:20\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets:138:20\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets:70:11\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets:119:70\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets:223:25\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets:297:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets:333:43\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:391:17\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:392:13\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:394:26\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:399:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:405:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:409:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:412:26\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:417:13\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:419:26\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets:464:49\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SystemChannel.ets:29:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets:98:27\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets:102:72\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets:169:53\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets:170:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets:42:45\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets:42:84\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets:44:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets:44:93\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:61:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:132:36\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:144:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:161:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:175:23\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:206:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:430:36\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:433:28\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:460:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:461:33\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets:545:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/OhosTouchProcessor.ets:25:59\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets:34:67\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets:34:139\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets:34:158\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets:35:46\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets:60:52\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:23:19\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:43:18\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:44:14\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:46:48\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:46:71\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets:53:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:47:64\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:47:135\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:48:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:52:71\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:52:137\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets:53:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets:30:34\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets:126:15\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets:127:11\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets:129:59\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets:129:77\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets:133:64\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets:133:135\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets:134:44\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets:288:9\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:27:45\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:28:28\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:45:12\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:47:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:87:35\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:95:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:96:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:102:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:102:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:104:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:104:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:110:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:123:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:124:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:131:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:131:49\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:133:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:133:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:139:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:152:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:153:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:159:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:159:49\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:161:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:161:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:167:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:180:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:181:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:187:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:187:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:189:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:189:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:207:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:220:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:221:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:227:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:227:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:229:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:229:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:235:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:248:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:249:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:255:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:255:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:257:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:257:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:263:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:277:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:278:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:284:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:284:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:286:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:286:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:292:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:305:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:306:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:312:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:312:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:314:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:314:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:321:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:335:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:336:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:342:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:342:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:344:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:344:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:351:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:365:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:366:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:372:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:372:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:374:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:374:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:380:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:394:42\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:395:31\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:401:38\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:401:55\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:403:32\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:403:54\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[33mWARN: \u001b[33mArkTS:WARN File: E:/work/dev/sqflite/sqflite_ohos/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets:410:41\n Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)\n\u001b[39m\r\n\u001b[39m\n", + "taskPath": "sqflite", + "taskName": "default@LintArkTS", + "taskCompletePath": "sqflite:default@LintArkTS" + } + ], + "workerIdList": [ + -1, + 0 + ], + "metrics": [ + { + "type": "build_line", + "endTime": 1706084761928, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@PreBuild", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084761836 + }, + { + "type": "build_line", + "endTime": 1706084761933, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@MergeProfile", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084761929 + }, + { + "type": "build_line", + "endTime": 1706084761934, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@BuildNativeWithCmake", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084761934 + }, + { + "type": "build_line", + "endTime": 1706084762749, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessProfile", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084761972 + }, + { + "type": "build_line", + "endTime": 1706084762750, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@BuildNativeWithNinja", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084762749 + }, + { + "type": "build_line", + "endTime": 1706084762752, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessResource", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084762750 + }, + { + "type": "build_line", + "endTime": 1706084762758, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessLibs", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084762752 + }, + { + "type": "build_line", + "endTime": 1706084764873, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@CompileResource", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084762758 + }, + { + "type": "build_line", + "endTime": 1706084764874, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessObfuscationFiles", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084764874 + }, + { + "type": "build_line", + "endTime": 1706084776579, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": 0, + "startTime": 1706084761972 + }, + { + "type": "default", + "endTime": 1706084776579, + "status": "closed", + "children": [ + { + "type": "build_line", + "endTime": 1706084776579, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": 0, + "startTime": 1706084761972 + } + ], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084761934 + }, + { + "type": "build_line", + "endTime": 1706084843911, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@PreBuild", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843908 + }, + { + "type": "build_line", + "endTime": 1706084843913, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@MergeProfile", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843911 + }, + { + "type": "build_line", + "endTime": 1706084843914, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@BuildNativeWithCmake", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843913 + }, + { + "type": "build_line", + "endTime": 1706084843937, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessProfile", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843935 + }, + { + "type": "build_line", + "endTime": 1706084843937, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@BuildNativeWithNinja", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843937 + }, + { + "type": "build_line", + "endTime": 1706084843938, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessResource", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843937 + }, + { + "type": "build_line", + "endTime": 1706084843940, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessLibs", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843938 + }, + { + "type": "build_line", + "endTime": 1706084843950, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@CompileResource", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843941 + }, + { + "type": "build_line", + "endTime": 1706084843950, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@ProcessObfuscationFiles", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843950 + }, + { + "type": "build_line", + "endTime": 1706084858009, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": 0, + "startTime": 1706084843935 + }, + { + "type": "default", + "endTime": 1706084858009, + "status": "closed", + "children": [ + { + "type": "build_line", + "endTime": 1706084858009, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": 0, + "startTime": 1706084843935 + } + ], + "name": "overallTime", + "taskName": "default@LintArkTS", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084843914 + }, + { + "type": "build_line", + "endTime": 1706084858104, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "default@PackageHar", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084858013 + }, + { + "type": "build_line", + "endTime": 1706084858105, + "status": "closed", + "children": [], + "name": "overallTime", + "taskName": "assembleHar", + "taskPath": "sqflite", + "workerId": -1, + "startTime": 1706084858105 + } + ] +} \ No newline at end of file diff --git a/sqflite/ohos/AppScope/app.json5 b/sqflite/ohos/AppScope/app.json5 new file mode 100644 index 0000000..9e8f799 --- /dev/null +++ b/sqflite/ohos/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +{ + "app": { + "bundleName": "io.flutter.plugins.sqflite", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/sqflite/ohos/AppScope/resources/base/element/string.json b/sqflite/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..5d22dac --- /dev/null +++ b/sqflite/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "sqflite" + } + ] +} diff --git a/sqflite/ohos/AppScope/resources/base/media/app_icon.png b/sqflite/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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"a"&&e<="z"||e>="A"&&e<="Z"||"$"===e||"_"===e||te.Unicode.ID_Start.test(e))}static isIdContinueChar(e){return"string"==typeof e&&(e>="a"&&e<="z"||e>="A"&&e<="Z"||e>="0"&&e<="9"||"$"===e||"_"===e||"‌"===e||"‍"===e||te.Unicode.ID_Continue.test(e))}static isDigitWithoutZero(e){return/[1-9]/.test(e)}static isDigit(e){return"string"==typeof e&&/[0-9]/.test(e)}static isHexDigit(e){return"string"==typeof e&&/[0-9A-Fa-f]/.test(e)}};var ne={},re={fromCallback:function(e){return Object.defineProperty((function(...t){if("function"!=typeof t[t.length-1])return new Promise(((n,r)=>{e.call(this,...t,((e,t)=>null!=e?r(e):n(t)))}));e.apply(this,t)}),"name",{value:e.name})},fromPromise:function(e){return Object.defineProperty((function(...t){const n=t[t.length-1];if("function"!=typeof n)return e.apply(this,t);e.apply(this,t.slice(0,-1)).then((e=>n(null,e)),n)}),"name",{value:e.name})}},ue=y.default,oe=process.cwd,ie=null,se=process.env.GRACEFUL_FS_PLATFORM||process.platform;process.cwd=function(){return ie||(ie=oe.call(process)),ie};try{process.cwd()}catch(e){}if("function"==typeof process.chdir){var ce=process.chdir;process.chdir=function(e){ie=null,ce.call(process,e)},Object.setPrototypeOf&&Object.setPrototypeOf(process.chdir,ce)}var ae=function(e){ue.hasOwnProperty("O_SYMLINK")&&process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)&&function(e){e.lchmod=function(t,n,r){e.open(t,ue.O_WRONLY|ue.O_SYMLINK,n,(function(t,u){t?r&&r(t):e.fchmod(u,n,(function(t){e.close(u,(function(e){r&&r(t||e)}))}))}))},e.lchmodSync=function(t,n){var r,u=e.openSync(t,ue.O_WRONLY|ue.O_SYMLINK,n),o=!0;try{r=e.fchmodSync(u,n),o=!1}finally{if(o)try{e.closeSync(u)}catch(e){}else e.closeSync(u)}return r}}(e);e.lutimes||function(e){ue.hasOwnProperty("O_SYMLINK")&&e.futimes?(e.lutimes=function(t,n,r,u){e.open(t,ue.O_SYMLINK,(function(t,o){t?u&&u(t):e.futimes(o,n,r,(function(t){e.close(o,(function(e){u&&u(t||e)}))}))}))},e.lutimesSync=function(t,n,r){var u,o=e.openSync(t,ue.O_SYMLINK),i=!0;try{u=e.futimesSync(o,n,r),i=!1}finally{if(i)try{e.closeSync(o)}catch(e){}else e.closeSync(o)}return u}):e.futimes&&(e.lutimes=function(e,t,n,r){r&&process.nextTick(r)},e.lutimesSync=function(){})}(e);e.chown=r(e.chown),e.fchown=r(e.fchown),e.lchown=r(e.lchown),e.chmod=t(e.chmod),e.fchmod=t(e.fchmod),e.lchmod=t(e.lchmod),e.chownSync=u(e.chownSync),e.fchownSync=u(e.fchownSync),e.lchownSync=u(e.lchownSync),e.chmodSync=n(e.chmodSync),e.fchmodSync=n(e.fchmodSync),e.lchmodSync=n(e.lchmodSync),e.stat=o(e.stat),e.fstat=o(e.fstat),e.lstat=o(e.lstat),e.statSync=i(e.statSync),e.fstatSync=i(e.fstatSync),e.lstatSync=i(e.lstatSync),e.chmod&&!e.lchmod&&(e.lchmod=function(e,t,n){n&&process.nextTick(n)},e.lchmodSync=function(){});e.chown&&!e.lchown&&(e.lchown=function(e,t,n,r){r&&process.nextTick(r)},e.lchownSync=function(){});"win32"===se&&(e.rename="function"!=typeof e.rename?e.rename:function(t){function n(n,r,u){var o=Date.now(),i=0;t(n,r,(function s(c){if(c&&("EACCES"===c.code||"EPERM"===c.code||"EBUSY"===c.code)&&Date.now()-o<6e4)return setTimeout((function(){e.stat(r,(function(e,o){e&&"ENOENT"===e.code?t(n,r,s):u(c)}))}),i),void(i<100&&(i+=10));u&&u(c)}))}return Object.setPrototypeOf&&Object.setPrototypeOf(n,t),n}(e.rename));function t(t){return t?function(n,r,u){return t.call(e,n,r,(function(e){s(e)&&(e=null),u&&u.apply(this,arguments)}))}:t}function n(t){return t?function(n,r){try{return t.call(e,n,r)}catch(e){if(!s(e))throw e}}:t}function r(t){return t?function(n,r,u,o){return t.call(e,n,r,u,(function(e){s(e)&&(e=null),o&&o.apply(this,arguments)}))}:t}function u(t){return t?function(n,r,u){try{return t.call(e,n,r,u)}catch(e){if(!s(e))throw e}}:t}function o(t){return t?function(n,r,u){function o(e,t){t&&(t.uid<0&&(t.uid+=4294967296),t.gid<0&&(t.gid+=4294967296)),u&&u.apply(this,arguments)}return"function"==typeof r&&(u=r,r=null),r?t.call(e,n,r,o):t.call(e,n,o)}:t}function i(t){return t?function(n,r){var u=r?t.call(e,n,r):t.call(e,n);return u&&(u.uid<0&&(u.uid+=4294967296),u.gid<0&&(u.gid+=4294967296)),u}:t}function s(e){return!e||("ENOSYS"===e.code||!(process.getuid&&0===process.getuid()||"EINVAL"!==e.code&&"EPERM"!==e.code))}e.read="function"!=typeof e.read?e.read:function(t){function n(n,r,u,o,i,s){var c;if(s&&"function"==typeof s){var a=0;c=function(l,f,d){if(l&&"EAGAIN"===l.code&&a<10)return a++,t.call(e,n,r,u,o,i,c);s.apply(this,arguments)}}return t.call(e,n,r,u,o,i,c)}return Object.setPrototypeOf&&Object.setPrototypeOf(n,t),n}(e.read),e.readSync="function"!=typeof e.readSync?e.readSync:(c=e.readSync,function(t,n,r,u,o){for(var i=0;;)try{return c.call(e,t,n,r,u,o)}catch(e){if("EAGAIN"===e.code&&i<10){i++;continue}throw e}});var c};var le=C.default.Stream,fe=function(e){return{ReadStream:function t(n,r){if(!(this instanceof t))return new t(n,r);le.call(this);var u=this;this.path=n,this.fd=null,this.readable=!0,this.paused=!1,this.flags="r",this.mode=438,this.bufferSize=65536,r=r||{};for(var o=Object.keys(r),i=0,s=o.length;ithis.end)throw new Error("start must be <= end");this.pos=this.start}if(null!==this.fd)return void process.nextTick((function(){u._read()}));e.open(this.path,this.flags,this.mode,(function(e,t){if(e)return u.emit("error",e),void(u.readable=!1);u.fd=t,u.emit("open",t),u._read()}))},WriteStream:function t(n,r){if(!(this instanceof t))return new t(n,r);le.call(this),this.path=n,this.fd=null,this.writable=!0,this.flags="w",this.encoding="binary",this.mode=438,this.bytesWritten=0,r=r||{};for(var u=Object.keys(r),o=0,i=u.length;o= zero");this.pos=this.start}this.busy=!1,this._queue=[],null===this.fd&&(this._open=e.open,this._queue.push([this._open,this.path,this.flags,this.mode,void 0]),this.flush())}}};var de=function(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Object)var t={__proto__:De(e)};else t=Object.create(null);return Object.getOwnPropertyNames(e).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t},De=Object.getPrototypeOf||function(e){return e.__proto__};var pe,Ee,me=D.default,he=ae,ye=fe,Ce=de,Fe=F.default;function ge(e,t){Object.defineProperty(e,pe,{get:function(){return t}})}"function"==typeof Symbol&&"function"==typeof Symbol.for?(pe=Symbol.for("graceful-fs.queue"),Ee=Symbol.for("graceful-fs.previous")):(pe="___graceful-fs.queue",Ee="___graceful-fs.previous");var Ae=function(){};if(Fe.debuglog?Ae=Fe.debuglog("gfs4"):/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&(Ae=function(){var e=Fe.format.apply(Fe,arguments);e="GFS4: "+e.split(/\n/).join("\nGFS4: "),console.error(e)}),!me[pe]){var ve=w[pe]||[];ge(me,ve),me.close=function(e){function t(t,n){return e.call(me,t,(function(e){e||_e(),"function"==typeof n&&n.apply(this,arguments)}))}return Object.defineProperty(t,Ee,{value:e}),t}(me.close),me.closeSync=function(e){function t(t){e.apply(me,arguments),_e()}return Object.defineProperty(t,Ee,{value:e}),t}(me.closeSync),/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&process.on("exit",(function(){Ae(me[pe]),g.default.equal(me[pe].length,0)}))}w[pe]||ge(w,me[pe]);var Se,we=Oe(Ce(me));function Oe(e){he(e),e.gracefulify=Oe,e.createReadStream=function(t,n){return new e.ReadStream(t,n)},e.createWriteStream=function(t,n){return new e.WriteStream(t,n)};var t=e.readFile;e.readFile=function(e,n,r){"function"==typeof n&&(r=n,n=null);return function e(n,r,u,o){return t(n,r,(function(t){!t||"EMFILE"!==t.code&&"ENFILE"!==t.code?"function"==typeof u&&u.apply(this,arguments):be([e,[n,r,u],t,o||Date.now(),Date.now()])}))}(e,n,r)};var n=e.writeFile;e.writeFile=function(e,t,r,u){"function"==typeof r&&(u=r,r=null);return function e(t,r,u,o,i){return n(t,r,u,(function(n){!n||"EMFILE"!==n.code&&"ENFILE"!==n.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,r,u,o],n,i||Date.now(),Date.now()])}))}(e,t,r,u)};var r=e.appendFile;r&&(e.appendFile=function(e,t,n,u){"function"==typeof n&&(u=n,n=null);return function e(t,n,u,o,i){return r(t,n,u,(function(r){!r||"EMFILE"!==r.code&&"ENFILE"!==r.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,n,u,o],r,i||Date.now(),Date.now()])}))}(e,t,n,u)});var u=e.copyFile;u&&(e.copyFile=function(e,t,n,r){"function"==typeof n&&(r=n,n=0);return function e(t,n,r,o,i){return u(t,n,r,(function(u){!u||"EMFILE"!==u.code&&"ENFILE"!==u.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,n,r,o],u,i||Date.now(),Date.now()])}))}(e,t,n,r)});var o=e.readdir;e.readdir=function(e,t,n){"function"==typeof t&&(n=t,t=null);var r=i.test(process.version)?function(e,t,n,r){return o(e,u(e,t,n,r))}:function(e,t,n,r){return o(e,t,u(e,t,n,r))};return r(e,t,n);function u(e,t,n,u){return function(o,i){!o||"EMFILE"!==o.code&&"ENFILE"!==o.code?(i&&i.sort&&i.sort(),"function"==typeof n&&n.call(this,o,i)):be([r,[e,t,n],o,u||Date.now(),Date.now()])}}};var i=/^v[0-5]\./;if("v0.8"===process.version.substr(0,4)){var s=ye(e);d=s.ReadStream,D=s.WriteStream}var c=e.ReadStream;c&&(d.prototype=Object.create(c.prototype),d.prototype.open=function(){var e=this;E(e.path,e.flags,e.mode,(function(t,n){t?(e.autoClose&&e.destroy(),e.emit("error",t)):(e.fd=n,e.emit("open",n),e.read())}))});var a=e.WriteStream;a&&(D.prototype=Object.create(a.prototype),D.prototype.open=function(){var e=this;E(e.path,e.flags,e.mode,(function(t,n){t?(e.destroy(),e.emit("error",t)):(e.fd=n,e.emit("open",n))}))}),Object.defineProperty(e,"ReadStream",{get:function(){return d},set:function(e){d=e},enumerable:!0,configurable:!0}),Object.defineProperty(e,"WriteStream",{get:function(){return D},set:function(e){D=e},enumerable:!0,configurable:!0});var l=d;Object.defineProperty(e,"FileReadStream",{get:function(){return l},set:function(e){l=e},enumerable:!0,configurable:!0});var f=D;function d(e,t){return this instanceof d?(c.apply(this,arguments),this):d.apply(Object.create(d.prototype),arguments)}function D(e,t){return this instanceof D?(a.apply(this,arguments),this):D.apply(Object.create(D.prototype),arguments)}Object.defineProperty(e,"FileWriteStream",{get:function(){return f},set:function(e){f=e},enumerable:!0,configurable:!0});var p=e.open;function E(e,t,n,r){return"function"==typeof n&&(r=n,n=null),function e(t,n,r,u,o){return p(t,n,r,(function(i,s){!i||"EMFILE"!==i.code&&"ENFILE"!==i.code?"function"==typeof u&&u.apply(this,arguments):be([e,[t,n,r,u],i,o||Date.now(),Date.now()])}))}(e,t,n,r)}return e.open=E,e}function be(e){Ae("ENQUEUE",e[0].name,e[1]),me[pe].push(e),Be()}function _e(){for(var e=Date.now(),t=0;t2&&(me[pe][t][3]=e,me[pe][t][4]=e);Be()}function Be(){if(clearTimeout(Se),Se=void 0,0!==me[pe].length){var e=me[pe].shift(),t=e[0],n=e[1],r=e[2],u=e[3],o=e[4];if(void 0===u)Ae("RETRY",t.name,n),t.apply(null,n);else if(Date.now()-u>=6e4){Ae("TIMEOUT",t.name,n);var i=n.pop();"function"==typeof i&&i.call(null,r)}else{var s=Date.now()-o,c=Math.max(o-u,1);s>=Math.min(1.2*c,100)?(Ae("RETRY",t.name,n),t.apply(null,n.concat([u]))):me[pe].push(e)}void 0===Se&&(Se=setTimeout(Be,0))}}process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH&&!me.__patched&&(we=Oe(me),me.__patched=!0),function(e){const t=re.fromCallback,n=we,r=["access","appendFile","chmod","chown","close","copyFile","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchmod","lchown","link","lstat","mkdir","mkdtemp","open","opendir","readdir","readFile","readlink","realpath","rename","rm","rmdir","stat","symlink","truncate","unlink","utimes","writeFile"].filter((e=>"function"==typeof n[e]));Object.assign(e,n),r.forEach((r=>{e[r]=t(n[r])})),e.realpath.native=t(n.realpath.native),e.exists=function(e,t){return"function"==typeof t?n.exists(e,t):new Promise((t=>n.exists(e,t)))},e.read=function(e,t,r,u,o,i){return"function"==typeof i?n.read(e,t,r,u,o,i):new Promise(((i,s)=>{n.read(e,t,r,u,o,((e,t,n)=>{if(e)return s(e);i({bytesRead:t,buffer:n})}))}))},e.write=function(e,t,...r){return"function"==typeof r[r.length-1]?n.write(e,t,...r):new Promise(((u,o)=>{n.write(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffer:n})}))}))},"function"==typeof n.writev&&(e.writev=function(e,t,...r){return"function"==typeof r[r.length-1]?n.writev(e,t,...r):new Promise(((u,o)=>{n.writev(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffers:n})}))}))})}(ne);var Pe={},ke={};const xe=p.default;ke.checkPath=function(e){if("win32"===process.platform){if(/[<>:"|?*]/.test(e.replace(xe.parse(e).root,""))){const t=new Error(`Path contains invalid characters: ${e}`);throw t.code="EINVAL",t}}};const Ne=ne,{checkPath:Ie}=ke,Te=e=>"number"==typeof e?e:{mode:511,...e}.mode;Pe.makeDir=async(e,t)=>(Ie(e),Ne.mkdir(e,{mode:Te(t),recursive:!0})),Pe.makeDirSync=(e,t)=>(Ie(e),Ne.mkdirSync(e,{mode:Te(t),recursive:!0}));const Re=re.fromPromise,{makeDir:Me,makeDirSync:Le}=Pe,je=Re(Me);var $e={mkdirs:je,mkdirsSync:Le,mkdirp:je,mkdirpSync:Le,ensureDir:je,ensureDirSync:Le};const He=re.fromPromise,Je=ne;var Ge={pathExists:He((function(e){return Je.access(e).then((()=>!0)).catch((()=>!1))})),pathExistsSync:Je.existsSync};const Ve=we;var Ue=function(e,t,n,r){Ve.open(e,"r+",((e,u)=>{if(e)return r(e);Ve.futimes(u,t,n,(e=>{Ve.close(u,(t=>{r&&r(e||t)}))}))}))},We=function(e,t,n){const r=Ve.openSync(e,"r+");return Ve.futimesSync(r,t,n),Ve.closeSync(r)};const ze=ne,Ke=p.default,qe=F.default;function Ye(e,t,n){const r=n.dereference?e=>ze.stat(e,{bigint:!0}):e=>ze.lstat(e,{bigint:!0});return Promise.all([r(e),r(t).catch((e=>{if("ENOENT"===e.code)return null;throw e}))]).then((([e,t])=>({srcStat:e,destStat:t})))}function Xe(e,t){return t.ino&&t.dev&&t.ino===e.ino&&t.dev===e.dev}function Ze(e,t){const n=Ke.resolve(e).split(Ke.sep).filter((e=>e)),r=Ke.resolve(t).split(Ke.sep).filter((e=>e));return n.reduce(((e,t,n)=>e&&r[n]===t),!0)}function Qe(e,t,n){return`Cannot ${n} '${e}' to a subdirectory of itself, '${t}'.`}var et={checkPaths:function(e,t,n,r,u){qe.callbackify(Ye)(e,t,r,((r,o)=>{if(r)return u(r);const{srcStat:i,destStat:s}=o;if(s){if(Xe(i,s)){const r=Ke.basename(e),o=Ke.basename(t);return"move"===n&&r!==o&&r.toLowerCase()===o.toLowerCase()?u(null,{srcStat:i,destStat:s,isChangingCase:!0}):u(new Error("Source and destination must not be the same."))}if(i.isDirectory()&&!s.isDirectory())return u(new Error(`Cannot overwrite non-directory '${t}' with directory '${e}'.`));if(!i.isDirectory()&&s.isDirectory())return u(new Error(`Cannot overwrite directory '${t}' with non-directory '${e}'.`))}return i.isDirectory()&&Ze(e,t)?u(new Error(Qe(e,t,n))):u(null,{srcStat:i,destStat:s})}))},checkPathsSync:function(e,t,n,r){const{srcStat:u,destStat:o}=function(e,t,n){let r;const u=n.dereference?e=>ze.statSync(e,{bigint:!0}):e=>ze.lstatSync(e,{bigint:!0}),o=u(e);try{r=u(t)}catch(e){if("ENOENT"===e.code)return{srcStat:o,destStat:null};throw e}return{srcStat:o,destStat:r}}(e,t,r);if(o){if(Xe(u,o)){const r=Ke.basename(e),i=Ke.basename(t);if("move"===n&&r!==i&&r.toLowerCase()===i.toLowerCase())return{srcStat:u,destStat:o,isChangingCase:!0};throw new Error("Source and destination must not be the same.")}if(u.isDirectory()&&!o.isDirectory())throw new Error(`Cannot overwrite non-directory '${t}' with directory '${e}'.`);if(!u.isDirectory()&&o.isDirectory())throw new Error(`Cannot overwrite directory '${t}' with non-directory '${e}'.`)}if(u.isDirectory()&&Ze(e,t))throw new Error(Qe(e,t,n));return{srcStat:u,destStat:o}},checkParentPaths:function e(t,n,r,u,o){const i=Ke.resolve(Ke.dirname(t)),s=Ke.resolve(Ke.dirname(r));if(s===i||s===Ke.parse(s).root)return o();ze.stat(s,{bigint:!0},((i,c)=>i?"ENOENT"===i.code?o():o(i):Xe(n,c)?o(new Error(Qe(t,r,u))):e(t,n,s,u,o)))},checkParentPathsSync:function e(t,n,r,u){const o=Ke.resolve(Ke.dirname(t)),i=Ke.resolve(Ke.dirname(r));if(i===o||i===Ke.parse(i).root)return;let s;try{s=ze.statSync(i,{bigint:!0})}catch(e){if("ENOENT"===e.code)return;throw e}if(Xe(n,s))throw new Error(Qe(t,r,u));return e(t,n,i,u)},isSrcSubdir:Ze,areIdentical:Xe};const tt=we,nt=p.default,rt=$e.mkdirs,ut=Ge.pathExists,ot=Ue,it=et;function st(e,t,n,r,u){const o=nt.dirname(n);ut(o,((i,s)=>i?u(i):s?at(e,t,n,r,u):void rt(o,(o=>o?u(o):at(e,t,n,r,u)))))}function ct(e,t,n,r,u,o){Promise.resolve(u.filter(n,r)).then((i=>i?e(t,n,r,u,o):o()),(e=>o(e)))}function at(e,t,n,r,u){(r.dereference?tt.stat:tt.lstat)(t,((o,i)=>o?u(o):i.isDirectory()?function(e,t,n,r,u,o){return t?Dt(n,r,u,o):function(e,t,n,r,u){tt.mkdir(n,(o=>{if(o)return u(o);Dt(t,n,r,(t=>t?u(t):dt(n,e,u)))}))}(e.mode,n,r,u,o)}(i,e,t,n,r,u):i.isFile()||i.isCharacterDevice()||i.isBlockDevice()?function(e,t,n,r,u,o){return t?function(e,t,n,r,u){if(!r.overwrite)return r.errorOnExist?u(new Error(`'${n}' already exists`)):u();tt.unlink(n,(o=>o?u(o):lt(e,t,n,r,u)))}(e,n,r,u,o):lt(e,n,r,u,o)}(i,e,t,n,r,u):i.isSymbolicLink()?function(e,t,n,r,u){tt.readlink(t,((t,o)=>t?u(t):(r.dereference&&(o=nt.resolve(process.cwd(),o)),e?void tt.readlink(n,((t,i)=>t?"EINVAL"===t.code||"UNKNOWN"===t.code?tt.symlink(o,n,u):u(t):(r.dereference&&(i=nt.resolve(process.cwd(),i)),it.isSrcSubdir(o,i)?u(new Error(`Cannot copy '${o}' to a subdirectory of itself, '${i}'.`)):e.isDirectory()&&it.isSrcSubdir(i,o)?u(new Error(`Cannot overwrite '${i}' with '${o}'.`)):function(e,t,n){tt.unlink(t,(r=>r?n(r):tt.symlink(e,t,n)))}(o,n,u)))):tt.symlink(o,n,u))))}(e,t,n,r,u):i.isSocket()?u(new Error(`Cannot copy a socket file: ${t}`)):i.isFIFO()?u(new Error(`Cannot copy a FIFO pipe: ${t}`)):u(new Error(`Unknown file: ${t}`))))}function lt(e,t,n,r,u){tt.copyFile(t,n,(o=>o?u(o):r.preserveTimestamps?function(e,t,n,r){if(function(e){return 0==(128&e)}(e))return function(e,t,n){return dt(e,128|t,n)}(n,e,(u=>u?r(u):ft(e,t,n,r)));return ft(e,t,n,r)}(e.mode,t,n,u):dt(n,e.mode,u)))}function ft(e,t,n,r){!function(e,t,n){tt.stat(e,((e,r)=>e?n(e):ot(t,r.atime,r.mtime,n)))}(t,n,(t=>t?r(t):dt(n,e,r)))}function dt(e,t,n){return tt.chmod(e,t,n)}function Dt(e,t,n,r){tt.readdir(e,((u,o)=>u?r(u):pt(o,e,t,n,r)))}function pt(e,t,n,r,u){const o=e.pop();return o?function(e,t,n,r,u,o){const i=nt.join(n,t),s=nt.join(r,t);it.checkPaths(i,s,"copy",u,((t,c)=>{if(t)return o(t);const{destStat:a}=c;!function(e,t,n,r,u){r.filter?ct(at,e,t,n,r,u):at(e,t,n,r,u)}(a,i,s,u,(t=>t?o(t):pt(e,n,r,u,o)))}))}(e,o,t,n,r,u):u()}var Et=function(e,t,n,r){"function"!=typeof n||r?"function"==typeof n&&(n={filter:n}):(r=n,n={}),r=r||function(){},(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269"),it.checkPaths(e,t,"copy",n,((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;it.checkParentPaths(e,i,t,"copy",(u=>u?r(u):n.filter?ct(st,s,e,t,n,r):st(s,e,t,n,r)))}))};const mt=we,ht=p.default,yt=$e.mkdirsSync,Ct=We,Ft=et;function gt(e,t,n,r){const u=(r.dereference?mt.statSync:mt.lstatSync)(t);if(u.isDirectory())return function(e,t,n,r,u){return t?St(n,r,u):function(e,t,n,r){return mt.mkdirSync(n),St(t,n,r),vt(n,e)}(e.mode,n,r,u)}(u,e,t,n,r);if(u.isFile()||u.isCharacterDevice()||u.isBlockDevice())return function(e,t,n,r,u){return t?function(e,t,n,r){if(r.overwrite)return mt.unlinkSync(n),At(e,t,n,r);if(r.errorOnExist)throw new Error(`'${n}' already exists`)}(e,n,r,u):At(e,n,r,u)}(u,e,t,n,r);if(u.isSymbolicLink())return function(e,t,n,r){let u=mt.readlinkSync(t);r.dereference&&(u=ht.resolve(process.cwd(),u));if(e){let e;try{e=mt.readlinkSync(n)}catch(e){if("EINVAL"===e.code||"UNKNOWN"===e.code)return mt.symlinkSync(u,n);throw e}if(r.dereference&&(e=ht.resolve(process.cwd(),e)),Ft.isSrcSubdir(u,e))throw new Error(`Cannot copy '${u}' to a subdirectory of itself, '${e}'.`);if(mt.statSync(n).isDirectory()&&Ft.isSrcSubdir(e,u))throw new Error(`Cannot overwrite '${e}' with '${u}'.`);return function(e,t){return mt.unlinkSync(t),mt.symlinkSync(e,t)}(u,n)}return mt.symlinkSync(u,n)}(e,t,n,r);if(u.isSocket())throw new Error(`Cannot copy a socket file: ${t}`);if(u.isFIFO())throw new Error(`Cannot copy a FIFO pipe: ${t}`);throw new Error(`Unknown file: ${t}`)}function At(e,t,n,r){return mt.copyFileSync(t,n),r.preserveTimestamps&&function(e,t,n){(function(e){return 0==(128&e)})(e)&&function(e,t){vt(e,128|t)}(n,e);(function(e,t){const n=mt.statSync(e);Ct(t,n.atime,n.mtime)})(t,n)}(e.mode,t,n),vt(n,e.mode)}function vt(e,t){return mt.chmodSync(e,t)}function St(e,t,n){mt.readdirSync(e).forEach((r=>function(e,t,n,r){const u=ht.join(t,e),o=ht.join(n,e),{destStat:i}=Ft.checkPathsSync(u,o,"copy",r);return function(e,t,n,r){if(!r.filter||r.filter(t,n))return gt(e,t,n,r)}(i,u,o,r)}(r,e,t,n)))}var wt=function(e,t,n){"function"==typeof n&&(n={filter:n}),(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269");const{srcStat:r,destStat:u}=Ft.checkPathsSync(e,t,"copy",n);return Ft.checkParentPathsSync(e,r,t,"copy"),function(e,t,n,r){if(r.filter&&!r.filter(t,n))return;const u=ht.dirname(n);mt.existsSync(u)||yt(u);return gt(e,t,n,r)}(u,e,t,n)};var Ot={copy:(0,re.fromCallback)(Et),copySync:wt};const bt=we,_t=p.default,Bt=g.default,Pt="win32"===process.platform;function kt(e){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach((t=>{e[t]=e[t]||bt[t],e[t+="Sync"]=e[t]||bt[t]})),e.maxBusyTries=e.maxBusyTries||3}function xt(e,t,n){let r=0;"function"==typeof t&&(n=t,t={}),Bt(e,"rimraf: missing path"),Bt.strictEqual(typeof e,"string","rimraf: path should be a string"),Bt.strictEqual(typeof n,"function","rimraf: callback function required"),Bt(t,"rimraf: invalid options argument provided"),Bt.strictEqual(typeof t,"object","rimraf: options should be object"),kt(t),Nt(e,t,(function u(o){if(o){if(("EBUSY"===o.code||"ENOTEMPTY"===o.code||"EPERM"===o.code)&&rNt(e,t,u)),100*r)}"ENOENT"===o.code&&(o=null)}n(o)}))}function Nt(e,t,n){Bt(e),Bt(t),Bt("function"==typeof n),t.lstat(e,((r,u)=>r&&"ENOENT"===r.code?n(null):r&&"EPERM"===r.code&&Pt?It(e,t,r,n):u&&u.isDirectory()?Rt(e,t,r,n):void t.unlink(e,(r=>{if(r){if("ENOENT"===r.code)return n(null);if("EPERM"===r.code)return Pt?It(e,t,r,n):Rt(e,t,r,n);if("EISDIR"===r.code)return Rt(e,t,r,n)}return n(r)}))))}function It(e,t,n,r){Bt(e),Bt(t),Bt("function"==typeof r),t.chmod(e,438,(u=>{u?r("ENOENT"===u.code?null:n):t.stat(e,((u,o)=>{u?r("ENOENT"===u.code?null:n):o.isDirectory()?Rt(e,t,n,r):t.unlink(e,r)}))}))}function Tt(e,t,n){let r;Bt(e),Bt(t);try{t.chmodSync(e,438)}catch(e){if("ENOENT"===e.code)return;throw n}try{r=t.statSync(e)}catch(e){if("ENOENT"===e.code)return;throw n}r.isDirectory()?Lt(e,t,n):t.unlinkSync(e)}function Rt(e,t,n,r){Bt(e),Bt(t),Bt("function"==typeof r),t.rmdir(e,(u=>{!u||"ENOTEMPTY"!==u.code&&"EEXIST"!==u.code&&"EPERM"!==u.code?u&&"ENOTDIR"===u.code?r(n):r(u):function(e,t,n){Bt(e),Bt(t),Bt("function"==typeof n),t.readdir(e,((r,u)=>{if(r)return n(r);let o,i=u.length;if(0===i)return t.rmdir(e,n);u.forEach((r=>{xt(_t.join(e,r),t,(r=>{if(!o)return r?n(o=r):void(0==--i&&t.rmdir(e,n))}))}))}))}(e,t,r)}))}function Mt(e,t){let n;kt(t=t||{}),Bt(e,"rimraf: missing path"),Bt.strictEqual(typeof e,"string","rimraf: path should be a string"),Bt(t,"rimraf: missing options"),Bt.strictEqual(typeof t,"object","rimraf: options should be object");try{n=t.lstatSync(e)}catch(n){if("ENOENT"===n.code)return;"EPERM"===n.code&&Pt&&Tt(e,t,n)}try{n&&n.isDirectory()?Lt(e,t,null):t.unlinkSync(e)}catch(n){if("ENOENT"===n.code)return;if("EPERM"===n.code)return Pt?Tt(e,t,n):Lt(e,t,n);if("EISDIR"!==n.code)throw n;Lt(e,t,n)}}function Lt(e,t,n){Bt(e),Bt(t);try{t.rmdirSync(e)}catch(r){if("ENOTDIR"===r.code)throw n;if("ENOTEMPTY"===r.code||"EEXIST"===r.code||"EPERM"===r.code)!function(e,t){if(Bt(e),Bt(t),t.readdirSync(e).forEach((n=>Mt(_t.join(e,n),t))),!Pt){return t.rmdirSync(e,t)}{const n=Date.now();do{try{return t.rmdirSync(e,t)}catch{}}while(Date.now()-n<500)}}(e,t);else if("ENOENT"!==r.code)throw r}}var jt=xt;xt.sync=Mt;const $t=we,Ht=re.fromCallback,Jt=jt;var Gt={remove:Ht((function(e,t){if($t.rm)return $t.rm(e,{recursive:!0,force:!0},t);Jt(e,t)})),removeSync:function(e){if($t.rmSync)return $t.rmSync(e,{recursive:!0,force:!0});Jt.sync(e)}};const Vt=re.fromPromise,Ut=ne,Wt=p.default,zt=$e,Kt=Gt,qt=Vt((async function(e){let t;try{t=await Ut.readdir(e)}catch{return zt.mkdirs(e)}return Promise.all(t.map((t=>Kt.remove(Wt.join(e,t)))))}));function Yt(e){let t;try{t=Ut.readdirSync(e)}catch{return zt.mkdirsSync(e)}t.forEach((t=>{t=Wt.join(e,t),Kt.removeSync(t)}))}var Xt={emptyDirSync:Yt,emptydirSync:Yt,emptyDir:qt,emptydir:qt};const Zt=re.fromCallback,Qt=p.default,en=we,tn=$e;var nn={createFile:Zt((function(e,t){function n(){en.writeFile(e,"",(e=>{if(e)return t(e);t()}))}en.stat(e,((r,u)=>{if(!r&&u.isFile())return t();const o=Qt.dirname(e);en.stat(o,((e,r)=>{if(e)return"ENOENT"===e.code?tn.mkdirs(o,(e=>{if(e)return t(e);n()})):t(e);r.isDirectory()?n():en.readdir(o,(e=>{if(e)return t(e)}))}))}))})),createFileSync:function(e){let t;try{t=en.statSync(e)}catch{}if(t&&t.isFile())return;const n=Qt.dirname(e);try{en.statSync(n).isDirectory()||en.readdirSync(n)}catch(e){if(!e||"ENOENT"!==e.code)throw e;tn.mkdirsSync(n)}en.writeFileSync(e,"")}};const rn=re.fromCallback,un=p.default,on=we,sn=$e,cn=Ge.pathExists,{areIdentical:an}=et;var ln={createLink:rn((function(e,t,n){function r(e,t){on.link(e,t,(e=>{if(e)return n(e);n(null)}))}on.lstat(t,((u,o)=>{on.lstat(e,((u,i)=>{if(u)return u.message=u.message.replace("lstat","ensureLink"),n(u);if(o&&an(i,o))return n(null);const s=un.dirname(t);cn(s,((u,o)=>u?n(u):o?r(e,t):void sn.mkdirs(s,(u=>{if(u)return n(u);r(e,t)}))))}))}))})),createLinkSync:function(e,t){let n;try{n=on.lstatSync(t)}catch{}try{const t=on.lstatSync(e);if(n&&an(t,n))return}catch(e){throw e.message=e.message.replace("lstat","ensureLink"),e}const r=un.dirname(t);return on.existsSync(r)||sn.mkdirsSync(r),on.linkSync(e,t)}};const fn=p.default,dn=we,Dn=Ge.pathExists;var pn={symlinkPaths:function(e,t,n){if(fn.isAbsolute(e))return dn.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:e})));{const r=fn.dirname(t),u=fn.join(r,e);return Dn(u,((t,o)=>t?n(t):o?n(null,{toCwd:u,toDst:e}):dn.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:fn.relative(r,e)})))))}},symlinkPathsSync:function(e,t){let n;if(fn.isAbsolute(e)){if(n=dn.existsSync(e),!n)throw new Error("absolute srcpath does not exist");return{toCwd:e,toDst:e}}{const r=fn.dirname(t),u=fn.join(r,e);if(n=dn.existsSync(u),n)return{toCwd:u,toDst:e};if(n=dn.existsSync(e),!n)throw new Error("relative srcpath does not exist");return{toCwd:e,toDst:fn.relative(r,e)}}}};const En=we;var mn={symlinkType:function(e,t,n){if(n="function"==typeof t?t:n,t="function"!=typeof t&&t)return n(null,t);En.lstat(e,((e,r)=>{if(e)return n(null,"file");t=r&&r.isDirectory()?"dir":"file",n(null,t)}))},symlinkTypeSync:function(e,t){let n;if(t)return t;try{n=En.lstatSync(e)}catch{return"file"}return n&&n.isDirectory()?"dir":"file"}};const hn=re.fromCallback,yn=p.default,Cn=ne,Fn=$e.mkdirs,gn=$e.mkdirsSync,An=pn.symlinkPaths,vn=pn.symlinkPathsSync,Sn=mn.symlinkType,wn=mn.symlinkTypeSync,On=Ge.pathExists,{areIdentical:bn}=et;function _n(e,t,n,r){An(e,t,((u,o)=>{if(u)return r(u);e=o.toDst,Sn(o.toCwd,n,((n,u)=>{if(n)return r(n);const o=yn.dirname(t);On(o,((n,i)=>n?r(n):i?Cn.symlink(e,t,u,r):void Fn(o,(n=>{if(n)return r(n);Cn.symlink(e,t,u,r)}))))}))}))}var Bn={createSymlink:hn((function(e,t,n,r){r="function"==typeof n?n:r,n="function"!=typeof n&&n,Cn.lstat(t,((u,o)=>{!u&&o.isSymbolicLink()?Promise.all([Cn.stat(e),Cn.stat(t)]).then((([u,o])=>{if(bn(u,o))return r(null);_n(e,t,n,r)})):_n(e,t,n,r)}))})),createSymlinkSync:function(e,t,n){let r;try{r=Cn.lstatSync(t)}catch{}if(r&&r.isSymbolicLink()){const n=Cn.statSync(e),r=Cn.statSync(t);if(bn(n,r))return}const u=vn(e,t);e=u.toDst,n=wn(u.toCwd,n);const o=yn.dirname(t);return Cn.existsSync(o)||gn(o),Cn.symlinkSync(e,t,n)}};const{createFile:Pn,createFileSync:kn}=nn,{createLink:xn,createLinkSync:Nn}=ln,{createSymlink:In,createSymlinkSync:Tn}=Bn;var Rn={createFile:Pn,createFileSync:kn,ensureFile:Pn,ensureFileSync:kn,createLink:xn,createLinkSync:Nn,ensureLink:xn,ensureLinkSync:Nn,createSymlink:In,createSymlinkSync:Tn,ensureSymlink:In,ensureSymlinkSync:Tn};var Mn={stringify:function(e,{EOL:t="\n",finalEOL:n=!0,replacer:r=null,spaces:u}={}){const o=n?t:"";return JSON.stringify(e,r,u).replace(/\n/g,t)+o},stripBom:function(e){return Buffer.isBuffer(e)&&(e=e.toString("utf8")),e.replace(/^\uFEFF/,"")}};let Ln;try{Ln=we}catch(e){Ln=D.default}const jn=re,{stringify:$n,stripBom:Hn}=Mn;const Jn=jn.fromPromise((async function(e,t={}){"string"==typeof t&&(t={encoding:t});const n=t.fs||Ln,r=!("throws"in t)||t.throws;let u,o=await jn.fromCallback(n.readFile)(e,t);o=Hn(o);try{u=JSON.parse(o,t?t.reviver:null)}catch(t){if(r)throw t.message=`${e}: ${t.message}`,t;return null}return u}));const Gn=jn.fromPromise((async function(e,t,n={}){const r=n.fs||Ln,u=$n(t,n);await jn.fromCallback(r.writeFile)(e,u,n)}));const Vn={readFile:Jn,readFileSync:function(e,t={}){"string"==typeof t&&(t={encoding:t});const n=t.fs||Ln,r=!("throws"in t)||t.throws;try{let r=n.readFileSync(e,t);return r=Hn(r),JSON.parse(r,t.reviver)}catch(t){if(r)throw t.message=`${e}: ${t.message}`,t;return null}},writeFile:Gn,writeFileSync:function(e,t,n={}){const r=n.fs||Ln,u=$n(t,n);return r.writeFileSync(e,u,n)}};var Un={readJson:Vn.readFile,readJsonSync:Vn.readFileSync,writeJson:Vn.writeFile,writeJsonSync:Vn.writeFileSync};const Wn=re.fromCallback,zn=we,Kn=p.default,qn=$e,Yn=Ge.pathExists;var Xn={outputFile:Wn((function(e,t,n,r){"function"==typeof n&&(r=n,n="utf8");const u=Kn.dirname(e);Yn(u,((o,i)=>o?r(o):i?zn.writeFile(e,t,n,r):void qn.mkdirs(u,(u=>{if(u)return r(u);zn.writeFile(e,t,n,r)}))))})),outputFileSync:function(e,...t){const n=Kn.dirname(e);if(zn.existsSync(n))return zn.writeFileSync(e,...t);qn.mkdirsSync(n),zn.writeFileSync(e,...t)}};const{stringify:Zn}=Mn,{outputFile:Qn}=Xn;var er=async function(e,t,n={}){const r=Zn(t,n);await Qn(e,r,n)};const{stringify:tr}=Mn,{outputFileSync:nr}=Xn;var rr=function(e,t,n){const r=tr(t,n);nr(e,r,n)};const ur=re.fromPromise,or=Un;or.outputJson=ur(er),or.outputJsonSync=rr,or.outputJSON=or.outputJson,or.outputJSONSync=or.outputJsonSync,or.writeJSON=or.writeJson,or.writeJSONSync=or.writeJsonSync,or.readJSON=or.readJson,or.readJSONSync=or.readJsonSync;var ir=or;const sr=we,cr=p.default,ar=Ot.copy,lr=Gt.remove,fr=$e.mkdirp,dr=Ge.pathExists,Dr=et;function pr(e,t,n,r,u){return r?Er(e,t,n,u):n?lr(t,(r=>r?u(r):Er(e,t,n,u))):void dr(t,((r,o)=>r?u(r):o?u(new Error("dest already exists.")):Er(e,t,n,u)))}function Er(e,t,n,r){sr.rename(e,t,(u=>u?"EXDEV"!==u.code?r(u):function(e,t,n,r){const u={overwrite:n,errorOnExist:!0};ar(e,t,u,(t=>t?r(t):lr(e,r)))}(e,t,n,r):r()))}var mr=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=n.overwrite||n.clobber||!1;Dr.checkPaths(e,t,"move",n,((n,o)=>{if(n)return r(n);const{srcStat:i,isChangingCase:s=!1}=o;Dr.checkParentPaths(e,i,t,"move",(n=>n?r(n):function(e){const t=cr.dirname(e);return cr.parse(t).root===t}(t)?pr(e,t,u,s,r):void fr(cr.dirname(t),(n=>n?r(n):pr(e,t,u,s,r)))))}))};const hr=we,yr=p.default,Cr=Ot.copySync,Fr=Gt.removeSync,gr=$e.mkdirpSync,Ar=et;function vr(e,t,n){try{hr.renameSync(e,t)}catch(r){if("EXDEV"!==r.code)throw r;return function(e,t,n){const r={overwrite:n,errorOnExist:!0};return Cr(e,t,r),Fr(e)}(e,t,n)}}var Sr=function(e,t,n){const r=(n=n||{}).overwrite||n.clobber||!1,{srcStat:u,isChangingCase:o=!1}=Ar.checkPathsSync(e,t,"move",n);return Ar.checkParentPathsSync(e,u,t,"move"),function(e){const t=yr.dirname(e);return yr.parse(t).root===t}(t)||gr(yr.dirname(t)),function(e,t,n,r){if(r)return vr(e,t,n);if(n)return Fr(t),vr(e,t,n);if(hr.existsSync(t))throw new Error("dest already exists.");return vr(e,t,n)}(e,t,r,o)};var wr,Or,br,_r,Br,Pr={move:(0,re.fromCallback)(mr),moveSync:Sr},kr={...ne,...Ot,...Xt,...Rn,...ir,...$e,...Pr,...Xn,...Ge,...Gt},xr={},Nr={exports:{}},Ir={exports:{}};function Tr(){if(Or)return wr;Or=1;var e=1e3,t=60*e,n=60*t,r=24*n,u=7*r,o=365.25*r;function i(e,t,n,r){var u=t>=1.5*n;return Math.round(e/n)+" "+r+(u?"s":"")}return wr=function(s,c){c=c||{};var a=typeof s;if("string"===a&&s.length>0)return function(i){if((i=String(i)).length>100)return;var s=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(i);if(!s)return;var c=parseFloat(s[1]);switch((s[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return c*o;case"weeks":case"week":case"w":return c*u;case"days":case"day":case"d":return c*r;case"hours":case"hour":case"hrs":case"hr":case"h":return c*n;case"minutes":case"minute":case"mins":case"min":case"m":return c*t;case"seconds":case"second":case"secs":case"sec":case"s":return c*e;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return c;default:return}}(s);if("number"===a&&isFinite(s))return c.long?function(u){var o=Math.abs(u);if(o>=r)return i(u,o,r,"day");if(o>=n)return i(u,o,n,"hour");if(o>=t)return i(u,o,t,"minute");if(o>=e)return i(u,o,e,"second");return u+" ms"}(s):function(u){var o=Math.abs(u);if(o>=r)return Math.round(u/r)+"d";if(o>=n)return Math.round(u/n)+"h";if(o>=t)return Math.round(u/t)+"m";if(o>=e)return Math.round(u/e)+"s";return u+"ms"}(s);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(s))}}function Rr(){if(_r)return br;return _r=1,br=function(e){function t(e){let r,u,o,i=null;function s(...e){if(!s.enabled)return;const n=s,u=Number(new Date),o=u-(r||u);n.diff=o,n.prev=r,n.curr=u,r=u,e[0]=t.coerce(e[0]),"string"!=typeof e[0]&&e.unshift("%O");let i=0;e[0]=e[0].replace(/%([a-zA-Z%])/g,((r,u)=>{if("%%"===r)return"%";i++;const o=t.formatters[u];if("function"==typeof o){const t=e[i];r=o.call(n,t),e.splice(i,1),i--}return r})),t.formatArgs.call(n,e);(n.log||t.log).apply(n,e)}return s.namespace=e,s.useColors=t.useColors(),s.color=t.selectColor(e),s.extend=n,s.destroy=t.destroy,Object.defineProperty(s,"enabled",{enumerable:!0,configurable:!1,get:()=>null!==i?i:(u!==t.namespaces&&(u=t.namespaces,o=t.enabled(e)),o),set:e=>{i=e}}),"function"==typeof t.init&&t.init(s),s}function n(e,n){const r=t(this.namespace+(void 0===n?":":n)+e);return r.log=this.log,r}function r(e){return e.toString().substring(2,e.toString().length-2).replace(/\.\*\?$/,"*")}return t.debug=t,t.default=t,t.coerce=function(e){if(e instanceof Error)return e.stack||e.message;return e},t.disable=function(){const e=[...t.names.map(r),...t.skips.map(r).map((e=>"-"+e))].join(",");return t.enable(""),e},t.enable=function(e){let n;t.save(e),t.namespaces=e,t.names=[],t.skips=[];const r=("string"==typeof e?e:"").split(/[\s,]+/),u=r.length;for(n=0;n{t[n]=e[n]})),t.names=[],t.skips=[],t.formatters={},t.selectColor=function(e){let n=0;for(let t=0;t{const n=e.startsWith("-")?"":1===e.length?"-":"--",r=t.indexOf(n+e),u=t.indexOf("--");return-1!==r&&(-1===u||r{}),"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),t.colors=[6,2,3,4,5,1];try{const e=function(){if($r)return jr;$r=1;const e=E.default,t=A.default,n=Vr(),{env:r}=process;let u;function o(e){return 0!==e&&{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function i(t,o){if(0===u)return 0;if(n("color=16m")||n("color=full")||n("color=truecolor"))return 3;if(n("color=256"))return 2;if(t&&!o&&void 0===u)return 0;const i=u||0;if("dumb"===r.TERM)return i;if("win32"===process.platform){const t=e.release().split(".");return Number(t[0])>=10&&Number(t[2])>=10586?Number(t[2])>=14931?3:2:1}if("CI"in r)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some((e=>e in r))||"codeship"===r.CI_NAME?1:i;if("TEAMCITY_VERSION"in r)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(r.TEAMCITY_VERSION)?1:0;if("truecolor"===r.COLORTERM)return 3;if("TERM_PROGRAM"in r){const e=parseInt((r.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(r.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(r.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(r.TERM)||"COLORTERM"in r?1:i}return n("no-color")||n("no-colors")||n("color=false")||n("color=never")?u=0:(n("color")||n("colors")||n("color=true")||n("color=always"))&&(u=1),"FORCE_COLOR"in r&&(u="true"===r.FORCE_COLOR?1:"false"===r.FORCE_COLOR?0:0===r.FORCE_COLOR.length?1:Math.min(parseInt(r.FORCE_COLOR,10),3)),jr={supportsColor:function(e){return o(i(e,e&&e.isTTY))},stdout:o(i(!0,t.isatty(1))),stderr:o(i(!0,t.isatty(2)))}}();e&&(e.stderr||e).level>=2&&(t.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch(e){}t.inspectOpts=Object.keys(process.env).filter((e=>/^debug_/i.test(e))).reduce(((e,t)=>{const n=t.substring(6).toLowerCase().replace(/_([a-z])/g,((e,t)=>t.toUpperCase()));let r=process.env[t];return r=!!/^(yes|on|true|enabled)$/i.test(r)||!/^(no|off|false|disabled)$/i.test(r)&&("null"===r?null:Number(r)),e[n]=r,e}),{}),e.exports=Rr()(t);const{formatters:u}=e.exports;u.o=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts).split("\n").map((e=>e.trim())).join(" ")},u.O=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts)}}(Gr,Gr.exports)),Gr.exports}Jr=Nr,"undefined"==typeof process||"renderer"===process.type||!0===process.browser||process.__nwjs?Jr.exports=(Br||(Br=1,function(e,t){t.formatArgs=function(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+e.exports.humanize(this.diff),!this.useColors)return;const n="color: "+this.color;t.splice(1,0,n,"color: inherit");let r=0,u=0;t[0].replace(/%[a-zA-Z%]/g,(e=>{"%%"!==e&&(r++,"%c"===e&&(u=r))})),t.splice(u,0,n)},t.save=function(e){try{e?t.storage.setItem("debug",e):t.storage.removeItem("debug")}catch(e){}},t.load=function(){let e;try{e=t.storage.getItem("debug")}catch(e){}return!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG),e},t.useColors=function(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type&&!window.process.__nwjs)||("undefined"==typeof navigator||!navigator.userAgent||!navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))&&("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))},t.storage=function(){try{return localStorage}catch(e){}}(),t.destroy=(()=>{let e=!1;return()=>{e||(e=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),t.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.log=console.debug||console.log||(()=>{}),e.exports=Rr()(t);const{formatters:n}=e.exports;n.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}}(Ir,Ir.exports)),Ir.exports):Jr.exports=Ur();var Wr=function(e){return(e=e||{}).circles?function(e){var t=[],n=[];return e.proto?function e(u){if("object"!=typeof u||null===u)return u;if(u instanceof Date)return new Date(u);if(Array.isArray(u))return r(u,e);if(u instanceof Map)return new Map(r(Array.from(u),e));if(u instanceof Set)return new Set(r(Array.from(u),e));var o={};for(var i in t.push(u),n.push(o),u){var s=u[i];if("object"!=typeof s||null===s)o[i]=s;else if(s instanceof Date)o[i]=new Date(s);else if(s instanceof Map)o[i]=new Map(r(Array.from(s),e));else if(s instanceof Set)o[i]=new Set(r(Array.from(s),e));else if(ArrayBuffer.isView(s))o[i]=zr(s);else{var c=t.indexOf(s);o[i]=-1!==c?n[c]:e(s)}}return t.pop(),n.pop(),o}:function e(u){if("object"!=typeof u||null===u)return u;if(u instanceof Date)return new Date(u);if(Array.isArray(u))return r(u,e);if(u instanceof Map)return new Map(r(Array.from(u),e));if(u instanceof Set)return new Set(r(Array.from(u),e));var o={};for(var i in t.push(u),n.push(o),u)if(!1!==Object.hasOwnProperty.call(u,i)){var s=u[i];if("object"!=typeof s||null===s)o[i]=s;else if(s instanceof Date)o[i]=new Date(s);else if(s instanceof Map)o[i]=new Map(r(Array.from(s),e));else if(s instanceof Set)o[i]=new Set(r(Array.from(s),e));else if(ArrayBuffer.isView(s))o[i]=zr(s);else{var c=t.indexOf(s);o[i]=-1!==c?n[c]:e(s)}}return t.pop(),n.pop(),o};function r(e,r){for(var u=Object.keys(e),o=new Array(u.length),i=0;i!e,Qr=e=>e&&"object"==typeof e&&!Array.isArray(e),eu=(e,t,n)=>{(Array.isArray(t)?t:[t]).forEach((t=>{if(t)throw new Error(`Problem with log4js configuration: (${Kr.inspect(e,{depth:5})}) - ${n}`)}))};var tu={configure:e=>{qr("New configuration to be validated: ",e),eu(e,Zr(Qr(e)),"must be an object."),qr(`Calling pre-processing listeners (${Yr.length})`),Yr.forEach((t=>t(e))),qr("Configuration pre-processing finished."),qr(`Calling configuration listeners (${Xr.length})`),Xr.forEach((t=>t(e))),qr("Configuration finished.")},addListener:e=>{Xr.push(e),qr(`Added listener, now ${Xr.length} listeners`)},addPreProcessingListener:e=>{Yr.push(e),qr(`Added pre-processing listener, now ${Yr.length} listeners`)},throwExceptionIf:eu,anObject:Qr,anInteger:e=>e&&"number"==typeof e&&Number.isInteger(e),validIdentifier:e=>/^[A-Za-z][A-Za-z0-9_]*$/g.test(e),not:Zr},nu={exports:{}};!function(e){function t(e,t){for(var n=e.toString();n.length-1?s:c,l=n(u.getHours()),f=n(u.getMinutes()),d=n(u.getSeconds()),D=t(u.getMilliseconds(),3),p=function(e){var t=Math.abs(e),n=String(Math.floor(t/60)),r=String(t%60);return n=("0"+n).slice(-2),r=("0"+r).slice(-2),0===e?"Z":(e<0?"+":"-")+n+":"+r}(u.getTimezoneOffset());return r.replace(/dd/g,o).replace(/MM/g,i).replace(/y{1,4}/g,a).replace(/hh/g,l).replace(/mm/g,f).replace(/ss/g,d).replace(/SSS/g,D).replace(/O/g,p)}function u(e,t,n,r){e["set"+(r?"":"UTC")+t](n)}e.exports=r,e.exports.asString=r,e.exports.parse=function(t,n,r){if(!t)throw new Error("pattern must be supplied");return function(t,n,r){var o=t.indexOf("O")<0,i=!1,s=[{pattern:/y{1,4}/,regexp:"\\d{1,4}",fn:function(e,t){u(e,"FullYear",t,o)}},{pattern:/MM/,regexp:"\\d{1,2}",fn:function(e,t){u(e,"Month",t-1,o),e.getMonth()!==t-1&&(i=!0)}},{pattern:/dd/,regexp:"\\d{1,2}",fn:function(e,t){i&&u(e,"Month",e.getMonth()-1,o),u(e,"Date",t,o)}},{pattern:/hh/,regexp:"\\d{1,2}",fn:function(e,t){u(e,"Hours",t,o)}},{pattern:/mm/,regexp:"\\d\\d",fn:function(e,t){u(e,"Minutes",t,o)}},{pattern:/ss/,regexp:"\\d\\d",fn:function(e,t){u(e,"Seconds",t,o)}},{pattern:/SSS/,regexp:"\\d\\d\\d",fn:function(e,t){u(e,"Milliseconds",t,o)}},{pattern:/O/,regexp:"[+-]\\d{1,2}:?\\d{2}?|Z",fn:function(e,t){t="Z"===t?0:t.replace(":","");var n=Math.abs(t),r=(t>0?-1:1)*(n%100+60*Math.floor(n/100));e.setUTCMinutes(e.getUTCMinutes()+r)}}],c=s.reduce((function(e,t){return t.pattern.test(e.regexp)?(t.index=e.regexp.match(t.pattern).index,e.regexp=e.regexp.replace(t.pattern,"("+t.regexp+")")):t.index=-1,e}),{regexp:t,index:[]}),a=s.filter((function(e){return e.index>-1}));a.sort((function(e,t){return e.index-t.index}));var l=new RegExp(c.regexp).exec(n);if(l){var f=r||e.exports.now();return a.forEach((function(e,t){e.fn(f,l[t+1])})),f}throw new Error("String '"+n+"' could not be parsed as '"+t+"'")}(t,n,r)},e.exports.now=function(){return new Date},e.exports.ISO8601_FORMAT="yyyy-MM-ddThh:mm:ss.SSS",e.exports.ISO8601_WITH_TZ_OFFSET_FORMAT="yyyy-MM-ddThh:mm:ss.SSSO",e.exports.DATETIME_FORMAT="dd MM yyyy hh:mm:ss.SSS",e.exports.ABSOLUTETIME_FORMAT="hh:mm:ss.SSS"}(nu);const ru=nu.exports,uu=E.default,ou=F.default,iu=p.default,su={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[90,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[91,39],yellow:[33,39]};function cu(e){return e?`[${su[e][0]}m`:""}function au(e){return e?`[${su[e][1]}m`:""}function lu(e,t){return n=ou.format("[%s] [%s] %s - ",ru.asString(e.startTime),e.level.toString(),e.categoryName),cu(r=t)+n+au(r);var n,r}function fu(e){return lu(e)+ou.format(...e.data)}function du(e){return lu(e,e.level.colour)+ou.format(...e.data)}function Du(e){return ou.format(...e.data)}function pu(e){return e.data[0]}function Eu(e,t){const n=/%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflos%])(\{([^}]+)\})?|([^%]+)/;function r(e){return e&&e.pid?e.pid.toString():process.pid.toString()}e=e||"%r %p %c - %m%n";const u={c:function(e,t){let n=e.categoryName;if(t){const e=parseInt(t,10),r=n.split(".");ee&&(n=r.slice(-e).join(iu.sep))}return n},l:function(e){return e.lineNumber?`${e.lineNumber}`:""},o:function(e){return e.columnNumber?`${e.columnNumber}`:""},s:function(e){return e.callStack||""}};function o(e,t,n){return u[e](t,n)}function i(e,t,n){let r=e;return r=function(e,t){let n;return e?(n=parseInt(e.substr(1),10),n>0?t.slice(0,n):t.slice(n)):t}(t,r),r=function(e,t){let n;if(e)if("-"===e.charAt(0))for(n=parseInt(e.substr(1),10);t.lengthDu,basic:()=>fu,colored:()=>du,coloured:()=>du,pattern:e=>Eu(e&&e.pattern,e&&e.tokens),dummy:()=>pu};var hu={basicLayout:fu,messagePassThroughLayout:Du,patternLayout:Eu,colouredLayout:du,coloredLayout:du,dummyLayout:pu,addLayout(e,t){mu[e]=t},layout:(e,t)=>mu[e]&&mu[e](t)};const yu=tu,Cu=["white","grey","black","blue","cyan","green","magenta","red","yellow"];class Fu{constructor(e,t,n){this.level=e,this.levelStr=t,this.colour=n}toString(){return this.levelStr}static getLevel(e,t){return e?e instanceof Fu?e:(e instanceof Object&&e.levelStr&&(e=e.levelStr),Fu[e.toString().toUpperCase()]||t):t}static addLevels(e){if(e){Object.keys(e).forEach((t=>{const n=t.toUpperCase();Fu[n]=new Fu(e[t].value,n,e[t].colour);const r=Fu.levels.findIndex((e=>e.levelStr===n));r>-1?Fu.levels[r]=Fu[n]:Fu.levels.push(Fu[n])})),Fu.levels.sort(((e,t)=>e.level-t.level))}}isLessThanOrEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level<=e.level}isGreaterThanOrEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level>=e.level}isEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level===e.level}}Fu.levels=[],Fu.addLevels({ALL:{value:Number.MIN_VALUE,colour:"grey"},TRACE:{value:5e3,colour:"blue"},DEBUG:{value:1e4,colour:"cyan"},INFO:{value:2e4,colour:"green"},WARN:{value:3e4,colour:"yellow"},ERROR:{value:4e4,colour:"red"},FATAL:{value:5e4,colour:"magenta"},MARK:{value:9007199254740992,colour:"grey"},OFF:{value:Number.MAX_VALUE,colour:"grey"}}),yu.addListener((e=>{const t=e.levels;if(t){yu.throwExceptionIf(e,yu.not(yu.anObject(t)),"levels must be an object");Object.keys(t).forEach((n=>{yu.throwExceptionIf(e,yu.not(yu.validIdentifier(n)),`level name "${n}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`),yu.throwExceptionIf(e,yu.not(yu.anObject(t[n])),`level "${n}" must be an object`),yu.throwExceptionIf(e,yu.not(t[n].value),`level "${n}" must have a 'value' property`),yu.throwExceptionIf(e,yu.not(yu.anInteger(t[n].value)),`level "${n}".value must have an integer value`),yu.throwExceptionIf(e,yu.not(t[n].colour),`level "${n}" must have a 'colour' property`),yu.throwExceptionIf(e,yu.not(Cu.indexOf(t[n].colour)>-1),`level "${n}".colour must be one of ${Cu.join(", ")}`)}))}})),yu.addListener((e=>{Fu.addLevels(e.levels)}));var gu=Fu,Au={exports:{}},vu={};/*! (c) 2020 Andrea Giammarchi */ +const{parse:Su,stringify:wu}=JSON,{keys:Ou}=Object,bu=String,_u="string",Bu={},Pu="object",ku=(e,t)=>t,xu=e=>e instanceof bu?bu(e):e,Nu=(e,t)=>typeof t===_u?new bu(t):t,Iu=(e,t,n,r)=>{const u=[];for(let o=Ou(n),{length:i}=o,s=0;s{const r=bu(t.push(n)-1);return e.set(n,r),r},Ru=(e,t)=>{const n=Su(e,Nu).map(xu),r=n[0],u=t||ku,o=typeof r===Pu&&r?Iu(n,new Set,r,u):r;return u.call({"":o},"",o)};vu.parse=Ru;const Mu=(e,t,n)=>{const r=t&&typeof t===Pu?(e,n)=>""===e||-1Su(Mu(e));vu.fromJSON=e=>Ru(wu(e));const Lu=vu,ju=gu;class $u{constructor(e,t,n,r,u){this.startTime=new Date,this.categoryName=e,this.data=n,this.level=t,this.context=Object.assign({},r),this.pid=process.pid,u&&(this.functionName=u.functionName,this.fileName=u.fileName,this.lineNumber=u.lineNumber,this.columnNumber=u.columnNumber,this.callStack=u.callStack)}serialise(){const e=this.data.map((e=>(e&&e.message&&e.stack&&(e=Object.assign({message:e.message,stack:e.stack},e)),e)));return this.data=e,Lu.stringify(this)}static deserialise(e){let t;try{const n=Lu.parse(e);n.data=n.data.map((e=>{if(e&&e.message&&e.stack){const t=new Error(e);Object.keys(e).forEach((n=>{t[n]=e[n]})),e=t}return e})),t=new $u(n.categoryName,ju.getLevel(n.level.levelStr),n.data,n.context),t.startTime=new Date(n.startTime),t.pid=n.pid,t.cluster=n.cluster}catch(n){t=new $u("log4js",ju.ERROR,["Unable to parse log:",e,"because: ",n])}return t}}var Hu=$u;const Ju=Nr.exports("log4js:clustering"),Gu=Hu,Vu=tu;let Uu=!1,Wu=null;try{Wu=require("cluster")}catch(e){Ju("cluster module not present"),Uu=!0}const zu=[];let Ku=!1,qu="NODE_APP_INSTANCE";const Yu=()=>Ku&&"0"===process.env[qu],Xu=()=>Uu||Wu.isMaster||Yu(),Zu=e=>{zu.forEach((t=>t(e)))},Qu=(e,t)=>{if(Ju("cluster message received from worker ",e,": ",t),e.topic&&e.data&&(t=e,e=void 0),t&&t.topic&&"log4js:message"===t.topic){Ju("received message: ",t.data);const e=Gu.deserialise(t.data);Zu(e)}};Uu||Vu.addListener((e=>{zu.length=0,({pm2:Ku,disableClustering:Uu,pm2InstanceVar:qu="NODE_APP_INSTANCE"}=e),Ju(`clustering disabled ? ${Uu}`),Ju(`cluster.isMaster ? ${Wu&&Wu.isMaster}`),Ju(`pm2 enabled ? ${Ku}`),Ju(`pm2InstanceVar = ${qu}`),Ju(`process.env[${qu}] = ${process.env[qu]}`),Ku&&process.removeListener("message",Qu),Wu&&Wu.removeListener&&Wu.removeListener("message",Qu),Uu||e.disableClustering?Ju("Not listening for cluster messages, because clustering disabled."):Yu()?(Ju("listening for PM2 broadcast messages"),process.on("message",Qu)):Wu.isMaster?(Ju("listening for cluster messages"),Wu.on("message",Qu)):Ju("not listening for messages, because we are not a master process")}));var eo={onlyOnMaster:(e,t)=>Xu()?e():t,isMaster:Xu,send:e=>{Xu()?Zu(e):(Ku||(e.cluster={workerId:Wu.worker.id,worker:process.pid}),process.send({topic:"log4js:message",data:e.serialise()}))},onMessage:e=>{zu.push(e)}},to={};function no(e){if("number"==typeof e&&Number.isInteger(e))return e;const t={K:1024,M:1048576,G:1073741824},n=Object.keys(t),r=e.substr(e.length-1).toLocaleUpperCase(),u=e.substring(0,e.length-1).trim();if(n.indexOf(r)<0||!Number.isInteger(Number(u)))throw Error(`maxLogSize: "${e}" is invalid`);return u*t[r]}function ro(e){return function(e,t){const n=Object.assign({},t);return Object.keys(e).forEach((r=>{n[r]&&(n[r]=e[r](t[r]))})),n}({maxLogSize:no},e)}const uo={file:ro,fileSync:ro};to.modifyConfig=e=>uo[e.type]?uo[e.type](e):e;var oo={};const io=console.log.bind(console);oo.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{io(e(n,t))}}(n,e.timezoneOffset)};var so={};so.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{process.stdout.write(`${e(n,t)}\n`)}}(n,e.timezoneOffset)};var co={};co.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{process.stderr.write(`${e(n,t)}\n`)}}(n,e.timezoneOffset)};var ao={};ao.configure=function(e,t,n,r){const u=n(e.appender);return function(e,t,n,r){const u=r.getLevel(e),o=r.getLevel(t,r.FATAL);return e=>{const t=e.level;t.isGreaterThanOrEqualTo(u)&&t.isLessThanOrEqualTo(o)&&n(e)}}(e.level,e.maxLevel,u,r)};var lo={};const fo=Nr.exports("log4js:categoryFilter");lo.configure=function(e,t,n){const r=n(e.appender);return function(e,t){return"string"==typeof e&&(e=[e]),n=>{fo(`Checking ${n.categoryName} against ${e}`),-1===e.indexOf(n.categoryName)&&(fo("Not excluded, sending to appender"),t(n))}}(e.exclude,r)};var Do={};const po=Nr.exports("log4js:noLogFilter");Do.configure=function(e,t,n){const r=n(e.appender);return function(e,t){return n=>{po(`Checking data: ${n.data} against filters: ${e}`),"string"==typeof e&&(e=[e]),e=e.filter((e=>null!=e&&""!==e));const r=new RegExp(e.join("|"),"i");(0===e.length||n.data.findIndex((e=>r.test(e)))<0)&&(po("Not excluded, sending to appender"),t(n))}}(e.exclude,r)};var Eo={},mo={exports:{}},ho={},yo={fromCallback:function(e){return Object.defineProperty((function(){if("function"!=typeof arguments[arguments.length-1])return new Promise(((t,n)=>{arguments[arguments.length]=(e,r)=>{if(e)return n(e);t(r)},arguments.length++,e.apply(this,arguments)}));e.apply(this,arguments)}),"name",{value:e.name})},fromPromise:function(e){return Object.defineProperty((function(){const t=arguments[arguments.length-1];if("function"!=typeof t)return e.apply(this,arguments);e.apply(this,arguments).then((e=>t(null,e)),t)}),"name",{value:e.name})}};!function(e){const t=yo.fromCallback,n=we,r=["access","appendFile","chmod","chown","close","copyFile","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchown","lchmod","link","lstat","mkdir","mkdtemp","open","readFile","readdir","readlink","realpath","rename","rmdir","stat","symlink","truncate","unlink","utimes","writeFile"].filter((e=>"function"==typeof n[e]));Object.keys(n).forEach((t=>{"promises"!==t&&(e[t]=n[t])})),r.forEach((r=>{e[r]=t(n[r])})),e.exists=function(e,t){return"function"==typeof t?n.exists(e,t):new Promise((t=>n.exists(e,t)))},e.read=function(e,t,r,u,o,i){return"function"==typeof i?n.read(e,t,r,u,o,i):new Promise(((i,s)=>{n.read(e,t,r,u,o,((e,t,n)=>{if(e)return s(e);i({bytesRead:t,buffer:n})}))}))},e.write=function(e,t,...r){return"function"==typeof r[r.length-1]?n.write(e,t,...r):new Promise(((u,o)=>{n.write(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffer:n})}))}))},"function"==typeof n.realpath.native&&(e.realpath.native=t(n.realpath.native))}(ho);const Co=p.default;function Fo(e){return(e=Co.normalize(Co.resolve(e)).split(Co.sep)).length>0?e[0]:null}const go=/[<>:"|?*]/;var Ao=function(e){const t=Fo(e);return e=e.replace(t,""),go.test(e)};const vo=we,So=p.default,wo=Ao,Oo=parseInt("0777",8);var bo=function e(t,n,r,u){if("function"==typeof n?(r=n,n={}):n&&"object"==typeof n||(n={mode:n}),"win32"===process.platform&&wo(t)){const e=new Error(t+" contains invalid WIN32 path characters.");return e.code="EINVAL",r(e)}let o=n.mode;const i=n.fs||vo;void 0===o&&(o=Oo&~process.umask()),u||(u=null),r=r||function(){},t=So.resolve(t),i.mkdir(t,o,(o=>{if(!o)return r(null,u=u||t);if("ENOENT"===o.code){if(So.dirname(t)===t)return r(o);e(So.dirname(t),n,((u,o)=>{u?r(u,o):e(t,n,r,o)}))}else i.stat(t,((e,t)=>{e||!t.isDirectory()?r(o,u):r(null,u)}))}))};const _o=we,Bo=p.default,Po=Ao,ko=parseInt("0777",8);var xo=function e(t,n,r){n&&"object"==typeof n||(n={mode:n});let u=n.mode;const o=n.fs||_o;if("win32"===process.platform&&Po(t)){const e=new Error(t+" contains invalid WIN32 path characters.");throw e.code="EINVAL",e}void 0===u&&(u=ko&~process.umask()),r||(r=null),t=Bo.resolve(t);try{o.mkdirSync(t,u),r=r||t}catch(u){if("ENOENT"===u.code){if(Bo.dirname(t)===t)throw u;r=e(Bo.dirname(t),n,r),e(t,n,r)}else{let e;try{e=o.statSync(t)}catch(e){throw u}if(!e.isDirectory())throw u}}return r};const No=(0,yo.fromCallback)(bo);var Io={mkdirs:No,mkdirsSync:xo,mkdirp:No,mkdirpSync:xo,ensureDir:No,ensureDirSync:xo};const To=we;E.default,p.default;var Ro=function(e,t,n,r){To.open(e,"r+",((e,u)=>{if(e)return r(e);To.futimes(u,t,n,(e=>{To.close(u,(t=>{r&&r(e||t)}))}))}))},Mo=function(e,t,n){const r=To.openSync(e,"r+");return To.futimesSync(r,t,n),To.closeSync(r)};const Lo=we,jo=p.default,$o=10,Ho=5,Jo=0,Go=process.versions.node.split("."),Vo=Number.parseInt(Go[0],10),Uo=Number.parseInt(Go[1],10),Wo=Number.parseInt(Go[2],10);function zo(){if(Vo>$o)return!0;if(Vo===$o){if(Uo>Ho)return!0;if(Uo===Ho&&Wo>=Jo)return!0}return!1}function Ko(e,t){const n=jo.resolve(e).split(jo.sep).filter((e=>e)),r=jo.resolve(t).split(jo.sep).filter((e=>e));return n.reduce(((e,t,n)=>e&&r[n]===t),!0)}function qo(e,t,n){return`Cannot ${n} '${e}' to a subdirectory of itself, '${t}'.`}var Yo,Xo,Zo={checkPaths:function(e,t,n,r){!function(e,t,n){zo()?Lo.stat(e,{bigint:!0},((e,r)=>{if(e)return n(e);Lo.stat(t,{bigint:!0},((e,t)=>e?"ENOENT"===e.code?n(null,{srcStat:r,destStat:null}):n(e):n(null,{srcStat:r,destStat:t})))})):Lo.stat(e,((e,r)=>{if(e)return n(e);Lo.stat(t,((e,t)=>e?"ENOENT"===e.code?n(null,{srcStat:r,destStat:null}):n(e):n(null,{srcStat:r,destStat:t})))}))}(e,t,((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;return s&&s.ino&&s.dev&&s.ino===i.ino&&s.dev===i.dev?r(new Error("Source and destination must not be the same.")):i.isDirectory()&&Ko(e,t)?r(new Error(qo(e,t,n))):r(null,{srcStat:i,destStat:s})}))},checkPathsSync:function(e,t,n){const{srcStat:r,destStat:u}=function(e,t){let n,r;n=zo()?Lo.statSync(e,{bigint:!0}):Lo.statSync(e);try{r=zo()?Lo.statSync(t,{bigint:!0}):Lo.statSync(t)}catch(e){if("ENOENT"===e.code)return{srcStat:n,destStat:null};throw e}return{srcStat:n,destStat:r}}(e,t);if(u&&u.ino&&u.dev&&u.ino===r.ino&&u.dev===r.dev)throw new Error("Source and destination must not be the same.");if(r.isDirectory()&&Ko(e,t))throw new Error(qo(e,t,n));return{srcStat:r,destStat:u}},checkParentPaths:function e(t,n,r,u,o){const i=jo.resolve(jo.dirname(t)),s=jo.resolve(jo.dirname(r));if(s===i||s===jo.parse(s).root)return o();zo()?Lo.stat(s,{bigint:!0},((i,c)=>i?"ENOENT"===i.code?o():o(i):c.ino&&c.dev&&c.ino===n.ino&&c.dev===n.dev?o(new Error(qo(t,r,u))):e(t,n,s,u,o))):Lo.stat(s,((i,c)=>i?"ENOENT"===i.code?o():o(i):c.ino&&c.dev&&c.ino===n.ino&&c.dev===n.dev?o(new Error(qo(t,r,u))):e(t,n,s,u,o)))},checkParentPathsSync:function e(t,n,r,u){const o=jo.resolve(jo.dirname(t)),i=jo.resolve(jo.dirname(r));if(i===o||i===jo.parse(i).root)return;let s;try{s=zo()?Lo.statSync(i,{bigint:!0}):Lo.statSync(i)}catch(e){if("ENOENT"===e.code)return;throw e}if(s.ino&&s.dev&&s.ino===n.ino&&s.dev===n.dev)throw new Error(qo(t,r,u));return e(t,n,i,u)},isSrcSubdir:Ko};const Qo=we,ei=p.default,ti=Io.mkdirsSync,ni=Mo,ri=Zo;function ui(e,t,n,r){if(!r.filter||r.filter(t,n))return function(e,t,n,r){const u=r.dereference?Qo.statSync:Qo.lstatSync,o=u(t);if(o.isDirectory())return function(e,t,n,r,u){if(!t)return function(e,t,n,r){return Qo.mkdirSync(n),ii(t,n,r),Qo.chmodSync(n,e.mode)}(e,n,r,u);if(t&&!t.isDirectory())throw new Error(`Cannot overwrite non-directory '${r}' with directory '${n}'.`);return ii(n,r,u)}(o,e,t,n,r);if(o.isFile()||o.isCharacterDevice()||o.isBlockDevice())return function(e,t,n,r,u){return t?function(e,t,n,r){if(r.overwrite)return Qo.unlinkSync(n),oi(e,t,n,r);if(r.errorOnExist)throw new Error(`'${n}' already exists`)}(e,n,r,u):oi(e,n,r,u)}(o,e,t,n,r);if(o.isSymbolicLink())return function(e,t,n,r){let u=Qo.readlinkSync(t);r.dereference&&(u=ei.resolve(process.cwd(),u));if(e){let e;try{e=Qo.readlinkSync(n)}catch(e){if("EINVAL"===e.code||"UNKNOWN"===e.code)return Qo.symlinkSync(u,n);throw e}if(r.dereference&&(e=ei.resolve(process.cwd(),e)),ri.isSrcSubdir(u,e))throw new Error(`Cannot copy '${u}' to a subdirectory of itself, '${e}'.`);if(Qo.statSync(n).isDirectory()&&ri.isSrcSubdir(e,u))throw new Error(`Cannot overwrite '${e}' with '${u}'.`);return function(e,t){return Qo.unlinkSync(t),Qo.symlinkSync(e,t)}(u,n)}return Qo.symlinkSync(u,n)}(e,t,n,r)}(e,t,n,r)}function oi(e,t,n,r){return"function"==typeof Qo.copyFileSync?(Qo.copyFileSync(t,n),Qo.chmodSync(n,e.mode),r.preserveTimestamps?ni(n,e.atime,e.mtime):void 0):function(e,t,n,r){const u=65536,o=(Xo?Yo:(Xo=1,Yo=function(e){if("function"==typeof Buffer.allocUnsafe)try{return Buffer.allocUnsafe(e)}catch(t){return new Buffer(e)}return new Buffer(e)}))(u),i=Qo.openSync(t,"r"),s=Qo.openSync(n,"w",e.mode);let c=0;for(;cfunction(e,t,n,r){const u=ei.join(t,e),o=ei.join(n,e),{destStat:i}=ri.checkPathsSync(u,o,"copy");return ui(i,u,o,r)}(r,e,t,n)))}var si=function(e,t,n){"function"==typeof n&&(n={filter:n}),(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269");const{srcStat:r,destStat:u}=ri.checkPathsSync(e,t,"copy");return ri.checkParentPathsSync(e,r,t,"copy"),function(e,t,n,r){if(r.filter&&!r.filter(t,n))return;const u=ei.dirname(n);Qo.existsSync(u)||ti(u);return ui(e,t,n,r)}(u,e,t,n)},ci={copySync:si};const ai=yo.fromPromise,li=ho;var fi={pathExists:ai((function(e){return li.access(e).then((()=>!0)).catch((()=>!1))})),pathExistsSync:li.existsSync};const di=we,Di=p.default,pi=Io.mkdirs,Ei=fi.pathExists,mi=Ro,hi=Zo;function yi(e,t,n,r,u){const o=Di.dirname(n);Ei(o,((i,s)=>i?u(i):s?Fi(e,t,n,r,u):void pi(o,(o=>o?u(o):Fi(e,t,n,r,u)))))}function Ci(e,t,n,r,u,o){Promise.resolve(u.filter(n,r)).then((i=>i?e(t,n,r,u,o):o()),(e=>o(e)))}function Fi(e,t,n,r,u){return r.filter?Ci(gi,e,t,n,r,u):gi(e,t,n,r,u)}function gi(e,t,n,r,u){(r.dereference?di.stat:di.lstat)(t,((o,i)=>o?u(o):i.isDirectory()?function(e,t,n,r,u,o){if(!t)return function(e,t,n,r,u){di.mkdir(n,(o=>{if(o)return u(o);Si(t,n,r,(t=>t?u(t):di.chmod(n,e.mode,u)))}))}(e,n,r,u,o);if(t&&!t.isDirectory())return o(new Error(`Cannot overwrite non-directory '${r}' with directory '${n}'.`));return Si(n,r,u,o)}(i,e,t,n,r,u):i.isFile()||i.isCharacterDevice()||i.isBlockDevice()?function(e,t,n,r,u,o){return t?function(e,t,n,r,u){if(!r.overwrite)return r.errorOnExist?u(new Error(`'${n}' already exists`)):u();di.unlink(n,(o=>o?u(o):Ai(e,t,n,r,u)))}(e,n,r,u,o):Ai(e,n,r,u,o)}(i,e,t,n,r,u):i.isSymbolicLink()?function(e,t,n,r,u){di.readlink(t,((t,o)=>t?u(t):(r.dereference&&(o=Di.resolve(process.cwd(),o)),e?void di.readlink(n,((t,i)=>t?"EINVAL"===t.code||"UNKNOWN"===t.code?di.symlink(o,n,u):u(t):(r.dereference&&(i=Di.resolve(process.cwd(),i)),hi.isSrcSubdir(o,i)?u(new Error(`Cannot copy '${o}' to a subdirectory of itself, '${i}'.`)):e.isDirectory()&&hi.isSrcSubdir(i,o)?u(new Error(`Cannot overwrite '${i}' with '${o}'.`)):function(e,t,n){di.unlink(t,(r=>r?n(r):di.symlink(e,t,n)))}(o,n,u)))):di.symlink(o,n,u))))}(e,t,n,r,u):void 0))}function Ai(e,t,n,r,u){return"function"==typeof di.copyFile?di.copyFile(t,n,(t=>t?u(t):vi(e,n,r,u))):function(e,t,n,r,u){const o=di.createReadStream(t);o.on("error",(e=>u(e))).once("open",(()=>{const t=di.createWriteStream(n,{mode:e.mode});t.on("error",(e=>u(e))).on("open",(()=>o.pipe(t))).once("close",(()=>vi(e,n,r,u)))}))}(e,t,n,r,u)}function vi(e,t,n,r){di.chmod(t,e.mode,(u=>u?r(u):n.preserveTimestamps?mi(t,e.atime,e.mtime,r):r()))}function Si(e,t,n,r){di.readdir(e,((u,o)=>u?r(u):wi(o,e,t,n,r)))}function wi(e,t,n,r,u){const o=e.pop();return o?function(e,t,n,r,u,o){const i=Di.join(n,t),s=Di.join(r,t);hi.checkPaths(i,s,"copy",((t,c)=>{if(t)return o(t);const{destStat:a}=c;Fi(a,i,s,u,(t=>t?o(t):wi(e,n,r,u,o)))}))}(e,o,t,n,r,u):u()}var Oi=function(e,t,n,r){"function"!=typeof n||r?"function"==typeof n&&(n={filter:n}):(r=n,n={}),r=r||function(){},(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269"),hi.checkPaths(e,t,"copy",((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;hi.checkParentPaths(e,i,t,"copy",(u=>u?r(u):n.filter?Ci(yi,s,e,t,n,r):yi(s,e,t,n,r)))}))};var bi={copy:(0,yo.fromCallback)(Oi)};const _i=we,Bi=p.default,Pi=g.default,ki="win32"===process.platform;function xi(e){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach((t=>{e[t]=e[t]||_i[t],e[t+="Sync"]=e[t]||_i[t]})),e.maxBusyTries=e.maxBusyTries||3}function Ni(e,t,n){let r=0;"function"==typeof t&&(n=t,t={}),Pi(e,"rimraf: missing path"),Pi.strictEqual(typeof e,"string","rimraf: path should be a string"),Pi.strictEqual(typeof n,"function","rimraf: callback function required"),Pi(t,"rimraf: invalid options argument provided"),Pi.strictEqual(typeof t,"object","rimraf: options should be object"),xi(t),Ii(e,t,(function u(o){if(o){if(("EBUSY"===o.code||"ENOTEMPTY"===o.code||"EPERM"===o.code)&&rIi(e,t,u)),100*r)}"ENOENT"===o.code&&(o=null)}n(o)}))}function Ii(e,t,n){Pi(e),Pi(t),Pi("function"==typeof n),t.lstat(e,((r,u)=>r&&"ENOENT"===r.code?n(null):r&&"EPERM"===r.code&&ki?Ti(e,t,r,n):u&&u.isDirectory()?Mi(e,t,r,n):void t.unlink(e,(r=>{if(r){if("ENOENT"===r.code)return n(null);if("EPERM"===r.code)return ki?Ti(e,t,r,n):Mi(e,t,r,n);if("EISDIR"===r.code)return Mi(e,t,r,n)}return n(r)}))))}function Ti(e,t,n,r){Pi(e),Pi(t),Pi("function"==typeof r),n&&Pi(n instanceof Error),t.chmod(e,438,(u=>{u?r("ENOENT"===u.code?null:n):t.stat(e,((u,o)=>{u?r("ENOENT"===u.code?null:n):o.isDirectory()?Mi(e,t,n,r):t.unlink(e,r)}))}))}function Ri(e,t,n){let r;Pi(e),Pi(t),n&&Pi(n instanceof Error);try{t.chmodSync(e,438)}catch(e){if("ENOENT"===e.code)return;throw n}try{r=t.statSync(e)}catch(e){if("ENOENT"===e.code)return;throw n}r.isDirectory()?ji(e,t,n):t.unlinkSync(e)}function Mi(e,t,n,r){Pi(e),Pi(t),n&&Pi(n instanceof Error),Pi("function"==typeof r),t.rmdir(e,(u=>{!u||"ENOTEMPTY"!==u.code&&"EEXIST"!==u.code&&"EPERM"!==u.code?u&&"ENOTDIR"===u.code?r(n):r(u):function(e,t,n){Pi(e),Pi(t),Pi("function"==typeof n),t.readdir(e,((r,u)=>{if(r)return n(r);let o,i=u.length;if(0===i)return t.rmdir(e,n);u.forEach((r=>{Ni(Bi.join(e,r),t,(r=>{if(!o)return r?n(o=r):void(0==--i&&t.rmdir(e,n))}))}))}))}(e,t,r)}))}function Li(e,t){let n;xi(t=t||{}),Pi(e,"rimraf: missing path"),Pi.strictEqual(typeof e,"string","rimraf: path should be a string"),Pi(t,"rimraf: missing options"),Pi.strictEqual(typeof t,"object","rimraf: options should be object");try{n=t.lstatSync(e)}catch(n){if("ENOENT"===n.code)return;"EPERM"===n.code&&ki&&Ri(e,t,n)}try{n&&n.isDirectory()?ji(e,t,null):t.unlinkSync(e)}catch(n){if("ENOENT"===n.code)return;if("EPERM"===n.code)return ki?Ri(e,t,n):ji(e,t,n);if("EISDIR"!==n.code)throw n;ji(e,t,n)}}function ji(e,t,n){Pi(e),Pi(t),n&&Pi(n instanceof Error);try{t.rmdirSync(e)}catch(r){if("ENOTDIR"===r.code)throw n;if("ENOTEMPTY"===r.code||"EEXIST"===r.code||"EPERM"===r.code)!function(e,t){if(Pi(e),Pi(t),t.readdirSync(e).forEach((n=>Li(Bi.join(e,n),t))),!ki){return t.rmdirSync(e,t)}{const n=Date.now();do{try{return t.rmdirSync(e,t)}catch(e){}}while(Date.now()-n<500)}}(e,t);else if("ENOENT"!==r.code)throw r}}var $i=Ni;Ni.sync=Li;const Hi=$i;var Ji={remove:(0,yo.fromCallback)(Hi),removeSync:Hi.sync};const Gi=yo.fromCallback,Vi=we,Ui=p.default,Wi=Io,zi=Ji,Ki=Gi((function(e,t){t=t||function(){},Vi.readdir(e,((n,r)=>{if(n)return Wi.mkdirs(e,t);r=r.map((t=>Ui.join(e,t))),function e(){const n=r.pop();if(!n)return t();zi.remove(n,(n=>{if(n)return t(n);e()}))}()}))}));function qi(e){let t;try{t=Vi.readdirSync(e)}catch(t){return Wi.mkdirsSync(e)}t.forEach((t=>{t=Ui.join(e,t),zi.removeSync(t)}))}var Yi={emptyDirSync:qi,emptydirSync:qi,emptyDir:Ki,emptydir:Ki};const Xi=yo.fromCallback,Zi=p.default,Qi=we,es=Io,ts=fi.pathExists;var ns={createFile:Xi((function(e,t){function n(){Qi.writeFile(e,"",(e=>{if(e)return t(e);t()}))}Qi.stat(e,((r,u)=>{if(!r&&u.isFile())return t();const o=Zi.dirname(e);ts(o,((e,r)=>e?t(e):r?n():void es.mkdirs(o,(e=>{if(e)return t(e);n()}))))}))})),createFileSync:function(e){let t;try{t=Qi.statSync(e)}catch(e){}if(t&&t.isFile())return;const n=Zi.dirname(e);Qi.existsSync(n)||es.mkdirsSync(n),Qi.writeFileSync(e,"")}};const rs=yo.fromCallback,us=p.default,os=we,is=Io,ss=fi.pathExists;var cs={createLink:rs((function(e,t,n){function r(e,t){os.link(e,t,(e=>{if(e)return n(e);n(null)}))}ss(t,((u,o)=>u?n(u):o?n(null):void os.lstat(e,(u=>{if(u)return u.message=u.message.replace("lstat","ensureLink"),n(u);const o=us.dirname(t);ss(o,((u,i)=>u?n(u):i?r(e,t):void is.mkdirs(o,(u=>{if(u)return n(u);r(e,t)}))))}))))})),createLinkSync:function(e,t){if(os.existsSync(t))return;try{os.lstatSync(e)}catch(e){throw e.message=e.message.replace("lstat","ensureLink"),e}const n=us.dirname(t);return os.existsSync(n)||is.mkdirsSync(n),os.linkSync(e,t)}};const as=p.default,ls=we,fs=fi.pathExists;var ds={symlinkPaths:function(e,t,n){if(as.isAbsolute(e))return ls.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:e})));{const r=as.dirname(t),u=as.join(r,e);return fs(u,((t,o)=>t?n(t):o?n(null,{toCwd:u,toDst:e}):ls.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:as.relative(r,e)})))))}},symlinkPathsSync:function(e,t){let n;if(as.isAbsolute(e)){if(n=ls.existsSync(e),!n)throw new Error("absolute srcpath does not exist");return{toCwd:e,toDst:e}}{const r=as.dirname(t),u=as.join(r,e);if(n=ls.existsSync(u),n)return{toCwd:u,toDst:e};if(n=ls.existsSync(e),!n)throw new Error("relative srcpath does not exist");return{toCwd:e,toDst:as.relative(r,e)}}}};const Ds=we;var ps={symlinkType:function(e,t,n){if(n="function"==typeof t?t:n,t="function"!=typeof t&&t)return n(null,t);Ds.lstat(e,((e,r)=>{if(e)return n(null,"file");t=r&&r.isDirectory()?"dir":"file",n(null,t)}))},symlinkTypeSync:function(e,t){let n;if(t)return t;try{n=Ds.lstatSync(e)}catch(e){return"file"}return n&&n.isDirectory()?"dir":"file"}};const Es=yo.fromCallback,ms=p.default,hs=we,ys=Io.mkdirs,Cs=Io.mkdirsSync,Fs=ds.symlinkPaths,gs=ds.symlinkPathsSync,As=ps.symlinkType,vs=ps.symlinkTypeSync,Ss=fi.pathExists;var ws={createSymlink:Es((function(e,t,n,r){r="function"==typeof n?n:r,n="function"!=typeof n&&n,Ss(t,((u,o)=>u?r(u):o?r(null):void Fs(e,t,((u,o)=>{if(u)return r(u);e=o.toDst,As(o.toCwd,n,((n,u)=>{if(n)return r(n);const o=ms.dirname(t);Ss(o,((n,i)=>n?r(n):i?hs.symlink(e,t,u,r):void ys(o,(n=>{if(n)return r(n);hs.symlink(e,t,u,r)}))))}))}))))})),createSymlinkSync:function(e,t,n){if(hs.existsSync(t))return;const r=gs(e,t);e=r.toDst,n=vs(r.toCwd,n);const u=ms.dirname(t);return hs.existsSync(u)||Cs(u),hs.symlinkSync(e,t,n)}};var Os,bs={createFile:ns.createFile,createFileSync:ns.createFileSync,ensureFile:ns.createFile,ensureFileSync:ns.createFileSync,createLink:cs.createLink,createLinkSync:cs.createLinkSync,ensureLink:cs.createLink,ensureLinkSync:cs.createLinkSync,createSymlink:ws.createSymlink,createSymlinkSync:ws.createSymlinkSync,ensureSymlink:ws.createSymlink,ensureSymlinkSync:ws.createSymlinkSync};try{Os=we}catch(e){Os=D.default}function _s(e,t){var n,r="\n";return"object"==typeof t&&null!==t&&(t.spaces&&(n=t.spaces),t.EOL&&(r=t.EOL)),JSON.stringify(e,t?t.replacer:null,n).replace(/\n/g,r)+r}function Bs(e){return Buffer.isBuffer(e)&&(e=e.toString("utf8")),e=e.replace(/^\uFEFF/,"")}var Ps={readFile:function(e,t,n){null==n&&(n=t,t={}),"string"==typeof t&&(t={encoding:t});var r=(t=t||{}).fs||Os,u=!0;"throws"in t&&(u=t.throws),r.readFile(e,t,(function(r,o){if(r)return n(r);var i;o=Bs(o);try{i=JSON.parse(o,t?t.reviver:null)}catch(t){return u?(t.message=e+": "+t.message,n(t)):n(null,null)}n(null,i)}))},readFileSync:function(e,t){"string"==typeof(t=t||{})&&(t={encoding:t});var n=t.fs||Os,r=!0;"throws"in t&&(r=t.throws);try{var u=n.readFileSync(e,t);return u=Bs(u),JSON.parse(u,t.reviver)}catch(t){if(r)throw t.message=e+": "+t.message,t;return null}},writeFile:function(e,t,n,r){null==r&&(r=n,n={});var u=(n=n||{}).fs||Os,o="";try{o=_s(t,n)}catch(e){return void(r&&r(e,null))}u.writeFile(e,o,n,r)},writeFileSync:function(e,t,n){var r=(n=n||{}).fs||Os,u=_s(t,n);return r.writeFileSync(e,u,n)}},ks=Ps;const xs=yo.fromCallback,Ns=ks;var Is={readJson:xs(Ns.readFile),readJsonSync:Ns.readFileSync,writeJson:xs(Ns.writeFile),writeJsonSync:Ns.writeFileSync};const Ts=p.default,Rs=Io,Ms=fi.pathExists,Ls=Is;var js=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=Ts.dirname(e);Ms(u,((o,i)=>o?r(o):i?Ls.writeJson(e,t,n,r):void Rs.mkdirs(u,(u=>{if(u)return r(u);Ls.writeJson(e,t,n,r)}))))};const $s=we,Hs=p.default,Js=Io,Gs=Is;var Vs=function(e,t,n){const r=Hs.dirname(e);$s.existsSync(r)||Js.mkdirsSync(r),Gs.writeJsonSync(e,t,n)};const Us=yo.fromCallback,Ws=Is;Ws.outputJson=Us(js),Ws.outputJsonSync=Vs,Ws.outputJSON=Ws.outputJson,Ws.outputJSONSync=Ws.outputJsonSync,Ws.writeJSON=Ws.writeJson,Ws.writeJSONSync=Ws.writeJsonSync,Ws.readJSON=Ws.readJson,Ws.readJSONSync=Ws.readJsonSync;var zs=Ws;const Ks=we,qs=p.default,Ys=ci.copySync,Xs=Ji.removeSync,Zs=Io.mkdirpSync,Qs=Zo;function ec(e,t,n){try{Ks.renameSync(e,t)}catch(r){if("EXDEV"!==r.code)throw r;return function(e,t,n){const r={overwrite:n,errorOnExist:!0};return Ys(e,t,r),Xs(e)}(e,t,n)}}var tc=function(e,t,n){const r=(n=n||{}).overwrite||n.clobber||!1,{srcStat:u}=Qs.checkPathsSync(e,t,"move");return Qs.checkParentPathsSync(e,u,t,"move"),Zs(qs.dirname(t)),function(e,t,n){if(n)return Xs(t),ec(e,t,n);if(Ks.existsSync(t))throw new Error("dest already exists.");return ec(e,t,n)}(e,t,r)},nc={moveSync:tc};const rc=we,uc=p.default,oc=bi.copy,ic=Ji.remove,sc=Io.mkdirp,cc=fi.pathExists,ac=Zo;function lc(e,t,n,r){rc.rename(e,t,(u=>u?"EXDEV"!==u.code?r(u):function(e,t,n,r){const u={overwrite:n,errorOnExist:!0};oc(e,t,u,(t=>t?r(t):ic(e,r)))}(e,t,n,r):r()))}var fc=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=n.overwrite||n.clobber||!1;ac.checkPaths(e,t,"move",((n,o)=>{if(n)return r(n);const{srcStat:i}=o;ac.checkParentPaths(e,i,t,"move",(n=>{if(n)return r(n);sc(uc.dirname(t),(n=>n?r(n):function(e,t,n,r){if(n)return ic(t,(u=>u?r(u):lc(e,t,n,r)));cc(t,((u,o)=>u?r(u):o?r(new Error("dest already exists.")):lc(e,t,n,r)))}(e,t,u,r)))}))}))};var dc={move:(0,yo.fromCallback)(fc)};const Dc=yo.fromCallback,pc=we,Ec=p.default,mc=Io,hc=fi.pathExists;var yc={outputFile:Dc((function(e,t,n,r){"function"==typeof n&&(r=n,n="utf8");const u=Ec.dirname(e);hc(u,((o,i)=>o?r(o):i?pc.writeFile(e,t,n,r):void mc.mkdirs(u,(u=>{if(u)return r(u);pc.writeFile(e,t,n,r)}))))})),outputFileSync:function(e,...t){const n=Ec.dirname(e);if(pc.existsSync(n))return pc.writeFileSync(e,...t);mc.mkdirsSync(n),pc.writeFileSync(e,...t)}};!function(e){e.exports=Object.assign({},ho,ci,bi,Yi,bs,zs,Io,nc,dc,yc,fi,Ji);const t=D.default;Object.getOwnPropertyDescriptor(t,"promises")&&Object.defineProperty(e.exports,"promises",{get:()=>t.promises})}(mo);const Cc=Nr.exports("streamroller:fileNameFormatter"),Fc=p.default;const gc=Nr.exports("streamroller:fileNameParser"),Ac=nu.exports;const vc=Nr.exports("streamroller:moveAndMaybeCompressFile"),Sc=mo.exports,wc=v.default;var Oc=async(e,t,n)=>{if(n=function(e){const t={mode:parseInt("0600",8),compress:!1},n=Object.assign({},t,e);return vc(`_parseOption: moveAndMaybeCompressFile called with option=${JSON.stringify(n)}`),n}(n),e!==t){if(await Sc.pathExists(e))if(vc(`moveAndMaybeCompressFile: moving file from ${e} to ${t} ${n.compress?"with":"without"} compress`),n.compress)await new Promise(((r,u)=>{let o=!1;const i=Sc.createWriteStream(t,{mode:n.mode,flags:"wx"}).on("open",(()=>{o=!0;const t=Sc.createReadStream(e).on("open",(()=>{t.pipe(wc.createGzip()).pipe(i)})).on("error",(t=>{vc(`moveAndMaybeCompressFile: error reading ${e}`,t),i.destroy(t)}))})).on("finish",(()=>{vc(`moveAndMaybeCompressFile: finished compressing ${t}, deleting ${e}`),Sc.unlink(e).then(r).catch((t=>{vc(`moveAndMaybeCompressFile: error deleting ${e}, truncating instead`,t),Sc.truncate(e).then(r).catch((t=>{vc(`moveAndMaybeCompressFile: error truncating ${e}`,t),u(t)}))}))})).on("error",(e=>{o?(vc(`moveAndMaybeCompressFile: error writing ${t}, deleting`,e),Sc.unlink(t).then((()=>{u(e)})).catch((e=>{vc(`moveAndMaybeCompressFile: error deleting ${t}`,e),u(e)}))):(vc(`moveAndMaybeCompressFile: error creating ${t}`,e),u(e))}))})).catch((()=>{}));else{vc(`moveAndMaybeCompressFile: renaming ${e} to ${t}`);try{await Sc.move(e,t,{overwrite:!0})}catch(n){if(vc(`moveAndMaybeCompressFile: error renaming ${e} to ${t}`,n),"ENOENT"!==n.code){vc("moveAndMaybeCompressFile: trying copy+truncate instead");try{await Sc.copy(e,t,{overwrite:!0}),await Sc.truncate(e)}catch(e){vc("moveAndMaybeCompressFile: error copy+truncate",e)}}}}}else vc("moveAndMaybeCompressFile: source and target are the same, not doing anything")};const bc=Nr.exports("streamroller:RollingFileWriteStream"),_c=mo.exports,Bc=p.default,Pc=E.default,kc=()=>new Date,xc=nu.exports,{Writable:Nc}=C.default,Ic=({file:e,keepFileExt:t,needsIndex:n,alwaysIncludeDate:r,compress:u,fileNameSep:o})=>{let i=o||".";const s=Fc.join(e.dir,e.name),c=t=>t+e.ext,a=(e,t,r)=>!n&&r||!t?e:e+i+t,l=(e,t,n)=>(t>0||r)&&n?e+i+n:e,f=(e,t)=>t&&u?e+".gz":e,d=t?[l,a,c,f]:[c,l,a,f];return({date:e,index:t})=>(Cc(`_formatFileName: date=${e}, index=${t}`),d.reduce(((n,r)=>r(n,t,e)),s))},Tc=({file:e,keepFileExt:t,pattern:n,fileNameSep:r})=>{let u=r||".";const o="__NOT_MATCHING__";let i=[(e,t)=>e.endsWith(".gz")?(gc("it is gzipped"),t.isCompressed=!0,e.slice(0,-1*".gz".length)):e,t?t=>t.startsWith(e.name)&&t.endsWith(e.ext)?(gc("it starts and ends with the right things"),t.slice(e.name.length+1,-1*e.ext.length)):o:t=>t.startsWith(e.base)?(gc("it starts with the right things"),t.slice(e.base.length+1)):o,n?(e,t)=>{const r=e.split(u);let o=r[r.length-1];gc("items: ",r,", indexStr: ",o);let i=e;void 0!==o&&o.match(/^\d+$/)?(i=e.slice(0,-1*(o.length+1)),gc(`dateStr is ${i}`),n&&!i&&(i=o,o="0")):o="0";try{const r=Ac.parse(n,i,new Date(0,0));return Ac.asString(n,r)!==i?e:(t.index=parseInt(o,10),t.date=i,t.timestamp=r.getTime(),"")}catch(t){return gc(`Problem parsing ${i} as ${n}, error was: `,t),e}}:(e,t)=>e.match(/^\d+$/)?(gc("it has an index"),t.index=parseInt(e,10),""):e];return e=>{let t={filename:e,index:0,isCompressed:!1};return i.reduce(((e,n)=>n(e,t)),e)?null:t}},Rc=Oc;var Mc=class extends Nc{constructor(e,t){if(bc(`constructor: creating RollingFileWriteStream. path=${e}`),"string"!=typeof e||0===e.length)throw new Error(`Invalid filename: ${e}`);if(e.endsWith(Bc.sep))throw new Error(`Filename is a directory: ${e}`);0===e.indexOf(`~${Bc.sep}`)&&(e=e.replace("~",Pc.homedir())),super(t),this.options=this._parseOption(t),this.fileObject=Bc.parse(e),""===this.fileObject.dir&&(this.fileObject=Bc.parse(Bc.join(process.cwd(),e))),this.fileFormatter=Ic({file:this.fileObject,alwaysIncludeDate:this.options.alwaysIncludePattern,needsIndex:this.options.maxSize 0`)}else delete n.maxSize;if(n.numBackups||0===n.numBackups){if(n.numBackups<0)throw new Error(`options.numBackups (${n.numBackups}) should be >= 0`);if(n.numBackups>=Number.MAX_SAFE_INTEGER)throw new Error(`options.numBackups (${n.numBackups}) should be < Number.MAX_SAFE_INTEGER`);n.numToKeep=n.numBackups+1}else if(n.numToKeep<=0)throw new Error(`options.numToKeep (${n.numToKeep}) should be > 0`);return bc(`_parseOption: creating stream with option=${JSON.stringify(n)}`),n}_final(e){this.currentFileStream.end("",this.options.encoding,e)}_write(e,t,n){this._shouldRoll().then((()=>{bc(`_write: writing chunk. file=${this.currentFileStream.path} state=${JSON.stringify(this.state)} chunk=${e}`),this.currentFileStream.write(e,t,(t=>{this.state.currentSize+=e.length,n(t)}))}))}async _shouldRoll(){(this._dateChanged()||this._tooBig())&&(bc(`_shouldRoll: rolling because dateChanged? ${this._dateChanged()} or tooBig? ${this._tooBig()}`),await this._roll())}_dateChanged(){return this.state.currentDate&&this.state.currentDate!==xc(this.options.pattern,kc())}_tooBig(){return this.state.currentSize>=this.options.maxSize}_roll(){return bc("_roll: closing the current stream"),new Promise(((e,t)=>{this.currentFileStream.end("",this.options.encoding,(()=>{this._moveOldFiles().then(e).catch(t)}))}))}async _moveOldFiles(){const e=await this._getExistingFiles();for(let t=(this.state.currentDate?e.filter((e=>e.date===this.state.currentDate)):e).length;t>=0;t--){bc(`_moveOldFiles: i = ${t}`);const e=this.fileFormatter({date:this.state.currentDate,index:t}),n=this.fileFormatter({date:this.state.currentDate,index:t+1}),r={compress:this.options.compress&&0===t,mode:this.options.mode};await Rc(e,n,r)}this.state.currentSize=0,this.state.currentDate=this.state.currentDate?xc(this.options.pattern,kc()):null,bc(`_moveOldFiles: finished rolling files. state=${JSON.stringify(this.state)}`),this._renewWriteStream(),await new Promise(((e,t)=>{this.currentFileStream.write("","utf8",(()=>{this._clean().then(e).catch(t)}))}))}async _getExistingFiles(){const e=await _c.readdir(this.fileObject.dir).catch((()=>[]));bc(`_getExistingFiles: files=${e}`);const t=e.map((e=>this.fileNameParser(e))).filter((e=>e)),n=e=>(e.timestamp?e.timestamp:kc().getTime())-e.index;return t.sort(((e,t)=>n(e)-n(t))),t}_renewWriteStream(){const e=this.fileFormatter({date:this.state.currentDate,index:0}),t=e=>{try{return _c.mkdirSync(e,{recursive:!0})}catch(n){if("ENOENT"===n.code)return t(Bc.dirname(e)),t(e);if("EEXIST"!==n.code&&"EROFS"!==n.code)throw n;try{if(_c.statSync(e).isDirectory())return e;throw n}catch(e){throw n}}};t(this.fileObject.dir);const n={flags:this.options.flags,encoding:this.options.encoding,mode:this.options.mode};var r,u;_c.appendFileSync(e,"",(r={...n},u="flags",r["flag"]=r[u],delete r[u],r)),this.currentFileStream=_c.createWriteStream(e,n),this.currentFileStream.on("error",(e=>{this.emit("error",e)}))}async _clean(){const e=await this._getExistingFiles();if(bc(`_clean: numToKeep = ${this.options.numToKeep}, existingFiles = ${e.length}`),bc("_clean: existing files are: ",e),this._tooManyFiles(e.length)){const n=e.slice(0,e.length-this.options.numToKeep).map((e=>Bc.format({dir:this.fileObject.dir,base:e.filename})));await(t=n,bc(`deleteFiles: files to delete: ${t}`),Promise.all(t.map((e=>_c.unlink(e).catch((t=>{bc(`deleteFiles: error when unlinking ${e}, ignoring. Error was ${t}`)}))))))}var t}_tooManyFiles(e){return this.options.numToKeep>0&&e>this.options.numToKeep}};const Lc=Mc;var jc=class extends Lc{constructor(e,t,n,r){r||(r={}),t&&(r.maxSize=t),r.numBackups||0===r.numBackups||(n||0===n||(n=1),r.numBackups=n),super(e,r),this.backups=r.numBackups,this.size=this.options.maxSize}get theStream(){return this.currentFileStream}};const $c=Mc;var Hc={RollingFileWriteStream:Mc,RollingFileStream:jc,DateRollingFileStream:class extends $c{constructor(e,t,n){t&&"object"==typeof t&&(n=t,t=null),n||(n={}),t||(t="yyyy-MM-dd"),n.pattern=t,n.numBackups||0===n.numBackups?n.daysToKeep=n.numBackups:(n.daysToKeep||0===n.daysToKeep?process.emitWarning("options.daysToKeep is deprecated due to the confusion it causes when used together with file size rolling. Please use options.numBackups instead.","DeprecationWarning","streamroller-DEP0001"):n.daysToKeep=1,n.numBackups=n.daysToKeep),super(e,n),this.mode=this.options.mode}get theStream(){return this.currentFileStream}}};const Jc=Nr.exports("log4js:file"),Gc=p.default,Vc=Hc,Uc=E.default.EOL;let Wc=!1;const zc=new Set;function Kc(){zc.forEach((e=>{e.sighupHandler()}))}function qc(e,t,n,r){const u=new Vc.RollingFileStream(e,t,n,r);return u.on("error",(t=>{console.error("log4js.fileAppender - Writing to file %s, error happened ",e,t)})),u.on("drain",(()=>{process.emit("log4js:pause",!1)})),u}Eo.configure=function(e,t){let n=t.basicLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),e.mode=e.mode||384,function(e,t,n,r,u,o){e=Gc.normalize(e),Jc("Creating file appender (",e,", ",n,", ",r=r||0===r?r:5,", ",u,", ",o,")");let i=qc(e,n,r,u);const s=function(e){if(i.writable){if(!0===u.removeColor){const t=/\x1b[[0-9;]*m/g;e.data=e.data.map((e=>"string"==typeof e?e.replace(t,""):e))}i.write(t(e,o)+Uc,"utf8")||process.emit("log4js:pause",!0)}};return s.reopen=function(){i.end((()=>{i=qc(e,n,r,u)}))},s.sighupHandler=function(){Jc("SIGHUP handler called."),s.reopen()},s.shutdown=function(e){zc.delete(s),0===zc.size&&Wc&&(process.removeListener("SIGHUP",Kc),Wc=!1),i.end("","utf-8",e)},zc.add(s),Wc||(process.on("SIGHUP",Kc),Wc=!0),s}(e.filename,n,e.maxLogSize,e.backups,e,e.timezoneOffset)};var Yc={};const Xc=Hc,Zc=E.default.EOL;function Qc(e,t,n,r,u){r.maxSize=r.maxLogSize;const o=function(e,t,n){const r=new Xc.DateRollingFileStream(e,t,n);return r.on("error",(t=>{console.error("log4js.dateFileAppender - Writing to file %s, error happened ",e,t)})),r.on("drain",(()=>{process.emit("log4js:pause",!1)})),r}(e,t,r),i=function(e){o.writable&&(o.write(n(e,u)+Zc,"utf8")||process.emit("log4js:pause",!0))};return i.shutdown=function(e){o.end("","utf-8",e)},i}Yc.configure=function(e,t){let n=t.basicLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),e.alwaysIncludePattern||(e.alwaysIncludePattern=!1),e.mode=e.mode||384,Qc(e.filename,e.pattern,n,e,e.timezoneOffset)};var ea={};const ta=Nr.exports("log4js:fileSync"),na=p.default,ra=D.default,ua=E.default.EOL||"\n";function oa(e,t){if(ra.existsSync(e))return;const n=ra.openSync(e,t.flags,t.mode);ra.closeSync(n)}class ia{constructor(e,t,n,r){ta("In RollingFileStream"),function(){if(!e||!t||t<=0)throw new Error("You must specify a filename and file size")}(),this.filename=e,this.size=t,this.backups=n,this.options=r,this.currentSize=0,this.currentSize=function(e){let t=0;try{t=ra.statSync(e).size}catch(t){oa(e,r)}return t}(this.filename)}shouldRoll(){return ta("should roll with current size %d, and max size %d",this.currentSize,this.size),this.currentSize>=this.size}roll(e){const t=this,n=new RegExp(`^${na.basename(e)}`);function r(e){return n.test(e)}function u(t){return parseInt(t.substring(`${na.basename(e)}.`.length),10)||0}function o(e,t){return u(e)>u(t)?1:u(e) ${e}.${r+1}`),ra.renameSync(na.join(na.dirname(e),n),`${e}.${r+1}`)}}ta("Rolling, rolling, rolling"),ta("Renaming the old files"),ra.readdirSync(na.dirname(e)).filter(r).sort(o).reverse().forEach(i)}write(e,t){const n=this;ta("in write"),this.shouldRoll()&&(this.currentSize=0,this.roll(this.filename)),ta("writing the chunk to the file"),n.currentSize+=e.length,ra.appendFileSync(n.filename,e)}}ea.configure=function(e,t){let n=t.basicLayout;e.layout&&(n=t.layout(e.layout.type,e.layout));const r={flags:e.flags||"a",encoding:e.encoding||"utf8",mode:e.mode||384};return function(e,t,n,r,u,o){ta("fileSync appender created");const i=function(e,t,n){let r;var u;return t?r=new ia(e,t,n,o):(oa(u=e,o),r={write(e){ra.appendFileSync(u,e)}}),r}(e=na.normalize(e),n,r=r||0===r?r:5);return e=>{i.write(t(e,u)+ua)}}(e.filename,n,e.maxLogSize,e.backups,e.timezoneOffset,r)};var sa={};const ca=Nr.exports("log4js:tcp"),aa=S.default;sa.configure=function(e,t){ca(`configure with config = ${e}`);let n=function(e){return e.serialise()};return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){let n=!1;const r=[];let u,o=3,i="__LOG4JS__";function s(e){ca("Writing log event to socket"),n=u.write(`${t(e)}${i}`,"utf8")}function c(){let e;for(ca("emptying buffer");e=r.shift();)s(e)}function a(e){n?s(e):(ca("buffering log event because it cannot write at the moment"),r.push(e))}return function t(){ca(`appender creating socket to ${e.host||"localhost"}:${e.port||5e3}`),i=`${e.endMsg||"__LOG4JS__"}`,u=aa.createConnection(e.port||5e3,e.host||"localhost"),u.on("connect",(()=>{ca("socket connected"),c(),n=!0})),u.on("drain",(()=>{ca("drain event received, emptying buffer"),n=!0,c()})),u.on("timeout",u.end.bind(u)),u.on("error",(e=>{ca("connection error",e),n=!1,c()})),u.on("close",t)}(),a.shutdown=function(e){ca("shutdown called"),r.length&&o?(ca("buffer has items, waiting 100ms to empty"),o-=1,setTimeout((()=>{a.shutdown(e)}),100)):(u.removeAllListeners("close"),u.end(e))},a}(e,n)};const la=p.default,fa=Nr.exports("log4js:appenders"),da=tu,Da=eo,pa=gu,Ea=hu,ma=to,ha=new Map;ha.set("console",oo),ha.set("stdout",so),ha.set("stderr",co),ha.set("logLevelFilter",ao),ha.set("categoryFilter",lo),ha.set("noLogFilter",Do),ha.set("file",Eo),ha.set("dateFile",Yc),ha.set("fileSync",ea),ha.set("tcp",sa);const ya=new Map,Ca=(e,t)=>{fa("Loading module from ",e);try{return require(e)}catch(n){return void da.throwExceptionIf(t,"MODULE_NOT_FOUND"!==n.code,`appender "${e}" could not be loaded (error was: ${n})`)}},Fa=new Set,ga=(e,t)=>{if(ya.has(e))return ya.get(e);if(!t.appenders[e])return!1;if(Fa.has(e))throw new Error(`Dependency loop detected for appender ${e}.`);Fa.add(e),fa(`Creating appender ${e}`);const n=Aa(e,t);return Fa.delete(e),ya.set(e,n),n},Aa=(e,t)=>{const n=t.appenders[e],r=n.type.configure?n.type:((e,t)=>ha.get(e)||Ca(`./${e}`,t)||Ca(e,t)||require.main&&Ca(la.join(la.dirname(require.main.filename),e),t)||Ca(la.join(process.cwd(),e),t))(n.type,t);return da.throwExceptionIf(t,da.not(r),`appender "${e}" is not valid (type "${n.type}" could not be found)`),r.appender&&fa(`DEPRECATION: Appender ${n.type} exports an appender function.`),r.shutdown&&fa(`DEPRECATION: Appender ${n.type} exports a shutdown function.`),fa(`${e}: clustering.isMaster ? ${Da.isMaster()}`),fa(`${e}: appenderModule is ${F.default.inspect(r)}`),Da.onlyOnMaster((()=>(fa(`calling appenderModule.configure for ${e} / ${n.type}`),r.configure(ma.modifyConfig(n),Ea,(e=>ga(e,t)),pa))),(()=>{}))},va=e=>{ya.clear(),Fa.clear();const t=[];Object.values(e.categories).forEach((e=>{t.push(...e.appenders)})),Object.keys(e.appenders).forEach((n=>{(t.includes(n)||"tcp-server"===e.appenders[n].type)&&ga(n,e)}))},Sa=()=>{va({appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"trace"}}})};Sa(),da.addListener((e=>{da.throwExceptionIf(e,da.not(da.anObject(e.appenders)),'must have a property "appenders" of type object.');const t=Object.keys(e.appenders);da.throwExceptionIf(e,da.not(t.length),"must define at least one appender."),t.forEach((t=>{da.throwExceptionIf(e,da.not(e.appenders[t].type),`appender "${t}" is not valid (must be an object with property "type")`)}))})),da.addListener(va),Au.exports=ya,Au.exports.init=Sa;var wa={exports:{}};!function(e){const t=Nr.exports("log4js:categories"),n=tu,r=gu,u=Au.exports,o=new Map;function i(e,t,n){if(!1===t.inherit)return;const r=n.lastIndexOf(".");if(r<0)return;const u=n.substring(0,r);let o=e.categories[u];o||(o={inherit:!0,appenders:[]}),i(e,o,u),!e.categories[u]&&o.appenders&&o.appenders.length&&o.level&&(e.categories[u]=o),t.appenders=t.appenders||[],t.level=t.level||o.level,o.appenders.forEach((e=>{t.appenders.includes(e)||t.appenders.push(e)})),t.parent=o}function s(e){if(!e.categories)return;Object.keys(e.categories).forEach((t=>{const n=e.categories[t];i(e,n,t)}))}n.addPreProcessingListener((e=>s(e))),n.addListener((e=>{n.throwExceptionIf(e,n.not(n.anObject(e.categories)),'must have a property "categories" of type object.');const t=Object.keys(e.categories);n.throwExceptionIf(e,n.not(t.length),"must define at least one category."),t.forEach((t=>{const o=e.categories[t];n.throwExceptionIf(e,[n.not(o.appenders),n.not(o.level)],`category "${t}" is not valid (must be an object with properties "appenders" and "level")`),n.throwExceptionIf(e,n.not(Array.isArray(o.appenders)),`category "${t}" is not valid (appenders must be an array of appender names)`),n.throwExceptionIf(e,n.not(o.appenders.length),`category "${t}" is not valid (appenders must contain at least one appender name)`),Object.prototype.hasOwnProperty.call(o,"enableCallStack")&&n.throwExceptionIf(e,"boolean"!=typeof o.enableCallStack,`category "${t}" is not valid (enableCallStack must be boolean type)`),o.appenders.forEach((r=>{n.throwExceptionIf(e,n.not(u.get(r)),`category "${t}" is not valid (appender "${r}" is not defined)`)})),n.throwExceptionIf(e,n.not(r.getLevel(o.level)),`category "${t}" is not valid (level "${o.level}" not recognised; valid levels are ${r.levels.join(", ")})`)})),n.throwExceptionIf(e,n.not(e.categories.default),'must define a "default" category.')}));const c=e=>{o.clear();Object.keys(e.categories).forEach((n=>{const i=e.categories[n],s=[];i.appenders.forEach((e=>{s.push(u.get(e)),t(`Creating category ${n}`),o.set(n,{appenders:s,level:r.getLevel(i.level),enableCallStack:i.enableCallStack||!1})}))}))},a=()=>{c({categories:{default:{appenders:["out"],level:"OFF"}}})};a(),n.addListener(c);const l=e=>(t(`configForCategory: searching for config for ${e}`),o.has(e)?(t(`configForCategory: ${e} exists in config, returning it`),o.get(e)):e.indexOf(".")>0?(t(`configForCategory: ${e} has hierarchy, searching for parents`),l(e.substring(0,e.lastIndexOf(".")))):(t("configForCategory: returning config for default category"),l("default")));e.exports=o,e.exports=Object.assign(e.exports,{appendersForCategory:e=>l(e).appenders,getLevelForCategory:e=>l(e).level,setLevelForCategory:(e,n)=>{let r=o.get(e);if(t(`setLevelForCategory: found ${r} for ${e}`),!r){const n=l(e);t(`setLevelForCategory: no config found for category, found ${n} for parents of ${e}`),r={appenders:n.appenders}}r.level=n,o.set(e,r)},getEnableCallStackForCategory:e=>!0===l(e).enableCallStack,setEnableCallStackForCategory:(e,t)=>{l(e).enableCallStack=t},init:a})}(wa);const Oa=Nr.exports("log4js:logger"),ba=Hu,_a=gu,Ba=eo,Pa=wa.exports,ka=tu,xa=/at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;function Na(e,t=4){const n=e.stack.split("\n").slice(t),r=xa.exec(n[0]);return r&&6===r.length?{functionName:r[1],fileName:r[2],lineNumber:parseInt(r[3],10),columnNumber:parseInt(r[4],10),callStack:n.join("\n")}:null}class Ia{constructor(e){if(!e)throw new Error("No category provided.");this.category=e,this.context={},this.parseCallStack=Na,Oa(`Logger created (${this.category}, ${this.level})`)}get level(){return _a.getLevel(Pa.getLevelForCategory(this.category),_a.TRACE)}set level(e){Pa.setLevelForCategory(this.category,_a.getLevel(e,this.level))}get useCallStack(){return Pa.getEnableCallStackForCategory(this.category)}set useCallStack(e){Pa.setEnableCallStackForCategory(this.category,!0===e)}log(e,...t){let n=_a.getLevel(e);n||(this._log(_a.WARN,"log4js:logger.log: invalid value for log-level as first parameter given: ",e),n=_a.INFO),this.isLevelEnabled(n)&&this._log(n,t)}isLevelEnabled(e){return this.level.isLessThanOrEqualTo(e)}_log(e,t){Oa(`sending log data (${e}) to appenders`);const n=new ba(this.category,e,t,this.context,this.useCallStack&&this.parseCallStack(new Error));Ba.send(n)}addContext(e,t){this.context[e]=t}removeContext(e){delete this.context[e]}clearContext(){this.context={}}setParseCallStackFunction(e){this.parseCallStack=e}}function Ta(e){const t=_a.getLevel(e),n=t.toString().toLowerCase().replace(/_([a-z])/g,(e=>e[1].toUpperCase())),r=n[0].toUpperCase()+n.slice(1);Ia.prototype[`is${r}Enabled`]=function(){return this.isLevelEnabled(t)},Ia.prototype[n]=function(...e){this.log(t,...e)}}_a.levels.forEach(Ta),ka.addListener((()=>{_a.levels.forEach(Ta)}));var Ra=Ia;const Ma=gu;function La(e){return e.originalUrl||e.url}function ja(e,t){for(let n=0;ne.source?e.source:e));t=new RegExp(n.join("|"))}return t}(t.nolog);return(e,i,s)=>{if(e._logging)return s();if(o&&o.test(e.originalUrl))return s();if(n.isLevelEnabled(r)||"auto"===t.level){const o=new Date,{writeHead:s}=i;e._logging=!0,i.writeHead=(e,t)=>{i.writeHead=s,i.writeHead(e,t),i.__statusCode=e,i.__headers=t||{}},i.on("finish",(()=>{i.responseTime=new Date-o,i.statusCode&&"auto"===t.level&&(r=Ma.INFO,i.statusCode>=300&&(r=Ma.WARN),i.statusCode>=400&&(r=Ma.ERROR)),r=function(e,t,n){let r=t;if(n){const t=n.find((t=>{let n=!1;return n=t.from&&t.to?e>=t.from&&e<=t.to:-1!==t.codes.indexOf(e),n}));t&&(r=Ma.getLevel(t.level,r))}return r}(i.statusCode,r,t.statusRules);const s=function(e,t,n){const r=[];return r.push({token:":url",replacement:La(e)}),r.push({token:":protocol",replacement:e.protocol}),r.push({token:":hostname",replacement:e.hostname}),r.push({token:":method",replacement:e.method}),r.push({token:":status",replacement:t.__statusCode||t.statusCode}),r.push({token:":response-time",replacement:t.responseTime}),r.push({token:":date",replacement:(new Date).toUTCString()}),r.push({token:":referrer",replacement:e.headers.referer||e.headers.referrer||""}),r.push({token:":http-version",replacement:`${e.httpVersionMajor}.${e.httpVersionMinor}`}),r.push({token:":remote-addr",replacement:e.headers["x-forwarded-for"]||e.ip||e._remoteAddress||e.socket&&(e.socket.remoteAddress||e.socket.socket&&e.socket.socket.remoteAddress)}),r.push({token:":user-agent",replacement:e.headers["user-agent"]}),r.push({token:":content-length",replacement:t.getHeader("content-length")||t.__headers&&t.__headers["Content-Length"]||"-"}),r.push({token:/:req\[([^\]]+)]/g,replacement:(t,n)=>e.headers[n.toLowerCase()]}),r.push({token:/:res\[([^\]]+)]/g,replacement:(e,n)=>t.getHeader(n.toLowerCase())||t.__headers&&t.__headers[n]}),(e=>{const t=e.concat();for(let e=0;eja(e,s)));t&&n.log(r,t)}else n.log(r,ja(u,s));t.context&&n.removeContext("res")}))}return s()}},nl=Va;let rl=!1;function ul(e){if(!rl)return;Ua("Received log event ",e);Za.appendersForCategory(e.categoryName).forEach((t=>{t(e)}))}function ol(e){rl&&il();let t=e;return"string"==typeof t&&(t=function(e){Ua(`Loading configuration from ${e}`);try{return JSON.parse(Wa.readFileSync(e,"utf8"))}catch(t){throw new Error(`Problem reading config from file "${e}". Error was ${t.message}`,t)}}(e)),Ua(`Configuration is ${t}`),Ka.configure(za(t)),el.onMessage(ul),rl=!0,sl}function il(e){Ua("Shutdown called. Disabling all log writing."),rl=!1;const t=Array.from(Xa.values());Xa.init(),Za.init();const n=t.reduceRight(((e,t)=>t.shutdown?e+1:e),0);if(0===n)return Ua("No appenders with shutdown functions found."),void 0!==e&&e();let r,u=0;function o(t){r=r||t,u+=1,Ua(`Appender shutdowns complete: ${u} / ${n}`),u>=n&&(Ua("All shutdown functions completed."),e&&e(r))}return Ua(`Found ${n} appenders with shutdown functions.`),t.filter((e=>e.shutdown)).forEach((e=>e.shutdown(o))),null}const sl={getLogger:function(e){return rl||ol(process.env.LOG4JS_CONFIG||{appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"OFF"}}}),new Qa(e||"default")},configure:ol,shutdown:il,connectLogger:tl,levels:Ya,addLayout:qa.addLayout,recording:function(){return nl}};var cl=sl,al={};Object.defineProperty(al,"__esModule",{value:!0}),al.levelMap=al.getLevel=al.setCategoriesLevel=al.getConfiguration=al.setConfiguration=void 0;const ll=cl;let fl={appenders:{debug:{type:"stdout",layout:{type:"pattern",pattern:"[%d] > hvigor %p %c %[%m%]"}},info:{type:"stdout",layout:{type:"pattern",pattern:"[%d] > hvigor %[%m%]"}},"no-pattern-info":{type:"stdout",layout:{type:"pattern",pattern:"%m"}},wrong:{type:"stderr",layout:{type:"pattern",pattern:"[%d] > hvigor %[%p: %m%]"}},"just-debug":{type:"logLevelFilter",appender:"debug",level:"debug",maxLevel:"debug"},"just-info":{type:"logLevelFilter",appender:"info",level:"info",maxLevel:"info"},"just-wrong":{type:"logLevelFilter",appender:"wrong",level:"warn",maxLevel:"error"}},categories:{default:{appenders:["just-debug","just-info","just-wrong"],level:"debug"},"no-pattern-info":{appenders:["no-pattern-info"],level:"info"}}};al.setConfiguration=e=>{fl=e};al.getConfiguration=()=>fl;let dl=ll.levels.DEBUG;al.setCategoriesLevel=(e,t)=>{dl=e;const n=fl.categories;for(const r in n)(null==t?void 0:t.includes(r))||Object.prototype.hasOwnProperty.call(n,r)&&(n[r].level=e.levelStr)};al.getLevel=()=>dl,al.levelMap=new Map([["ALL",ll.levels.ALL],["MARK",ll.levels.MARK],["TRACE",ll.levels.TRACE],["DEBUG",ll.levels.DEBUG],["INFO",ll.levels.INFO],["WARN",ll.levels.WARN],["ERROR",ll.levels.ERROR],["FATAL",ll.levels.FATAL],["OFF",ll.levels.OFF]]);var Dl=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),pl=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),El=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&Dl(t,e,n);return pl(t,e),t};Object.defineProperty(xr,"__esModule",{value:!0}),xr.evaluateLogLevel=xr.HvigorLogger=void 0;const ml=El(cl),hl=cl,yl=El(F.default),Cl=al;class Fl{constructor(e){ml.configure((0,Cl.getConfiguration)()),this._logger=ml.getLogger(e),this._logger.level=(0,Cl.getLevel)()}static getLogger(e){return new Fl(e)}log(e,...t){this._logger.log(e,...t)}debug(e,...t){this._logger.debug(e,...t)}info(e,...t){this._logger.info(e,...t)}warn(e,...t){void 0!==e&&""!==e&&this._logger.warn(e,...t)}error(e,...t){this._logger.error(e,...t)}_printTaskExecuteInfo(e,t){this.info(`Finished :${e}... after ${t}`)}_printFailedTaskInfo(e){this.error(`Failed :${e}... `)}_printDisabledTaskInfo(e){this.info(`Disabled :${e}... `)}_printUpToDateTaskInfo(e){this.info(`UP-TO-DATE :${e}... `)}errorMessageExit(e,...t){throw new Error(yl.format(e,...t))}errorExit(e,t,...n){t&&this._logger.error(t,n),this._logger.error(e.stack)}setLevel(e,t){(0,Cl.setCategoriesLevel)(e,t),ml.shutdown(),ml.configure((0,Cl.getConfiguration)())}getLevel(){return this._logger.level}configure(e){const t=(0,Cl.getConfiguration)(),n={appenders:{...t.appenders,...e.appenders},categories:{...t.categories,...e.categories}};(0,Cl.setConfiguration)(n),ml.shutdown(),ml.configure(n)}}xr.HvigorLogger=Fl,xr.evaluateLogLevel=function(e,t){t.debug?e.setLevel(hl.levels.DEBUG):t.warn?e.setLevel(hl.levels.WARN):t.error?e.setLevel(hl.levels.ERROR):e.setLevel(hl.levels.INFO)};var gl=w&&w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(X,"__esModule",{value:!0}),X.parseJsonText=X.parseJsonFile=void 0;const Al=Z,vl=gl(kr),Sl=gl(p.default),wl=gl(E.default),Ol=xr.HvigorLogger.getLogger("parse-json-util");var bl;!function(e){e[e.Char=0]="Char",e[e.EOF=1]="EOF",e[e.Identifier=2]="Identifier"}(bl||(bl={}));let _l,Bl,Pl,kl,xl,Nl,Il="start",Tl=[],Rl=0,Ml=1,Ll=0,jl=!1,$l="default",Hl="'",Jl=1;function Gl(e,t=!1){Bl=String(e),Il="start",Tl=[],Rl=0,Ml=1,Ll=0,kl=void 0,jl=t;do{_l=Vl(),Xl[Il]()}while("eof"!==_l.type);return kl}function Vl(){for($l="default",xl="",Hl="'",Jl=1;;){Nl=Ul();const e=zl[$l]();if(e)return e}}function Ul(){if(Bl[Rl])return String.fromCodePoint(Bl.codePointAt(Rl))}function Wl(){const e=Ul();return"\n"===e?(Ml++,Ll=0):e?Ll+=e.length:Ll++,e&&(Rl+=e.length),e}X.parseJsonFile=function(e,t=!1,n="utf-8"){const r=vl.default.readFileSync(Sl.default.resolve(e),{encoding:n});try{return Gl(r,t)}catch(t){if(t instanceof SyntaxError){const n=t.message.split("at");2===n.length&&Ol.errorMessageExit(`${n[0].trim()}${wl.default.EOL}\t at ${e}:${n[1].trim()}`)}Ol.errorMessageExit(`${e} is not in valid JSON/JSON5 format.`)}},X.parseJsonText=Gl;const zl={default(){switch(Nl){case"/":return Wl(),void($l="comment");case void 0:return Wl(),Kl("eof")}if(!Al.JudgeUtil.isIgnoreChar(Nl)&&!Al.JudgeUtil.isSpaceSeparator(Nl))return zl[Il]();Wl()},start(){$l="value"},beforePropertyName(){switch(Nl){case"$":case"_":return xl=Wl(),void($l="identifierName");case"\\":return Wl(),void($l="identifierNameStartEscape");case"}":return Kl("punctuator",Wl());case'"':case"'":return Hl=Nl,Wl(),void($l="string")}if(Al.JudgeUtil.isIdStartChar(Nl))return xl+=Wl(),void($l="identifierName");throw tf(bl.Char,Wl())},afterPropertyName(){if(":"===Nl)return Kl("punctuator",Wl());throw tf(bl.Char,Wl())},beforePropertyValue(){$l="value"},afterPropertyValue(){switch(Nl){case",":case"}":return Kl("punctuator",Wl())}throw tf(bl.Char,Wl())},beforeArrayValue(){if("]"===Nl)return Kl("punctuator",Wl());$l="value"},afterArrayValue(){switch(Nl){case",":case"]":return Kl("punctuator",Wl())}throw tf(bl.Char,Wl())},end(){throw tf(bl.Char,Wl())},comment(){switch(Nl){case"*":return Wl(),void($l="multiLineComment");case"/":return Wl(),void($l="singleLineComment")}throw tf(bl.Char,Wl())},multiLineComment(){switch(Nl){case"*":return Wl(),void($l="multiLineCommentAsterisk");case void 0:throw tf(bl.Char,Wl())}Wl()},multiLineCommentAsterisk(){switch(Nl){case"*":return void Wl();case"/":return Wl(),void($l="default");case void 0:throw tf(bl.Char,Wl())}Wl(),$l="multiLineComment"},singleLineComment(){switch(Nl){case"\n":case"\r":case"\u2028":case"\u2029":return Wl(),void($l="default");case void 0:return Wl(),Kl("eof")}Wl()},value(){switch(Nl){case"{":case"[":return Kl("punctuator",Wl());case"n":return Wl(),ql("ull"),Kl("null",null);case"t":return Wl(),ql("rue"),Kl("boolean",!0);case"f":return Wl(),ql("alse"),Kl("boolean",!1);case"-":case"+":return"-"===Wl()&&(Jl=-1),void($l="numerical");case".":case"0":case"I":case"N":return void($l="numerical");case'"':case"'":return Hl=Nl,Wl(),xl="",void($l="string")}if(void 0===Nl||!Al.JudgeUtil.isDigitWithoutZero(Nl))throw tf(bl.Char,Wl());$l="numerical"},numerical(){switch(Nl){case".":return xl=Wl(),void($l="decimalPointLeading");case"0":return xl=Wl(),void($l="zero");case"I":return Wl(),ql("nfinity"),Kl("numeric",Jl*(1/0));case"N":return Wl(),ql("aN"),Kl("numeric",NaN)}if(void 0!==Nl&&Al.JudgeUtil.isDigitWithoutZero(Nl))return xl=Wl(),void($l="decimalInteger");throw tf(bl.Char,Wl())},zero(){switch(Nl){case".":case"e":case"E":return void($l="decimal");case"x":case"X":return xl+=Wl(),void($l="hexadecimal")}return Kl("numeric",0)},decimalInteger(){switch(Nl){case".":case"e":case"E":return void($l="decimal")}if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},decimal(){switch(Nl){case".":xl+=Wl(),$l="decimalFraction";break;case"e":case"E":xl+=Wl(),$l="decimalExponent"}},decimalPointLeading(){if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalFraction");throw tf(bl.Char,Wl())},decimalFraction(){switch(Nl){case"e":case"E":return xl+=Wl(),void($l="decimalExponent")}if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},decimalExponent(){switch(Nl){case"+":case"-":return xl+=Wl(),void($l="decimalExponentSign")}if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalExponentInteger");throw tf(bl.Char,Wl())},decimalExponentSign(){if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalExponentInteger");throw tf(bl.Char,Wl())},decimalExponentInteger(){if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},hexadecimal(){if(Al.JudgeUtil.isHexDigit(Nl))return xl+=Wl(),void($l="hexadecimalInteger");throw tf(bl.Char,Wl())},hexadecimalInteger(){if(!Al.JudgeUtil.isHexDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},identifierNameStartEscape(){if("u"!==Nl)throw tf(bl.Char,Wl());Wl();const e=Yl();switch(e){case"$":case"_":break;default:if(!Al.JudgeUtil.isIdStartChar(e))throw tf(bl.Identifier)}xl+=e,$l="identifierName"},identifierName(){switch(Nl){case"$":case"_":case"‌":case"‍":return void(xl+=Wl());case"\\":return Wl(),void($l="identifierNameEscape")}if(!Al.JudgeUtil.isIdContinueChar(Nl))return Kl("identifier",xl);xl+=Wl()},identifierNameEscape(){if("u"!==Nl)throw tf(bl.Char,Wl());Wl();const e=Yl();switch(e){case"$":case"_":case"‌":case"‍":break;default:if(!Al.JudgeUtil.isIdContinueChar(e))throw tf(bl.Identifier)}xl+=e,$l="identifierName"},string(){switch(Nl){case"\\":return Wl(),void(xl+=function(){const e=Ul(),t=function(){switch(Ul()){case"b":return Wl(),"\b";case"f":return Wl(),"\f";case"n":return Wl(),"\n";case"r":return Wl(),"\r";case"t":return Wl(),"\t";case"v":return Wl(),"\v"}return}();if(t)return t;switch(e){case"0":if(Wl(),Al.JudgeUtil.isDigit(Ul()))throw tf(bl.Char,Wl());return"\0";case"x":return Wl(),function(){let e="",t=Ul();if(!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());if(e+=Wl(),t=Ul(),!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());return e+=Wl(),String.fromCodePoint(parseInt(e,16))}();case"u":return Wl(),Yl();case"\n":case"\u2028":case"\u2029":return Wl(),"";case"\r":return Wl(),"\n"===Ul()&&Wl(),""}if(void 0===e||Al.JudgeUtil.isDigitWithoutZero(e))throw tf(bl.Char,Wl());return Wl()}());case'"':case"'":if(Nl===Hl){const e=Kl("string",xl);return Wl(),e}return void(xl+=Wl());case"\n":case"\r":case void 0:throw tf(bl.Char,Wl());case"\u2028":case"\u2029":!function(e){Ol.warn(`JSON5: '${ef(e)}' in strings is not valid ECMAScript; consider escaping.`)}(Nl)}xl+=Wl()}};function Kl(e,t){return{type:e,value:t,line:Ml,column:Ll}}function ql(e){for(const t of e){if(Ul()!==t)throw tf(bl.Char,Wl());Wl()}}function Yl(){let e="",t=4;for(;t-- >0;){const t=Ul();if(!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());e+=Wl()}return String.fromCodePoint(parseInt(e,16))}const Xl={start(){if("eof"===_l.type)throw tf(bl.EOF);Zl()},beforePropertyName(){switch(_l.type){case"identifier":case"string":return Pl=_l.value,void(Il="afterPropertyName");case"punctuator":return void Ql();case"eof":throw tf(bl.EOF)}},afterPropertyName(){if("eof"===_l.type)throw tf(bl.EOF);Il="beforePropertyValue"},beforePropertyValue(){if("eof"===_l.type)throw tf(bl.EOF);Zl()},afterPropertyValue(){if("eof"===_l.type)throw tf(bl.EOF);switch(_l.value){case",":return void(Il="beforePropertyName");case"}":Ql()}},beforeArrayValue(){if("eof"===_l.type)throw tf(bl.EOF);"punctuator"!==_l.type||"]"!==_l.value?Zl():Ql()},afterArrayValue(){if("eof"===_l.type)throw tf(bl.EOF);switch(_l.value){case",":return void(Il="beforeArrayValue");case"]":Ql()}},end(){}};function Zl(){const e=function(){let e;switch(_l.type){case"punctuator":switch(_l.value){case"{":e={};break;case"[":e=[]}break;case"null":case"boolean":case"numeric":case"string":e=_l.value}return e}();if(jl&&"object"==typeof e&&(e._line=Ml,e._column=Ll),void 0===kl)kl=e;else{const t=Tl[Tl.length-1];Array.isArray(t)?jl&&"object"!=typeof e?t.push({value:e,_line:Ml,_column:Ll}):t.push(e):t[Pl]=jl&&"object"!=typeof e?{value:e,_line:Ml,_column:Ll}:e}!function(e){if(e&&"object"==typeof e)Tl.push(e),Il=Array.isArray(e)?"beforeArrayValue":"beforePropertyName";else{const e=Tl[Tl.length-1];Il=e?Array.isArray(e)?"afterArrayValue":"afterPropertyValue":"end"}}(e)}function Ql(){Tl.pop();const e=Tl[Tl.length-1];Il=e?Array.isArray(e)?"afterArrayValue":"afterPropertyValue":"end"}function ef(e){const t={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(t[e])return t[e];if(e<" "){const t=e.charCodeAt(0).toString(16);return`\\x${`00${t}`.substring(t.length)}`}return e}function tf(e,t){let n="";switch(e){case bl.Char:n=void 0===t?`JSON5: invalid end of input at ${Ml}:${Ll}`:`JSON5: invalid character '${ef(t)}' at ${Ml}:${Ll}`;break;case bl.EOF:n=`JSON5: invalid end of input at ${Ml}:${Ll}`;break;case bl.Identifier:Ll-=5,n=`JSON5: invalid identifier character at ${Ml}:${Ll}`}const r=new nf(n);return r.lineNumber=Ml,r.columnNumber=Ll,r}class nf extends SyntaxError{}var rf=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),uf=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),of=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&rf(t,e,n);return uf(t,e),t};Object.defineProperty(Y,"__esModule",{value:!0});var sf=Y.cleanWorkSpace=Ff=Y.executeInstallHvigor=yf=Y.isHvigorInstalled=mf=Y.isAllDependenciesInstalled=void 0;const cf=of(D.default),af=of(p.default),lf=b,ff=j,df=$,Df=X;let pf,Ef;var mf=Y.isAllDependenciesInstalled=function(){function e(e){const t=null==e?void 0:e.dependencies;return void 0===t?0:Object.getOwnPropertyNames(t).length}if(pf=gf(),Ef=Af(),e(pf)+1!==e(Ef))return!1;for(const e in null==pf?void 0:pf.dependencies)if(!(0,ff.hasNpmPackInPaths)(e,[lf.HVIGOR_PROJECT_DEPENDENCIES_HOME])||!hf(e,pf,Ef))return!1;return!0};function hf(e,t,n){return void 0!==n.dependencies&&(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,t.dependencies[e])===n.dependencies[e]}var yf=Y.isHvigorInstalled=function(){return pf=gf(),Ef=Af(),(0,ff.hasNpmPackInPaths)(lf.HVIGOR_ENGINE_PACKAGE_NAME,[lf.HVIGOR_PROJECT_DEPENDENCIES_HOME])&&(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,pf.hvigorVersion)===Ef.dependencies[lf.HVIGOR_ENGINE_PACKAGE_NAME]};const Cf={cwd:lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,stdio:["inherit","inherit","inherit"]};var Ff=Y.executeInstallHvigor=function(){(0,df.logInfoPrintConsole)("Hvigor installing...");const e={dependencies:{}};e.dependencies[lf.HVIGOR_ENGINE_PACKAGE_NAME]=(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,pf.hvigorVersion);try{cf.mkdirSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,{recursive:!0});const t=af.resolve(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,lf.DEFAULT_PACKAGE_JSON);cf.writeFileSync(t,JSON.stringify(e))}catch(e){(0,df.logErrorAndExit)(e)}!function(){const e=["config","set","store-dir",lf.HVIGOR_PNPM_STORE_PATH];(0,ff.executeCommand)(lf.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,e,Cf)}(),(0,ff.executeCommand)(lf.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,["install"],Cf)};function gf(){const e=af.resolve(lf.HVIGOR_PROJECT_WRAPPER_HOME,lf.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);return cf.existsSync(e)||(0,df.logErrorAndExit)(`Error: Hvigor config file ${e} does not exist.`),(0,Df.parseJsonFile)(e)}function Af(){return cf.existsSync(lf.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH)?(0,Df.parseJsonFile)(lf.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH):{dependencies:{}}}sf=Y.cleanWorkSpace=function(){if((0,df.logInfoPrintConsole)("Hvigor cleaning..."),!cf.existsSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME))return;const e=cf.readdirSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME);if(e&&0!==e.length){cf.existsSync(lf.HVIGOR_BOOT_JS_FILE_PATH)&&(0,ff.executeCommand)(process.argv[0],[lf.HVIGOR_BOOT_JS_FILE_PATH,"--stop-daemon"],{});try{e.forEach((e=>{cf.rmSync(af.resolve(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,e),{recursive:!0})}))}catch(e){(0,df.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${lf.HVIGOR_PROJECT_DEPENDENCIES_HOME}.`)}}};var vf={},Sf=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),wf=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Of=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&Sf(t,e,n);return wf(t,e),t};Object.defineProperty(vf,"__esModule",{value:!0});var bf=vf.executeBuild=void 0;const _f=b,Bf=Of(D.default),Pf=Of(p.default),kf=$;bf=vf.executeBuild=function(){const e=Pf.resolve(_f.HVIGOR_PROJECT_DEPENDENCIES_HOME,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const t=Bf.realpathSync(e);require(t)}catch(t){(0,kf.logErrorAndExit)(`Error: ENOENT: no such file ${e},delete ${_f.HVIGOR_PROJECT_DEPENDENCIES_HOME} and retry.`)}},function(){if(O.checkNpmConifg(),O.environmentHandler(),O.isPnpmAvailable()||O.executeInstallPnpm(),yf()&&mf())bf();else{sf();try{Ff()}catch(e){return void sf()}bf()}}(); \ No newline at end of file diff --git a/sqflite/ohos/hvigorfile.ts b/sqflite/ohos/hvigorfile.ts new file mode 100644 index 0000000..6478186 --- /dev/null +++ b/sqflite/ohos/hvigorfile.ts @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { appTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/sqflite/ohos/hvigorw b/sqflite/ohos/hvigorw new file mode 100644 index 0000000..1f9378f --- /dev/null +++ b/sqflite/ohos/hvigorw @@ -0,0 +1,61 @@ +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# 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. + +#!/bin/bash + +# ---------------------------------------------------------------------------- +# Hvigor startup script, version 1.0.0 +# +# Required ENV vars: +# ------------------ +# NODE_HOME - location of a Node home dir +# or +# Add /usr/local/nodejs/bin to the PATH environment variable +# ---------------------------------------------------------------------------- + +HVIGOR_APP_HOME=$(dirname $(readlink -f $0)) +HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js +warn() { + echo "" + echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +error() { + echo "" + echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +fail() { + error "$@" + exit 1 +} + +# Determine node to start hvigor wrapper script +if [ -n "${NODE_HOME}" ];then + EXECUTABLE_NODE="${NODE_HOME}/bin/node" + if [ ! -x "$EXECUTABLE_NODE" ];then + fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed" + fi +else + EXECUTABLE_NODE="node" + which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path" +fi + +# Check hvigor wrapper script +if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then + fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}" +fi + +# start hvigor-wrapper script +exec "${EXECUTABLE_NODE}" \ + "${HVIGOR_WRAPPER_SCRIPT}" "$@" diff --git a/sqflite/ohos/hvigorw.bat b/sqflite/ohos/hvigorw.bat new file mode 100644 index 0000000..015ad71 --- /dev/null +++ b/sqflite/ohos/hvigorw.bat @@ -0,0 +1,77 @@ +:: Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +:: 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. + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Hvigor startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js +set NODE_EXE=node.exe + +goto start + +:start +@rem Find node.exe +if defined NODE_HOME goto findNodeFromNodeHome + +%NODE_EXE% --version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:findNodeFromNodeHome +set NODE_HOME=%NODE_HOME:"=% +set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE% + +if exist "%NODE_EXE_PATH%" goto execute +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:execute +@rem Execute hvigor +"%NODE_EXE%" %WRAPPER_MODULE_PATH% %* + +if "%ERRORLEVEL%" == "0" goto hvigorwEnd + +:fail +exit /b 1 + +:hvigorwEnd +if "%OS%" == "Windows_NT" endlocal + +:end diff --git a/sqflite/ohos/oh-package-lock.json5 b/sqflite/ohos/oh-package-lock.json5 new file mode 100644 index 0000000..bc40219 --- /dev/null +++ b/sqflite/ohos/oh-package-lock.json5 @@ -0,0 +1,13 @@ +{ + "lockfileVersion": 1, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hypium@1.0.6": "@ohos/hypium@1.0.6" + }, + "packages": { + "@ohos/hypium@1.0.6": { + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.6.tgz", + "integrity": "sha512-bb3DWeWhYrFqj9mPFV3yZQpkm36kbcK+YYaeY9g292QKSjOdmhEIQR2ULPvyMsgSR4usOBf5nnYrDmaCCXirgQ==" + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/oh-package.json5 b/sqflite/ohos/oh-package.json5 new file mode 100644 index 0000000..4cdaff2 --- /dev/null +++ b/sqflite/ohos/oh-package.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +{ + "name": "sqflite", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.6" + } +} diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/CHANGELOG.md b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/CHANGELOG.md new file mode 100644 index 0000000..fb0366d --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/CHANGELOG.md @@ -0,0 +1,45 @@ +## 1.0.6 + +- 适配模块化编译 +- 适配IDE覆盖率数据输出 + +## 1.0.5 + +- 优化接口异常场景处理能力 +- 修复大规模压力测试下内存溢出问题 +- 修复测试脚本定义扩展原型方法与框架的兼容性问题 +- 异步promise状态判断断言与取反断言兼容 + +## 1.0.4 + +- 新增异步promise状态判断断言 +- 新增基础数据判断断言 +- 新增断言异常信息描述 +- 优化用例计时逻辑,采用相对时间计时 +- 修改用例执行过程,异步执行 +- 修复用例结果偶现的乱序问题 + +## 1.0.3 + +- 新增mock对象的能力,支持mock无参数函数 +- 新增测试套、测试用例随机执行功能 +- 解决测试套声明不规范,导致用例加载异常的问题 +- 修复命令行窗口输出乱序的问题 + +## 1.0.2 + +- 新增mock接口,判断当前mock方法状态、使用次数 +- 修复用例耗时统计问题 +- 修改断言功能,断言失败后,会抛出异常 + +## 1.0.1 +- 新增mock基础能力 +- 修复部分断言失败后,消息提示异常问题 + +## 1.0.0 +- 新增应用日志关键字查询接口,查询hilog日志中是否包含指定字符串 +- 支持用例筛选功能,用于指定测试用例的执行。可按用例名称、类型、规模、级别与测试套名称筛选 +- 支持新SDK下单元测试 +- 支持dry run 功能,通过命令行传参数,返回当前测试套用例名称全集 +- 新增框架接口声明文件,用于deveco联想 +- 修复用例状态统计问题 \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/README.md b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/README.md new file mode 100644 index 0000000..743361c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/README.md @@ -0,0 +1,219 @@ +
Hypium
+
A unit test framework for OpenHarmonyOS application
+ +## Hypium是什么? +*** +- Hypium是OpenHarmony上的测试框架,提供测试用例编写、执行、结果显示能力,用于OpenHarmony系统应用接口以及应用界面测试。 +- Hypium结构化模型:hypium工程主要由List.test.js与TestCase.test.js组成。 +``` +rootProject // Hypium工程根目录 +├── moduleA +│   ├── src +│      ├── main // 被测试应用目录 +│      ├── ohosTest // 测试用例目录 +│         ├── js/ets +│            └── test +│               └── List.test.js // 测试用例加载脚本,ets目录下为.ets后缀 +│               └── TestCase.test.js // 测试用例脚本,ets目录下为.ets后缀 +└── moduleB + ... +│               └── List.test.js // 测试用例加载脚本,ets目录下为.ets后缀 +│               └── TestCase.test.js // 测试用例脚本,ets目录下为.ets后缀 +``` + +## 安装使用 +*** +- 在DevEco Studio内使用Hypium +- 工程级package.json内配置: +```json +"dependencies": { + "@ohos/hypium": "1.0.6" +} +``` +注: +hypium服务于OpenHarmonyOS应用对外接口测试、系统对外接口测试(SDK中接口),完成HAP自动化测试。详细指导: +[Deveco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio) + +#### 通用语法 + +- 测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 + +| No. | API | 功能说明 | +| --- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 | +| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | +| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | +| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | +| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | +| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 | +| 7 | expect | 支持bool类型判断等多种断言方法 | + +#### 断言库 + +- 示例代码: + +```javascript + expect(${actualvalue}).assertX(${expectvalue}) +``` + +- 断言功能列表: + +| No. | API | 功能说明 | +| :--- | :------------------------------- | ---------------------------------------------------------------------------------------------- | +| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) | +| 2 | assertContain | 检验actualvalue中是否包含expectvalue | +| 3 | assertDeepEquals | @since1.0.4 检验actualvalue和expectvalue(0)是否是同一个对象 | +| 4 | assertEqual | 检验actualvalue是否等于expectvalue[0] | +| 5 | assertFail | 抛出一个错误 | +| 6 | assertFalse | 检验actualvalue是否是false | +| 7 | assertTrue | 检验actualvalue是否是true | +| 8 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | +| 9 | assertLarger | 检验actualvalue是否大于expectvalue | +| 10 | assertLess | 检验actualvalue是否小于expectvalue | +| 11 | assertNaN | @since1.0.4 检验actualvalue是否是NaN | +| 12 | assertNegUnlimited | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY | +| 13 | assertNull | 检验actualvalue是否是null | +| 14 | assertPosUnlimited | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY | +| 15 | assertPromiseIsPending | @since1.0.4 检验actualvalue是否处于Pending状态【actualvalue为promse对象】 | +| 16 | assertPromiseIsRejected | @since1.0.4 检验actualvalue是否处于Rejected状态【同15】 | +| 17 | assertPromiseIsRejectedWith | @since1.0.4 检验actualvalue是否处于Rejected状态,并且比较执行的结果值【同15】 | +| 18 | assertPromiseIsRejectedWithError | @since1.0.4 检验actualvalue是否处于Rejected状态并有异常,同时比较异常的类型和message值【同15】 | +| 19 | assertPromiseIsResolved | @since1.0.4 检验actualvalue是否处于Resolved状态【同15】 | +| 20 | assertPromiseIsResolvedWith | @since1.0.4 检验actualvalue是否处于Resolved状态,并且比较执行的结果值【同15】 | +| 21 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | +| 22 | assertUndefined | 检验actualvalue是否是undefined | +| 23 | not | @since1.0.4 断言结果取反 | + + + 示例代码: + +```javascript + import { describe, it, expect } from '@ohos/hypium'; + + export default async function assertCloseTest() { + describe('assertClose', function () { + it('assertClose_success', 0, function () { + let a = 100; + let b = 0.1; + expect(a).assertClose(99, b); + }) + }) + } +``` + +#### 公共系统能力 + +| No. | API | 功能描述 | +| ---- | ------------------------------------------------------- | ------------------------------------------------------------ | +| 1 | existKeyword(keyword: string, timeout: number): boolean | @since1.0.3 hilog日志中查找指定字段是否存在,keyword是待查找关键字,timeout为设置的查找时间 | +| 2 | actionStart(tag: string): void | @since1.0.3 cmd窗口输出开始tag | +| 3 | actionEnd(tag: string): void | @since1.0.3 cmd窗口输出结束tag | + + 示例代码: + +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function existKeywordTest() { + describe('existKeywordTest', function () { + it('existKeyword',DEFAULT, async function () { + console.info("HelloTest"); + let isExist = await SysTestKit.existKeyword('HelloTest'); + console.info('isExist ------>' + isExist); + }) + }) +} +``` +```javascript +import { describe, it, expect, SysTestKit} from '@ohos/hypium'; + +export default function actionTest() { + describe('actionTest', function () { + it('existKeyword',DEFAULT, async function () { + let tag = '[MyTest]'; + SysTestKit.actionStart(tag); + //do something + SysTestKit.actionEnd(tag); + }) + }) +} +``` + +#### 专项能力 + +- 测试用例属性筛选能力:hypium支持根据用例属性筛选执行指定测试用例,使用方式是先在测试用例上标记用例属性后,再在测试应用的启动shell命令后新增" -s ${Key} ${Value}"。 + +| Key | 含义说明 | Value取值范围 | +| -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| level | 用例级别 | "0","1","2","3","4", 例如:-s level 1 | +| size | 用例粒度 | "small","medium","large", 例如:-s size small | +| testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function | + + 示例代码 + +```javascript +import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium'; + +export default function attributeTest() { + describe('attributeTest', function () { + it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () { + console.info('Hello Test'); + }) + }) +} +``` + + 示例命令 +```shell +XX -s level 1 -s size small -s testType function +``` +该命令的作用是:筛选测试应用中同时满足a)用例级别是1 b)用例粒度是small c)用例测试类型是function 三个条件的用例执行。 + +- 测试套/测试用例名称筛选能力(测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔) + +| Key | 含义说明 | Value取值范围 | +| -------- | ----------------------- | -------------------------------------------------------------------------------------------- | +| class | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt | +| notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttributeIt | + + 示例命令 +```shell +XX -s class attributeTest#testAttributeIt,abilityTest#testAbilityIt +``` +该命令的作用是:筛选测试应用中attributeTest测试套下的testAttributeIt测试用例,abilityTest测试套下的testAbilityIt测试用例,只执行这两条用例。 + +- 其他能力 + +| 能力项 | Key | 含义说明 | Value取值范围 | +| ------------ | ------- | ---------------------------- | ---------------------------------------------- | +| 随机执行能力 | random | 测试套&测试用例随机执行 | true, 不传参默认为false, 例如:-s random true | +| 空跑能力 | dryRun | 显示要执行的测试用例信息全集 | true , 不传参默认为false,例如:-s dryRun true | +| 异步超时能力 | timeout | 异步用例执行的超时时间 | 正整数 , 单位ms,例如:-s timeout 5000 | + +##### 约束限制 +随机执行能力和空跑能力从npm包1.0.3版本开始支持 + +#### Mock能力 + +##### 约束限制 + +单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium/v/1.0.1)开始支持 + +## 约束 + +*** + 本模块首批接口从OpenHarmony SDK API version 8开始支持。 + +## Hypium开放能力隐私声明 + +- 我们如何收集和使用您的个人信息 + 您在使用集成了Hypium开放能力的测试应用时,Hypium不会处理您的个人信息。 +- SDK处理的个人信息 + 不涉及。 +- SDK集成第三方服务声明 + 不涉及。 +- SDK数据安全保护 + 不涉及。 +- SDK版本更新声明 + 为了向您提供最新的服务,我们会不时更新Hypium版本。我们强烈建议开发者集成使用最新版本的Hypium。 + diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts new file mode 100644 index 0000000..b0b4394 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.d.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +export const DEFAULT = 0B0000 + +export const when: when; + +export enum TestType { + FUNCTION = 0B1, + PERFORMANCE = 0B1 << 1, + POWER = 0B1 << 2, + RELIABILITY = 0B1 << 3, + SECURITY = 0B1 << 4, + GLOBAL = 0B1 << 5, + COMPATIBILITY = 0B1 << 6, + USER = 0B1 << 7, + STANDARD = 0B1 << 8, + SAFETY = 0B1 << 9, + RESILIENCE = 0B1 << 10 +} + +export enum Size { + SMALLTEST = 0B1 << 16, + MEDIUMTEST = 0B1 << 17, + LARGETEST = 0B1 << 18 +} + +export enum Level { + LEVEL0 = 0B1 << 24, + LEVEL1 = 0B1 << 25, + LEVEL2 = 0B1 << 26, + LEVEL3 = 0B1 << 27, + LEVEL4 = 0B1 << 28 +} + +export function describe(testSuiteName: string, callback: Function): void + +export function beforeEach(callback: Function): void + +export function afterEach(callback: Function): void + +export function beforeAll(callback: Function): void + +export function afterAll(callback: Function): void + +export function it(testCaseName: string, attribute: (TestType | Size | Level), callback: Function) + +export interface Assert { + assertClose(expectValue: number, precision: number): void + assertContain(expectValue: any): void + assertEqual(expectValue: any): void + assertFail(): void + assertFalse(): void + assertTrue(): void + assertInstanceOf(expectValue: string): void + assertLarger(expectValue: number): void + assertLess(expectValue: number): void + assertNull(): void + assertThrowError(expectValue: string): void + assertUndefined(): void + assertLargerOrEqual(expectValue: number):void + assertLessOrEqual(expectValue: number):void + assertNaN():void + assertNegUnlimited(): void + assertPosUnlimited(): void + not(): Assert; + assertDeepEquals(expectValue: any):void + assertPromiseIsPending(): void + assertPromiseIsRejected(): void + assertPromiseIsRejectedWith(expectValue?: any): void + assertPromiseIsRejectedWithError(...expectValue): void + assertPromiseIsResolved(): void + assertPromiseIsResolvedWith(expectValue?: any): void +} + +export function expect(actualValue?: any): Assert + +export class ArgumentMatchers { + static any; + static anyString; + static anyBoolean; + static anyNumber; + static anyObj; + static anyFunction; + static matchRegexs(Regex: RegExp): void +} + +declare interface when { + afterReturn(value: any): any + afterReturnNothing(): undefined + afterAction(action: any): any + afterThrow(e_msg: string): string + (argMatchers?: any): when; +} + +export interface VerificationMode { + times(count: Number): void + never(): void + once(): void + atLeast(count: Number): void + atMost(count: Number): void +} + +export class MockKit { + constructor() + mockFunc(obj: Object, func: Function): Function + mockObject(obj: Object): Object + verify(methodName: String, argsArray: Array): VerificationMode + ignoreMock(obj: Object, func: Function): void + clear(obj: Object): void + clearAll(): void +} + +export class SysTestKit { + static actionStart(tag: string): void + static actionEnd(tag: string): void + static existKeyword(keyword: string, timeout?: number): boolean +} + +export class Hypium { + static setData(data: {[key: string]: any}): void + static setTimeConfig(systemTime: any) + static hypiumTest(abilityDelegator: any, abilityDelegatorArguments: any, testsuite: Function): void +} \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.ets b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.ets new file mode 100644 index 0000000..3c3fe31 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.ets @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import Core from './src/main/core'; +import {DEFAULT, TestType, Size, Level} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + 'delegator': abilityDelegator, + 'abilityDelegatorArguments': abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService = core.getDefaultService('config'); + + let testParameters = {}; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info('parameters:' + JSON.stringify(testParameters)); + configService.setConfig(testParameters); + + testsuite(); + if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { + globalThis.setupUiTestEnvironment().then(() => { + console.info('UiTestKit::after run uitest setup, start run testcases'); + core.execute(abilityDelegator); + }).catch((error) => { + console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error); + core.execute(abilityDelegator); + }); + } else { + console.info('UiTestKit:: no need to setup uitest, start run testcases'); + core.execute(abilityDelegator); + } + } +} + +export { + Hypium, + Core, + DEFAULT, + TestType, + Size, + Level, + DataDriver, + ExpectExtend, + OhReport, + SysTestKit, + describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, + MockKit, when, + ArgumentMatchers +}; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.js new file mode 100644 index 0000000..3c3fe31 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/index.js @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import Core from './src/main/core'; +import {DEFAULT, TestType, Size, Level} from './src/main/Constant'; +import DataDriver from './src/main/module/config/DataDriver'; +import ExpectExtend from './src/main/module/assert/ExpectExtend'; +import OhReport from './src/main/module/report/OhReport'; +import SysTestKit from './src/main/module/kit/SysTestKit'; +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from './src/main/interface'; +import {MockKit, when} from './src/main/module/mock/MockKit'; +import ArgumentMatchers from './src/main/module/mock/ArgumentMatchers'; + +class Hypium { + static setData(data) { + const core = Core.getInstance(); + const dataDriver = new DataDriver({data}); + core.addService('dataDriver', dataDriver); + } + + static setTimeConfig(systemTime) { + SysTestKit.systemTime = systemTime; + } + + static hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) { + const core = Core.getInstance(); + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }); + core.addService('expect', expectExtend); + const ohReport = new OhReport({ + 'delegator': abilityDelegator, + 'abilityDelegatorArguments': abilityDelegatorArguments + }); + SysTestKit.delegator = abilityDelegator; + core.addService('report', ohReport); + core.init(); + core.subscribeEvent('spec', ohReport); + core.subscribeEvent('suite', ohReport); + core.subscribeEvent('task', ohReport); + const configService = core.getDefaultService('config'); + + let testParameters = {}; + if (abilityDelegatorArguments !== null) { + testParameters = configService.translateParams(abilityDelegatorArguments.parameters); + } + console.info('parameters:' + JSON.stringify(testParameters)); + configService.setConfig(testParameters); + + testsuite(); + if (Object.prototype.hasOwnProperty.call(globalThis, 'setupUiTestEnvironment')) { + globalThis.setupUiTestEnvironment().then(() => { + console.info('UiTestKit::after run uitest setup, start run testcases'); + core.execute(abilityDelegator); + }).catch((error) => { + console.error('UiTestKit:: call setupUiTestEnvironment failure:' + error); + core.execute(abilityDelegator); + }); + } else { + console.info('UiTestKit:: no need to setup uitest, start run testcases'); + core.execute(abilityDelegator); + } + } +} + +export { + Hypium, + Core, + DEFAULT, + TestType, + Size, + Level, + DataDriver, + ExpectExtend, + OhReport, + SysTestKit, + describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, + MockKit, when, + ArgumentMatchers +}; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/oh-package.json5 b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/oh-package.json5 new file mode 100644 index 0000000..84d3f85 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "@ohos/hypium", + "version": "1.0.6", + "description": "A unit test framework for OpenHarmony application", + "main": "index.js", + "keywords": [], + "author": "huawei", + "license": "Apache-2.0", + "dependencies": { + } +} diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/Constant.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/Constant.js new file mode 100644 index 0000000..f182910 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/Constant.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +/** + * define the testcase type : TestType, Size , Level + */ +export const DEFAULT = 0B0000; + +export class TestType { + static FUNCTION = 0B1; + static PERFORMANCE = 0B1 << 1; + static POWER = 0B1 << 2; + static RELIABILITY = 0B1 << 3; + static SECURITY = 0B1 << 4; + static GLOBAL = 0B1 << 5; + static COMPATIBILITY = 0B1 << 6; + static USER = 0B1 << 7; + static STANDARD = 0B1 << 8; + static SAFETY = 0B1 << 9; + static RESILIENCE = 0B1 << 10; +} + +export class Size { + static SMALLTEST = 0B1 << 16; + static MEDIUMTEST = 0B1 << 17; + static LARGETEST = 0B1 << 18; +} + +export class Level { + static LEVEL0 = 0B1 << 24; + static LEVEL1 = 0B1 << 25; + static LEVEL2 = 0B1 << 26; + static LEVEL3 = 0B1 << 27; + static LEVEL4 = 0B1 << 28; +} diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/core.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/core.js new file mode 100644 index 0000000..cfcb5f1 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/core.js @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import {SuiteService, SpecService, ExpectService, ReportService} from './service'; +import {ConfigService} from './module/config/configService'; +import {SpecEvent, TaskEvent, SuiteEvent} from './event'; + +/** + * core service for execute testcase. + */ +class Core { + static getInstance() { + if (!this.instance) { + this.instance = new Core(); + } + return this.instance; + } + + constructor() { + this.instance = null; + this.services = { + suite: {}, + spec: {}, + config: {}, + expect: {}, + log: {}, + report: {} + + }; + this.events = { + suite: {}, + spec: {}, + task: {} + }; + } + + addService(name, service) { + let serviceObj = {}; + if (!this.services[name]) { + this.services[name] = serviceObj; + } else { + serviceObj = this.services[name]; + } + serviceObj[service.id] = service; + } + + getDefaultService(name) { + return this.services[name].default; + } + + getServices(name) { + return this.services[name]; + } + + registerEvent(serviceName, event) { + let eventObj = {}; + if (!this.events[serviceName]) { + this.events[serviceName] = eventObj; + } else { + eventObj = this.events[serviceName]; + } + eventObj[event.id] = event; + } + + unRegisterEvent(serviceName, eventID) { + const eventObj = this.events[serviceName]; + if (eventObj) { + delete eventObj[eventID]; + } + } + + subscribeEvent(serviceName, serviceObj) { + const eventObj = this.events[serviceName]; + if (eventObj) { + for (const attr in eventObj) { + eventObj[attr]['subscribeEvent'](serviceObj); + } + } + } + + async fireEvents(serviceName, eventName) { + const eventObj = this.events[serviceName]; + if (!eventObj) { + return; + } + for (const attr in eventObj) { + await eventObj[attr][eventName](); + } + } + + addToGlobal(apis) { + if (typeof globalThis !== 'undefined') { + for (let api in apis) { + globalThis[api] = apis[api]; + } + } + for (const api in apis) { + this[api] = apis[api]; + } + } + + init() { + this.addService('suite', new SuiteService({id: 'default'})); + this.addService('spec', new SpecService({id: 'default'})); + this.addService('expect', new ExpectService({id: 'default'})); + this.addService('report', new ReportService({id: 'default'})); + this.addService('config', new ConfigService({id: 'default'})); + this.registerEvent('task', new TaskEvent({id: 'default', coreContext: this})); + this.registerEvent('suite', new SuiteEvent({id: 'default', coreContext: this})); + this.registerEvent('spec', new SpecEvent({id: 'default', coreContext: this})); + this.subscribeEvent('spec', this.getDefaultService('report')); + this.subscribeEvent('suite', this.getDefaultService('report')); + this.subscribeEvent('task', this.getDefaultService('report')); + const context = this; + for (const key in this.services) { + const serviceObj = this.services[key]; + for (const serviceID in serviceObj) { + const service = serviceObj[serviceID]; + service.init(context); + + if (typeof service.apis !== 'function') { + continue; + } + const apis = service.apis(); + if (apis) { + this.addToGlobal(apis); + } + } + } + } + + execute(abilityDelegator) { + const suiteService = this.getDefaultService('suite'); + const configService = this.getDefaultService('config'); + if (configService['dryRun'] === 'true') { + (async function () { + await suiteService.dryRun(abilityDelegator); + })(); + return; + } + setTimeout(() => { + suiteService.execute(); + }, 10); + } +} + +export default Core; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/event.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/event.js new file mode 100644 index 0000000..1333a1c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/event.js @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +class SpecEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.context; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async specStart() { + for (const monitor of this.eventMonitors) { + await monitor['specStart'](); + } + } + + async specDone() { + for (const monitor of this.eventMonitors) { + await monitor['specDone'](); + } + } +} + +class SuiteEvent { + constructor(attr) { + this.id = attr.id; + this.suiteContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async suiteStart() { + for (const monitor of this.eventMonitors) { + await monitor['suiteStart'](); + } + } + + async suiteDone() { + for (const monitor of this.eventMonitors) { + await monitor['suiteDone'](); + } + } +} + +class TaskEvent { + constructor(attr) { + this.id = attr.id; + this.coreContext = attr.coreContext; + this.eventMonitors = []; + } + + subscribeEvent(service) { + this.eventMonitors.push(service); + } + + async taskStart() { + for (const monitor of this.eventMonitors) { + await monitor['taskStart'](); + } + } + + async taskDone() { + for (const monitor of this.eventMonitors) { + await monitor['taskDone'](); + } + } + + incorrectFormat() { + for (const monitor of this.eventMonitors) { + monitor['incorrectFormat'](); + } + } +} + +export {SpecEvent, TaskEvent, SuiteEvent}; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/interface.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/interface.js new file mode 100644 index 0000000..40398c8 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/interface.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import Core from './core'; + +const core = Core.getInstance(); + +const describe = function (desc, func) { + return Reflect.has(core, 'describe') ? core.describe(desc, func) : (desc, func) => { }; +}; +const it = function (desc, filter, func) { + return Reflect.has(core, 'it') ? core.it(desc, filter, func) : (desc, filter, func) => { }; +}; +const beforeEach = function (func) { + return Reflect.has(core, 'beforeEach') ? core.beforeEach(func) : (func) => { }; +}; +const afterEach = function (func) { + return Reflect.has(core, 'afterEach') ? core.afterEach(func) : (func) => { }; +}; +const beforeAll = function (func) { + return Reflect.has(core, 'beforeAll') ? core.beforeAll(func) : (func) => { }; +}; +const afterAll = function (func) { + return Reflect.has(core, 'afterAll') ? core.afterAll(func) : (func) => { }; +}; +const expect = function (actualValue) { + return Reflect.has(core, 'expect') ? core.expect(actualValue) : (actualValue) => { }; +}; + +export { + describe, it, beforeAll, beforeEach, afterEach, afterAll, expect +}; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js new file mode 100644 index 0000000..d10d15e --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/ExpectExtend.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import assertNull from './assertNull'; +import assertClose from './assertClose'; +import assertContain from './assertContain'; +import assertLess from './assertLess'; +import assertLarger from './assertLarger'; +import assertFail from './assertFail'; +import assertUndefined from './assertUndefined'; +import assertFalse from './assertFalse'; +import assertInstanceOf from './assertInstanceOf'; +import assertThrowError from './assertThrowError'; +import assertLargerOrEqual from './assertLargerOrEqual' +import assertLessOrEqual from './assertLessOrEqual' +import assertNaN from './assertNaN' +import assertNegUnlimited from './assertNegUnlimited' +import assertPosUnlimited from './assertPosUnlimited' +import assertDeepEquals from './deepEquals/assertDeepEquals' +import assertPromiseIsPending from './assertPromiseIsPending'; +import assertPromiseIsRejected from './assertPromiseIsRejected'; +import assertPromiseIsRejectedWith from './assertPromiseIsRejectedWith'; +import assertPromiseIsRejectedWithError from './assertPromiseIsRejectedWithError'; +import assertPromiseIsResolved from './assertPromiseIsResolved'; +import assertPromiseIsResolvedWith from './assertPromiseIsResolvedWith'; +class ExpectExtend { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + extendsMatchers() { + this.matchers.assertNull = assertNull; + this.matchers.assertClose = assertClose; + this.matchers.assertContain = assertContain; + this.matchers.assertLess = assertLess; + this.matchers.assertLarger = assertLarger; + this.matchers.assertFail = assertFail; + this.matchers.assertUndefined = assertUndefined; + this.matchers.assertFalse = assertFalse; + this.matchers.assertInstanceOf = assertInstanceOf; + this.matchers.assertThrowError = assertThrowError; + this.matchers.assertLargerOrEqual = assertLargerOrEqual; + this.matchers.assertLessOrEqual = assertLessOrEqual; + this.matchers.assertNaN = assertNaN; + this.matchers.assertNegUnlimited = assertNegUnlimited; + this.matchers.assertPosUnlimited = assertPosUnlimited; + this.matchers.assertDeepEquals = assertDeepEquals; + this.matchers.assertPromiseIsPending = assertPromiseIsPending; + this.matchers.assertPromiseIsRejected = assertPromiseIsRejected; + this.matchers.assertPromiseIsRejectedWith = assertPromiseIsRejectedWith; + this.matchers.assertPromiseIsRejectedWithError = assertPromiseIsRejectedWithError; + this.matchers.assertPromiseIsResolved = assertPromiseIsResolved; + this.matchers.assertPromiseIsResolvedWith = assertPromiseIsResolvedWith; + } + + init(coreContext) { + this.coreContext = coreContext; + this.extendsMatchers(); + const expectService = this.coreContext.getDefaultService('expect'); + expectService.addMatchers(this.matchers); + } + + apis() { + return { + 'expect': function (actualValue) { + return this.coreContext.getDefaultService('expect').expect(actualValue); + } + }; + } +} + +export default ExpectExtend; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js new file mode 100644 index 0000000..63635be --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertClose.js @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertClose(actualValue, expected) { + console.log('expected:' + expected[0] + ',precision:' + expected[1]); + if (actualValue === null && expected[0] === null) { + throw new Error('actualValue and expected can not be both null!!!'); + } + let result; + let diff = Math.abs(expected[0] - actualValue); + let actualAbs = Math.abs(actualValue); + if ((actualAbs - 0) === 0) { + if ((diff - 0) === 0) { + result = true; + } else { + result = false; + } + } else if (diff / actualAbs < expected[1]) { + result = true; + } else { + result = false; + } + return { + pass: result, + message: '|' + actualValue + ' - ' + expected[0] + '|/' + actualValue + ' is not less than ' + expected[1] + }; +} + +export default assertClose; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js new file mode 100644 index 0000000..7fba0d9 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertContain.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertContain(actualValue, expect) { + let result = false; + if (Object.prototype.toString.call(actualValue).indexOf('Array')) { + for (let i in actualValue) { + if (actualValue[i] == expect[0]) { + result = true; + } + } + } + let type = Object.prototype.toString.call(actualValue); + if (type === '[object String]') { + result = actualValue.indexOf(expect[0]) >= 0; + } + return { + pass: result, + message: 'expect false, ' + actualValue + ' do not have ' + expect[0] + }; +} + +export default assertContain; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js new file mode 100644 index 0000000..8ab4ac5 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFail.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertFail() { + return { + pass: false, + message: 'fail ' + }; +} + +export default assertFail; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js new file mode 100644 index 0000000..c5008e9 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertFalse.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertFalse(actualValue) { + return { + pass: (actualValue) === false, + message: 'expect false, actualValue is ' + actualValue + }; +} + +export default assertFalse; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js new file mode 100644 index 0000000..1e11b93 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertInstanceOf.js @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertInstanceOf(actualValue, expected) { + if (Object.prototype.toString.call(actualValue) == '[object ' + expected[0] + ']') { + return { + pass: true + }; + } else { + return { + pass: false, + message: actualValue + ' is ' + Object.prototype.toString.call(actualValue) + 'not ' + expected[0] + }; + } +} + +export default assertInstanceOf; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js new file mode 100644 index 0000000..a74f4a8 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLarger.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertLarger(actualValue, expected) { + return { + pass: (actualValue) > expected[0], + message: (actualValue) + ' is not larger than ' + expected[0] + }; +} + +export default assertLarger; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js new file mode 100644 index 0000000..e847e6c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLargerOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertLargerOrEqual(actualValue, expected) { + return { + pass: (actualValue) >= expected[0], + message: (actualValue) + ' is not larger than ' + expected[0] + }; +} + +export default assertLargerOrEqual; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js new file mode 100644 index 0000000..17e84b0 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLess.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertLess(actualValue, expected) { + return { + pass: (actualValue) < expected[0], + message: (actualValue) + ' is not less than ' + expected[0] + }; +} + +export default assertLess; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js new file mode 100644 index 0000000..f754f97 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertLessOrEqual.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertLessOrEqual(actualValue, expected) { + return { + pass: (actualValue) <= expected[0], + message: (actualValue) + ' is not less than ' + expected[0] + }; +} + +export default assertLessOrEqual; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js new file mode 100644 index 0000000..8d45d6a --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNaN.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertNaN(actualValue) { + return { + pass: actualValue !== actualValue, + message: 'expect NaN, actualValue is ' + actualValue + }; +} + +export default assertNaN; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js new file mode 100644 index 0000000..ceac555 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNegUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* 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. +*/ + +function assertNegUnlimited(actualValue) { + return { + pass: actualValue === Number.NEGATIVE_INFINITY, + message: 'Expected actualValue not to be -Infinity. actualValue is,' + actualValue + }; +} + +export default assertNegUnlimited; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js new file mode 100644 index 0000000..53a7bad --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertNull.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertNull(actualValue) { + return { + pass: (actualValue) === null, + message: 'expect null, actualValue is ' + (actualValue) + }; +} + +export default assertNull; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js new file mode 100644 index 0000000..6e68c0e --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPosUnlimited.js @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2022 Huawei Device Co., Ltd. +* 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. +*/ + +function assertPosUnlimited(actualValue) { + return { + pass: actualValue === Number.POSITIVE_INFINITY, + message: 'Expected actualValue is POSITIVE_INFINITY. actualValue is,' + actualValue + }; +} + +export default assertPosUnlimited; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js new file mode 100644 index 0000000..7e2ca2c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsPending.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsPending(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? {pass: true, message: 'actualValue is isPending'} + : { + pass: false, + message: 'expect isPending, actualValue is resolve' + }; + }, + function () { + return { + pass: false + , message: 'expect isPending, actualValue is reject' + }; + }); +} + +export default assertPromiseIsPending; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js new file mode 100644 index 0000000..eb8e65c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejected.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejected(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'expect isRejected, but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function () { + return {pass: true, message: 'actualValue is isRejected'}; + } + ); +} + +export default assertPromiseIsRejected; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js new file mode 100644 index 0000000..48eaf78 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWith.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWith(actualPromise, expectedValue) { + + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ('Expected a promise ' + (passed ? 'not ' : '') + + 'to be rejected with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: tips(false) + ' but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + if (JSON.stringify(actualValue) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } else { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(actualValue) + '.' + }; + } + } + ); +} + +export default assertPromiseIsRejectedWith; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js new file mode 100644 index 0000000..334a3d3 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsRejectedWithError.js @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsRejectedWithError(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return { + pass: false, + message: 'Expected a promise to be rejected but actualValue is ' + + (helper === got ? 'isPending' : 'resolve') + }; + }, + function (actualValue) { + return matchError(actualValue, expectedValue); + } + ); + +} + +function matchError(actualValue, expectedValue) { + if (expectedValue.length == 1 && typeof expectedValue[0] === 'function') { + if (expectedValue[0].name === actualValue.__proto__.name) { + return {pass: true, message: 'actual error type is ' + actualValue.name + '.'}; + } + return { + pass: false, + message: 'except error type is ' + expectedValue[0].name + ',but actual is ' + actualValue.name + '.' + }; + } + + if (expectedValue.length == 1 && typeof expectedValue[0] === 'string') { + if (expectedValue[0] === actualValue.message) { + return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; + } + return { + pass: false, + message: 'except error message ' + expectedValue[0] + ',but actual is ' + actualValue.message + '.' + }; + } + + if (expectedValue.length == 1) { + return { + pass: false, + message: 'When only one parameter, it ' + + 'should be error type or error message.' + }; + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name === actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return {pass: true, message: 'actual error message is ' + actualValue.message + '.'}; + } else { + return { + pass: false, + message: 'except error message is ' + expectedValue[1] + ',but actual is ' + actualValue.message + '.' + }; + } + } + + if (expectedValue.length == 2 && typeof expectedValue[0] === 'function' && expectedValue[0].name !== actualValue.name) { + if (typeof expectedValue[1] === 'string' && actualValue.message === expectedValue[1]) { + return { + pass: false, + message: 'except error type is ' + expectedValue[0].name + ',but actual is ' + actualValue.name + '.' + }; + } else { + return { + pass: false, + message: 'except error type and message are incorrect.' + }; + } + } + + if (expectedValue.length > 2) { + return { + pass: false, + message: 'Up to two parameters are supported.' + }; + } +} + +export default assertPromiseIsRejectedWithError; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js new file mode 100644 index 0000000..855426c --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolved.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolved(actualPromise) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + return helper === got ? { + pass: false, + message: 'expect resolve, actualValue is isPending' + } + : {pass: true, message: 'actualValue is isResolved'}; + }, + function (rej) { + return { + pass: false, + message: 'Expected a promise to be resolved but it was ' + + 'rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolved; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js new file mode 100644 index 0000000..d5eb01e --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertPromiseIsResolvedWith.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import isPromiseLike from './isPromiseLike'; + +function assertPromiseIsResolvedWith(actualPromise, expectedValue) { + if (!isPromiseLike(actualPromise)) { + return Promise.reject().then(function () { + }, function () { + return {pass: false, message: 'Expected not be called on a promise.'}; + }); + } + + function tips(passed) { + return ( + 'Expected a promise ' + (passed ? 'not ' : '') + + 'to be resolved with ' + JSON.stringify(expectedValue[0])); + } + + const helper = {}; + return Promise.race([actualPromise, Promise.resolve(helper)]).then( + function (got) { + if (helper === got) { + return {pass: false, message: 'expect resolve, actualValue is isPending'}; + } + if (JSON.stringify(got) == JSON.stringify(expectedValue[0])) { + return { + pass: true, + message: 'actualValue was resolved with ' + JSON.stringify(got) + '.' + }; + } + return { + pass: false, + message: tips(false) + ' but it was resolved with ' + + JSON.stringify(got) + '.' + }; + }, + function (rej) { + return { + pass: false, + message: tips(false) + ' but it was rejected with ' + JSON.stringify(rej) + '.' + }; + } + ); +} + +export default assertPromiseIsResolvedWith; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js new file mode 100644 index 0000000..749cab0 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertThrowError.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertThrowError(actualValue, expected) { + let result = false; + let err; + if (typeof actualValue !== 'function') { + throw new Error('actualValue is not a function'); + } + try { + actualValue(); + return { + pass: result, + message: ' An error is not thrown while it is expected!' + }; + } catch (e) { + err = e; + } + + if (err instanceof Error) { + console.log(err.message); + if (err.message == expected[0]) { + result = true; + } + } + return { + pass: result, + message: 'expected throw failed , ' + err.message + ' is not ' + expected[0] + }; +} + +export default assertThrowError; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js new file mode 100644 index 0000000..61f092d --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/assertUndefined.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function assertUndefined(actualValue) { + return { + pass: undefined === (actualValue), + message: 'expect Undefined, actualValue is ' + (actualValue) + }; +} + +export default assertUndefined; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js new file mode 100644 index 0000000..b0be667 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/DeepTypeUtils.js @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +class DeepTypeUtils { + static getType_(value) { + return Object.prototype.toString.apply(value); + } + static isA_(typeName, value) { + return this.getType_(value) === '[object ' + typeName + ']'; + } + static isAsymmetricEqualityTester_(obj) { + return obj ? this.isA_('Function', obj.asymmetricMatch) : false; + } + + /** + * 是否是function + * @param value + */ + static isFunction_(value) { + return this.isA_('Function', value); + } + + /** + * 是否是undefined + * @param obj + */ + static isUndefined(obj) { + return obj === void 0; + } + + /** + * 是否是Node + * @param obj + */ + static isDomNode(obj) { + return obj !== null && + typeof obj === 'object' && + typeof obj.nodeType === 'number' && + typeof obj.nodeName === 'string'; + } + + /** + * 是否是promise对象 + * @param obj + */ + static isPromise (obj) { + return !!obj && obj.constructor === Promise; + }; + /** + * 是否是map对象 + * @param obj + */ + static isMap(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Map + ); + } + + /** + * 是否是set对象 + * @param obj 对象 + */ + static isSet(obj) { + return ( + obj !== null && + typeof obj !== 'undefined' && + obj.constructor === Set + ); + } + + /** + * 对象是否有key属性 + * @param obj 对象 + * @param key 对象属性名称 + */ + static has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + + /** + * 获取对象的自有属性 + * @param obj 对象 + * @param isArray 是否是数组,[object Array] + */ + static keys(obj, isArray) { + const extraKeys = []; + // 获取对象所有属性 + const allKeys = this.getAllKeys(obj); + if (!isArray) { + return allKeys; + } + if (allKeys.length === 0) { + return allKeys; + } + for (const k of allKeys) { + if (typeof k === 'symbol' || !/^[0-9]+$/.test(k)) { + extraKeys.push(k); + } + } + return extraKeys; + } + + /** + * 获取obj对象的所有属性 + * @param obj obj对象 + */ + static getAllKeys(obj) { + const keys = []; + for (let key in obj) { + if(this.has(obj, key)) { + keys.push(key); + } + } + const symbols = Object.getOwnPropertySymbols(obj); + for (const sym of symbols) { + if (obj.propertyIsEnumerable(sym)) { + keys.push(sym); + } + } + return keys; + } + +} +export default DeepTypeUtils; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js new file mode 100644 index 0000000..4d991b4 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/deepEquals/assertDeepEquals.js @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import DeepTypeUtils from './DeepTypeUtils' +function assertDeepEquals(actualValue, expected) { + console.log('actualValue:' + actualValue + ',expected:' + expected[0]); + let result = eq(actualValue, expected[0],[], []) + let msg = logMsg(actualValue, expected[0]); + return { + pass: result, + message: msg + }; +} + +/** + * 获取失败显示日志 + * @param actualValue 实际对象 + * @param expected 期待比较对象 + */ +function logMsg(actualValue, expected) { + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(actualValue); + const bClassName = Object.prototype.toString.call(expected); + let actualMsg; + let expectMsg; + if(aClassName == "[object Function]") { + actualMsg = "actualValue Function" + }else if(aClassName == "[object Promise]") { + actualMsg = "actualValue Promise" + }else if(aClassName == "[object Set]" || aClassName == "[object Map]") { + actualMsg = JSON.stringify(Array.from(actualValue));; + }else if(aClassName == "[object RegExp]") { + actualMsg = JSON.stringify(actualValue.source.replace("\\",""));; + } + else{ + actualMsg = JSON.stringify(actualValue); + } + if(bClassName == "[object Function]") { + expectMsg = "expected Function" + }else if(bClassName == "[object Promise]") { + expectMsg = "expected Promise" + }else if(aClassName == "[object Set]" || bClassName == "[object Map]") { + expectMsg = JSON.stringify(Array.from(expected)); + }else if(aClassName == "[object RegExp]") { + expectMsg = JSON.stringify(expected.source.replace("\\",""));; + } + else{ + expectMsg = JSON.stringify(expected); + } + return actualMsg + " is not deep equal " + expectMsg; +} + +function eq(a, b, aStack, bStack) { + let result = true; + console.log('a is:' + a + ',b is:' + b); + const asymmetricResult = asymmetricMatch_(a,b); + if (!DeepTypeUtils.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + + if (a instanceof Error && b instanceof Error) { + result = a.message == b.message; + return result; + } + + if (a === b) { + result = a !== 0 || 1 / a == 1 / b; + return result; + } + + if (a === null || b === null) { + result = a === b; + return result; + } + // 获取a的对象名称 + const aClassName = Object.prototype.toString.call(a); + const bClassName = Object.prototype.toString.call(b); + console.log('aClassName is:' + aClassName); + console.log('bClassName is:' + bClassName); + // 不同类型不同对象 + if (aClassName != bClassName) { + return false; + } + // 俩个string对象 + if(aClassName === '[object String]') { + result = a == String(b); + return result; + } + // 俩个Number对象 + if(aClassName === '[object Number]') { + result = a != +a ? b != +b : a === 0 && b === 0 ? 1 / a == 1 / b : a == +b; + return result; + } + + if(aClassName === '[object Date]' || aClassName === '[object Boolean]') { + result = +a == +b; + return result; + } + + // 数组 + if(aClassName === '[object ArrayBuffer]') { + return eq(new Uint8Array(a), new Uint8Array(b), aStack, bStack); + } + + // 正则表达式 + if(aClassName === '[object RegExp]') { + return ( + a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase + ); + } + + if (typeof a != 'object' || typeof b != 'object') { + return false; + } + + const aIsDomNode = DeepTypeUtils.isDomNode(a); + const bIsDomNode = DeepTypeUtils.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + result = a.isEqualNode(b); + return result; + } + if (aIsDomNode || bIsDomNode) { + return false; + } + const aIsPromise = DeepTypeUtils.isPromise(a); + const bIsPromise = DeepTypeUtils.isPromise(b); + if (aIsPromise && bIsPromise) { + return a === b; + } + let length = aStack.length; + while (length--) { + if (aStack[length] == a) { + return bStack[length] == b; + } + } + aStack.push(a); + bStack.push(b); + let size = 0; + + // 都是数组 + if(aClassName == '[object Array]') { + const aLength = a.length; + const bLength = b.length; + if (aLength !== bLength) { + // 数组长度不同,不是同一个对象 + return false; + } + for (let i = 0; i < aLength || i < bLength; i++) { + // 递归每一个元素是否相同 + result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack) && result; + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isMap(a) && DeepTypeUtils.isMap(b)) { + if (a.size != b.size) { + return false; + } + const keysA = []; + const keysB = []; + a.forEach(function(valueA, keyA) { + keysA.push(keyA); + }); + b.forEach(function(valueB, keyB) { + keysB.push(keyB); + }); + const mapKeys = [keysA, keysB]; + const cmpKeys = [keysB, keysA]; + for (let i = 0; result && i < mapKeys.length; i++) { + const mapIter = mapKeys[i]; + const cmpIter = cmpKeys[i]; + + for (let j = 0; result && j < mapIter.length; j++) { + const mapKey = mapIter[j]; + const cmpKey = cmpIter[j]; + const mapValueA = a.get(mapKey); + let mapValueB; + if ( + DeepTypeUtils.isAsymmetricEqualityTester_(mapKey) || + (DeepTypeUtils.isAsymmetricEqualityTester_(cmpKey) && + eq(mapKey, cmpKey)) + ) { + mapValueB = b.get(cmpKey); + } else { + mapValueB = b.get(mapKey); + } + result = eq(mapValueA, mapValueB, aStack, bStack); + } + } + if (!result) { + return false; + } + } else if(DeepTypeUtils.isSet(a) && DeepTypeUtils.isSet(b)) { + if (a.size != b.size) { + return false; + } + const valuesA = []; + a.forEach(function(valueA) { + valuesA.push(valueA); + }); + const valuesB = []; + b.forEach(function(valueB) { + valuesB.push(valueB); + }); + const setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; + const stackPairs = [[aStack, bStack], [bStack, aStack]]; + for (let i = 0; result && i < setPairs.length; i++) { + const baseValues = setPairs[i][0]; + const otherValues = setPairs[i][1]; + const baseStack = stackPairs[i][0]; + const otherStack = stackPairs[i][1]; + for (const baseValue of baseValues) { + let found = false; + for (let j = 0; !found && j < otherValues.length; j++) { + const otherValue = otherValues[j]; + const prevStackSize = baseStack.length; + // 深度比较对象 + found = eq(baseValue, otherValue, baseStack, otherStack); + if (!found && prevStackSize !== baseStack.length) { + baseStack.splice(prevStackSize); + otherStack.splice(prevStackSize); + } + } + result = result && found; + } + } + if (!result) { + return false; + } + } else { + const aCtor = a.constructor, + bCtor = b.constructor; + if ( + aCtor !== bCtor && + DeepTypeUtils.isFunction_(aCtor) && + DeepTypeUtils.isFunction_(bCtor) && + a instanceof aCtor && + b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor) + ) { + return false; + } + } + + // 获取对象所有的属性集合 + const aKeys = DeepTypeUtils.keys(a, aClassName == '[object Array]'); + size = aKeys.length; + + // 俩个对象属性长度不一致, 俩对象不相同 + if (DeepTypeUtils.keys(b, bClassName == '[object Array]').length !== size) { + return false; + } + + // 俩对象属性数量相同, 递归比较每个属性值得值 + for (const key of aKeys) { + console.log('key is:' + key); + // b 没有 key 属性 + if(!DeepTypeUtils.has(b, key)) { + result = false; + continue; + } + if (!eq(a[key], b[key], aStack, bStack)) { + result = false; + } + } + if (!result) { + return false; + } + aStack.pop(); + bStack.pop(); + return result; +} + +function asymmetricMatch_(a, b) { + const asymmetricA = DeepTypeUtils.isAsymmetricEqualityTester_(a); + const asymmetricB = DeepTypeUtils.isAsymmetricEqualityTester_(b); + + if (asymmetricA === asymmetricB) { + return undefined; + } + +} + +/** + * 获取对象的自有属性 + * + * @param obj 对象 + * @param isArray 是否是一个数组 + */ +function keys(obj, isArray) { + const keys = []; + +} + +export default assertDeepEquals; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js new file mode 100644 index 0000000..015ab19 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/assert/isPromiseLike.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +function isPromiseLike(obj) { + return !!obj && isFunction_(obj.then); +} + +function isFunction_(value) { + return isA_('Function', value); +} + +function isA_(typeName, value) { + return getType_(value) === '[object ' + typeName + ']'; +} + +function getType_(value) { + return Object.prototype.toString.apply(value); +} + +export default isPromiseLike; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js new file mode 100644 index 0000000..639dffc --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/DataDriver.js @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +const SUITES_KEY = 'suites'; +const SPECS_KEY = 'items'; +const DESCRIBE_KEY = 'describe'; +const IT_KEY = 'it'; +const PARAMS_KEY = 'params'; +const STRESS_KEY = 'stress'; + +class ObjectUtils { + static get(object, name, defaultValue) { + let result = defaultValue; + for (const key in object) { + if (key === name) { + return object[key]; + } + } + return result; + } + + static has(object, key) { + return Object.prototype.hasOwnProperty.call(object, key); + } +} + +class DataDriver { + constructor(attr) { + this.id = 'dataDriver'; + this.data = attr.data || {}; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + this.specService = this.coreContext.getDefaultService('spec'); + } + + getSpecParams() { + let specParams = []; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let specDesc = this.specService.getCurrentRunningSpec().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + return ObjectUtils.get(specItem, PARAMS_KEY, specParams); + } + } + } + } + return specParams; + } + + getSuiteParams() { + let suiteParams = {}; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + suiteParams = Object.assign({}, suiteParams, ObjectUtils.get(suiteItem, PARAMS_KEY, suiteParams)); + } + } + return suiteParams; + } + + getSpecStress(specDesc) { + let stress = 1; + let suiteDesc = this.suiteService.getCurrentRunningSuite().description; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, ''); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let specs = ObjectUtils.get(suiteItem, SPECS_KEY, []); + for (const specItem of specs) { + if (ObjectUtils.has(specItem, IT_KEY) && ObjectUtils.get(specItem, IT_KEY) === specDesc) { + let tempStress = ObjectUtils.get(specItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + } + } + return stress; + } + + getSuiteStress(suiteDesc) { + let stress = 1; + let suites = ObjectUtils.get(this.data, SUITES_KEY, []); + for (const suiteItem of suites) { + let describeValue = ObjectUtils.get(suiteItem, DESCRIBE_KEY, []); + if (ObjectUtils.has(suiteItem, DESCRIBE_KEY) && (typeof describeValue === 'object') && describeValue.constructor === Array && describeValue.includes(suiteDesc)) { + let tempStress = ObjectUtils.get(suiteItem, STRESS_KEY, stress); + return (Number.isInteger(tempStress) && tempStress >= 1) ? tempStress : stress; + } + } + return stress; + } +} + +export default DataDriver; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/Filter.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/Filter.js new file mode 100644 index 0000000..0ca3b4f --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/Filter.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +class ClassFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return !this.params.split(',').map(item => item.split('#')[0]).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + let classArray = this.params.split(',') || []; + let suiteFilterResult = classArray.filter(item => !item.includes('#')).map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + let itFilterResult = classArray.filter(item => item.includes('#')).map(item => item == (this.suiteName + '#' + this.itName)).reduce((pre, cur) => pre || cur, false); + return !(suiteFilterResult || itFilterResult); + } +} + +class NotClassFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + return this.params.split(',').some(item => item == (this.suiteName + '#' + this.itName)); + } +} + +class SuiteAndItNameFilter { + constructor(suiteName, itName, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + } + + filterSuite() { + return !this.params.split(',').map(item => item == this.suiteName).reduce((pre, cur) => pre || cur, false); + } + + filterIt() { + return !this.params.split(',').map(item => item == this.itName).reduce((pre, cur) => pre || cur, false); + } +} + + +class TestTypesFilter { + constructor(suiteName, itName, fi, params) { + this.suiteName = suiteName; + this.itName = itName; + this.params = params; + this.fi = fi; + } + + filterIt() { + return !((this.params === (this.fi & this.params)) || this.fi === 0); + } +} + +export {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter}; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/configService.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/configService.js new file mode 100644 index 0000000..745f137 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/config/configService.js @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import {ClassFilter, NotClassFilter, SuiteAndItNameFilter, TestTypesFilter} from './Filter'; +const STRESS_RULE = /^[1-9]\d*$/; + +class ConfigService { + constructor(attr) { + this.id = attr.id; + this.supportAsync = false; + this.random = false; + this.filterValid = []; + this.filter = 0; + this.flag = false; + this.suite = null; + this.itName = null; + this.testType = null; + this.level = null; + this.size = null; + this.class = null; + this.notClass = null; + this.timeout = null; + // 遇错即停模式配置 + this.breakOnError = false; + // 压力测试配置 + this.stress = null; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + isNormalInteger(str) { + const n = Math.floor(Number(str)); + return n !== Infinity && String(n) === String(str) && n >= 0; + } + + getStress() { + if (this.stress === undefined || this.stress === '' || this.stress === null) { + return 1; + } + return !this.stress.match(STRESS_RULE) ? 1 : Number.parseInt(this.stress); + } + + basicParamValidCheck(params) { + let size = params.size; + if (size !== undefined && size !== '' && size !== null) { + let sizeArray = ['small', 'medium', 'large']; + if (sizeArray.indexOf(size) === -1) { + this.filterValid.push('size:' + size); + } + } + let level = params.level; + if (level !== undefined && level !== '' && level !== null) { + let levelArray = ['0', '1', '2', '3', '4']; + if (levelArray.indexOf(level) === -1) { + this.filterValid.push('level:' + level); + } + } + let testType = params.testType; + if (testType !== undefined && testType !== '' && testType !== null) { + let testTypeArray = ['function', 'performance', 'power', 'reliability', 'security', + 'global', 'compatibility', 'user', 'standard', 'safety', 'resilience']; + if (testTypeArray.indexOf(testType) === -1) { + this.filterValid.push('testType:' + testType); + } + } + } + + filterParamValidCheck(params) { + let timeout = params.timeout; + if (timeout !== undefined && timeout !== '' && timeout !== null) { + if (!this.isNormalInteger(timeout)) { + this.filterValid.push('timeout:' + timeout); + } + } + + let paramKeys = ['dryRun', 'random', 'breakOnError', 'coverage']; + for (const key of paramKeys) { + if (params[key] !== undefined && params[key] !== 'true' && params[key] !== 'false') { + this.filterValid.push(`${key}:${params[key]}`); + } + } + + // 压力测试参数验证,正整数 + if (params.stress !== undefined && params.stress !== '' && params.stress !== null) { + if (!params.stress.match(STRESS_RULE)) { + this.filterValid.push('stress:' + params.stress); + } + } + + let nameRule = /^[A-Za-z]{1}[\w#,.]*$/; + let paramClassKeys = ['class', 'notClass']; + for (const key of paramClassKeys) { + if (params[key] !== undefined && params[key] !== '' && params[key] !== null) { + let classArray = params[key].split(','); + classArray.forEach(item => !item.match(nameRule) ? this.filterValid.push(`${key}:${params[key]}`) : null); + } + } + } + + setConfig(params) { + this.basicParamValidCheck(params); + this.filterParamValidCheck(params); + try { + this.class = params.class; + this.notClass = params.notClass; + this.flag = params.flag || {flag: false}; + this.suite = params.suite; + this.itName = params.itName; + this.filter = params.filter; + this.testType = params.testType; + this.level = params.level; + this.size = params.size; + this.timeout = params.timeout; + this.dryRun = params.dryRun; + this.breakOnError = params.breakOnError; + this.random = params.random === 'true' ? true : false; + this.stress = params.stress; + this.coverage = params.coverage; + this.filterParam = { + testType: { + 'function': 1, + 'performance': 1 << 1, + 'power': 1 << 2, + 'reliability': 1 << 3, + 'security': 1 << 4, + 'global': 1 << 5, + 'compatibility': 1 << 6, + 'user': 1 << 7, + 'standard': 1 << 8, + 'safety': 1 << 9, + 'resilience': 1 << 10, + }, + level: { + '0': 1 << 24, + '1': 1 << 25, + '2': 1 << 26, + '3': 1 << 27, + '4': 1 << 28, + }, + size: { + 'small': 1 << 16, + 'medium': 1 << 17, + 'large': 1 << 18, + } + }; + this.parseParams(); + } catch (err) { + console.info('setConfig error: ' + err.message); + } + } + + parseParams() { + if (this.filter != null) { + return; + } + let testTypeFilter = 0; + let sizeFilter = 0; + let levelFilter = 0; + if (this.testType != null) { + testTypeFilter = this.testType.split(',') + .map(item => this.filterParam.testType[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.level != null) { + levelFilter = this.level.split(',') + .map(item => this.filterParam.level[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + if (this.size != null) { + sizeFilter = this.size.split(',') + .map(item => this.filterParam.size[item] || 0) + .reduce((pre, cur) => pre | cur, 0); + } + this.filter = testTypeFilter | sizeFilter | levelFilter; + console.info('filter params:' + this.filter); + } + + isCurrentSuite(description) { + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + let suiteArray = this.suite.split(','); + return suiteArray.indexOf(description) !== -1; + } + return false; + } + + filterSuite(currentSuiteName) { + let filterArray = []; + if (this.suite !== undefined && this.suite !== '' && this.suite !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, '', this.suite)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, '', this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, '', this.notClass)); + } + + let result = filterArray.map(item => item.filterSuite()).reduce((pre, cur) => pre || cur, false); + return result; + } + + filterDesc(currentSuiteName, desc, fi, coreContext) { + let filterArray = []; + if (this.itName !== undefined && this.itName !== '' && this.itName !== null) { + filterArray.push(new SuiteAndItNameFilter(currentSuiteName, desc, this.itName)); + } + if (this.class !== undefined && this.class !== '' && this.class !== null) { + filterArray.push(new ClassFilter(currentSuiteName, desc, this.class)); + } + if (this.notClass !== undefined && this.notClass !== '' && this.notClass !== null) { + filterArray.push(new NotClassFilter(currentSuiteName, desc, this.notClass)); + } + if (typeof (this.filter) !== 'undefined' && this.filter !== 0 && fi !== 0) { + filterArray.push(new TestTypesFilter('', '', fi, this.filter)); + } + let result = filterArray.map(item => item.filterIt()).reduce((pre, cur) => pre || cur, false); + return result; + } + + isRandom() { + return this.random || false; + } + + isBreakOnError() { + return this.breakOnError !== 'true' ? false : true; + } + + setSupportAsync(value) { + this.supportAsync = value; + } + + isSupportAsync() { + return this.supportAsync; + } + + translateParams(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage', 'class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = {}; + for (const key in parameters) { + if (keySet.has(key)) { + var newKey = key.replace("-s ", ""); + targetParams[newKey] = parameters[key]; + } + } + return targetParams; + } + translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s itName', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun', '-s random', '-s breakOnError', '-s stress', + '-s coverage','class', 'notClass', 'suite', 'itName', + 'level', 'testType', 'size', 'timeout', 'dryRun', 'random', + 'breakOnError', 'stress', 'coverage' + ]); + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams += ' ' + key + ' ' + parameters[key]; + } + } + return targetParams.trim(); + } + + execute() { + } +} + +export { + ConfigService +}; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js new file mode 100644 index 0000000..d73d46d --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/kit/SysTestKit.js @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +class SysTestKit { + + static delegator = null; + static systemTime = null; + + constructor() { + this.id = 'sysTestKit'; + this.index = 0; + } + + static actionStart(tag) { + console.info(JSON.stringify(tag)); + var message = '\n' + 'OHOS_REPORT_ACTIONSTART: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(tag + ' actionStart print success'); + } + + static actionEnd(tag) { + console.info(JSON.stringify(tag)); + var message = '\n' + 'OHOS_REPORT_ACTIONEND: ' + JSON.stringify(tag) + '\n'; + SysTestKit.print(message); + console.info(tag + ' actionEnd print success'); + } + + static async existKeyword(keyword, timeout) { + let reg = new RegExp(/^[a-zA-Z0-9]{1,}$/) + if (!reg.test(keyword)) { + throw new Error('keyword must contain more than one string, and only letters and numbers are supported.') + } + timeout = timeout || 4; + + let searchResult = false; + let cmd = 'hilog -x | grep -i \'' + keyword + '\' | wc -l'; + await executePromise(cmd, timeout).then((data) => { + searchResult = data; + }); + return searchResult; + } + static async print(message) { + if ('printSync' in SysTestKit.delegator) { + console.debug(`printSync called ...`); + SysTestKit.delegator.printSync(message); + } else { + await SysTestKit.delegator.print(message); + } + } + + static async getRealTime() { + let currentTime = new Date().getTime(); + if (SysTestKit.systemTime !== null && SysTestKit.systemTime !== undefined) { + await SysTestKit.systemTime.getRealTime().then((time) => { + console.info(`systemTime.getRealTime success data: ${JSON.stringify(time)}`); + currentTime = time; + }).catch((error) => { + console.error(`failed to systemTime.getRealTime because ${JSON.stringify(error)}`); + }); + } + return currentTime; + } +} + +function executePromise(cmd, timeout) { + return new Promise((resolve, reject) => { + SysTestKit.delegator.executeShellCommand(cmd, timeout, + (error, data) => { + console.info('existKeyword CallBack: err : ' + JSON.stringify(error)); + console.info('existKeyword CallBack: data : ' + JSON.stringify(data)); + resolve(parseInt(data.stdResult) > 3 ? true : false); + }); + }); +} + +export default SysTestKit; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js new file mode 100644 index 0000000..6a9d7aa --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ArgumentMatchers.js @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +class ArgumentMatchers { + ANY = ""; + ANY_STRING = ""; + ANY_BOOLEAN = ""; + ANY_NUMBER = ""; + ANY_OBJECT = ""; + ANY_FUNCTION = ""; + MATCH_REGEXS = ""; + + static any() { + } + + static anyString() { + } + + static anyBoolean() { + } + + static anyNumber() { + } + + static anyObj() { + } + + static anyFunction() { + } + + static matchRegexs() { + let regex = arguments[0]; + if (ArgumentMatchers.isRegExp(regex)) { + return regex; + } + throw Error("not a regex"); + } + + static isRegExp(value) { + return Object.prototype.toString.call(value) === "[object RegExp]"; + } + + matcheReturnKey() { + let arg = arguments[0]; + let regex = arguments[1]; + let stubSetKey = arguments[2]; + + if (stubSetKey && stubSetKey == this.ANY) { + return this.ANY; + } + + if (typeof arg === "string" && !regex) { + return this.ANY_STRING; + } + + if (typeof arg === "boolean" && !regex) { + return this.ANY_BOOLEAN; + } + + if (typeof arg === "number" && !regex) { + return this.ANY_NUMBER; + } + + if (typeof arg === "object" && !regex) { + return this.ANY_OBJECT; + } + + if (typeof arg === "function" && !regex) { + return this.ANY_FUNCTION; + } + + if (typeof arg === "string" && regex) { + return regex.test(arg); + } + + return null; + } + + matcheStubKey() { + let key = arguments[0]; + + if (key === ArgumentMatchers.any) { + return this.ANY; + } + + if (key === ArgumentMatchers.anyString) { + return this.ANY_STRING; + } + if (key === ArgumentMatchers.anyBoolean) { + return this.ANY_BOOLEAN; + } + if (key === ArgumentMatchers.anyNumber) { + return this.ANY_NUMBER; + } + if (key === ArgumentMatchers.anyObj) { + return this.ANY_OBJECT; + } + if (key === ArgumentMatchers.anyFunction) { + return this.ANY_FUNCTION; + } + + if (ArgumentMatchers.isRegExp(key)) { + return key; + } + + return null; + } +} + +export default ArgumentMatchers; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js new file mode 100644 index 0000000..c6a866a --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/ExtendInterface.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +class ExtendInterface { + constructor(mocker) { + this.mocker = mocker; + } + + stub() { + this.params = arguments; + return this; + } + + stubMockedCall(returnInfo) { + this.mocker.stubApply(this, this.params, returnInfo); + } + + afterReturn(value) { + this.stubMockedCall(function () { + return value; + }); + } + + afterReturnNothing() { + this.stubMockedCall(function () { + return undefined; + }); + } + + afterAction(action) { + this.stubMockedCall(action); + } + + afterThrow(msg) { + this.stubMockedCall(function () { + throw msg; + }); + } + + clear() { + this.mocker.clear(); + } +} + +export default ExtendInterface; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js new file mode 100644 index 0000000..a234624 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/MockKit.js @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import ExtendInterface from "./ExtendInterface"; +import VerificationMode from "./VerificationMode"; +import ArgumentMatchers from "./ArgumentMatchers"; + +class MockKit { + + constructor() { + this.mFunctions = []; + this.stubs = new Map(); + this.recordCalls = new Map(); + this.currentSetKey = null; + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + init() { + this.reset(); + } + + reset() { + this.mFunctions = []; + this.stubs = {}; + this.recordCalls = {}; + this.currentSetKey = null; + this.mockObj = null; + this.recordMockedMethod = new Map(); + } + + clearAll() { + this.reset(); + var props = Object.keys(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + + var props = Object.getOwnPropertyNames(this); + for (var i = 0; i < props.length; i++) { + delete this[props[i]]; + } + for (var key in this) { + delete this[key]; + } + } + + clear(obj) { + if (!obj) throw Error("Please enter an object to be cleaned"); + if (typeof (obj) != 'object') throw new Error('Not a object'); + this.recordMockedMethod.forEach(function (value, key, map) { + if (key) { + obj[key] = value; + } + }); + } + + ignoreMock(obj, method) { + if (typeof (obj) != 'object') throw new Error('Not a object'); + if (typeof (method) != 'function') throw new Error('Not a function'); + let og = this.recordMockedMethod.get(method.propName); + if (og) { + obj[method.propName] = og; + this.recordMockedMethod.set(method.propName, undefined); + } + } + + extend(dest, source) { + dest["stub"] = source["stub"]; + dest["afterReturn"] = source["afterReturn"]; + dest["afterReturnNothing"] = source["afterReturnNothing"]; + dest["afterAction"] = source["afterAction"]; + dest["afterThrow"] = source["afterThrow"]; + dest["stubMockedCall"] = source["stubMockedCall"]; + dest["clear"] = source["clear"]; + return dest; + } + + stubApply(f, params, returnInfo) { + let values = this.stubs.get(f); + if (!values) { + values = new Map(); + } + let key = params[0]; + if (typeof key == "undefined") { + key = "anonymous-mock-" + f.propName; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheStubKey(key)) { + key = matcher.matcheStubKey(key); + if (key) { + this.currentSetKey = key; + } + } + values.set(key, returnInfo); + this.stubs.set(f, values); + } + + getReturnInfo(f, params) { + let values = this.stubs.get(f); + if (!values) { + return undefined; + } + let retrunKet = params[0]; + if (typeof retrunKet == "undefined") { + retrunKet = "anonymous-mock-" + f.propName; + } + let stubSetKey = this.currentSetKey; + + if (this.currentSetKey && (typeof (retrunKet) != "undefined")) { + retrunKet = stubSetKey; + } + let matcher = new ArgumentMatchers(); + if (matcher.matcheReturnKey(params[0], undefined, stubSetKey) && matcher.matcheReturnKey(params[0], undefined, stubSetKey) != stubSetKey) { + retrunKet = params[0]; + } + + values.forEach(function (value, key, map) { + if (ArgumentMatchers.isRegExp(key) && matcher.matcheReturnKey(params[0], key)) { + retrunKet = key; + } + }); + + return values.get(retrunKet); + } + + findName(obj, value) { + let properties = this.findProperties(obj); + let name = null; + properties.forEach( + function (va1, idx, array) { + if (obj[va1] === value) { + name = va1; + } + } + ); + return name; + } + + isFunctionFromPrototype(f, container, propName) { + if (container.constructor != Object && container.constructor.prototype !== container) { + return container.constructor.prototype[propName] === f; + } + return false; + } + + findProperties(obj, ...arg) { + function getProperty(new_obj) { + if (new_obj.__proto__ === null) { + return []; + } + let properties = Object.getOwnPropertyNames(new_obj); + return [...properties, ...getProperty(new_obj.__proto__)]; + } + return getProperty(obj); + } + + recordMethodCall(originalMethod, args) { + Function.prototype.getName = function () { + return this.name || this.toString().match(/function\s*([^(]*)\(/)[1]; + }; + let name = originalMethod.getName(); + let arglistString = name + '(' + Array.from(args).toString() + ')'; + let records = this.recordCalls.get(arglistString); + if (!records) { + records = 0; + } + records++; + this.recordCalls.set(arglistString, records); + } + + mockFunc(originalObject, originalMethod) { + let tmp = this; + this.originalMethod = originalMethod; + let f = function () { + let args = arguments; + let action = tmp.getReturnInfo(f, args); + if (originalMethod) { + tmp.recordMethodCall(originalMethod, args); + } + if (action) { + return action.apply(this, args); + } + }; + + f.container = null || originalObject; + f.original = originalMethod || null; + + if (originalObject && originalMethod) { + if (typeof (originalMethod) != 'function') throw new Error('Not a function'); + var name = this.findName(originalObject, originalMethod); + originalObject[name] = f; + this.recordMockedMethod.set(name, originalMethod); + f.propName = name; + f.originalFromPrototype = this.isFunctionFromPrototype(f.original, originalObject, f.propName); + } + f.mocker = this; + this.mFunctions.push(f); + this.extend(f, new ExtendInterface(this)); + return f; + } + + verify(methodName, argsArray) { + if (!methodName) { + throw Error("not a function name"); + } + let a = this.recordCalls.get(methodName + '(' + argsArray.toString() + ')'); + return new VerificationMode(a ? a : 0); + } + + mockObject(object) { + if (!object || typeof object === "string") { + throw Error(`this ${object} cannot be mocked`); + } + const _this = this; + let mockedObject = {}; + let keys = Reflect.ownKeys(object); + keys.filter(key => (typeof Reflect.get(object, key)) === 'function') + .forEach(key => { + mockedObject[key] = object[key]; + mockedObject[key] = _this.mockFunc(mockedObject, mockedObject[key]); + }); + return mockedObject; + } +} + +function ifMockedFunction(f) { + if (Object.prototype.toString.call(f) != "[object Function]" && + Object.prototype.toString.call(f) != "[object AsyncFunction]") { + throw Error("not a function"); + } + if (!f.stub) { + throw Error("not a mock function"); + } + return true; +} + +function when(f) { + if (ifMockedFunction(f)) { + return f.stub.bind(f); + } +} + +export {MockKit, when}; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js new file mode 100644 index 0000000..7bd04c8 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/mock/VerificationMode.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import {expect} from '../../interface'; + +class VerificationMode { + constructor(times) { + this.doTimes = times; + } + + times(count) { + expect(count).assertEqual(this.doTimes); + } + + never() { + console.log(this.doTimes); + expect(0).assertEqual(this.doTimes); + } + + once() { + expect(1).assertEqual(this.doTimes); + } + + atLeast(count) { + if (count > this.doTimes) { + throw Error('failed ' + count + ' greater than the actual execution times of method'); + } + } + + atMost(count) { + if (count < this.doTimes) { + throw Error('failed ' + count + ' less than the actual execution times of method'); + } + } +} + +export default VerificationMode; \ No newline at end of file diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js new file mode 100644 index 0000000..da120dd --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/OhReport.js @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import SysTestKit from "../kit/SysTestKit"; +import {collectCoverageData} from '../coverage/coverageCollect'; + +class OhReport { + constructor(attr) { + this.delegator = attr.delegator; + this.abilityDelegatorArguments = attr.abilityDelegatorArguments; + this.id = 'report'; + this.index = 0; + this.duration = 0; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + this.specService = this.coreContext.getDefaultService('spec'); + } + + taskStart() { + } + + async taskDone() { + if (this.abilityDelegatorArguments !== null) { + this.taskDoneTime = new Date().getTime(); + let summary = this.suiteService.getSummary(); + const configService = this.coreContext.getDefaultService('config'); + if (configService['coverage'] === 'true') { + await collectCoverageData(); + } + let message = '\n' + 'OHOS_REPORT_RESULT: stream=Tests run: ' + summary.total + ', Failure: ' + summary.failure; + message += ', Error: ' + summary.error; + message += ', Pass: ' + summary.pass; + message += ', Ignore: ' + summary.ignore; + message += '\n' + 'OHOS_REPORT_CODE: ' + (summary.failure > 0 ? -1 : 0) + '\n'; + let isHasError = summary.failure > 0 || summary.error > 0; + let config = this.coreContext.getDefaultService('config'); + if (config.isBreakOnError() && isHasError) { + // 未执行全部说明 + message += '\n' + 'OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error' + '\n'; + } + message += 'OHOS_REPORT_STATUS: taskconsuming=' + summary.duration + '\n'; + console.info(message); + await SysTestKit.print(message); + } + console.info('report print success'); + this.delegator.finishTest('your test finished!!!', 0, () => { }); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + var value = this.coreContext.getDefaultService('config').filterValid; + var message = 'this param ' + value.join(',') + ' is invalid' + '\n'; + this.delegator.finishTest(message, 0, () => { + }); + } + } + + async suiteStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_SUM: ' + this.suiteService.getCurrentRunningSuite().getSpecsNum(); + message += '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description + '\n'; + console.info(message); + await SysTestKit.print(message); + console.info(this.suiteService.getCurrentRunningSuite().description + ' suiteStart print success'); + } + } + + async suiteDone() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: suiteconsuming=' + this.suiteService.getCurrentRunningSuite().duration + '\n'; + console.info(message); + await SysTestKit.print(message); + console.info(this.suiteService.getCurrentRunningSuite().description + ' suiteDone print success'); + } + } + + async specStart() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (++this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 1' + '\n'; + console.info(message); + await SysTestKit.print(message); + console.info(this.specService.currentRunningSpec.description + ' specStart start print success'); + } + } + + async specDone() { + if (this.abilityDelegatorArguments !== null) { + let message = '\n' + 'OHOS_REPORT_STATUS: class=' + this.suiteService.getCurrentRunningSuite().description; + message += '\n' + 'OHOS_REPORT_STATUS: current=' + (this.index); + message += '\n' + 'OHOS_REPORT_STATUS: id=JS'; + message += '\n' + 'OHOS_REPORT_STATUS: numtests=' + this.specService.getTestTotal(); + let errorMsg = ''; + if (this.specService.currentRunningSpec.error) { + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + this.specService.currentRunningSpec.error.message; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -1' + '\n'; + } else if (this.specService.currentRunningSpec.result) { + if (this.specService.currentRunningSpec.result.failExpects.length > 0) { + this.specService.currentRunningSpec.result.failExpects.forEach(failExpect => { + errorMsg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue)); + }); + message += '\n' + 'OHOS_REPORT_STATUS: stack=' + errorMsg; + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'Error in ' + this.specService.currentRunningSpec.description; + message += '\n' + errorMsg + '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: -2' + '\n'; + } else { + message += '\n' + 'OHOS_REPORT_STATUS: stream='; + message += '\n' + 'OHOS_REPORT_STATUS: test=' + this.specService.currentRunningSpec.description; + message += '\n' + 'OHOS_REPORT_STATUS_CODE: 0' + '\n'; + } + } else { + message += '\n'; + } + message += 'OHOS_REPORT_STATUS: consuming=' + this.specService.currentRunningSpec.duration + '\n'; + console.info(message); + await SysTestKit.print(message); + console.info(this.specService.currentRunningSpec.description + ' specDone end print success'); + } + } +} + +export default OhReport; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js new file mode 100644 index 0000000..852fbcd --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/module/report/ReportExtend.js @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +class ReportExtend { + constructor(fileModule) { + this.id = 'extend'; + this.fileModule = fileModule; + } + + init(coreContext) { + this.coreContext = coreContext; + this.suiteService = this.coreContext.getDefaultService('suite'); + } + + taskStart() { + + } + + taskDone() { + const report = { + tag: 'testsuites', + name: 'summary_report', + timestamp: new Date().toDateString(), + time: '1', + errors: 0, + failures: 0, + tests: 0, + children: [] + }; + const rootSuite = this.suiteService.rootSuite; + if (rootSuite && rootSuite.childSuites) { + for (let testsuite of rootSuite.childSuites) { + let suiteReport = { + tag: 'testsuite', + name: testsuite['description'], + errors: 0, + tests: 0, + failures: 0, + time: '0.1', + children: [] + }; + let specs = testsuite['specs']; + for (let testcase of specs) { + report.tests++; + suiteReport.tests++; + let caseReport = { + tag: 'testcase', + name: testcase['description'], + status: 'run', + time: '0.0', + classname: testsuite['description'] + }; + if (testcase.error) { + caseReport['result'] = false; + caseReport['children'] = [{ + tag: 'error', + type: '', + message: testcase.error.message + }]; + report.errors++; + suiteReport.errors++; + } else if (testcase.result.failExpects.length > 0) { + caseReport['result'] = false; + let message = ''; + testcase.result.failExpects.forEach(failExpect => { + message += failExpect.message || ('expect ' + failExpect.actualValue + ' ' + failExpect.checkFunc + ' ' + (failExpect.expectValue || '')) + ';'; + }); + caseReport['children'] = [{ + tag: 'failure', + type: '', + message: message + }]; + report.failures++; + suiteReport.failures++; + } else { + caseReport['result'] = true; + } + suiteReport.children.push(caseReport); + } + report.children.push(suiteReport); + } + } + + let reportXml = '\n' + json2xml(report); + this.fileModule.writeText({ + uri: 'internal://app/report.xml', + text: reportXml, + success: function () { + console.info('call success callback success'); + }, + fail: function (data, code) { + console.info('call fail callback success:'); + }, + complete: function () { + console.info('call complete callback success'); + } + }); + } +} + +function json2xml(json) { + let tagName; + let hasChildren = false; + let childrenStr = ''; + let attrStr = ''; + for (let key in json) { + if (key === 'tag') { + tagName = json[key]; + } else if (key === 'children') { + if (json[key].length > 0) { + hasChildren = true; + for (let child of json[key]) { + childrenStr += json2xml(child); + } + } + } else { + attrStr += ` ${key}="${json[key]}"`; + } + } + let xml = `<${tagName}${attrStr}`; + xml += hasChildren ? `>${childrenStr}` : '/>'; + return xml; +} + +export default ReportExtend; diff --git a/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/service.js b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/service.js new file mode 100644 index 0000000..e55a2e4 --- /dev/null +++ b/sqflite/ohos/oh_modules/.ohpm/@ohos+hypium@1.0.6/oh_modules/@ohos/hypium/src/main/service.js @@ -0,0 +1,929 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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. + */ + +import SysTestKit from "./module/kit/SysTestKit"; + +class AssertException extends Error { + constructor(message) { + super(); + this.name = "AssertException"; + this.message = message; + } +} + +function getFuncWithArgsZero(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + try { + await func(); + } catch (err) { + reject(err); + } + timer !== null ? clearTimeout(timer) : null; + resolve(); + }); +} + +function getFuncWithArgsOne(func, timeout, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout);; + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function getFuncWithArgsTwo(func, timeout, paramItem, isStressTest) { + return new Promise(async (resolve, reject) => { + let timer = null; + if (!isStressTest) { + timer = setTimeout(() => { + reject(new Error('execute timeout ' + timeout + 'ms')); + }, timeout); + } + + function done() { + timer !== null ? clearTimeout(timer) : null; + resolve(); + } + + try { + await func(done, paramItem); + } catch (err) { + timer !== null ? clearTimeout(timer) : null; + reject(err); + } + }); +} + +function processFunc(coreContext, func) { + let argNames = ((func || '').toString() + .replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '') + .match(/^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m) || ['', '', ''])[2] + .split(',') // split parameters + .map(item => item.replace(/^\s*(_?)(.+?)\1\s*$/, name => name.split('=')[0].trim())) + .filter(String); + let funcLen = func.length; + let processedFunc; + const config = coreContext.getDefaultService('config'); + config.setSupportAsync(true); + const timeout = + (config.timeout === undefined ? 5000 : config.timeout); + const isStressTest = (coreContext.getServices('dataDriver') !== undefined || config.getStress() > 1); + switch (funcLen) { + case 0: { + processedFunc = function () { + return getFuncWithArgsZero(func, timeout, isStressTest); + }; + break; + } + case 1: { + if (argNames[0] === 'data') { + processedFunc = function (paramItem) { + func(paramItem); + }; + } else { + processedFunc = function () { + return getFuncWithArgsOne(func, timeout, isStressTest); + }; + } + break; + } + default: { + processedFunc = function (paramItem) { + return getFuncWithArgsTwo(func, timeout, paramItem, isStressTest); + }; + break; + } + } + return processedFunc; +} + +function secureRandomNumber() { + return crypto.randomBytes(8).readUInt32LE() / 0xffffffff; +} + +class SuiteService { + constructor(attr) { + this.id = attr.id; + this.rootSuite = new SuiteService.Suite({}); + this.currentRunningSuite = this.rootSuite; + this.suitesStack = [this.rootSuite]; + } + + describe(desc, func) { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterSuite(desc)) { + console.info('filter suite :' + desc); + return; + } + const suite = new SuiteService.Suite({description: desc}); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let suiteStress = this.coreContext.getServices('dataDriver').dataDriver.getSuiteStress(desc); + for (let i = 1; i < suiteStress; i++) { + this.currentRunningSuite.childSuites.push(suite); + } + } + this.currentRunningSuite.childSuites.push(suite); + this.currentRunningSuite = suite; + this.suitesStack.push(suite); + func.call(); + let childSuite = this.suitesStack.pop(); + if (this.suitesStack.length === 0) { + this.currentRunningSuite = childSuite; + this.suitesStack.push(childSuite); + } + if (this.suitesStack.length > 1) { + this.currentRunningSuite = this.suitesStack.pop(); + } else { + this.currentRunningSuite = this.suitesStack.pop(); + this.suitesStack.push(this.currentRunningSuite); + } + } + + beforeAll(func) { + this.currentRunningSuite.beforeAll.push(processFunc(this.coreContext, func)); + } + + beforeEach(func) { + this.currentRunningSuite.beforeEach.push(processFunc(this.coreContext, func)); + } + + afterAll(func) { + this.currentRunningSuite.afterAll.push(processFunc(this.coreContext, func)); + } + + afterEach(func) { + this.currentRunningSuite.afterEach.push(processFunc(this.coreContext, func)); + } + + getCurrentRunningSuite() { + return this.currentRunningSuite; + } + + setCurrentRunningSuite(suite) { + this.currentRunningSuite = suite; + } + + traversalResults(suite, obj, breakOnError) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return obj; + } + if (suite.specs.length > 0) { + for (const itItem of suite.specs) { + obj.total++; + if (breakOnError && (obj.error > 0 || obj.failure > 0)) { // breakOnError模式 + continue; + } + if (itItem.error) { + obj.error++; + } else if (itItem.result.failExpects.length > 0) { + obj.failure++; + } else if (itItem.result.pass === true) { + obj.pass++; + } + } + } + + obj.duration += suite.duration; + + if (suite.childSuites.length > 0) { + for (const suiteItem of suite.childSuites) { + this.traversalResults(suiteItem, obj, breakOnError); + } + } + } + + getSummary() { + let suiteService = this.coreContext.getDefaultService('suite'); + let rootSuite = suiteService.rootSuite; + const specService = this.coreContext.getDefaultService('spec'); + const configService = this.coreContext.getDefaultService('config'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + let isBreaKOnError = breakOnError && isError; + let obj = {total: 0, failure: 0, error: 0, pass: 0, ignore: 0, duration: 0}; + for (const suiteItem of rootSuite.childSuites) { + this.traversalResults(suiteItem, obj, isBreaKOnError); + } + obj.ignore = obj.total - obj.pass - obj.failure - obj.error; + return obj; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + traversalSuites(suite, obj, configService) { + if (suite.childSuites.length === 0 && suite.specs.length === 0) { + return []; + } + if (suite.specs.length > 0) { + let itArray = []; + for (const itItem of suite['specs']) { + if (!configService.filterDesc(suite.description, itItem.description, itItem.fi, null)) { + itArray.push({'itName': itItem.description}); + } + } + obj[suite.description] = itArray; + } + + if (suite.childSuites.length > 0) { + let suiteArray = []; + for (const suiteItem of suite.childSuites) { + let suiteObj = {}; + this.traversalSuites(suiteItem, suiteObj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suiteArray.push(suiteObj); + } + } + obj.suites = suiteArray; + } + } + + async dryRun(abilityDelegator) { + const configService = this.coreContext.getDefaultService('config'); + let testSuitesObj = {}; + let suitesArray = []; + for (const suiteItem of this.rootSuite.childSuites) { + let obj = {}; + this.traversalSuites(suiteItem, obj, configService); + if (!configService.filterSuite(suiteItem.description)) { + suitesArray.push(obj); + } + } + testSuitesObj['suites'] = suitesArray; + + let strJson = JSON.stringify(testSuitesObj); + let strLen = strJson.length; + let maxLen = 500; + let maxCount = Math.floor(strLen / maxLen); + + for (let count = 0; count <= maxCount; count++) { + await SysTestKit.print(strJson.substring(count * maxLen, (count + 1) * maxLen)); + } + console.info('dryRun print success'); + abilityDelegator.finishTest('dry run finished!!!', 0, () => { }); + } + + execute() { + const configService = this.coreContext.getDefaultService('config'); + if (configService.filterValid.length !== 0) { + this.coreContext.fireEvents('task', 'incorrectFormat'); + return; + } + + if (configService.isRandom() && this.rootSuite.childSuites.length > 0) { + this.rootSuite.childSuites.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + this.currentRunningSuite = this.rootSuite.childSuites[0]; + } + + if (configService.isSupportAsync()) { + let asyncExecute = async () => { + await this.coreContext.fireEvents('task', 'taskStart'); + await this.rootSuite.asyncRun(this.coreContext); + }; + asyncExecute().then(async () => { + await this.coreContext.fireEvents('task', 'taskDone'); + }); + } else { + this.coreContext.fireEvents('task', 'taskStart'); + this.rootSuite.run(this.coreContext); + this.coreContext.fireEvents('task', 'taskDone'); + } + } + + apis() { + const _this = this; + return { + describe: function (desc, func) { + return _this.describe(desc, func); + }, + beforeAll: function (func) { + return _this.beforeAll(func); + }, + beforeEach: function (func) { + return _this.beforeEach(func); + }, + afterAll: function (func) { + return _this.afterAll(func); + }, + afterEach: function (func) { + return _this.afterEach(func); + } + }; + } +} + +SuiteService.Suite = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.childSuites = []; + this.specs = []; + this.beforeAll = []; + this.afterAll = []; + this.beforeEach = []; + this.afterEach = []; + this.duration = 0; + } + + pushSpec(spec) { + this.specs.push(spec); + } + + removeSpec(desc) { + this.specs = this.specs.filter((item, index) => { + return item.description !== desc; + }); + } + + getSpecsNum() { + return this.specs.length; + } + + isRun(coreContext) { + const configService = coreContext.getDefaultService('config'); + const suiteService = coreContext.getDefaultService('suite'); + const specService = coreContext.getDefaultService('spec'); + let breakOnError = configService.isBreakOnError(); + let isError = specService.getStatus(); + return breakOnError && isError; + } + + run(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteStart', this); + } + this.runHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + for (let spec in this.specs) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + this.runHookFunc('beforeEach'); + spec.run(coreContext); + this.runHookFunc('afterEach'); + } + } + if (this.childSuites.length > 0) { + for (let suite in this.childSuites) { + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + break; + } + suite.run(coreContext); + suiteService.setCurrentRunningSuite(suite); + } + } + this.runHookFunc('afterAll'); + if (this.description !== '') { + coreContext.fireEvents('suite', 'suiteDone'); + } + } + + async asyncRun(coreContext) { + const suiteService = coreContext.getDefaultService('suite'); + suiteService.setCurrentRunningSuite(this); + suiteService.suitesStack.push(this); + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteStart', this); + } + await this.runAsyncHookFunc('beforeAll'); + if (this.specs.length > 0) { + const configService = coreContext.getDefaultService('config'); + if (configService.isRandom()) { + this.specs.sort(function () { + return Math.random().toFixed(1) > 0.5 ? -1 : 1; + }); + } + for (let i = 0; i < this.specs.length; i++) { + // 遇错即停模式,发现用例有问题,直接返回,不在执行后面的it + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log("break description :" + this.description); + break; + } + await this.runAsyncHookFunc('beforeEach'); + await this.specs[i].asyncRun(coreContext); + await this.runAsyncHookFunc('afterEach'); + } + } + + if (this.childSuites.length > 0) { + for (let i = 0; i < this.childSuites.length; i++) { + // 遇错即停模式, 发现用例有问题,直接返回,不在执行后面的description + let isBreakOnError = this.isRun(coreContext); + if (isBreakOnError) { + console.log("break description :" + this.description); + break; + } + await this.childSuites[i].asyncRun(coreContext); + } + } + + await this.runAsyncHookFunc('afterAll'); + if (this.description !== '') { + await coreContext.fireEvents('suite', 'suiteDone'); + let childSuite = suiteService.suitesStack.pop(); + if (suiteService.suitesStack.length === 0) { + suiteService.suitesStack.push(childSuite); + } + if (suiteService.suitesStack.length > 1) { + suiteService.setCurrentRunningSuite(suiteService.suitesStack.pop()); + } else { + let currentRunningSuite = suiteService.suitesStack.pop(); + suiteService.setCurrentRunningSuite(currentRunningSuite); + suiteService.suitesStack.push(currentRunningSuite); + } + } + } + + runHookFunc(hookName) { + if (this[hookName] && this[hookName].length > 0) { + this[hookName].forEach(func => { + try { + func(); + } catch (e) { + console.error(e); + } + }); + } + } + + runAsyncHookFunc(hookName) { + if (this[hookName] && this[hookName].length > 0) { + return new Promise(async resolve => { + for (let i = 0; i < this[hookName].length; i++) { + try { + await this[hookName][i](); + } catch (e) { + console.error(e); + } + } + resolve(); + }); + } + } +}; + +class SpecService { + constructor(attr) { + this.id = attr.id; + this.totalTest = 0; + this.hasError = false; + } + + init(coreContext) { + this.coreContext = coreContext; + } + + setCurrentRunningSpec(spec) { + this.currentRunningSpec = spec; + } + + setStatus(obj) { + this.hasError = obj; + } + + getStatus() { + return this.hasError; + } + + getTestTotal() { + return this.totalTest; + } + + getCurrentRunningSpec() { + return this.currentRunningSpec; + } + + it(desc, filter, func) { + const configService = this.coreContext.getDefaultService('config'); + const currentSuiteName = this.coreContext.getDefaultService('suite').getCurrentRunningSuite().description; + if (configService.filterDesc(currentSuiteName, desc, filter, this.coreContext)) { + console.info('filter it :' + desc); + } else { + let processedFunc = processFunc(this.coreContext, func); + const spec = new SpecService.Spec({description: desc, fi: filter, fn: processedFunc}); + const suiteService = this.coreContext.getDefaultService('suite'); + if (typeof this.coreContext.getServices('dataDriver') !== 'undefined' && configService['dryRun'] !== 'true') { + let specStress = this.coreContext.getServices('dataDriver').dataDriver.getSpecStress(desc); + for (let i = 1; i < specStress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + // dryRun 状态下不统计压力测试重复数据 + if (configService['dryRun'] !== 'true') { + let stress = configService.getStress(); // 命令配置压力测试 + console.info('stress length :' + stress); + for (let i = 1; i < stress; i++) { + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + this.totalTest++; + suiteService.getCurrentRunningSuite().pushSpec(spec); + } + } + + apis() { + const _this = this; + return { + it: function (desc, filter, func) { + return _this.it(desc, filter, func); + } + }; + } +} + +SpecService.Spec = class { + constructor(attrs) { + this.description = attrs.description || ''; + this.fi = attrs.fi; + this.fn = attrs.fn || function () { + }; + this.result = { + failExpects: [], + passExpects: [] + }; + this.error = undefined; + this.duration = 0; + this.startTime = 0; + this.isExecuted = false; // 当前用例是否执行 + } + + setResult(coreContext) { + const specService = coreContext.getDefaultService('spec'); + if (this.result.failExpects.length > 0) { + this.result.pass = false; + specService.setStatus(true); + } else { + this.result.pass = true; + } + console.info('testcase ' + this.description + ' result:' + this.result.pass); + } + + run(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + coreContext.fireEvents('spec', 'specStart', this); + this.isExecuted = true; + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + this.fn(); + } else { + let suiteParams = dataDriver.dataDriver.getSuiteParams(); + let specParams = dataDriver.dataDriver.getSpecParams(); + console.info('[suite params] ' + JSON.stringify(suiteParams)); + console.info('[spec params] ' + JSON.stringify(specParams)); + if (this.fn.length === 0) { + this.fn(); + } else if (specParams.length === 0) { + this.fn(suiteParams); + } else { + specParams.forEach(paramItem => this.fn(Object.assign({}, paramItem, suiteParams))); + } + } + this.setResult(coreContext); + } catch (e) { + this.error = e; + specService.setStatus(true); + } + coreContext.fireEvents('spec', 'specDone', this); + } + + async asyncRun(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + + await coreContext.fireEvents('spec', 'specStart', this); + try { + let dataDriver = coreContext.getServices('dataDriver'); + if (typeof dataDriver === 'undefined') { + await this.fn(); + this.setResult(coreContext); + } else { + let suiteParams = dataDriver.dataDriver.getSuiteParams(); + let specParams = dataDriver.dataDriver.getSpecParams(); + console.info('[suite params] ' + JSON.stringify(suiteParams)); + console.info('[spec params] ' + JSON.stringify(specParams)); + if (this.fn.length === 0) { + await this.fn(); + this.setResult(coreContext); + } else if (specParams.length === 0) { + await this.fn(suiteParams); + this.setResult(coreContext); + } else { + for (const paramItem of specParams) { + await this.fn(Object.assign({}, paramItem, suiteParams)); + this.setResult(coreContext); + } + } + } + } catch (e) { + if (e instanceof AssertException) { + this.fail = e; + specService.setStatus(true); + } else { + this.error = e; + specService.setStatus(true); + } + } + this.isExecuted = true; + await coreContext.fireEvents('spec', 'specDone', this); + } + + filterCheck(coreContext) { + const specService = coreContext.getDefaultService('spec'); + specService.setCurrentRunningSpec(this); + return true; + } + + addExpectationResult(expectResult) { + if (this.result.failExpects.length === 0) { + this.result.failExpects.push(expectResult); + } + throw new AssertException(expectResult.message); + } +}; + +class ExpectService { + constructor(attr) { + this.id = attr.id; + this.matchers = {}; + } + + expect(actualValue) { + return this.wrapMatchers(actualValue); + } + + init(coreContext) { + this.coreContext = coreContext; + this.addMatchers(this.basicMatchers()); + } + + addMatchers(matchers) { + for (const matcherName in matchers) { + if (Object.prototype.hasOwnProperty.call(matchers, matcherName)) { + this.matchers[matcherName] = matchers[matcherName]; + } + } + } + + basicMatchers() { + return { + assertTrue: function (actualValue) { + return { + pass: (actualValue) === true, + message: 'expect true, actualValue is ' + actualValue + }; + }, + assertEqual: function (actualValue, args) { + return { + pass: (actualValue) === args[0], + expectValue: args[0], + message: 'expect ' + actualValue + ' equals ' + args[0] + }; + }, + assertThrow: function (actual, args) { + const result = { + pass: false + }; + if (typeof actual !== 'function') { + result.message = 'toThrow\'s Actual should be a Function'; + } else { + let hasThrow = false; + let throwError; + try { + actual(); + } catch (e) { + hasThrow = true; + throwError = e; + } + if (!hasThrow) { + result.message = 'function did not throw an exception'; + } else if (throwError && throwError.message === args[0]) { + result.pass = true; + } else { + result.message = `expect to throw ${args[0]} , actual throw ${throwError.message}`; + } + } + return result; + } + }; + } + + wrapMatchers(actualValue) { + const _this = this; + const wrappedMatchers = { + // 翻转标识 + isNot: false, + + // 翻转方法 + not: function () { + this.isNot = true; + return this; + } + }; + const specService = _this.coreContext.getDefaultService('spec'); + const currentRunningSpec = specService.getCurrentRunningSpec(); + for (const matcherName in this.matchers) { + let result = Object.prototype.hasOwnProperty.call(this.matchers, matcherName); + if (!result) { + continue; + } + if (matcherName.search('assertPromise') == 0) { + wrappedMatchers[matcherName] = async function () { + await _this.matchers[matcherName](actualValue, arguments).then(function (result) { + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + currentRunningSpec.addExpectationResult(result); + } + }); + }; + } else { + wrappedMatchers[matcherName] = function () { + const result = _this.matchers[matcherName](actualValue, arguments); + if (wrappedMatchers.isNot) { + result.pass = !result.pass; + } + result.actualValue = actualValue; + result.checkFunc = matcherName; + if (!result.pass) { + currentRunningSpec.addExpectationResult(result); + } + }; + } + } + return wrappedMatchers; + } + + apis() { + const _this = this; + return { + expect: function (actualValue) { + return _this.expect(actualValue); + } + }; + } +} + +class ReportService { + constructor(attr) { + this.id = attr.id; + } + + init(coreContext) { + this.coreContext = coreContext; + this.specService = this.coreContext.getDefaultService('spec'); + this.suiteService = this.coreContext.getDefaultService('suite'); + this.duration = 0; + } + + taskStart() { + console.info('[start] start run suites'); + } + + async suiteStart() { + console.info('[suite start]' + this.suiteService.getCurrentRunningSuite().description); + } + + async specStart() { + console.info('start running case \'' + this.specService.currentRunningSpec.description + '\''); + this.index = this.index + 1; + let spec = this.specService.currentRunningSpec; + spec.startTime = await SysTestKit.getRealTime(); + } + + async specDone() { + let msg = ''; + let spec = this.specService.currentRunningSpec; + let suite = this.suiteService.currentRunningSuite; + spec.duration = await SysTestKit.getRealTime() - spec.startTime; + suite.duration += spec.duration; + if (spec.error) { + this.formatPrint('error', spec.description + ' ; consuming ' + spec.duration + 'ms'); + this.formatPrint('errorDetail', spec.error); + } else if (spec.result) { + if (spec.result.failExpects.length > 0) { + this.formatPrint('fail', spec.description + ' ; consuming ' + spec.duration + 'ms'); + spec.result.failExpects.forEach(failExpect => { + msg = failExpect.message || ('expect ' + failExpect.actualValue + ' ' + + failExpect.checkFunc + ' ' + (failExpect.expectValue)); + this.formatPrint('failDetail', msg); + }); + } else { + this.formatPrint('pass', spec.description + ' ; consuming ' + spec.duration + 'ms'); + } + } + this.formatPrint(this.specService.currentRunningSpec.error, msg); + } + + suiteDone() { + let suite = this.suiteService.currentRunningSuite; + console.info(`[suite end] ${suite.description} consuming ${suite.duration} ms`); + } + + taskDone() { + let msg = ''; + let summary = this.suiteService.getSummary(); + msg = 'total cases:' + summary.total + ';failure ' + summary.failure + ',' + 'error ' + summary.error; + msg += ',pass ' + summary.pass + '; consuming ' + summary.duration + 'ms'; + console.info(msg); + console.info('[end] run suites end'); + } + + incorrectFormat() { + if (this.coreContext.getDefaultService('config').filterValid.length !== 0) { + this.coreContext.getDefaultService('config').filterValid.forEach(function (item) { + console.info('this param ' + item + ' is invalid'); + }); + } + } + + formatPrint(type, msg) { + switch (type) { + case 'pass': + console.info('[pass]' + msg); + break; + case 'fail': + console.info('[fail]' + msg); + break; + case 'failDetail': + console.info('[failDetail]' + msg); + break; + case 'error': + console.info('[error]' + msg); + break; + case 'errorDetail': + console.info('[errorDetail]' + msg); + break; + } + } + + sleep(numberMillis) { + var now = new Date(); + var exitTime = now.getTime() + numberMillis; + while (true) { + now = new Date(); + if (now.getTime() > exitTime) { + return; + } + } + } +} + +export { + SuiteService, + SpecService, + ExpectService, + ReportService +}; diff --git a/sqflite/ohos/sqflite/build-profile.json5 b/sqflite/ohos/sqflite/build-profile.json5 new file mode 100644 index 0000000..8d5a277 --- /dev/null +++ b/sqflite/ohos/sqflite/build-profile.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +{ + "apiType": "stageMode", + "buildOption": { + }, + "targets": [ + { + "name": "default" + } + ] +} diff --git a/sqflite/ohos/sqflite/hvigorfile.ts b/sqflite/ohos/sqflite/hvigorfile.ts new file mode 100644 index 0000000..47e6e1f --- /dev/null +++ b/sqflite/ohos/sqflite/hvigorfile.ts @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { harTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/index.ets b/sqflite/ohos/sqflite/index.ets new file mode 100644 index 0000000..1284ce5 --- /dev/null +++ b/sqflite/ohos/sqflite/index.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +import SqflitePlugin from './src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin' + +export default SqflitePlugin \ No newline at end of file diff --git a/sqflite/ohos/sqflite/libs/flutter_embedding.har b/sqflite/ohos/sqflite/libs/flutter_embedding.har new file mode 100644 index 0000000000000000000000000000000000000000..25da71e65d13d29d4b86246daa35bca9cbd9a636 GIT binary patch literal 84259 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 napiContext; + +export class napiContext { + onPageShow(); + + onPageHide(); +} + +/** + * 设置刷新率 + */ +export const nativeUpdateRefreshRate: ( + ate: number +) => void; + +/** + * 初始化dart vm和flutter engine + */ +export const nativeInit: ( + context: common.Context, + args: Array, + bundlePath: string, + appStoragePath: string, + engineCachesPath: string, + initTimeMillis: number +) => void; + +export const nativeAttach: (napi: FlutterNapi) => number; + +export const nativeSpawn: ( + nativeSpawningShellId: number | null, + entrypointFunctionName: string, + pathToEntrypointFunction: string, + initialRoute: string, + entrypointArgs: Array +) => number; + +export const nativeRunBundleAndSnapshotFromLibrary: ( + nativeShellHolderId: number, + bundlePath: string, + entrypointFunctionName: string, + pathToEntrypointFunction: string, + assetManager: resourceManager.ResourceManager, + entrypointArgs: Array +) => void; + +//Send a data-carrying response to a platform message received from Dart. +export const nativeInvokePlatformMessageResponseCallback: (nativeShellHolderId: number, responseId: number, message: ArrayBuffer, position: number) => void; + +// Send an empty response to a platform message received from Dart. +export const nativeInvokePlatformMessageEmptyResponseCallback: (nativeShellHolderId: number, responseId: number) => void; + +// Send a data-carrying platform message to Dart. +export const nativeDispatchPlatformMessage: (nativeShellHolderId: number, channel: String, message: ArrayBuffer, position: number, responseId: number) => void; + +// Send an empty platform message to Dart. +export const nativeDispatchEmptyPlatformMessage: (nativeShellHolderId: number, channel: String, responseId: number) => void; + +export const nativeSetViewportMetrics: (nativeShellHolderId: number, devicePixelRatio: number, physicalWidth: number + , physicalHeight: number, physicalPaddingTop: number, physicalPaddingRight: number + , physicalPaddingBottom: number, physicalPaddingLeft: number, physicalViewInsetTop: number + , physicalViewInsetRight: number, physicalViewInsetBottom: number, physicalViewInsetLeft: number + , systemGestureInsetTop: number, systemGestureInsetRight: number, systemGestureInsetBottom: number + , systemGestureInsetLeft: number, physicalTouchSlop: number, displayFeaturesBounds: Array + , displayFeaturesType: Array, displayFeaturesState: Array) => void; + +export const nativeImageDecodeCallback: (width: number, height: number, imageGeneratorPointer: number, pixelMap : image.PixelMap | null) => void; + +export const nativeGetSystemLanguages: (nativeShellHolderId: number, languages: Array) => void; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/index_actual.d.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/index_actual.d.ets new file mode 100644 index 0000000..afab180 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/index_actual.d.ets @@ -0,0 +1,267 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import common from '@ohos.app.ability.common'; +import resourceManager from '@ohos.resourceManager'; +import FlutterNapi from '../../../ets/embedding/engine/FlutterNapi'; +import image from '@ohos.multimedia.image'; + +/** + * 设置刷新率 + */ +export const nativeUpdateRefreshRate: ( + ate: number +) => void; + +/** + * 初始化dart vm和flutter engine + */ +export const nativeInit: ( + context: common.Context, + args: Array, + bundlePath: string, + appStoragePath: string, + engineCachesPath: string, + initTimeMillis: number +) => void; + + +/** + * 加载dart工程构建产物 + */ +export const nativeRunBundleAndSnapshotFromLibrary: ( + bundlePath: string, + entrypointFunctionName: string, + pathToEntrypointFunction: string, + assetManager: resourceManager.ResourceManager, + entrypointArgs: Array +) => void; + +/** + * 初始化SkFontMgr::RefDefault(),skia引擎文字管理初始化 + */ +export const nativePrefetchDefaultFontManager: () => void; + +/** + * 返回是否支持软件绘制 + */ +export const nativeGetIsSoftwareRenderingEnabled: () => boolean; + +/** + * attach flutterNapi实例给到 native engine,这个支持rkts到flutter平台的无关引擎之间的通信。 + * attach只需要执行一次 + */ +export const nativeAttach: (flutterNapi: FlutterNapi) => number; + +/** + * 从当前的flutterNapi复制一个新的实例 + */ +export const nativeSpawn: ( + nativeSpawningShellId: number, + entrypointFunctionName: string, + pathToEntrypointFunction: string, + initialRoute: string, + entrypointArgs: Array +) => number; + +/** + * Detaches flutterNapi和engine之间的关联 + * 这个方法执行前提是flutterNapi已经和engine关联 + */ +export const nativeDestroy: ( + nativeShellHolderId: number +) => void; + +// 不需要实现,未使用到 +// export const nativeImageHeaderCallback: ( +// imageGeneratorPointer: number, +// width: number, +// height: number +// ) => void; + +/** + * 不需要实现,c++层已有nativeSurface回调 + */ +// export const nativeSurfaceCreated: ( +// nativeShellHolderId: number +// ) => void; + + +/** + * 不需要实现,c++层已有nativeSurface回调 + */ +// export const nativeSurfaceWindowChanged: ( +// nativeShellHolderId: number +// ) => void; + + +/** + * 不需要实现,c++层已有nativeSurface回调 + */ +// export const nativeSurfaceChanged: ( +// nativeShellHolderId: number, +// width: number, +// height: number +// ) => void; + +/** + * 不需要实现,c++层已有nativeSurface回调 + */ +// export const nativeSurfaceDestroyed: ( +// nativeShellHolderId: number +// ) => void; + +/** + * 把物理屏幕参数通知到native + */ +export const nativeSetViewportMetrics: ( + nativeShellHolderId: number, + devicePixelRatio: number, + physicalWidth: number, + physicalHeight: number, + physicalPaddingTop: number, + physicalPaddingRight: number, + physicalPaddingBottom: number, + physicalPaddingLeft: number, + physicalViewInsetTop: number, + physicalViewInsetRight: number, + physicalViewInsetBottom: number, + physicalViewInsetLeft: number, + systemGestureInsetTop: number, + systemGestureInsetRight: number, + systemGestureInsetBottom: number, + systemGestureInsetLeft: number, + physicalTouchSlop: number, + displayFeaturesBounds: Array, + displayFeaturesType: Array, + displayFeaturesState: Array +) => void; + +/** + * 设置能力参数 + */ +export const nativeSetAccessibilityFeatures: ( + nativeShellHolderId: number, + flags: number +) => void; + +/** + * 清除某个messageData + */ +export const nativeCleanupMessageData: ( + messageData: number +) => void; + +/** + * 发送一个空的PlatformMessage + */ +export const nativeDispatchEmptyPlatformMessage: ( + nativeShellHolderId: number, + channel: string, + responseId: number +) => void; + +/** + * 发送一个PlatformMessage + */ +export const nativeDispatchPlatformMessage: ( + nativeShellHolderId: number, + channel: string, + message: ArrayBuffer, + position: number, + responseId: number +) => void; + +/** + * 空的PlatformMessage响应回调 + */ +export const nativeInvokePlatformMessageEmptyResponseCallback: ( + nativeShellHolderId: number, + responseId: number +) => void; + +/** + * PlatformMessage响应回调 + */ +export const nativeInvokePlatformMessageResponseCallback: ( + nativeShellHolderId: number, + responseId: number, + message: ArrayBuffer, + position: number +) => void; + + +/** + * load一个合法的.so文件到dart vm + */ +export const nativeLoadDartDeferredLibrary: ( + nativeShellHolderId: number, + loadingUnitId: number, + searchPaths: Array +) => void; + +/** + * 设置ResourceManager和assetBundlePath到engine + */ +export const nativeUpdateOhosAssetManager: ( + nativeShellHolderId: number, + resourceManager: resourceManager.ResourceManager, + assetBundlePath: string +) => void; + +/** + * 加载动态库,或者dart库失败时的通知 + */ +export const nativeDeferredComponentInstallFailure: ( + loadingUnitId: number, + error: string, + isTransient: boolean +) => void; + +/** + * 从engine获取当前绘制pixelMap + */ +export const nativeGetPixelMap: () => image.PixelMap; + +/** + * 应用低内存警告 + */ +export const nativeNotifyLowMemoryWarning: ( + nativeShellHolderId: number +) => void; + +// ----- Start FlutterTextUtils Methods ---- +/** + * 下面的方法,从键盘输入中判断当前字符是否是emoji,实现优先级低 + */ +export const nativeFlutterTextUtilsIsEmoji: ( + codePoint: number +) => boolean; + +export const nativeFlutterTextUtilsIsEmojiModifier: ( + codePoint: number +) => boolean; + +export const nativeFlutterTextUtilsIsEmojiModifierBase: ( + codePoint: number +) => boolean; + +export const nativeFlutterTextUtilsIsVariationSelector: ( + codePoint: number +) => boolean; + +export const nativeFlutterTextUtilsIsRegionalIndicator: ( + codePoint: number +) => boolean; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/oh-package.json5 b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/oh-package.json5 new file mode 100644 index 0000000..5d1822e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/cpp/types/libflutter/oh-package.json5 @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +{ + "name": "libflutter.so", + "types": "./index.d.ets", + "version": "", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/FlutterInjector.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/FlutterInjector.ets new file mode 100644 index 0000000..4e6f2f8 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/FlutterInjector.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterNapi from './embedding/engine/FlutterNapi'; +import FlutterLoader from './embedding/engine/loader/FlutterLoader'; + +/** + * flutter相关主要类的单例持有,帮助实现自身和其他类的实例化管理 + */ +export default class FlutterInjector { + private static instance: FlutterInjector; + + private flutterLoader: FlutterLoader; + private flutterNapi: FlutterNapi; + + static getInstance(): FlutterInjector { + if (FlutterInjector.instance == null) { + FlutterInjector.instance = new FlutterInjector(); + } + return FlutterInjector.instance; + } + /** + * 初始化 + */ + private constructor() { + this.flutterNapi = new FlutterNapi(); + this.flutterLoader = new FlutterLoader(this.flutterNapi); + } + + getFlutterLoader(): FlutterLoader { + return this.flutterLoader; + } + + getFlutterNapi(): FlutterNapi { + return this.flutterNapi; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/app/FlutterPluginRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/app/FlutterPluginRegistry.ets new file mode 100644 index 0000000..2a2a449 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/app/FlutterPluginRegistry.ets @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import { FlutterView } from '../view/FlutterView'; +import common from '@ohos.app.ability.common'; +import PlatformViewController from '../plugin/platform/PlatformViewsController' + +export default class FlutterPluginRegistry { + private mPlatformViewsController: PlatformViewController; + private mFlutterView: FlutterView; + private mContext: common.Context; + + constructor() { + this.mPlatformViewsController = new PlatformViewController(); + } + + attach(flutterView: FlutterView, context: common.Context): void { + this.mFlutterView = flutterView; + this.mContext = context; + } + + detach(): void { + this.mPlatformViewsController.detach(); + this.mPlatformViewsController.onDetachedFromNapi(); + this.mFlutterView = null; + this.mContext = null; + } + + destroy(): void { + this.mPlatformViewsController.onDetachedFromNapi(); + } + + onPreEngineRestart(): void{ + this.mPlatformViewsController.onPreEngineRestart(); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/component/FlutterComponent.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/component/FlutterComponent.ets new file mode 100644 index 0000000..07497e6 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/component/FlutterComponent.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** + * 基础component,还未封装,看情况是否使用 + */ +@Component +export default struct FlutterComponent { + build() { + Row() { + Column() { + Text("xxx") + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine.ets new file mode 100644 index 0000000..47ff37a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine.ets @@ -0,0 +1,277 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import LifecycleChannel from './systemchannels/LifecycleChannel'; +import DartExecutor, { DartEntrypoint } from './dart/DartExecutor'; +import FlutterShellArgs from './FlutterShellArgs'; +import FlutterInjector from '../../FlutterInjector'; +import FlutterLoader from './loader/FlutterLoader'; +import common from '@ohos.app.ability.common'; +import resourceManager from '@ohos.resourceManager'; +import FlutterNapi from './FlutterNapi'; +import NavigationChannel from './systemchannels/NavigationChannel'; +import Log from '../../util/Log'; +import TestChannel from './systemchannels/TestChannel' +import FlutterEngineConnectionRegistry from './FlutterEngineConnectionRegistry'; +import PluginRegistry from './plugins/PluginRegistry'; +import AbilityControlSurface from './plugins/ability/AbilityControlSurface'; +import TextInputChannel from './systemchannels/TextInputChannel'; +import TextInputPlugin from '../../plugin/editing/TextInputPlugin'; +import PlatformChannel from './systemchannels/PlatformChannel'; +import FlutterEngineGroup from './FlutterEngineGroup'; +import SystemChannel from './systemchannels/SystemChannel'; +import MouseCursorChannel from './systemchannels/MouseCursorChannel'; +import RestorationChannel from './systemchannels/RestorationChannel'; +import LocalizationChannel from './systemchannels/LocalizationChannel'; +import AccessibilityChannel from './systemchannels/AccessibilityChannel'; +import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin' +import SettingsChannel from './systemchannels/SettingsChannel'; +import PlatformViewsController from '../../plugin/platform/PlatformViewsController'; + +const TAG = "FlutterEngine"; + +/** + * 操作FlutterEngin相关 + */ +export default class FlutterEngine implements EngineLifecycleListener{ + private engineLifecycleListeners = new Set(); + + dartExecutor: DartExecutor; + private flutterLoader: FlutterLoader; + private assetManager: resourceManager.ResourceManager; + //channel定义 + private lifecycleChannel: LifecycleChannel | null = null; + private navigationChannel: NavigationChannel | null = null; + private textInputChannel: TextInputChannel | null = null; + private testChannel: TestChannel | null = null; + private platformChannel: PlatformChannel | null = null; + private systemChannel: SystemChannel | null = null; + private mouseCursorChannel: MouseCursorChannel | null = null; + private restorationChannel: RestorationChannel | null = null; + + private accessibilityChannel: AccessibilityChannel | null = null; + private localeChannel: LocalizationChannel | null = null; + private flutterNapi: FlutterNapi; + private pluginRegistry: FlutterEngineConnectionRegistry | null = null; + private textInputPlugin: TextInputPlugin | null = null; + private localizationPlugin: LocalizationPlugin | null = null; + private settingsChannel: SettingsChannel | null = null; + private platformViewsController: PlatformViewsController; + + /** + * 需要初始化的工作: + * 1、初始化DartExecutor + * 2、初始化所有channel + * 3、初始化plugin + * 4、初始化flutterLoader + * 5、初始化flutterNapi + * 6、engineLifecycleListeners + */ + constructor(context: common.Context, flutterLoader: FlutterLoader | null, flutterNapi: FlutterNapi | null, platformViewsController: PlatformViewsController) { + const injector: FlutterInjector = FlutterInjector.getInstance(); + + if(flutterNapi == null){ + flutterNapi = FlutterInjector.getInstance().getFlutterNapi(); + } + this.flutterNapi = flutterNapi; + this.assetManager = context.resourceManager; + + this.dartExecutor = new DartExecutor(this.flutterNapi, this.assetManager); + this.dartExecutor.onAttachedToNAPI(); + + if(flutterLoader == null){ + flutterLoader = injector.getFlutterLoader(); + } + this.flutterLoader = flutterLoader; + + if(platformViewsController == null) { + platformViewsController = new PlatformViewsController(); + } + this.platformViewsController = platformViewsController; + this.platformViewsController.attach(context, null, this.dartExecutor); + } + + async init(context: common.Context, dartVmArgs: Array | null, automaticallyRegisterPlugins: boolean, + waitForRestorationData: boolean, group: FlutterEngineGroup | null) { + if (!this.flutterNapi.isAttached()) { + await this.flutterLoader.startInitialization(context) + this.flutterLoader.ensureInitializationComplete(dartVmArgs); + } + //channel初始化 + this.lifecycleChannel = new LifecycleChannel(this.dartExecutor); + this.navigationChannel = new NavigationChannel(this.dartExecutor); + this.textInputChannel = new TextInputChannel(this.dartExecutor); + this.testChannel = new TestChannel(this.dartExecutor); + this.platformChannel = new PlatformChannel(this.dartExecutor); + this.systemChannel = new SystemChannel(this.dartExecutor); + this.mouseCursorChannel = new MouseCursorChannel(this.dartExecutor); + this.restorationChannel = new RestorationChannel(this.dartExecutor, waitForRestorationData); + this.settingsChannel = new SettingsChannel(this.dartExecutor); + + this.localeChannel = new LocalizationChannel(this.dartExecutor); + this.accessibilityChannel = new AccessibilityChannel(this.dartExecutor, this.flutterNapi); + this.flutterNapi.addEngineLifecycleListener(this); + this.localizationPlugin = new LocalizationPlugin(context, this.localeChannel); + + // It should typically be a fresh, unattached NAPI. But on a spawned engine, the NAPI instance + // is already attached to a native shell. In that case, the Java FlutterEngine is created around + // an existing shell. + if (!this.flutterNapi.isAttached()) { + this.attachToNapi(); + } + + this.pluginRegistry = new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, this.flutterLoader, group!); + this.localizationPlugin.sendLocaleToFlutter(); + } + + private attachToNapi(): void { + Log.d(TAG, "Attaching to NAPI."); + this.flutterNapi.attachToNative(); + + if (!this.isAttachedToNapi()) { + throw new Error("FlutterEngine failed to attach to its native Object reference."); + } + this.flutterNapi.setLocalizationPlugin(this.localizationPlugin); + } + + async spawn(context: common.Context, + dartEntrypoint: DartEntrypoint, + initialRoute: string, + dartEntrypointArgs: Array, + platformViewsController: PlatformViewsController, + automaticallyRegisterPlugins: boolean, waitForRestorationData: boolean) { + if (!this.isAttachedToNapi()) { + throw new Error( + "Spawn can only be called on a fully constructed FlutterEngine"); + } + + const newFlutterNapi = + this.flutterNapi.spawn( + dartEntrypoint.dartEntrypointFunctionName, + dartEntrypoint.dartEntrypointLibrary, + initialRoute, + dartEntrypointArgs); + const flutterEngine = new FlutterEngine( + context, + null, + newFlutterNapi, + platformViewsController + ); + await flutterEngine.init(context, null, automaticallyRegisterPlugins, waitForRestorationData, null) + return flutterEngine + } + + private isAttachedToNapi(): boolean { + return this.flutterNapi.isAttached(); + } + + getLifecycleChannel(): LifecycleChannel | null { + return this.lifecycleChannel; + } + + getNavigationChannel(): NavigationChannel | null { + return this.navigationChannel; + } + + getTextInputChannel(): TextInputChannel | null { + return this.textInputChannel; + } + + getPlatformChannel(): PlatformChannel | null { + return this.platformChannel; + } + + getSystemChannel(): SystemChannel | null { + return this.systemChannel; + } + + getLocaleChannel(): LocalizationChannel | null { + return this.localeChannel; + } + + getMouseCursorChannel(): MouseCursorChannel | null { + return this.mouseCursorChannel; + } + + getFlutterNapi(): FlutterNapi { + return this.flutterNapi; + } + + getDartExecutor(): DartExecutor { + return this.dartExecutor + } + + getPlugins(): PluginRegistry | null { + return this.pluginRegistry; + } + + getAbilityControlSurface(): AbilityControlSurface | null { + return this.pluginRegistry; + } + + getSettingsChannel() { + return this.settingsChannel; + } + + onPreEngineRestart(): void { + + } + + onEngineWillDestroy(): void { + + } + + addEngineLifecycleListener(listener: EngineLifecycleListener): void { + this.engineLifecycleListeners.add(listener); + } + + removeEngineLifecycleListener(listener: EngineLifecycleListener): void { + this.engineLifecycleListeners.delete(listener); + } + + destroy(): void { + Log.d(TAG, "Destroying."); + this.engineLifecycleListeners.forEach(listener => listener.onEngineWillDestroy()) + this.flutterNapi.removeEngineLifecycleListener(this); + this.pluginRegistry?.detachFromAbility(); + this.platformViewsController?.onDetachedFromNapi(); + } + + getRestorationChannel(): RestorationChannel | null { + return this.restorationChannel; + } + + getAccessibilityChannel(): AccessibilityChannel | null { + return this.accessibilityChannel; + } + + getLocalizationPlugin(): LocalizationPlugin | null { + return this.localizationPlugin; + } + + getSystemLanguages(): void { + return this.flutterNapi.getSystemLanguages(); + } + + getPlatformViewsController(): PlatformViewsController | null { + return this.platformViewsController; + } +} + +export interface EngineLifecycleListener { + onPreEngineRestart(): void; + + onEngineWillDestroy(): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineCache.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineCache.ets new file mode 100644 index 0000000..7808dfd --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineCache.ets @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterEngine from "./FlutterEngine" + +export default class FlutterEngineCache { + private static instance : FlutterEngineCache; + private cachedEngines: Map = new Map(); + + static getInstance(): FlutterEngineCache { + if (FlutterEngineCache.instance == null) { + FlutterEngineCache.instance = new FlutterEngineCache(); + } + return FlutterEngineCache.instance; + } + /** + * 返回engineId对应的FlutterEngine是否存在 + */ + contains(engineId: String) : boolean { + return this.cachedEngines.has(engineId); + } + + /** + * 返回engineId对应的FlutterEngine + */ + get(engineId: String) : FlutterEngine | null { + return this.cachedEngines.get(engineId) || null; + } + /** + * 将传入的FlutterEngine与engineId放在缓存中 + */ + put(engineId :String, engine: FlutterEngine | null): void { + if(engine != null) { + this.cachedEngines.set(engineId, engine); + } else { + this.cachedEngines.delete(engineId); + } + } + /** + * 移除engineId对应的FlutterEngine + */ + remove(engineId: String) : void { + this.put(engineId, null); + } + + /** + * 移除cachedEngines所有中所有的FlutterEngine + */ + clear():void { + this.cachedEngines.clear(); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets new file mode 100644 index 0000000..a596d2e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineConnectionRegistry.ets @@ -0,0 +1,281 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import PluginRegistry from './plugins/PluginRegistry'; +import { FlutterAssets, FlutterPlugin, FlutterPluginBinding } from './plugins/FlutterPlugin'; +import FlutterEngine from './FlutterEngine'; +import AbilityAware from './plugins/ability/AbilityAware'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import { + AbilityPluginBinding, + WindowFocusChangedListener, + OnSaveStateListener, + NewWantListener +} from './plugins/ability/AbilityPluginBinding'; +import HashSet from '@ohos.util.HashSet'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import common from '@ohos.app.ability.common'; +import FlutterLoader from './loader/FlutterLoader'; +import Log from '../../util/Log'; +import ToolUtils from '../../util/ToolUtils'; +import AbilityControlSurface from './plugins/ability/AbilityControlSurface'; +import ExclusiveAppComponent from '../ohos/ExclusiveAppComponent'; +import FlutterEngineGroup from './FlutterEngineGroup'; + +const TAG = "FlutterEngineCxnRegstry"; + +export default class FlutterEngineConnectionRegistry implements PluginRegistry, AbilityControlSurface { + // PluginRegistry + private plugins = new Map(); + + private defaultPlugin : FlutterPlugin = new EmptyPlugin(); + + // Standard FlutterPlugin + private flutterEngine: FlutterEngine; + private pluginBinding: FlutterPluginBinding; + + // AbilityAware + private abilityAwarePlugins = new Map(); + + private exclusiveAbility: ExclusiveAppComponent | null = null; + private abilityPluginBinding: FlutterEngineAbilityPluginBinding | null = null; + + constructor(appContext: common.Context, flutterEngine: FlutterEngine, flutterLoader: FlutterLoader, group: FlutterEngineGroup) { + this.flutterEngine = flutterEngine; + this.pluginBinding = new FlutterPluginBinding(appContext, this.flutterEngine.getDartExecutor(), new DefaultFlutterAssets(flutterLoader), group, this.flutterEngine.getPlatformViewsController()?.getRegistry()); + } + + add(plugin: FlutterPlugin): void { + try { + if (this.has(plugin.getUniqueClassName())) { + Log.w( + TAG, + "Attempted to register plugin (" + + plugin + + ") but it was " + + "already registered with this FlutterEngine (" + + this.flutterEngine + + ")."); + return; + } + + Log.w(TAG, "Adding plugin: " + plugin); + // Add the plugin to our generic set of plugins and notify the plugin + // that is has been attached to an engine. + this.plugins.set(plugin.getUniqueClassName(), plugin); + plugin.onAttachedToEngine(this.pluginBinding); + + // For AbilityAware plugins, add the plugin to our set of AbilityAware + // plugins, and if this engine is currently attached to an Ability, + // notify the AbilityAware plugin that it is now attached to an Ability. + if (ToolUtils.implementsInterface(plugin, "onAttachedToAbility")) { + const abilityAware: ESObject = plugin; + this.abilityAwarePlugins.set(plugin.getUniqueClassName(), abilityAware); + if (this.isAttachedToAbility()) { + abilityAware.onAttachedToAbility(this.abilityPluginBinding); + } + } + } finally { + + } + } + + addList(plugins: Set): void { + plugins.forEach(plugin => this.add(plugin)) + } + + has(pluginClassName: string): boolean { + return this.plugins.has(pluginClassName); + } + + get(pluginClassName: string): FlutterPlugin { + return this.plugins.get(pluginClassName) ?? this.defaultPlugin; + } + + remove(pluginClassName: string): void { + const plugin = this.plugins.get(pluginClassName); + if (plugin == null) { + return; + } + if (ToolUtils.implementsInterface(plugin, "onAttachedToAbility")) { + if (this.isAttachedToAbility()) { + const abilityAware: ESObject = plugin; + abilityAware.onDetachedFromAbility(); + } + this.abilityAwarePlugins.delete(pluginClassName); + } + // Notify the plugin that is now detached from this engine. Then remove + // it from our set of generic plugins. + plugin.onDetachedFromEngine(this.pluginBinding); + this.plugins.delete(pluginClassName) + } + + removeList(pluginClassNames: Set): void { + pluginClassNames.forEach(plugin => this.remove(plugin)) + } + + removeAll(): void { + this.removeList(new Set(this.plugins.keys())); + this.plugins.clear(); + } + + private isAttachedToAbility(): boolean { + return this.exclusiveAbility != null; + } + + attachToAbility(exclusiveAbility: ExclusiveAppComponent): void { + if (this.exclusiveAbility != null) { + this.exclusiveAbility.detachFromFlutterEngine(); + } + // If we were already attached to an app component, detach from it. + this.detachFromAppComponent(); + this.exclusiveAbility = exclusiveAbility; + this.attachToAbilityInternal(exclusiveAbility.getAppComponent(),); + } + + detachFromAbility(): void { + if (this.isAttachedToAbility()) { + this.abilityAwarePlugins.forEach(abilityAware => abilityAware.onDetachedFromAbility()) + this.detachFromAbilityInternal(); + } else { + Log.e(TAG, "Attempted to detach plugins from an Ability when no Ability was attached."); + } + } + + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void { + this.abilityPluginBinding?.onNewWant(want, launchParams); + } + + onWindowFocusChanged(hasFocus: boolean): void { + this.abilityPluginBinding?.onWindowFocusChanged(hasFocus); + } + + onSaveState(reason: AbilityConstant.StateType, wantParam: Record): AbilityConstant.OnSaveResult { + return this.abilityPluginBinding?.onSaveState(reason, wantParam) ?? AbilityConstant.OnSaveResult.ALL_REJECT; + } + + private detachFromAppComponent(): void { + if (this.isAttachedToAbility()) { + this.detachFromAbility(); + } + } + + private attachToAbilityInternal(ability: UIAbility): void { + this.abilityPluginBinding = new FlutterEngineAbilityPluginBinding(ability); + // Notify all AbilityAware plugins that they are now attached to a new Ability. + this.abilityAwarePlugins.forEach(abilityAware => abilityAware.onAttachedToAbility(this.abilityPluginBinding!)); + } + + private detachFromAbilityInternal(): void { + this.exclusiveAbility = null; + this.abilityPluginBinding = null; + } + + destroy(): void{ + this.detachFromAppComponent(); + // Remove all registered plugins. + this.removeAll(); + } +} + +class FlutterEngineAbilityPluginBinding implements AbilityPluginBinding { + private ability: UIAbility; + private onNewWantListeners = new HashSet(); + private onWindowFocusChangedListeners = new HashSet(); + private onSaveStateListeners = new HashSet(); + + constructor(ability: UIAbility) { + this.ability = ability; + + } + + getAbility(): UIAbility { + return this.ability; + } + + addOnNewWantListener(listener: NewWantListener): void { + this.onNewWantListeners.add(listener) + } + + removeOnNewWantListener(listener: NewWantListener): void { + this.onNewWantListeners.remove(listener) + } + + addOnWindowFocusChangedListener(listener: WindowFocusChangedListener): void { + this.onWindowFocusChangedListeners.add(listener) + } + + removeOnWindowFocusChangedListener(listener: WindowFocusChangedListener): void { + this.onWindowFocusChangedListeners.remove(listener) + } + + addOnSaveStateListener(listener: OnSaveStateListener) { + this.onSaveStateListeners.add(listener) + } + + removeOnSaveStateListener(listener: OnSaveStateListener) { + this.onSaveStateListeners.remove(listener) + } + + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void { + this.onNewWantListeners.forEach((listener, key) => { + listener?.onNewWant(want, launchParams) + }); + } + + onWindowFocusChanged(hasFocus: boolean): void { + this.onWindowFocusChangedListeners.forEach((listener, key) => { + listener?.onWindowFocusChanged(hasFocus) + }); + } + + onSaveState(reason: AbilityConstant.StateType, wantParam: Record): AbilityConstant.OnSaveResult { + this.onSaveStateListeners.forEach((listener, key) => { + listener?.onSaveState(reason, wantParam) + }); + return AbilityConstant.OnSaveResult.ALL_AGREE; + } +} + +class DefaultFlutterAssets implements FlutterAssets { + private flutterLoader: FlutterLoader; + + constructor(flutterLoader: FlutterLoader) { + this.flutterLoader = flutterLoader; + } + + getAssetFilePathByName(assetFileName: string, packageName?: string): string { + return this.flutterLoader.getLookupKeyForAsset(assetFileName, packageName); + } + + getAssetFilePathBySubpath(assetSubpath: string, packageName?: string) { + return this.flutterLoader.getLookupKeyForAsset(assetSubpath, packageName); + } +} + +class EmptyPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return ''; + } + + onAttachedToEngine(binding: FlutterPluginBinding) { + + } + + onDetachedFromEngine(binding: FlutterPluginBinding) { + + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup.ets new file mode 100644 index 0000000..f9fab12 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroup.ets @@ -0,0 +1,184 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterEngine, { EngineLifecycleListener } from "./FlutterEngine" +import common from '@ohos.app.ability.common' +import FlutterLoader from './loader/FlutterLoader' +import FlutterInjector from '../../FlutterInjector' +import { DartEntrypoint } from './dart/DartExecutor' +import PlatformViewsController from '../../plugin/platform/PlatformViewsController' +import ArrayList from '@ohos.util.ArrayList' + +export default class FlutterEngineGroup { + private activeEngines: ArrayList = new ArrayList(); + + constructor() { + + } + + async checkLoader(context: common.Context, args: Array) { + let loader: FlutterLoader = FlutterInjector.getInstance().getFlutterLoader(); + if (!loader.initialized) { + await loader.startInitialization(context.getApplicationContext()); + loader.ensureInitializationComplete(args); + } + } + + async createAndRunEngineByOptions(options: Options) { + let engine: FlutterEngine | null = null; + let context: common.Context = options.getContext(); + let dartEntrypoint: DartEntrypoint | null = options.getDartEntrypoint(); + let initialRoute: string = options.getInitialRoute(); + let dartEntrypointArgs: Array = options.getDartEntrypointArgs(); + let platformViewsController: PlatformViewsController | null = options.getPlatformViewsController(); + let automaticallyRegisterPlugins: boolean = options.getAutomaticallyRegisterPlugins(); + let waitForRestorationData: boolean = options.getWaitForRestorationData(); + + if (dartEntrypoint == null) { + dartEntrypoint = DartEntrypoint.createDefault(); + } + + if (platformViewsController == null) { + platformViewsController = new PlatformViewsController(); + } + + if (this.activeEngines.length == 0) { + engine = this.createEngine(context, platformViewsController); + await engine.init(context, null, // String[]. The Dart VM has already started, this arguments will have no effect. + automaticallyRegisterPlugins, // boolean. + waitForRestorationData, // boolean. + this) + if (initialRoute != null) { + engine.getNavigationChannel()?.setInitialRoute(initialRoute); + } + } else { + engine = await this.activeEngines[0] + .spawn( + context, + dartEntrypoint, + initialRoute, + dartEntrypointArgs, + platformViewsController, + automaticallyRegisterPlugins, + waitForRestorationData); + } + this.activeEngines.add(engine); + + const engineToCleanUpOnDestroy = engine; + let listener: EngineLifecycleListener = new EngineLifecycleListenerImpl( + platformViewsController, + this.activeEngines, + engineToCleanUpOnDestroy); + engine?.addEngineLifecycleListener(listener); + return engine; + } + + createEngine(context: common.Context, platformViewsController: PlatformViewsController): FlutterEngine { + return new FlutterEngine(context, null, null, platformViewsController); + } +} + +class EngineLifecycleListenerImpl implements EngineLifecycleListener { + private platformViewsController: PlatformViewsController; + private activeEngines: ArrayList = new ArrayList(); + private engine: FlutterEngine | null; + + constructor( + platformViewsController: PlatformViewsController, + activeEngines: ArrayList, + engine: FlutterEngine | null) { + this.platformViewsController = platformViewsController; + this.activeEngines = activeEngines; + this.engine = engine; + } + onPreEngineRestart(): void { + this.platformViewsController.onPreEngineRestart(); + } + onEngineWillDestroy(): void { + this.activeEngines.remove(this.engine); + } +} + +export class Options { + private context: common.Context; + private dartEntrypoint: DartEntrypoint | null = null; + private initialRoute: string = ''; + private dartEntrypointArgs: Array = []; + private platformViewsController: PlatformViewsController | null = null; + private automaticallyRegisterPlugins: boolean = true; + private waitForRestorationData: boolean = false; + + constructor(context: common.Context) { + this.context = context; + } + + getContext(): common.Context { + return this.context; + } + + getDartEntrypoint(): DartEntrypoint | null { + return this.dartEntrypoint; + } + + getInitialRoute(): string { + return this.initialRoute; + } + + getDartEntrypointArgs(): Array { + return this.dartEntrypointArgs; + } + + getAutomaticallyRegisterPlugins(): boolean { + return this.automaticallyRegisterPlugins; + } + + getWaitForRestorationData(): boolean { + return this.waitForRestorationData; + } + + getPlatformViewsController(): PlatformViewsController | null { + return this.platformViewsController; + } + + setDartEntrypoint(dartEntrypoint: DartEntrypoint): Options { + this.dartEntrypoint = dartEntrypoint; + return this; + } + + setInitialRoute(initialRoute: string): Options { + this.initialRoute = initialRoute; + return this; + } + + setDartEntrypointArgs(dartEntrypointArgs: Array): Options { + this.dartEntrypointArgs = dartEntrypointArgs; + return this; + } + + setAutomaticallyRegisterPlugins(automaticallyRegisterPlugins: boolean): Options { + this.automaticallyRegisterPlugins = automaticallyRegisterPlugins; + return this; + } + + setWaitForRestorationData(waitForRestorationData: boolean): Options { + this.waitForRestorationData = waitForRestorationData; + return this; + } + + setPlatformViewsController(platformViewsController: PlatformViewsController): Options { + this.platformViewsController = platformViewsController; + return this; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroupCache.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroupCache.ets new file mode 100644 index 0000000..645507a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngineGroupCache.ets @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterEngineGroup from './FlutterEngineGroup'; + +export default class FlutterEngineGroupCache { + static readonly instance = new FlutterEngineGroupCache(); + + private cachedEngineGroups = new Map(); + + contains(engineGroupId: string): boolean { + return this.cachedEngineGroups.has(engineGroupId); + } + + get(engineGroupId: string): FlutterEngineGroup | null { + return this.cachedEngineGroups.get(engineGroupId) ?? null; + } + + put(engineGroupId: string, engineGroup?: FlutterEngineGroup) { + if (engineGroup != null) { + this.cachedEngineGroups.set(engineGroupId, engineGroup); + } else { + this.cachedEngineGroups.delete(engineGroupId); + } + } + + clear(): void { + this.cachedEngineGroups.clear(); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets new file mode 100644 index 0000000..eef82c9 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterNapi.ets @@ -0,0 +1,362 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import flutter from 'libflutter.so'; +import common from '@ohos.app.ability.common'; +import Log from '../../util/Log'; +import resourceManager from '@ohos.resourceManager'; +import { PlatformMessageHandler } from './dart/PlatformMessageHandler'; +import { FlutterCallbackInformation } from '../../view/FlutterCallbackInformation'; +import image from '@ohos.multimedia.image'; +import { EngineLifecycleListener } from './FlutterEngine'; +import { ByteBuffer } from '../../util/ByteBuffer'; +import { Action } from '../../view/AccessibilityBridge' +import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin'; +import i18n from '@ohos.i18n'; + +const TAG = "FlutterNapi"; + +enum ContextType { + APP_LIFECYCLE = 0, + JS_PAGE_LIFECYCLE, +} + +/** + * 提供arkTs的flutterNAPI接口 + */ +export default class FlutterNapi { + hasInit: boolean = false; + //是否已实现 + hasImplemented: boolean = false; + + nativeShellHolderId: number | null = null; + platformMessageHandler: PlatformMessageHandler | null = null; + private engineLifecycleListeners = new Set(); + accessibilityDelegate: AccessibilityDelegate | null = null; + localizationPlugin: LocalizationPlugin | null = null; + + /** + * 更新刷新率 + * @param rate + */ + updateRefreshRate(refreshRateFPS : number) { + flutter.nativeUpdateRefreshRate(refreshRateFPS); + } + + init(context: common.Context, + args: Array, + bundlePath: string, + appStoragePath: string, + engineCachesPath: string, + initTimeMillis: number) { + if (this.hasInit) { + throw Error("the engine has init"); + } + this.hasInit = true; + Log.w(TAG, "init: bundlePath=" + bundlePath + " appStoragePath=" + appStoragePath + " engineCachesPath=" + engineCachesPath + " args=" + JSON.stringify(args)); + flutter.nativeInit(context, args, bundlePath, appStoragePath, engineCachesPath, initTimeMillis); + } + + attachToNative(): void { + this.nativeShellHolderId = flutter.nativeAttach(this); + Log.w(TAG, "nativeShellHolderId=" + this.nativeShellHolderId); + } + + runBundleAndSnapshotFromLibrary( + bundlePath: string, + entrypointFunctionName: string, + pathToEntrypointFunction: string, + assetManager: resourceManager.ResourceManager, + entrypointArgs: Array) { + Log.w(TAG, "init: bundlePath=" + bundlePath + " entrypointFunctionName=" + entrypointFunctionName + " pathToEntrypointFunction=" + pathToEntrypointFunction + " entrypointArgs=" + JSON.stringify(entrypointArgs)) + flutter.nativeRunBundleAndSnapshotFromLibrary(this.nativeShellHolderId!, bundlePath, entrypointFunctionName, pathToEntrypointFunction, assetManager, entrypointArgs); + }; + + /** + * 当前so方法是否都实现 + * @returns + */ + checkImplemented(methodName: string = ""): boolean { + if (!this.hasImplemented) { + Log.e(TAG, "this method has not implemented -> " + methodName) + } + return this.hasImplemented; + } + + setPlatformMessageHandler(platformMessageHandler: PlatformMessageHandler | null): void { + this.ensureRunningOnMainThread(); + this.platformMessageHandler = platformMessageHandler; + } + + private ensureAttachedToNative(): void { + if (this.nativeShellHolderId == null) { + throw new Error( + "Cannot execute operation because FlutterNapi is not attached to native."); + } + } + + private nativeNotifyLowMemoryWarning(nativeShellHolderId: number): void { + + } + + static nativeLookupCallbackInformation(handle: number): FlutterCallbackInformation | null { + return null; + } + + notifyLowMemoryWarning(): void { + this.ensureRunningOnMainThread(); + this.ensureAttachedToNative(); + this.nativeNotifyLowMemoryWarning(this.nativeShellHolderId!); + } + + isAttached(): boolean { + return this.nativeShellHolderId != null; + } + + private ensureRunningOnMainThread(): void { + + } + + dispatchEmptyPlatformMessage(channel: String, responseId: number): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + flutter.nativeDispatchEmptyPlatformMessage(this.nativeShellHolderId!, channel, responseId); + } else { + Log.w( + TAG, + "Tried to send a platform message to Flutter, but FlutterNapi was detached from native C++. Could not send. Channel: " + + channel + + ". Response ID: " + + responseId); + } + } + + /** Sends a reply {@code message} from Android to Flutter over the given {@code channel}. */ + dispatchPlatformMessage(channel: String, message: ArrayBuffer, position: number, responseId: number): void { + this.ensureRunningOnMainThread(); + if (this.isAttached()) { + + const uintArrayBuff = new Uint8Array(message) + let text = '' + for (let i = 0; i < uintArrayBuff.byteLength; i++) { + text += uintArrayBuff[i] + ',' + } + Log.w(TAG, "message=" + message.byteLength + ",text=" + text); + flutter.nativeDispatchPlatformMessage(this.nativeShellHolderId!, channel, message, position, responseId); + } else { + Log.w( + TAG, + "Tried to send a platform message to Flutter, but FlutterNapi was detached from native C++. Could not send. Channel: " + + channel + + ". Response ID: " + + responseId); + } + } + + invokePlatformMessageEmptyResponseCallback(responseId: number): void { + if (this.isAttached()) { + flutter.nativeInvokePlatformMessageEmptyResponseCallback(this.nativeShellHolderId!, responseId); + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + invokePlatformMessageResponseCallback(responseId: number, message: ArrayBuffer, position: number) { + if (this.isAttached()) { + flutter.nativeInvokePlatformMessageResponseCallback( + this.nativeShellHolderId!, responseId, message, position); + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + setViewportMetrics(devicePixelRatio: number, physicalWidth: number + , physicalHeight: number, physicalPaddingTop: number, physicalPaddingRight: number + , physicalPaddingBottom: number, physicalPaddingLeft: number, physicalViewInsetTop: number + , physicalViewInsetRight: number, physicalViewInsetBottom: number, physicalViewInsetLeft: number + , systemGestureInsetTop: number, systemGestureInsetRight: number, systemGestureInsetBottom: number + , systemGestureInsetLeft: number, physicalTouchSlop: number, displayFeaturesBounds: Array + , displayFeaturesType: Array, displayFeaturesState: Array): void { + if (this.isAttached()) { + flutter.nativeSetViewportMetrics(this.nativeShellHolderId!, devicePixelRatio, + physicalWidth, + physicalHeight, + physicalPaddingTop, + physicalPaddingRight, + physicalPaddingBottom, + physicalPaddingLeft, + physicalViewInsetTop, + physicalViewInsetRight, + physicalViewInsetBottom, + physicalViewInsetLeft, + systemGestureInsetTop, + systemGestureInsetRight, + systemGestureInsetBottom, + systemGestureInsetLeft, + physicalTouchSlop, + displayFeaturesBounds, + displayFeaturesType, + displayFeaturesState); + } + } + + spawn(entrypointFunctionName: string, pathToEntrypointFunction: string, initialRoute: string, entrypointArgs: Array): FlutterNapi { + let shellHolderId = flutter.nativeSpawn(this.nativeShellHolderId, entrypointFunctionName, pathToEntrypointFunction, initialRoute, entrypointArgs) + let flutterNapi = new FlutterNapi() + flutterNapi.nativeShellHolderId = shellHolderId + return flutterNapi; + } + + addEngineLifecycleListener(engineLifecycleListener: EngineLifecycleListener): void { + this.engineLifecycleListeners.add(engineLifecycleListener); + } + + removeEngineLifecycleListener(engineLifecycleListener: EngineLifecycleListener) { + this.engineLifecycleListeners.delete(engineLifecycleListener); + } + + //Called by native to respond to a platform message that we sent. + handlePlatformMessageResponse(replyId: number, reply: ArrayBuffer): void { + Log.w(TAG, "called handlePlatformMessageResponse Response ID: " + replyId); + if (this.platformMessageHandler != null) { + this.platformMessageHandler.handlePlatformMessageResponse(replyId, reply); + } + } + + // Called by native on any thread. + handlePlatformMessage(channel: string, message: ArrayBuffer, replyId: number, messageData: number): void { + Log.w(TAG, "called handlePlatformMessage Channel: " + channel + ". Response ID: " + replyId); + if (this.platformMessageHandler != null) { + this.platformMessageHandler.handleMessageFromDart(channel, message, replyId, messageData); + } + } + + // Called by native to notify first Flutter frame rendered. + onFirstFrame(): void { + Log.d(TAG, "called onFirstFrame") + } + + // Called by native. + onPreEngineRestart(): void { + Log.d(TAG, "called onPreEngineRestart") + this.engineLifecycleListeners.forEach( listener => listener.onPreEngineRestart()); + } + + // /** Invoked by native to obtain the results of OHOS's locale resolution algorithm. */ + computePlatformResolvedLocale(strings: Array): Array { + Log.d(TAG, "called computePlatformResolvedLocale " + JSON.stringify(strings)) + return [] + } + + decodeImage(buffer: ArrayBuffer, imageGeneratorAddress: number): void { + Log.d(TAG, "called decodeImage=" + buffer.byteLength) + const imageSourceApi = image.createImageSource(buffer); + let tempPixelMap: image.PixelMap | null = null; + imageSourceApi.createPixelMap({ + desiredPixelFormat: image.PixelMapFormat.RGBA_8888 + }).then(pixelMap => { + Log.d(TAG, "called createPixelMap end " + pixelMap.getPixelBytesNumber()) + tempPixelMap = pixelMap + return pixelMap.getImageInfo() + }).then(imageInfo => { + Log.d(TAG, `nativeImageHeaderCallback width=${imageInfo.size.width} height=${imageInfo.size.height} imageGeneratorAddress=${imageGeneratorAddress}`) + flutter.nativeImageDecodeCallback(imageInfo.size.width, imageInfo.size.height, imageGeneratorAddress, tempPixelMap) + }).catch((error: ESObject) => { + Log.d(TAG, "decodeImage error=" + JSON.stringify(error)) + flutter.nativeImageDecodeCallback(0, 0, imageGeneratorAddress, null); + }) + } + + setSemanticsEnabled(enabled: boolean, responseId: number): void { + if (this.isAttached()) { + this.nativeSetSemanticsEnabled(enabled); + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + // Send an empty response to a platform message received from Dart. + nativeSetSemanticsEnabled(enabled: boolean):void {} + + setAccessibilityFeatures(accessibilityFeatureFlags: number, responseId: number): void { + if (this.isAttached()) { + this.nativeSetAccessibilityFeatures(accessibilityFeatureFlags, responseId); + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + nativeSetAccessibilityFeatures(accessibilityFeatureFlags: number, responseId: number): void {} + + dispatchSemanticsAction(virtualViewId: number, action: Action, responseId: number): void { + if (this.isAttached()) { + this.nativeDispatchSemanticsAction(virtualViewId, action, responseId); + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + nativeDispatchSemanticsAction(virtualViewId: number, action: Action, responseId: number): void {} + + setAccessibilityDelegate(delegate: AccessibilityDelegate, responseId: number): void { + if (this.isAttached()) { + this.accessibilityDelegate = delegate; + } else { + Log.w( + TAG, + "Tried to send a platform message response, but FlutterNapi was detached from native C++. Could not send. Response ID: " + + responseId); + } + } + + setLocalizationPlugin(localizationPlugin: LocalizationPlugin | null): void { + this.localizationPlugin = localizationPlugin; + } + + /** + * 获取系统语言列表 + * @param rate + */ + getSystemLanguages() { + Log.d(TAG, "called getSystemLanguages ") + let index: number; + let systemLanguages = i18n.System.getPreferredLanguageList(); + for (index = 0; index < systemLanguages.length; index++) { + Log.d(TAG, "systemlanguages "+ index + ":" + systemLanguages[index]); + } + flutter.nativeGetSystemLanguages(this.nativeShellHolderId!, systemLanguages); + } +} + +export interface AccessibilityDelegate { + updateCustomAccessibilityActions(buffer: ByteBuffer, strings: string[]): void; + + updateSemantics(buffer: ByteBuffer, strings: string[], stringAttributeArgs: ByteBuffer[]): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterOverlaySurface.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterOverlaySurface.ets new file mode 100644 index 0000000..2d63d83 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterOverlaySurface.ets @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export class FlutterOverlaySurface { + + private id: number; + + constructor(id: number) { + this.id = id + } + + getId(): number { + return this.id; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterShellArgs.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterShellArgs.ets new file mode 100644 index 0000000..7a3cd75 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterShellArgs.ets @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Want from '@ohos.app.ability.Want'; + +/** + * 封装flutter shell的参数 + */ +export default class FlutterShellArgs { + static ARG_KEY_TRACE_STARTUP = "trace-startup"; + static ARG_TRACE_STARTUP = "--trace-startup"; + static ARG_KEY_START_PAUSED = "start-paused"; + static ARG_START_PAUSED = "--start-paused"; + static ARG_KEY_DISABLE_SERVICE_AUTH_CODES = "disable-service-auth-codes"; + static ARG_DISABLE_SERVICE_AUTH_CODES = "--disable-service-auth-codes"; + static ARG_KEY_ENDLESS_TRACE_BUFFER = "endless-trace-buffer"; + static ARG_ENDLESS_TRACE_BUFFER = "--endless-trace-buffer"; + static ARG_KEY_USE_TEST_FONTS = "use-test-fonts"; + static ARG_USE_TEST_FONTS = "--use-test-fonts"; + static ARG_KEY_ENABLE_DART_PROFILING = "enable-dart-profiling"; + static ARG_ENABLE_DART_PROFILING = "--enable-dart-profiling"; + static ARG_KEY_ENABLE_SOFTWARE_RENDERING = "enable-software-rendering"; + static ARG_ENABLE_SOFTWARE_RENDERING = "--enable-software-rendering"; + static ARG_KEY_SKIA_DETERMINISTIC_RENDERING = "skia-deterministic-rendering"; + static ARG_SKIA_DETERMINISTIC_RENDERING = "--skia-deterministic-rendering"; + static ARG_KEY_TRACE_SKIA = "trace-skia"; + static ARG_TRACE_SKIA = "--trace-skia"; + static ARG_KEY_TRACE_SKIA_ALLOWLIST = "trace-skia-allowlist"; + static ARG_TRACE_SKIA_ALLOWLIST = "--trace-skia-allowlist="; + static ARG_KEY_TRACE_SYSTRACE = "trace-systrace"; + static ARG_TRACE_SYSTRACE = "--trace-systrace"; + static ARG_KEY_ENABLE_IMPELLER = "enable-impeller"; + static ARG_ENABLE_IMPELLER = "--enable-impeller"; + static ARG_KEY_DUMP_SHADER_SKP_ON_SHADER_COMPILATION = + "dump-skp-on-shader-compilation"; + static ARG_DUMP_SHADER_SKP_ON_SHADER_COMPILATION = + "--dump-skp-on-shader-compilation"; + static ARG_KEY_CACHE_SKSL = "cache-sksl"; + static ARG_CACHE_SKSL = "--cache-sksl"; + static ARG_KEY_PURGE_PERSISTENT_CACHE = "purge-persistent-cache"; + static ARG_PURGE_PERSISTENT_CACHE = "--purge-persistent-cache"; + static ARG_KEY_VERBOSE_LOGGING = "verbose-logging"; + static ARG_VERBOSE_LOGGING = "--verbose-logging"; + static ARG_KEY_OBSERVATORY_PORT = "observatory-port"; + static ARG_OBSERVATORY_PORT = "--observatory-port="; + static ARG_KEY_DART_FLAGS = "dart-flags"; + static ARG_DART_FLAGS = "--dart-flags"; + static ARG_KEY_MSAA_SAMPLES = "msaa-samples"; + static ARG_MSAA_SAMPLES = "--msaa-samples"; + + /** + * 从意图中解析参数,创建shellArgs + * @returns + */ + static fromWant(want: Want): FlutterShellArgs { + //tdo 解析want + return new FlutterShellArgs(); + } + + //参数 + args: Set = new Set(); + + add(arg: string) { + this.args.add(arg); + } + + remove(arg: string) { + this.args.delete(arg); + } + + toArray(): Array { + return Array.from(this.args); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor.ets new file mode 100644 index 0000000..46d08cd --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartExecutor.ets @@ -0,0 +1,379 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import resourceManager from '@ohos.resourceManager'; +import FlutterInjector from '../../../FlutterInjector'; +import { BinaryMessageHandler, BinaryReply, TaskQueue, TaskQueueOptions } from '../../../plugin/common/BinaryMessenger'; +import { BinaryMessenger } from '../../../plugin/common/BinaryMessenger'; +import StringCodec from '../../../plugin/common/StringCodec'; +import Log from '../../../util/Log'; +import { TraceSection } from '../../../util/TraceSection'; +import { FlutterCallbackInformation } from '../../../view/FlutterCallbackInformation'; +import FlutterNapi from '../FlutterNapi'; +import { DartMessenger } from './DartMessenger'; + + +const TAG = "DartExecutor"; + +/** + * dart代码执行器 + */ +export default class DartExecutor implements BinaryMessenger { + flutterNapi: FlutterNapi; + assetManager: resourceManager.ResourceManager; + private dartMessenger: DartMessenger; + private binaryMessenger: BinaryMessenger; + private isApplicationRunning: boolean = false; + private isolateServiceId: String = ""; + private isolateServiceIdListener: IsolateServiceIdListener | null = null; + + private isolateChannelMessageHandler: BinaryMessageHandler = + new IsolateChannelMessageHandler(this.isolateServiceId, this.isolateServiceIdListener); + + constructor(flutterNapi: FlutterNapi, assetManager: resourceManager.ResourceManager) { + this.flutterNapi = flutterNapi; + this.assetManager = assetManager; + this.dartMessenger = new DartMessenger(flutterNapi); + this.dartMessenger.setMessageHandler("flutter/isolate", this.isolateChannelMessageHandler); + this.binaryMessenger = new DefaultBinaryMessenger(this.dartMessenger); + // The JNI might already be attached if coming from a spawned engine. If so, correctly report + // that this DartExecutor is already running. + if (flutterNapi.isAttached()) { + this.isApplicationRunning = true; + } + } + + + /** + * Invoked when the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@link + * DartExecutor} attaches to JNI. + * + *

When attached to JNI, this {@link DartExecutor} begins handling 2-way communication to/from + * the Dart execution context. This communication is facilitate via 2 APIs: + * + *

    + *
  • {@link BinaryMessenger}, which sends messages to Dart + *
  • {@link PlatformMessageHandler}, which receives messages from Dart + *
+ */ + onAttachedToNAPI(): void { + Log.d(TAG, "Attached to NAPI. Registering the platform message handler for this Dart execution context."); + this.flutterNapi.setPlatformMessageHandler(this.dartMessenger); + } + + /** + * Invoked when the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@link + * DartExecutor} detaches from JNI. + * + *

When detached from JNI, this {@link DartExecutor} stops handling 2-way communication to/from + * the Dart execution context. + */ + onDetachedFromNAPI(): void { + Log.d(TAG, "Detached from NAPI. De-registering the platform message handler for this Dart execution context."); + this.flutterNapi.setPlatformMessageHandler(null); + } + + /** + * Is this {@link DartExecutor} currently executing Dart code? + * + * @return true if Dart code is being executed, false otherwise + */ + isExecutingDart(): boolean { + return this.isApplicationRunning; + } + + /** + * Starts executing Dart code based on the given {@code dartEntrypoint} and the {@code + * dartEntrypointArgs}. + * + *

See {@link DartEntrypoint} for configuration options. + * + * @param dartEntrypoint specifies which Dart function to run, and where to find it + * @param dartEntrypointArgs Arguments passed as a list of string to Dart's entrypoint function. + */ + executeDartEntrypoint(dartEntrypoint: DartEntrypoint, dartEntrypointArgs?: string[]): void { + if (this.isApplicationRunning) { + Log.w(TAG, "Attempted to run a DartExecutor that is already running."); + return; + } + + TraceSection.begin("DartExecutor#executeDartEntrypoint"); + try { + Log.d(TAG, "Executing Dart entrypoint: " + dartEntrypoint); + this.flutterNapi.runBundleAndSnapshotFromLibrary( + dartEntrypoint.pathToBundle, + dartEntrypoint.dartEntrypointFunctionName, + dartEntrypoint.dartEntrypointLibrary, + this.assetManager, + dartEntrypointArgs ?? []); + + this.isApplicationRunning = true; + } finally { + TraceSection.end("DartExecutor#executeDartEntrypoint"); + } + } + + /** + * Starts executing Dart code based on the given {@code dartCallback}. + * + *

See {@link DartCallback} for configuration options. + * + * @param dartCallback specifies which Dart callback to run, and where to find it + */ + executeDartCallback(dartCallback: DartCallback): void { + if (this.isApplicationRunning) { + Log.w(TAG, "Attempted to run a DartExecutor that is already running."); + return; + } + + TraceSection.begin("DartExecutor#executeDartCallback"); + try { + Log.d(TAG, "Executing Dart callback: " + dartCallback); + this.flutterNapi.runBundleAndSnapshotFromLibrary( + dartCallback.pathToBundle, + dartCallback.callbackHandle.callbackName, + dartCallback.callbackHandle.callbackLibraryPath, + dartCallback.resourceManager, + []); + + this.isApplicationRunning = true; + } finally { + TraceSection.end("DartExecutor#executeDartCallback"); + } + } + + /** + * Returns a {@link BinaryMessenger} that can be used to send messages to, and receive messages + * from, Dart code that this {@code DartExecutor} is executing. + */ + + getBinaryMessenger(): BinaryMessenger { + return this.binaryMessenger; + } + + makeBackgroundTaskQueue(options: TaskQueueOptions): TaskQueue { + return this.getBinaryMessenger().makeBackgroundTaskQueue(options); + } + + + send(channel: String, message: ArrayBuffer, callback?: BinaryReply): void { + this.getBinaryMessenger().send(channel, message, callback); + } + + setMessageHandler(channel: String, handler: BinaryMessageHandler, taskQueue?: TaskQueue): void { + this.getBinaryMessenger().setMessageHandler(channel, handler, taskQueue); + } + + enableBufferingIncomingMessages(): void { + this.getBinaryMessenger().enableBufferingIncomingMessages(); + } + + + /** + * Returns the number of pending channel callback replies. + * + *

When sending messages to the Flutter application using {@link BinaryMessenger#send(String, + * ByteBuffer, io.flutter.plugin.common.BinaryMessenger.BinaryReply)}, developers can optionally + * specify a reply callback if they expect a reply from the Flutter application. + * + *

This method tracks all the pending callbacks that are waiting for response, and is supposed + * to be called from the main thread (as other methods). Calling from a different thread could + * possibly capture an indeterministic internal state, so don't do it. + * + *

Currently, it's mainly useful for a testing framework like Espresso to determine whether all + * the async channel callbacks are handled and the app is idle. + */ + getPendingChannelResponseCount(): number { + return this.dartMessenger.getPendingChannelResponseCount(); + } + + /** + * Returns an identifier for this executor's primary isolate. This identifier can be used in + * queries to the Dart service protocol. + */ + + getIsolateServiceId(): String { + return this.isolateServiceId; + } + + + + /** + * Set a listener that will be notified when an isolate identifier is available for this + * executor's primary isolate. + */ + setIsolateServiceIdListener(listener: IsolateServiceIdListener): void { + this.isolateServiceIdListener = listener; + if (this.isolateServiceIdListener != null && this.isolateServiceId != null) { + this.isolateServiceIdListener.onIsolateServiceIdAvailable(this.isolateServiceId); + } + } + + /** + * Notify the Dart VM of a low memory event, or that the application is in a state such that now + * is an appropriate time to free resources, such as going to the background. + * + *

This does not notify a Flutter application about memory pressure. For that, use the {@link + * io.flutter.embedding.engine.systemchannels.SystemChannel#sendMemoryPressureWarning}. + * + *

Calling this method may cause jank or latency in the application. Avoid calling it during + * critical periods like application startup or periods of animation. + */ + notifyLowMemoryWarning(): void { + if (this.flutterNapi.isAttached()) { + this.flutterNapi.notifyLowMemoryWarning(); + } + } + + disableBufferingIncomingMessages(): void { + this.getBinaryMessenger().enableBufferingIncomingMessages(); + } +} + + +/** + * Configuration options that specify which Dart entrypoint function is executed and where to find + * that entrypoint and other assets required for Dart execution. + */ +export class DartEntrypoint { + /** The path within the AssetManager where the app will look for assets. */ + pathToBundle: string; + + /** The library or file location that contains the Dart entrypoint function. */ + dartEntrypointLibrary: string; + + /** The name of a Dart function to execute. */ + dartEntrypointFunctionName: string; + + constructor(pathToBundle: string, + dartEntrypointLibrary: string, + dartEntrypointFunctionName: string) { + this.pathToBundle = pathToBundle; + this.dartEntrypointLibrary = dartEntrypointLibrary; + this.dartEntrypointFunctionName = dartEntrypointFunctionName; + } + + static createDefault() { + const flutterLoader = FlutterInjector.getInstance().getFlutterLoader(); + if (!flutterLoader.initialized) { + throw new Error( + "DartEntrypoints can only be created once a FlutterEngine is created."); + } + return new DartEntrypoint(flutterLoader.findAppBundlePath(), "", "main"); + } +} + + +/** Callback interface invoked when the isolate identifier becomes available. */ +interface IsolateServiceIdListener { + onIsolateServiceIdAvailable(isolateServiceId: String): void; +} + + +/** + * Configuration options that specify which Dart callback function is executed and where to find + * that callback and other assets required for Dart execution. + */ +export class DartCallback { + /** Standard Android AssetManager, provided from some {@code Context} or {@code Resources}. */ + public resourceManager: resourceManager.ResourceManager; + + /** The path within the AssetManager where the app will look for assets. */ + public pathToBundle: string; + + /** A Dart callback that was previously registered with the Dart VM. */ + public callbackHandle: FlutterCallbackInformation; + + constructor(resourceManager: resourceManager.ResourceManager, + pathToBundle: string, + callbackHandle: FlutterCallbackInformation) { + this.resourceManager = resourceManager; + this.pathToBundle = pathToBundle; + this.callbackHandle = callbackHandle; + } + + toString(): String { + return "DartCallback( bundle path: " + + this.pathToBundle + + ", library path: " + + this.callbackHandle.callbackLibraryPath + + ", function: " + + this.callbackHandle.callbackName + + " )"; + } +} + +export class DefaultBinaryMessenger implements BinaryMessenger { + private messenger: DartMessenger; + + constructor(messenger: DartMessenger) { + this.messenger = messenger; + } + + makeBackgroundTaskQueue(options: TaskQueueOptions): TaskQueue { + return this.messenger.makeBackgroundTaskQueue(options); + } + + /** + * Sends the given {@code messages} from Android to Dart over the given {@code channel} and then + * has the provided {@code callback} invoked when the Dart side responds. + * + * @param channel the name of the logical channel used for the message. + * @param message the message payload, a direct-allocated {@link ByteBuffer} with the message + * bytes between position zero and current position, or null. + * @param callback a callback invoked when the Dart application responds to the message + */ + + send(channel: String, message: ArrayBuffer, callback?: BinaryReply): void { + this.messenger.send(channel, message, callback); + } + + /** + * Sets the given {@link io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler} as the + * singular handler for all incoming messages received from the Dart side of this Dart execution + * context. + * + * @param channel the name of the channel. + * @param handler a {@link BinaryMessageHandler} to be invoked on incoming messages, or null. + */ + setMessageHandler(channel: String, handler: BinaryMessageHandler, taskQueue?: TaskQueue): void { + this.messenger.setMessageHandler(channel, handler); + } + + enableBufferingIncomingMessages(): void { + this.messenger.enableBufferingIncomingMessages(); + } + + disableBufferingIncomingMessages(): void { + this.messenger.disableBufferingIncomingMessages(); + } +} + +class IsolateChannelMessageHandler implements BinaryMessageHandler { + private isolateServiceId: String; + private isolateServiceIdListener: IsolateServiceIdListener | null = null; + + constructor(isolateServiceId: String, isolateServiceIdListener: IsolateServiceIdListener | null) { + this.isolateServiceId = isolateServiceId; + this.isolateServiceIdListener = isolateServiceIdListener; + } + + onMessage(message: ArrayBuffer, callback: BinaryReply): void { + this.isolateServiceId = StringCodec.INSTANCE.decodeMessage(message); + if (this.isolateServiceIdListener != null) { + this.isolateServiceIdListener.onIsolateServiceIdAvailable(this.isolateServiceId); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartMessenger.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartMessenger.ets new file mode 100644 index 0000000..6e9bfab --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/DartMessenger.ets @@ -0,0 +1,288 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '../../../util/Log' +import { BinaryMessageHandler, BinaryMessenger, BinaryReply, TaskQueue, TaskQueueOptions } from '../../../plugin/common/BinaryMessenger'; +import FlutterNapi from '../FlutterNapi'; +import { PlatformMessageHandler } from './PlatformMessageHandler'; +import { TraceSection } from '../../../util/TraceSection'; + +/** + * Message conduit for 2-way communication between Android and Dart. + * + *

See {@link BinaryMessenger}, which sends messages from Android to Dart + * + *

See {@link PlatformMessageHandler}, which handles messages to Android from Dart + */ + +const TAG = "DartMessenger"; + +export class DartMessenger implements BinaryMessenger, PlatformMessageHandler { + + flutterNapi: FlutterNapi; + + /** + * Maps a channel name to an object that contains the task queue and the handler associated with + * the channel. + * + *

Reads and writes to this map must lock {@code handlersLock}. + */ + messageHandlers: Map = new Map(); + + /** + * Maps a channel name to an object that holds information about the incoming Dart message. + * + *

Reads and writes to this map must lock {@code handlersLock}. + */ + bufferedMessages: Map = new Map(); + + handlersLock: Object = new Object(); + enableBufferingIncomingMessagesFlag: boolean = false; + + pendingReplies: Map = new Map(); + nextReplyId: number = 1; + taskQueueFactory: TaskQueueFactory; + createdTaskQueues: Map = new Map(); + + constructor(flutterNapi: FlutterNapi) { + this.flutterNapi = flutterNapi; + this.taskQueueFactory = new DefaultTaskQueueFactory(); + } + makeBackgroundTaskQueue(options: TaskQueueOptions): TaskQueue { + let taskQueue: DartMessengerTaskQueue = this.taskQueueFactory.makeBackgroundTaskQueue(options); + let token: TaskQueueToken = new TaskQueueToken(); + this.createdTaskQueues.set(token, taskQueue); + return token; + } + + + setMessageHandler(channel: String, handler: BinaryMessageHandler, taskQueue?: TaskQueue): void { + if (handler == null) { + Log.d(TAG, "Removing handler for channel '" + channel + "'"); + this.messageHandlers.delete(channel); + return; + } + let dartMessengerTaskQueue: DartMessengerTaskQueue | null = null; + if( taskQueue != null) { + dartMessengerTaskQueue = this.createdTaskQueues.get(taskQueue) ?? null; + if(dartMessengerTaskQueue == null) { + throw new Error( + "Unrecognized TaskQueue, use BinaryMessenger to create your TaskQueue (ex makeBackgroundTaskQueue)." + ); + } + } + Log.d(TAG, "Setting handler for channel '" + channel + "'"); + + this.messageHandlers.set(channel, new HandlerInfo(handler, dartMessengerTaskQueue)); + this.bufferedMessages.delete(channel); + } + + + enableBufferingIncomingMessages(): void { + this.enableBufferingIncomingMessagesFlag = true; + } + + disableBufferingIncomingMessages(): void { + this.enableBufferingIncomingMessagesFlag = false; + this.bufferedMessages = new Map(); + } + + send(channel: String, message: ArrayBuffer, callback?: BinaryReply): void { + Log.d(TAG, "Sending message over channel '" + channel + "'"); + TraceSection.begin("DartMessenger#send on " + channel); + try { + Log.d(TAG, "Sending message with callback over channel '" + channel + "'"); + let replyId: number = this.nextReplyId++; + if (callback != null) { + this.pendingReplies.set(replyId, callback); + } + if (message == null) { + this.flutterNapi.dispatchEmptyPlatformMessage(channel, replyId); + } else { + this.flutterNapi.dispatchPlatformMessage(channel, message, message.byteLength, replyId); + } + } finally { + TraceSection.end("DartMessenger#send on " + channel); + } + } + + async asyncInvokeHandler(handlerInfo: HandlerInfo | null, message: ArrayBuffer, replyId: number): Promise { + // Called from any thread. + if (handlerInfo != null) { + try { + Log.d(TAG, "Deferring to registered handler to process message."); + handlerInfo.handler.onMessage(message, new Reply(this.flutterNapi, replyId)); + } catch (ex) { + Log.e(TAG, "Uncaught exception in binary message listener", ex); + this.flutterNapi.invokePlatformMessageEmptyResponseCallback(replyId); + } + } else { + Log.d(TAG, "No registered handler for message. Responding to Dart with empty reply message."); + this.flutterNapi.invokePlatformMessageEmptyResponseCallback(replyId); + } + } + + invokeHandler(handlerInfo: HandlerInfo | null, message: ArrayBuffer, replyId: number): void { + // Called from any thread. + if (handlerInfo != null) { + try { + Log.d(TAG, "Deferring to registered handler to process message."); + handlerInfo.handler.onMessage(message, new Reply(this.flutterNapi, replyId)); + } catch (ex) { + Log.e(TAG, "Uncaught exception in binary message listener", ex); + this.flutterNapi.invokePlatformMessageEmptyResponseCallback(replyId); + } + } else { + Log.d(TAG, "No registered handler for message. Responding to Dart with empty reply message."); + this.flutterNapi.invokePlatformMessageEmptyResponseCallback(replyId); + } + } + + handleMessageFromDart(channel: String, message: ArrayBuffer, replyId: number, messageData: number): void { + // Called from any thread. + Log.d(TAG, "Received message from Dart over channel '" + channel + "'"); + + let handlerInfo: HandlerInfo | null = this.messageHandlers.get(channel) ?? null; + let messageDeferred: boolean; + + messageDeferred = (this.enableBufferingIncomingMessagesFlag && handlerInfo == null); + if (messageDeferred) { + if (!this.bufferedMessages.has(channel)) { + this.bufferedMessages.set(channel, []); + } + let buffer: BufferedMessageInfo[] = this.bufferedMessages.get(channel) ?? []; + buffer.push(new BufferedMessageInfo(message, replyId, messageData)); + } + if (!messageDeferred) { + //ArkTS 没有线程池,任务队列使用异步实现 + if(handlerInfo?.taskQueue != null) { + this.asyncInvokeHandler(handlerInfo, message, replyId); + } else { + this.invokeHandler(handlerInfo, message, replyId); + } + } + } + + handlePlatformMessageResponse(replyId: number, reply: ArrayBuffer): void { + Log.d(TAG, "Received message reply from Dart."); + let callback: BinaryReply | null = this.pendingReplies.get(replyId) ?? null; + this.pendingReplies.delete(replyId); + if (callback != null) { + try { + Log.d(TAG, "Invoking registered callback for reply from Dart."); + callback.reply(reply); + } catch (e) { + Log.e(TAG, "Uncaught exception in binary message reply handler", e); + } + } + } + + /** + * Returns the number of pending channel callback replies. + * + *

When sending messages to the Flutter application using {@link BinaryMessenger#send(String, + * ByteBuffer, io.flutter.plugin.common.BinaryMessenger.BinaryReply)}, developers can optionally + * specify a reply callback if they expect a reply from the Flutter application. + * + *

This method tracks all the pending callbacks that are waiting for response, and is supposed + * to be called from the main thread (as other methods). Calling from a different thread could + * possibly capture an indeterministic internal state, so don't do it. + */ + getPendingChannelResponseCount(): number { + return this.pendingReplies.size; + } +} + + + + + + +/** + * Holds information about a platform handler, such as the task queue that processes messages from + * Dart. + */ +class HandlerInfo { + handler: BinaryMessageHandler; + taskQueue: DartMessengerTaskQueue | null; + constructor(handler: BinaryMessageHandler, taskQueue?:DartMessengerTaskQueue | null) { + this.handler = handler; + this.taskQueue = taskQueue ?? null; + } +} + +/** + * Holds information that allows to dispatch a Dart message to a platform handler when it becomes + * available. + */ +class BufferedMessageInfo { + message: ArrayBuffer; + replyId: number; + messageData: number; + + constructor(message: ArrayBuffer, + replyId: number, + messageData: number) { + this.message = message; + this.replyId = replyId; + this.messageData = messageData; + } +} + + + + + +class Reply implements BinaryReply { + flutterNapi: FlutterNapi; + replyId: number; + done: boolean = false; + + constructor(flutterNapi: FlutterNapi, replyId: number) { + this.flutterNapi = flutterNapi; + this.replyId = replyId; + } + + reply(reply: ArrayBuffer) { + if (this.done) { + throw new Error("Reply already submitted"); + } + if (reply == null) { + this.flutterNapi.invokePlatformMessageEmptyResponseCallback(this.replyId); + } else { + this.flutterNapi.invokePlatformMessageResponseCallback(this.replyId, reply, reply.byteLength); + } + } +} + +interface DartMessengerTaskQueue { + dispatch(): void; +} + +interface TaskQueueFactory { + makeBackgroundTaskQueue(options: TaskQueueOptions): DartMessengerTaskQueue; +} + +class ConcurrentTaskQueue implements DartMessengerTaskQueue { + dispatch(): void {} +} + +class DefaultTaskQueueFactory implements TaskQueueFactory { + makeBackgroundTaskQueue(options: TaskQueueOptions): DartMessengerTaskQueue { + return new ConcurrentTaskQueue(); + } +} + +class TaskQueueToken implements TaskQueue {} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/PlatformMessageHandler.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/PlatformMessageHandler.ets new file mode 100644 index 0000000..b6e3411 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/dart/PlatformMessageHandler.ets @@ -0,0 +1,22 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export interface PlatformMessageHandler { + + handleMessageFromDart(channel: String,message: ArrayBuffer,replyId: number, messageData: number): void; + + handlePlatformMessageResponse(replyId: number, reply: ArrayBuffer): void; + +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader.ets new file mode 100644 index 0000000..3c5bca8 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/ApplicationInfoLoader.ets @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterApplicationInfo from './FlutterApplicationInfo'; +import common from '@ohos.app.ability.common'; + +export default class ApplicationInfoLoader { + static load(context: common.Context) { + let applicationInfo = new FlutterApplicationInfo(null, null, null, null, null, context.bundleCodeDir + '/libs/arm64', true); + return applicationInfo + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterApplicationInfo.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterApplicationInfo.ets new file mode 100644 index 0000000..bdb9509 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterApplicationInfo.ets @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +const DEFAULT_AOT_SHARED_LIBRARY_NAME = "libapp.so"; +const DEFAULT_VM_SNAPSHOT_DATA = "vm_snapshot_data"; +const DEFAULT_ISOLATE_SNAPSHOT_DATA = "isolate_snapshot_data"; +const DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets"; + + +/** + * application 信息,后期看如何设置 + */ +export default class FlutterApplicationInfo { + aotSharedLibraryName: string; + vmSnapshotData: string; + isolateSnapshotData: string; + flutterAssetsDir: string; + domainNetworkPolicy: string; + nativeLibraryDir: string; + automaticallyRegisterPlugins: boolean; + //是否是开发模式,先放在这里,后续应该从context获取 + isDebugMode: boolean; + //是否是profile模式 + isProfile: boolean; + + constructor(aotSharedLibraryName: string | null, + vmSnapshotData: string | null, + isolateSnapshotData: string | null, + flutterAssetsDir: string | null, + domainNetworkPolicy: string | null, + nativeLibraryDir: string, + automaticallyRegisterPlugins: boolean) { + this.aotSharedLibraryName = aotSharedLibraryName == null ? DEFAULT_AOT_SHARED_LIBRARY_NAME : aotSharedLibraryName; + this.vmSnapshotData = vmSnapshotData == null ? DEFAULT_VM_SNAPSHOT_DATA : vmSnapshotData; + this.isolateSnapshotData = isolateSnapshotData == null ? DEFAULT_ISOLATE_SNAPSHOT_DATA : isolateSnapshotData; + this.flutterAssetsDir = flutterAssetsDir == null ? DEFAULT_FLUTTER_ASSETS_DIR : flutterAssetsDir; + this.domainNetworkPolicy = domainNetworkPolicy == null ? "" : domainNetworkPolicy; + this.nativeLibraryDir = nativeLibraryDir; + this.automaticallyRegisterPlugins = automaticallyRegisterPlugins; + this.isDebugMode = true; + this.isProfile = false; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterLoader.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterLoader.ets new file mode 100644 index 0000000..8917880 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/loader/FlutterLoader.ets @@ -0,0 +1,219 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** + * flutterLoader,负责dart虚拟机启动和dart代码加载 + */ +import FlutterShellArgs from '../FlutterShellArgs'; +import FlutterNapi from '../FlutterNapi'; +import Log from '../../../util/Log'; +import FlutterApplicationInfo from './FlutterApplicationInfo'; +import common from '@ohos.app.ability.common'; +import StringUtils from '../../../util/StringUtils'; +import ApplicationInfoLoader from './ApplicationInfoLoader'; +import bundleManager from '@ohos.bundle.bundleManager'; +import fs from '@ohos.file.fs'; + +const TAG = "FlutterLoader"; + +//flutter引擎so +const DEFAULT_LIBRARY = "libflutter.so"; +//jit产物默认kenel文件 +const DEFAULT_KERNEL_BLOB = "kernel_blob.bin"; +//jit产物,默认快照文件 +const VMSERVICE_SNAPSHOT_LIBRARY = "libvmservice_snapshot.so"; +//key值 +const SNAPSHOT_ASSET_PATH_KEY = "snapshot-asset-path"; +//key值 +const VM_SNAPSHOT_DATA_KEY = "vm-snapshot-data"; +//key值 +const ISOLATE_SNAPSHOT_DATA_KEY = "isolate-snapshot-data"; + + +const AOT_SHARED_LIBRARY_NAME = "aot-shared-library-name"; + +const AOT_VMSERVICE_SHARED_LIBRARY_NAME = "aot-vmservice-shared-library-name"; + +//文件路径分隔符 +const FILE_SEPARATOR = "/"; + +/** + * 定位在hap包中的flutter资源,并且加载flutter native library. + */ +export default class FlutterLoader { + flutterNapi: FlutterNapi; + initResult: InitResult | null = null; + flutterApplicationInfo: FlutterApplicationInfo | null = null; + context: common.Context | null = null; + initialized: boolean = false; + //初始化开始时间戳 + initStartTimestampMillis: number = 0; + + constructor(flutterNapi: FlutterNapi) { + this.flutterNapi = flutterNapi; + } + + /** + * Starts initialization of the native system. + * + *

This loads the Flutter engine's native library to enable subsequent JNI calls. This also + * starts locating and unpacking Dart resources packaged in the app's APK. + * + *

Calling this method multiple times has no effect. + * + * @param applicationContext The Android application context. + * @param settings Configuration settings. + */ + async startInitialization(context: common.Context) { + Log.d(TAG, "flutterLoader start init") + this.initStartTimestampMillis = Date.now(); + this.context = context; + this.flutterApplicationInfo = ApplicationInfoLoader.load(context); + Log.d(TAG, "context.filesDir=" + context.filesDir) + Log.d(TAG, "context.cacheDir=" + context.cacheDir) + Log.d(TAG, "context.bundleCodeDir=" + context.bundleCodeDir) + if (this.flutterApplicationInfo!.isDebugMode) { + await this.copyResource(context) + } + this.initResult = new InitResult( + `${context.filesDir}/`, + `${context.cacheDir}/`, + `${context.filesDir}` + ) + Log.d(TAG, "flutterLoader end init") + } + + private async copyResource(context: common.Context) { + let filePath = context.filesDir + FILE_SEPARATOR + this.flutterApplicationInfo!.flutterAssetsDir + if (!fs.accessSync(filePath + FILE_SEPARATOR + DEFAULT_KERNEL_BLOB) && this.context != null) { + Log.d(TAG, "start copyResource") + fs.mkdirSync(filePath) + + let icudtlBuffer = await this.context.resourceManager.getRawFileContent(this.flutterApplicationInfo!.flutterAssetsDir + "/icudtl.dat") + let icudtlFile = fs.openSync(filePath + FILE_SEPARATOR + "/icudtl.dat", fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) + fs.writeSync(icudtlFile.fd, icudtlBuffer.buffer) + + let kernelBuffer = await this.context.resourceManager.getRawFileContent(this.flutterApplicationInfo!.flutterAssetsDir + FILE_SEPARATOR + DEFAULT_KERNEL_BLOB) + let kernelFile = fs.openSync(filePath + FILE_SEPARATOR + DEFAULT_KERNEL_BLOB, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) + fs.writeSync(kernelFile.fd, kernelBuffer.buffer) + + let vmBuffer = await this.context.resourceManager.getRawFileContent(this.flutterApplicationInfo!.flutterAssetsDir + FILE_SEPARATOR + this.flutterApplicationInfo!.vmSnapshotData) + let vmFile = fs.openSync(filePath + FILE_SEPARATOR + this.flutterApplicationInfo!.vmSnapshotData, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) + fs.writeSync(vmFile.fd, vmBuffer.buffer) + + let isolateBuffer = await this.context.resourceManager.getRawFileContent(this.flutterApplicationInfo!.flutterAssetsDir + FILE_SEPARATOR + this.flutterApplicationInfo!.isolateSnapshotData) + let isolateFile = fs.openSync(filePath + FILE_SEPARATOR + this.flutterApplicationInfo!.isolateSnapshotData, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) + fs.writeSync(isolateFile.fd, isolateBuffer.buffer) + Log.d(TAG, "copyResource end") + } else { + Log.d(TAG, "no copyResource") + } + } + + /** + * 初始化dart虚拟机方法 + * @param flutterShellArgs + */ + ensureInitializationComplete(shellArgs: Array | null) { + if (this.initialized) { + return; + } + Log.d(TAG, "ensureInitializationComplete") + if (shellArgs == null) { + shellArgs = new Array(); + } + shellArgs.push( + "--icu-native-lib-path=" + + this.flutterApplicationInfo!.nativeLibraryDir + + FILE_SEPARATOR + DEFAULT_LIBRARY + ); + + let kernelPath: string = ""; + if (this.flutterApplicationInfo!.isDebugMode) { + Log.d(TAG, "this.initResult!.dataDirPath=" + this.initResult!.dataDirPath) + const snapshotAssetPath = this.initResult!.dataDirPath + FILE_SEPARATOR + this.flutterApplicationInfo!.flutterAssetsDir; + kernelPath = snapshotAssetPath + FILE_SEPARATOR + DEFAULT_KERNEL_BLOB; + shellArgs.push("--icu-data-file-path=" + snapshotAssetPath + "/icudtl.dat") + shellArgs.push("--" + SNAPSHOT_ASSET_PATH_KEY + "=" + snapshotAssetPath); + shellArgs.push("--" + VM_SNAPSHOT_DATA_KEY + "=" + this.flutterApplicationInfo!.vmSnapshotData); + shellArgs.push( + "--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + this.flutterApplicationInfo!.isolateSnapshotData); + } else { + shellArgs.push( + "--" + AOT_SHARED_LIBRARY_NAME + "=" + this.flutterApplicationInfo!.aotSharedLibraryName); + shellArgs.push( + "--" + + AOT_SHARED_LIBRARY_NAME + + "=" + + this.flutterApplicationInfo!.nativeLibraryDir + + FILE_SEPARATOR + + this.flutterApplicationInfo!.aotSharedLibraryName); + if (this.flutterApplicationInfo!.isProfile) { + shellArgs.push("--" + AOT_VMSERVICE_SHARED_LIBRARY_NAME + "=" + VMSERVICE_SNAPSHOT_LIBRARY); + } + } + shellArgs.push("--cache-dir-path=" + this.initResult!.engineCachesPath); + if (StringUtils.isNotEmpty(this.flutterApplicationInfo!.domainNetworkPolicy)) { + shellArgs.push("--domain-network-policy=" + this.flutterApplicationInfo!.domainNetworkPolicy); + } + + const resourceCacheMaxBytesThreshold = 1080 * 1920 * 12 * 4; + shellArgs.push("--resource-cache-max-bytes-threshold=" + resourceCacheMaxBytesThreshold); + + shellArgs.push("--prefetched-default-font-manager"); + + shellArgs.push("--leak-vm=" + true); + + //shellArgs.push("--enable-impeller"); + + // //最终初始化操作 + const costTime = Date.now() - this.initStartTimestampMillis; + this.flutterNapi!.init( + this.context!, + shellArgs, + kernelPath, + this.initResult!.appStoragePath, + this.initResult!.engineCachesPath!, + costTime + ); + this.initialized = true; + } + + findAppBundlePath(): string { + return this.flutterApplicationInfo == null ? "" : this.flutterApplicationInfo!.flutterAssetsDir; + } + + getLookupKeyForAsset(asset: string, packageName?: string): string { + return this.fullAssetPathFrom(asset); + } + + fullAssetPathFrom(filePath: string): string { + return this.flutterApplicationInfo == null ? "" : this.flutterApplicationInfo!.flutterAssetsDir + "/" + filePath; + } +} + +class InitResult { + appStoragePath: string; + engineCachesPath: string; + dataDirPath: string; + + constructor(appStoragePath: string, + engineCachesPath: string, + dataDirPath: string) { + this.appStoragePath = appStoragePath; + this.engineCachesPath = engineCachesPath; + this.dataDirPath = dataDirPath; + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets new file mode 100644 index 0000000..f2544f8 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorView.ets @@ -0,0 +1,135 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import ArrayList from '@ohos.util.ArrayList'; +import matrix4 from '@ohos.matrix4'; +import { DVModel, DVModelEvents, DVModelParameters } from '../../../view/DynamicView/dynamicView'; +import { createDVModelFromJson } from '../../../view/DynamicView/dynamicViewJson'; +import OhosTouchProcessor from '../../ohos/OhosTouchProcessor'; +import { FlutterMutator, FlutterMutatorsStack } from './FlutterMutatorsStack' + +export class FlutterMutatorView { + private mutatorsStack: FlutterMutatorsStack | null = null; + private screenDensity: number = 0; + private left: number = 0; + private top: number = 0; + private prevLeft: number = 0; + private prevTop: number = 0; + + private onTouch = (touchEvent: ESObject) => { + let params = this.model.params as Record; + switch (touchEvent.type) { + case TouchType.Down: + this.prevLeft = this.left; + this.prevTop = this.top; + params.translateX = this.left; + params.translateY = this.top; + break; + case TouchType.Move: + params.translateX = this.prevLeft; + params.translateY = this.prevTop; + this.prevLeft = this.left; + this.prevTop = this.top; + break; + case TouchType.Up: + case TouchType.Cancel: + default: + break; + } + } + + private model: DVModel = createDVModelFromJson( + new DVModelParam("Column", [], { backgroundColor: Color.Red }, { onTouch: this.onTouch }) + ); + + setOnDescendantFocusChangeListener(onFocus: () => void, onBlur: () => void) { + // this.model.events["onFocus"] = onFocus; + // this.model.events["onBlur"] = onBlur; + let events2 = this.model.events as Record; + events2.onFocus = onFocus; + events2.onBlur = onBlur; + } + + public setLayoutParams(parameters: DVModelParameters): void { + if (this.model.params == null) { + this.model.params = new DVModelParameters(); + } + let params = this.model.params as Record | matrix4.Matrix4Transit>; + let parametersRecord = parameters as Record | matrix4.Matrix4Transit>; + params.marginLeft = parametersRecord['marginLeft']; + params.marginTop = parametersRecord['marginTop']; + params.width = parametersRecord['width']; + params.height = parametersRecord['height']; + this.left = parametersRecord.marginLeft as number; + this.top = parametersRecord.marginTop as number ; + } + + public addDvModel(model: DVModel): void { + this.model?.children.push(model); + } + + public readyToDisplay(mutatorsStack: FlutterMutatorsStack, left: number, top: number, width: number, height: number) { + this.mutatorsStack = mutatorsStack; + this.left = left; + this.top = top; + let parameters = new DVModelParameters() as Record | matrix4.Matrix4Transit>; + parameters['marginLeft'] = left; + parameters['marginTop'] = top; + parameters['width'] = width; + parameters['height'] = height; + this.setLayoutParams(parameters); + this.dealMutators(); + } + + private dealMutators() { + if (this.mutatorsStack == null) { + return; + } + let paths = this.mutatorsStack.getFinalClippingPaths(); + let rects = this.mutatorsStack.getFinalClippingRects(); + let matrix = this.mutatorsStack.getFinalMatrix(); + let params = this.model.params as Record | matrix4.Matrix4Transit>; + if (!paths.isEmpty()) { + let path = paths.getLast(); + params.pathWidth = path.width; + params.pathHeight = path.height; + params.pathCommands = path.commands; + } + if (!rects.isEmpty()) { + let rect = rects.getLast(); + params.rectWidth = rect.width; + params.rectHeight = rect.height; + params.rectRadius = rect.radius; + } + params.matrix = matrix; + } + + public getDvModel(): DVModel | undefined { + return this.model; + } +} + +class DVModelParam { + compType: string + children: [] + attributes: ESObject + events: ESObject + + constructor(compType: string, children: [], attributes: ESObject, events: ESObject) { + this.compType = compType; + this.children = children; + this.attributes = attributes; + this.events = events; + } +}; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorsStack.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorsStack.ets new file mode 100644 index 0000000..2f53c6c --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/mutatorsstack/FlutterMutatorsStack.ets @@ -0,0 +1,136 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import matrix4 from '@ohos.matrix4' +import List from '@ohos.util.List'; + +export enum FlutterMutatorType { + CLIP_RECT, + CLIP_PATH, + TRANSFORM, + OPACITY +} + +class Rect { + width: number; + height: number; + radius: string | number | Array; + + constructor(width:number, height:number, radius?:string | number | Array) { + this.width = width; + this.height = height; + this.radius = radius ?? 0; + } +} + +class Path { + width: number | string; + height: number | string; + commands: string; + + constructor(width:number | string, height:number | string, commands?:string) { + this.width = width; + this.height = height; + this.commands = commands ?? ''; + } +} + +export class FlutterMutator { + private matrix: matrix4.Matrix4Transit | null = null; + private rect: Rect = new Rect(0, 0); + private path: Path = new Path(0, 0); + + constructor(args: matrix4.Matrix4Transit | Rect | Path) { + if (args instanceof Rect) { + this.rect = args; + } else if (args instanceof Path) { + this.path = args; + } else { + this.matrix = args; + } + } + + public getMatrix() : matrix4.Matrix4Transit | null { + return this.matrix; + } + + public getRect() { + return this.rect; + } + + public getPath() { + return this.path; + } +} + +export class FlutterMutatorsStack { + private mutators: List; + private finalClippingPaths: List; + private finalClippingRects: List; + + private finalMatrix: matrix4.Matrix4Transit; + + constructor() { + this.mutators = new List(); + this.finalClippingPaths = new List(); + this.finalClippingRects = new List(); + this.finalMatrix = matrix4.identity(); + } + + public pushTransform(values: Array): void { + if (values.length != 16) { + return; + } + let index = 0; + let matrix = matrix4.init( + [values[index++], values[index++], values[index++], values[index++], + values[index++], values[index++], values[index++], values[index++], + values[index++], values[index++], values[index++], values[index++], + values[index++], values[index++], values[index++], values[index++]]); + let mutator = new FlutterMutator(matrix); + this.mutators.add(mutator); + this.finalMatrix.combine(matrix); + } + + public pushClipRect(width:number, height:number, radius?:number) { + let rect = new Rect(width, height, radius); + let mutator = new FlutterMutator(rect); + this.mutators.add(mutator); + this.finalClippingRects.add(rect); + } + + public pushClipPath(width:number, height:number, command?:string) { + let path = new Path(width, height, command); + let mutator = new FlutterMutator(path); + this.mutators.add(mutator); + this.finalClippingPaths.add(path); + } + + public getMutators() { + return this.mutators; + } + + public getFinalClippingPaths() { + return this.finalClippingPaths; + } + + public getFinalClippingRects() { + return this.finalClippingRects; + } + + public getFinalMatrix() { + return this.finalMatrix; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin.ets new file mode 100644 index 0000000..6b0987a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin.ets @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import common from '@ohos.app.ability.common'; +import { BinaryMessenger } from '../../../plugin/common/BinaryMessenger'; +import PlatformViewFactory from '../../../plugin/platform/PlatformViewFactory'; +import PlatformViewRegistry from '../../../plugin/platform/PlatformViewRegistry'; +import FlutterEngineGroup from '../FlutterEngineGroup'; + +export interface FlutterPlugin { + //获取唯一的类名 类似安卓的ClassRelevant resources that this {@code FlutterPlugin} may need are provided via the {@code + * binding}. The {@code binding} may be cached and referenced until {@link + * #onDetachedFromEngine(FlutterPluginBinding)} is invoked and returns. + */ + onAttachedToEngine(binding: FlutterPluginBinding): void; + + /** + * This {@code FlutterPlugin} has been removed from a {@link + * io.flutter.embedding.engine.FlutterEngine} instance. + * + *

The {@code binding} passed to this method is the same instance that was passed in {@link + * #onAttachedToEngine(FlutterPluginBinding)}. It is provided again in this method as a + * convenience. The {@code binding} may be referenced during the execution of this method, but it + * must not be cached or referenced after this method returns. + * + *

{@code FlutterPlugin}s should release all resources in this method. + */ + onDetachedFromEngine(binding: FlutterPluginBinding): void; +} + +export class FlutterPluginBinding { + private applicationContext: common.Context; + private binaryMessenger: BinaryMessenger; + private flutterAssets: FlutterAssets; + private group: FlutterEngineGroup; + private platformViewRegistry: PlatformViewRegistry; + + constructor(applicationContext: common.Context, binaryMessenger: BinaryMessenger, flutterAssets: FlutterAssets, group: FlutterEngineGroup, platformViewRegistry?: PlatformViewRegistry) { + this.applicationContext = applicationContext; + this.binaryMessenger = binaryMessenger; + this.flutterAssets = flutterAssets; + this.group = group; + this.platformViewRegistry = platformViewRegistry ?? new EmptyPlatformViewRegistry(); + } + + getApplicationContext(): common.Context { + return this.applicationContext; + } + + getBinaryMessenger(): BinaryMessenger { + return this.binaryMessenger; + } + + getFlutterAssets(): FlutterAssets { + return this.flutterAssets; + } + + getEngineGroup(): FlutterEngineGroup { + return this.group; + } + + public getPlatformViewRegistry(): PlatformViewRegistry { + return this.platformViewRegistry; + } +} + +/** Provides Flutter plugins with access to Flutter asset information. */ +export interface FlutterAssets { + /** + * Returns the relative file path to the Flutter asset with the given name, including the file's + * extension, e.g., {@code "myImage.jpg"}. + * + *

The returned file path is relative to the Ohos app's standard assets directory. + * Therefore, the returned path is appropriate to pass to Ohos's {@code ResourceManage}, but + * the path is not appropriate to load as an absolute path. + */ + getAssetFilePathByName(assetFileName: string): string; + + /** + * Same as {@link #getAssetFilePathByName(String)} but with added support for an explicit + * Ohos {@code bundleName}. + */ + getAssetFilePathByName(assetFileName: string, bundleName: string): string; + + /** + * Returns the relative file path to the Flutter asset with the given subpath, including the + * file's extension, e.g., {@code "/dir1/dir2/myImage.jpg"}. + * + *

The returned file path is relative to the Ohos app's standard assets directory. + * Therefore, the returned path is appropriate to pass to Ohos's {@code ResourceManage}, but + * the path is not appropriate to load as an absolute path. + */ + getAssetFilePathBySubpath(assetSubpath: string): string; + + /** + * Same as {@link #getAssetFilePathBySubpath(String)} but with added support for an explicit + * Ohos {@code bundleName}. + */ + getAssetFilePathBySubpath(assetSubpath: string, bundleName: string): string; +} + +class EmptyPlatformViewRegistry implements PlatformViewRegistry { + registerViewFactory(viewTypeId: string, factory: PlatformViewFactory): boolean { + return false; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/PluginRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/PluginRegistry.ets new file mode 100644 index 0000000..1a322ec --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/PluginRegistry.ets @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { FlutterPlugin } from './FlutterPlugin'; + +export default interface PluginRegistry { + /** + * Attaches the given {@code plugin} to the {@link io.flutter.embedding.engine.FlutterEngine} + * associated with this {@code PluginRegistry}. + */ + add(plugin: FlutterPlugin): void; + + /** + * Attaches the given {@code plugins} to the {@link io.flutter.embedding.engine.FlutterEngine} + * associated with this {@code PluginRegistry}. + */ + addList(plugins: Set): void; + + /** + * Returns true if a plugin of the given type is currently attached to the {@link + * io.flutter.embedding.engine.FlutterEngine} associated with this {@code PluginRegistry}. + */ + //Class + has(pluginClassName: string): boolean; + + /** + * Returns the instance of a plugin that is currently attached to the {@link + * io.flutter.embedding.engine.FlutterEngine} associated with this {@code PluginRegistry}, which + * matches the given {@code pluginClass}. + * + *

If no matching plugin is found, {@code null} is returned. + */ + //Class + get(pluginClassName: string): FlutterPlugin; + + /** + * Detaches the plugin of the given type from the {@link + * io.flutter.embedding.engine.FlutterEngine} associated with this {@code PluginRegistry}. + * + *

If no such plugin exists, this method does nothing. + */ + //Class + remove(pluginClassName: string): void; + + /** + * Detaches the plugins of the given types from the {@link + * io.flutter.embedding.engine.FlutterEngine} associated with this {@code PluginRegistry}. + * + *

If no such plugins exist, this method does nothing. + */ + //Class + removeList(pluginClassNames: Set): void; + + /** + * Detaches all plugins that are currently attached to the {@link + * io.flutter.embedding.engine.FlutterEngine} associated with this {@code PluginRegistry}. + * + *

If no plugins are currently attached, this method does nothing. + */ + removeAll(): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware.ets new file mode 100644 index 0000000..bd68f68 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware.ets @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** + * {@link io.flutter.embedding.engine.plugins.FlutterPlugin} that is interested in {@link + * ohos.app.ability.UIAbility} lifecycle events related to a {@link + * io.flutter.embedding.engine.FlutterEngine} running within the given {@link ohos.app.ability.UIAbility}. + */ +import { AbilityPluginBinding } from './AbilityPluginBinding'; + +export default interface AbilityAware { + /** + * This {@code AbilityAware} {@link io.flutter.embedding.engine.plugins.FlutterPlugin} is now + * associated with an {@link ohos.app.ability.UIAbility}. + * + *

This method can be invoked in 1 of 2 situations: + * + *

    + *
  • This {@code AbilityAware} {@link io.flutter.embedding.engine.plugins.FlutterPlugin} was + * just added to a {@link io.flutter.embedding.engine.FlutterEngine} that was already + * connected to a running {@link ohos.app.ability.UIAbility}. + *
  • This {@code AbilityAware} {@link io.flutter.embedding.engine.plugins.FlutterPlugin} was + * already added to a {@link io.flutter.embedding.engine.FlutterEngine} and that {@link + * io.flutter.embedding.engine.FlutterEngine} was just connected to an {@link + * ohos.app.ability.UIAbility}. + *
+ * + * The given {@link AbilityPluginBinding} contains {@link ohos.app.ability.UIAbility}-related + * references that an {@code AbilityAware} {@link + * io.flutter.embedding.engine.plugins.FlutterPlugin} may require, such as a reference to the + * actual {@link ohos.app.ability.UIAbility} in question. The {@link AbilityPluginBinding} may be + * referenced until either {@link #onDetachedFromAbilityForConfigChanges()} or {@link + * #onDetachedFromAbility()} is invoked. At the conclusion of either of those methods, the + * binding is no longer valid. Clear any references to the binding or its resources, and do not + * invoke any further methods on the binding or its resources. + */ + onAttachedToAbility(binding: AbilityPluginBinding): void ; + + /** + * This plugin has been detached from an {@link ohos.app.ability.UIAbility}. + * + *

Detachment can occur for a number of reasons. + * + *

    + *
  • The app is no longer visible and the {@link ohos.app.ability.UIAbility} instance has been + * destroyed. + *
  • The {@link io.flutter.embedding.engine.FlutterEngine} that this plugin is connected to + * has been detached from its {@link io.flutter.embedding.android.FlutterView}. + *
  • This {@code AbilityAware} plugin has been removed from its {@link + * io.flutter.embedding.engine.FlutterEngine}. + *
+ * + * By the end of this method, the {@link ohos.app.ability.UIAbility} that was made available in {@link + * #onAttachedToAbility(AbilityPluginBinding)} is no longer valid. Any references to the + * associated {@link ohos.app.ability.UIAbility} or {@link AbilityPluginBinding} should be cleared. + * + *

Any {@code Lifecycle} listeners that were registered in {@link + * #onAttachedToAbility(AbilityPluginBinding)} or {@link + * #onReattachedToAbilityForConfigChanges(AbilityPluginBinding)} should be deregistered here to + * avoid a possible memory leak and other side effects. + */ + onDetachedFromAbility(): void; +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityControlSurface.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityControlSurface.ets new file mode 100644 index 0000000..947ccef --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityControlSurface.ets @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import Want from '@ohos.app.ability.Want'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import ExclusiveAppComponent from '../../../ohos/ExclusiveAppComponent'; + +export default interface ActivityControlSurface { + attachToAbility(exclusiveActivity: ExclusiveAppComponent): void; + detachFromAbility(): void; + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void; + onWindowFocusChanged(hasFocus: boolean): void; + onSaveState(reason: AbilityConstant.StateType, wantParam: Record): AbilityConstant.OnSaveResult; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding.ets new file mode 100644 index 0000000..349010b --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding.ets @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility' +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export interface AbilityPluginBinding { + getAbility(): UIAbility; + /** + * Adds a listener that is invoked whenever the associated {@link ohos.app.ability.UIAbility}'s {@code + * onNewWant(...)} method is invoked. + */ + addOnNewWantListener(listener: NewWantListener): void; + + /** + * Removes a listener that was added in {@link + * #addOnNewWantListener(NewWantListener)}. + */ + removeOnNewWantListener(listener: NewWantListener): void; + + /** + * Adds a listener that is invoked whenever the associated {@link ohos.app.ability.UIAbility}'s {@code + * windowStageEvent} method is invoked. + */ + addOnWindowFocusChangedListener(listener: WindowFocusChangedListener): void; + + /** + * Removes a listener that was added in {@link + * #addOnWindowFocusChangedListener(WindowFocusChangedListener)}. + */ + removeOnWindowFocusChangedListener(listener: WindowFocusChangedListener): void; + + /** + * Adds a listener that is invoked when the associated {@code UIAbility} saves + * and restores instance state. + */ + addOnSaveStateListener(listener: OnSaveStateListener): void; + + /** + * Removes a listener that was added in {@link + * #addOnSaveStateListener(OnSaveStateListener)}. + */ + removeOnSaveStateListener(listener: OnSaveStateListener): void; +} + +/** + * Delegate interface for handling new wants on behalf of the main {@link ohos.app.ability.UIAbility}. + */ +export interface NewWantListener { + /** + * @param intent The new want that was started for the UIAbility. + * @return true if the new want has been handled. + */ + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void; +} + +/** + * Delegate interface for handling window focus changes on behalf of the main {@link + * ohos.app.ability.UIAbility}. + */ +export interface WindowFocusChangedListener { + onWindowFocusChanged(hasFocus: boolean): void; +} + +export interface OnSaveStateListener { + /** + * Invoked when the associated {@code UIAbility} or {@code Fragment} executes {@link + * Activity#onSaveState(Bundle)}. + */ + onSaveState(reason: AbilityConstant.StateType, wantParam: Record): AbilityConstant.OnSaveResult; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterUiDisplayListener.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterUiDisplayListener.ets new file mode 100644 index 0000000..2a0af40 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/renderer/FlutterUiDisplayListener.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export interface FlutterUiDisplayListener { + onFlutterUiDisplayed(): void; + + onFlutterUiNoLongerDisplayed(): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets new file mode 100644 index 0000000..804994e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/AccessibilityChannel.ets @@ -0,0 +1,119 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; +import BasicMessageChannel, { MessageHandler, Reply} from '../../../plugin/common/BasicMessageChannel'; +import HashMap from '@ohos.util.HashMap'; +import FlutterNapi, {AccessibilityDelegate} from '../FlutterNapi'; +import { Action } from '../../../view/AccessibilityBridge' +import StandardMessageCodec from '../../../plugin/common/StandardMessageCodec'; +import StringUtils from '../../../util/StringUtils'; + +/** +* 辅助功能channel +*/ +export default class AccessibilityChannel implements MessageHandler{ + private static TAG = "AccessibilityChannel"; + private static CHANNEL_NAME = "flutter/accessibility"; + private channel: BasicMessageChannel; + private flutterNapi: FlutterNapi; + private handler: AccessibilityMessageHandler | null = null; + private nextReplyId: number = 1; + + onMessage(message: object, reply: Reply): void { + if (this.handler == null) { + Log.i(AccessibilityChannel.TAG, "NULL"); + reply.reply(StringUtils.stringToArrayBuffer("")); + return; + } + let annotatedEvent: HashMap = message as HashMap; + let type: string = annotatedEvent.get("type") as string; + let data: HashMap = annotatedEvent.get("data") as HashMap; + + Log.i(AccessibilityChannel.TAG, "Received " + type + " message."); + switch (type) { + case "announce": { + Log.i(AccessibilityChannel.TAG, "Announce"); + let announceMessage: string = data.get("message"); + if (announceMessage != null) { + this.handler.announce(announceMessage); + } + break; + } + case "tap": { + Log.i(AccessibilityChannel.TAG, "Tag"); + let nodeId: number = annotatedEvent.get("nodeId"); + if (nodeId != null) { + this.handler.onTap(nodeId); + } + break; + } + case "longPress": { + Log.i(AccessibilityChannel.TAG, "LongPress"); + let nodeId: number = annotatedEvent.get("nodeId"); + if (nodeId != null) { + this.handler.onLongPress(nodeId); + } + break; + } + case "tooltip": { + Log.i(AccessibilityChannel.TAG, "ToolTip"); + let tooltipMessage: string = data.get("message"); + if (tooltipMessage != null) { + this.handler.onTooltip(tooltipMessage); + } + break; + } + } + reply.reply(StringUtils.stringToArrayBuffer("")); + } + + constructor(dartExecutor: DartExecutor, flutterNapi: FlutterNapi) { + Log.i(AccessibilityChannel.TAG, "Channel entered"); + this.channel = new BasicMessageChannel(dartExecutor, AccessibilityChannel.CHANNEL_NAME, StandardMessageCodec.INSTANCE); + this.channel.setMessageHandler(this); + this.flutterNapi = flutterNapi; + } + + onOhosAccessibilityEnabled(): void { + let replyId: number = this.nextReplyId++; + this.flutterNapi.setSemanticsEnabled(true, replyId); + } + + onOhosAccessibilityFeatures(accessibilityFeatureFlags: number): void { + let replyId: number = this.nextReplyId++; + this.flutterNapi.setAccessibilityFeatures(accessibilityFeatureFlags, replyId); + } + + dispatchSemanticsAction(virtualViewId: number, action: Action): void { + let replyId: number = this.nextReplyId++; + this.flutterNapi.dispatchSemanticsAction(virtualViewId, action, replyId); + } + + setAccessibilityMessageHandler(handler: AccessibilityMessageHandler): void { + this.handler = handler; + let replyId: number = this.nextReplyId++; + this.flutterNapi.setAccessibilityDelegate(handler, replyId); + } + +} + +interface AccessibilityMessageHandler extends AccessibilityDelegate { + announce(message: string): void; + onTap(nodeId: number): void; + onLongPress(nodeId: number): void; + onTooltip(nodeId: string): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/KeyEventChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/KeyEventChannel.ets new file mode 100644 index 0000000..8ac0e08 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/KeyEventChannel.ets @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import BasicMessageChannel from '../../../plugin/common/BasicMessageChannel'; +import { BinaryMessenger } from '../../../plugin/common/BinaryMessenger'; +import { Reply } from '../../../plugin/common/BasicMessageChannel'; +import { Action, Key, KeyEvent } from '@ohos.multimodalInput.keyEvent'; +import Log from '../../../util/Log'; +import JSONMessageCodec from '../../../plugin/common/JSONMessageCodec'; + +export default class KeyEventChannel { + private static TAG = "KeyEventChannel"; + private static CHANNEL_NAME = "flutter/keyevent"; + private channel : BasicMessageChannel>; + + constructor(binaryMessenger: BinaryMessenger) { + this.channel = new BasicMessageChannel>(binaryMessenger, KeyEventChannel.CHANNEL_NAME, JSONMessageCodec.INSTANCE); + } + + sendFlutterKeyEvent(keyEvent: FlutterKeyEvent, + isKeyUp: boolean, + responseHandler: EventResponseHandler): void { + this.channel.send(this.encodeKeyEvent(keyEvent, isKeyUp), + (message:Map) => { + let isEventHandled = false; + try { + if (message != null) { + isEventHandled = message.get("handled") as boolean; + } + } catch (e) { + Log.e(KeyEventChannel.TAG, "Unable to unpack JSON message: " + e); + } + responseHandler.onFrameworkResponse(isEventHandled); + } + ); + } + + encodeKeyEvent(keyEvent: FlutterKeyEvent, isKeyUp: boolean): Map { + let message: Map = new Map(); + message.set("type", isKeyUp ? "keyup" : "keydown"); + message.set("keymap", "ohos"); + message.set("codePoint", keyEvent.event.unicodeChar); + message.set("keyCode", keyEvent.event.key.code); + message.set("deviceId", keyEvent.event.key.deviceId); + message.set("character", keyEvent.event.key.code.toString()); + message.set("repeatCount", 1); + return message; + } + + +} + +export interface EventResponseHandler { + onFrameworkResponse(isEventHandled: boolean): void; +} + +export class FlutterKeyEvent { + event: KeyEvent; + + constructor( ohosKeyEvent: KeyEvent) { + this.event = ohosKeyEvent; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LifecycleChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LifecycleChannel.ets new file mode 100644 index 0000000..ce5acbd --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LifecycleChannel.ets @@ -0,0 +1,105 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '../../../util/Log'; +import StringCodec from '../../../plugin/common/StringCodec'; +import DartExecutor from '../dart/DartExecutor'; +import BasicMessageChannel from '../../../plugin/common/BasicMessageChannel'; + +/** + * 生命周期channel + */ +export default class LifecycleChannel { + private static TAG = "LifecycleChannel"; + private static CHANNEL_NAME = "flutter/lifecycle"; + + // These should stay in sync with the AppLifecycleState enum in the framework. + private static RESUMED = "AppLifecycleState.resumed"; + private static INACTIVE = "AppLifecycleState.inactive"; + private static PAUSED = "AppLifecycleState.paused"; + private static DETACHED = "AppLifecycleState.detached"; + + private lastOhosState = ""; + private lastFlutterState = ""; + private lastFocus = true; + + private channel: BasicMessageChannel + + constructor(dartExecutor: DartExecutor) { + this.channel = new BasicMessageChannel(dartExecutor, LifecycleChannel.CHANNEL_NAME, StringCodec.INSTANCE) + } + + // Called if at least one window in the app has focus. + aWindowIsFocused(): void { + this.sendState(this.lastOhosState, true); + } + + // Called if no windows in the app have focus. + noWindowsAreFocused(): void { + this.sendState(this.lastOhosState, false); + } + + appIsResumed(): void { + this.sendState(LifecycleChannel.RESUMED, this.lastFocus); + } + + appIsInactive(): void { + this.sendState(LifecycleChannel.INACTIVE, this.lastFocus); + } + + appIsPaused(): void { + this.sendState(LifecycleChannel.PAUSED, this.lastFocus); + } + + appIsDetached(): void { + this.sendState(LifecycleChannel.DETACHED, this.lastFocus); + } + + // Here's the state table this implements: + // + // | UIAbility State | Window focused | Flutter state | + // |-----------------|----------------|---------------| + // | onCreate | true | resumed | + // | onCreate | false | inactive | + // | onForeground | true | resumed | + // | onForeground | false | inactive | + // | onBackground | true | paused | + // | onBackground | false | paused | + // | onDestroy | true | detached | + // | onDestroy | false | detached | + + private sendState(state: string, hasFocus: boolean): void { + if (this.lastOhosState == state && hasFocus == this.lastFocus) { + // No inputs changed, so Flutter state could not have changed. + return; + } + let newState: string; + if (state == LifecycleChannel.RESUMED) { + newState = hasFocus ? LifecycleChannel.RESUMED : LifecycleChannel.INACTIVE; + } else { + newState = state; + } + // Keep the last reported values for future updates. + this.lastOhosState = state; + this.lastFocus = hasFocus; + if (newState == this.lastFlutterState) { + // No change in the resulting Flutter state, so don't report anything. + return; + } + Log.i(LifecycleChannel.TAG, "Sending " + newState + " message."); + this.channel.send(newState); + this.lastFlutterState = newState; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LocalizationChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LocalizationChannel.ets new file mode 100644 index 0000000..d34d818 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/LocalizationChannel.ets @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import DartExecutor from '../dart/DartExecutor'; +import MethodChannel, { MethodCallHandler, MethodResult} from '../../../plugin/common/MethodChannel'; +import MethodCall from '../../../plugin/common/MethodCall'; +import List from '@ohos.util.List'; +import JSONMethodCodec from '../../../plugin/common/JSONMethodCodec'; +import intl from '@ohos.intl'; +import Log from '../../../util/Log'; + +const TAG = "LocalizationChannel"; +export default class LocalizationChannel implements MethodCallHandler{ + private static TAG = "LocalizationChannel"; + private static CHANNEL_NAME = "flutter/localization"; + private channel: MethodChannel; + private localizationMessageHandler: LocalizationMessageHandler | null = null; + + onMethodCall(call: MethodCall, result: MethodResult) :void { + if (this.localizationMessageHandler == null) { + Log.e(TAG, "localizationMessageHandler is null"); + return; + } + let method: string = call.method; + switch (method) { + case "Localization.getStringResource": { + Log.i(TAG, "Localization.getStringResource enter"); + let key: string = call.argument("key"); + let localeString: string = ""; + if (call.hasArgument("locale")) { + localeString = call.argument("locale"); + } + result.success(this.localizationMessageHandler?.getStringResource(key, localeString)); + break; + } + default: { + result.notImplemented(); + break; + } + } + } + + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, LocalizationChannel.CHANNEL_NAME, JSONMethodCodec.INSTANCE); + this.channel.setMethodCallHandler(this); + } + + setLocalizationMessageHandler(localizationMessageHandler: LocalizationMessageHandler): void { + this.localizationMessageHandler = localizationMessageHandler; + } + + sendLocales(locales: Array): void { + this.channel.invokeMethod("setLocale", locales); + } +} + +export interface LocalizationMessageHandler { + getStringResource(key: string, local: string); +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/MouseCursorChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/MouseCursorChannel.ets new file mode 100644 index 0000000..3e8b3d4 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/MouseCursorChannel.ets @@ -0,0 +1,85 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import HashMap from '@ohos.util.HashMap'; +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import StandardMethodCodec from '../../../plugin/common/StandardMethodCodec'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +const TAG:string = 'MouseCursorChannel' + +export default class MouseCursorChannel implements MethodCallHandler { + public channel: MethodChannel; + + private mouseCursorMethodHandler: MouseCursorMethodHandler | null = null; + + onMethodCall(call: MethodCall, result: MethodResult): void { + if (this.mouseCursorMethodHandler === null) { + // if no explicit mouseCursorMethodHandler has been registered then we don't + // need to formed this call to an API. Return + Log.e(TAG, "mouseCursorMethodHandler is null") + return; + } + + let method: string = call.method; + Log.i(TAG, "Received '" + method + "' message."); + try { + // More methods are expected to be added here, hence the switch. + switch (method) { + case "activateSystemCursor": + let argument: HashMap = call.args; + let kind: string = argument.get("kind"); + try { + this.mouseCursorMethodHandler.activateSystemCursor(kind); + } catch (err) { + result.error("error", "Error when setting cursors: " + JSON.stringify(err), null); + break; + } + result.success(true); + break; + default: + break; + } + } catch (error) { + result.error("error", "UnHandled error: " + JSON.stringify(error), null) + } + } + + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, "flutter/mousecursor", StandardMethodCodec.INSTANCE); + this.channel.setMethodCallHandler(this); + } + + /** + * Sets the {@link MouseCursorMethodHandler} which receives all events and requests that are + * parsed from the underlying platform channel. + * @param mouseCursorMethodHandler + */ + public setMethodHandler(mouseCursorMethodHandler: MouseCursorMethodHandler | null): void { + this.mouseCursorMethodHandler = mouseCursorMethodHandler; + } + + public synthesizeMethodCall(call: MethodCall, result: MethodResult): void { + this.onMethodCall(call, result); + } +} + +export interface MouseCursorMethodHandler { + // Called when the pointer should start displaying a system mouse cursor + // specified by {@code shapeCode}. + activateSystemCursor(kind: String): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/NavigationChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/NavigationChannel.ets new file mode 100644 index 0000000..f7ebcb6 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/NavigationChannel.ets @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import JSONMethodCodec from '../../../plugin/common/JSONMethodCodec'; +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +export default class NavigationChannel { + private static TAG = "NavigationChannel"; + private channel: MethodChannel + + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, "flutter/navigation", JSONMethodCodec.INSTANCE); + // Provide a default handler that returns an empty response to any messages + // on this channel. + this.channel.setMethodCallHandler(new NavigationCallback()); + } + + setInitialRoute(initialRoute: string): void { + Log.i(NavigationChannel.TAG, "Sending message to set initial route to '" + initialRoute + "'"); + this.channel.invokeMethod("setInitialRoute", initialRoute); + } + + pushRoute(route: string): void { + Log.i(NavigationChannel.TAG, "Sending message to push route '" + route + "'"); + this.channel.invokeMethod("pushRoute", route); + } + + pushRouteInformation(route: string): void { + Log.i(NavigationChannel.TAG, "Sending message to push route information '" + route + "'"); + this.channel.invokeMethod("pushRouteInformation", new Map().set("location", route) ); + } + + popRoute(): void { + Log.i(NavigationChannel.TAG, "Sending message to pop route."); + this.channel.invokeMethod("popRoute", null); + } + + setMethodCallHandler(handler: MethodCallHandler) { + this.channel.setMethodCallHandler(handler); + } +} + +class NavigationCallback implements MethodCallHandler { + onMethodCall(call: MethodCall, result: MethodResult) { + result.success(null); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets new file mode 100644 index 0000000..615dac7 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformChannel.ets @@ -0,0 +1,505 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import JSONMethodCodec from '../../../plugin/common/JSONMethodCodec'; +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; +import pasteboard from '@ohos.pasteboard'; +import bundleManager from '@ohos.bundle.bundleManager'; +import window from '@ohos.window'; + +export default class PlatformChannel { + private static TAG = "PlatformChannel"; + private static CHANNEL_NAME = "flutter/platform"; + channel: MethodChannel; + platformMessageHandler: PlatformMessageHandler | null = null; + + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, PlatformChannel.CHANNEL_NAME, JSONMethodCodec.INSTANCE); + let callback = new PlatformMethodCallback(this); + this.channel.setMethodCallHandler(callback); + } + + setPlatformMessageHandler(platformMessageHandler: PlatformMessageHandler): void { + this.platformMessageHandler = platformMessageHandler; + } + + systemChromeChanged(overlaysAreVisible: boolean): void { + Log.d(PlatformChannel.TAG, "Sending 'systemUIChange' message."); + this.channel.invokeMethod("SystemChrome.systemUIChange", [overlaysAreVisible]); + } + + decodeOrientations(encodedOrientations: string[]): number { + let requestedOrientation = 0x00; + let firstRequestedOrientation = 0x00; + for(let index = 0; index< encodedOrientations.length; index += 1) { + let encodedOrientation = encodedOrientations[index]; + Log.d(PlatformChannel.TAG,"encodedOrientation[" + index + "]: "+encodedOrientation); + let orientation = this.getDeviceOrientationFromValue(encodedOrientation); + switch (orientation) { + case DeviceOrientation.PORTRAIT_UP: + requestedOrientation |= 0x01; + break; + case DeviceOrientation.PORTRAIT_DOWN: + requestedOrientation |= 0x04; + break; + case DeviceOrientation.LANDSCAPE_LEFT: + requestedOrientation |= 0x02; + break; + case DeviceOrientation.LANDSCAPE_RIGHT: + requestedOrientation |= 0x08; + break; + } + if (firstRequestedOrientation == 0x00) { + firstRequestedOrientation = requestedOrientation; + } + } + + switch (requestedOrientation) { + case 0x00: + return window.Orientation.UNSPECIFIED; + case 0x01: + return window.Orientation.PORTRAIT; + case 0x02: + return window.Orientation.LANDSCAPE; + case 0x03: + case 0x04: + return window.Orientation.PORTRAIT_INVERTED; + case 0x05: + return window.Orientation.AUTO_ROTATION_PORTRAIT; + case 0x06: + case 0x07: + case 0x08: + return window.Orientation.LANDSCAPE_INVERTED; + case 0x09: + case 0x0a: + return window.Orientation.AUTO_ROTATION_LANDSCAPE; + case 0x0b: + return window.Orientation.LOCKED; + case 0x0c: + case 0x0d: + case 0x0e: + switch (firstRequestedOrientation) { + case 0x01: + return bundleManager.DisplayOrientation.PORTRAIT; + case 0x02: + return bundleManager.DisplayOrientation.LANDSCAPE; + case 0x04: + return bundleManager.DisplayOrientation.PORTRAIT_INVERTED; + case 0x08: + return bundleManager.DisplayOrientation.LANDSCAPE_INVERTED; + } + case 0x0f: + } + return bundleManager.DisplayOrientation.PORTRAIT; + } + + getFeedbackTypeFromValue(encodedName: string): HapticFeedbackType { + if (encodedName == null) { + return HapticFeedbackType.STANDARD; + } + let feedbackTypes: string[] = [ + HapticFeedbackType.STANDARD, + HapticFeedbackType.LIGHT_IMPACT, + HapticFeedbackType.MEDIUM_IMPACT, + HapticFeedbackType.HEAVY_IMPACT, + HapticFeedbackType.SELECTION_CLICK + ]; + if (feedbackTypes.includes(encodedName as HapticFeedbackType)) { + return encodedName as HapticFeedbackType; + } else { + Log.e(PlatformChannel.TAG, "No such HapticFeedbackType:" + encodedName); + return HapticFeedbackType.STANDARD; + } + } + + getClipboardContentFormatFromValue(encodedName: string): ClipboardContentFormat { + let clipboardFormats : string[]= [ClipboardContentFormat.PLAIN_TEXT]; + for (let i = 0; i < clipboardFormats.length; i++) { + let format = clipboardFormats[i]; + if (ClipboardContentFormat[format] === encodedName) { + return ClipboardContentFormat[format]; + } + } + return ClipboardContentFormat.PLAIN_TEXT; + } + getSystemUiOverlayFromValue(encodedName: string): SystemUiOverlay { + let systemUiOverlays : string[] = [SystemUiOverlay.TOP_OVERLAYS, SystemUiOverlay.BOTTOM_OVERLAYS]; + for (let i = 0; i < systemUiOverlays.length; i++) { + let overlay = systemUiOverlays[i]; + if (SystemUiOverlay[overlay] === encodedName) { + return SystemUiOverlay[overlay]; + } + } + throw new Error("No such SystemUiOverlay: " + encodedName); + } + + getSystemUiModeFromValue(encodedName: string): SystemUiMode { + let systemUiModes : string[] = [ + SystemUiMode.LEAN_BACK, SystemUiMode.IMMERSIVE, + SystemUiMode.IMMERSIVE_STICKY, SystemUiMode.EDGE_TO_EDGE + ]; + for (let i = 0; i < systemUiModes.length; i++) { + let mode = systemUiModes[i]; + if (SystemUiMode[mode] === encodedName) { + return SystemUiMode[mode]; + } + } + throw new Error("No such SystemUiOverlay: " + encodedName); + } + + getBrightnessFromValue(encodedName: string): Brightness { + let brightnesses : string[] = [Brightness.LIGHT, Brightness.DARK]; + for (let i = 0; i < brightnesses.length; i++) { + let brightness = brightnesses[i]; + if (Brightness[brightness] === encodedName) { + return Brightness[brightness]; + } + } + throw new Error("No such Brightness: " + encodedName); + } + + getDeviceOrientationFromValue(encodedName: string): DeviceOrientation { + let deviceOrientations: string[] = [ + DeviceOrientation.PORTRAIT_UP, DeviceOrientation.PORTRAIT_DOWN, + DeviceOrientation.LANDSCAPE_LEFT, DeviceOrientation.LANDSCAPE_RIGHT + ]; + for (let i = 0; i < deviceOrientations.length; i++) { + let orientation = deviceOrientations[i]; + if (DeviceOrientation[orientation] === encodedName) { + return DeviceOrientation[orientation]; + } + } + throw new Error("No such DeviceOrientation: " + encodedName); + } + +} + +export enum HapticFeedbackType { + STANDARD = "STANDARD", + LIGHT_IMPACT = "HapticFeedbackType.lightImpact", + MEDIUM_IMPACT = "HapticFeedbackType.mediumImpact", + HEAVY_IMPACT = "HapticFeedbackType.heavyImpact", + SELECTION_CLICK = "HapticFeedbackType.selectionClick" +} + +export interface PlatformMessageHandler { + playSystemSound(soundType: SoundType): void; + + vibrateHapticFeedback(feedbackType: HapticFeedbackType): void; + + setPreferredOrientations(ohosOrientation: number): void; + + setApplicationSwitcherDescription(description: AppSwitcherDescription): void; + + showSystemOverlays(overlays: SystemUiOverlay[]): void; + + showSystemUiMode(mode: SystemUiMode): void; + + setSystemUiChangeListener(): void; + + restoreSystemUiOverlays(): void; + + setSystemUiOverlayStyle(systemUiOverlayStyle: SystemChromeStyle): void; + + popSystemNavigator(): void; + + getClipboardData(format: ClipboardContentFormat): string; + + setClipboardData(text: string): void; + + clipboardHasStrings(): boolean; +} + +export enum ClipboardContentFormat { + PLAIN_TEXT = "text/plain", +} + +export enum SoundType { + CLICK = "SystemSoundType.click", + ALERT = "SystemSoundType.alert", +} + +export class AppSwitcherDescription { + public readonly color: number; + public readonly label: string; + + constructor(color: number, label: string) { + this.color = color; + this.label = label; + } +} + +export enum SystemUiOverlay { + TOP_OVERLAYS = "SystemUiOverlay.top", + BOTTOM_OVERLAYS = "SystemUiOverlay.bottom", +} + +export enum SystemUiMode { + LEAN_BACK = "SystemUiMode.leanBack", + IMMERSIVE = "SystemUiMode.immersive", + IMMERSIVE_STICKY = "SystemUiMode.immersiveSticky", + EDGE_TO_EDGE = "SystemUiMode.edgeToEdge", +} + +export enum Brightness { + LIGHT = "Brightness.light", + DARK = "Brightness.dark", +} + +export class SystemChromeStyle { + public readonly statusBarColor: number | null; + public readonly statusBarIconBrightness: Brightness | null; + public readonly systemStatusBarContrastEnforced: boolean | null; + public readonly systemNavigationBarColor: number | null; + public readonly systemNavigationBarIconBrightness: Brightness | null; + public readonly systemNavigationBarDividerColor: number | null; + public readonly systemNavigationBarContrastEnforced: boolean | null; + + constructor(statusBarColor: number | null, + statusBarIconBrightness: Brightness | null, + systemStatusBarContrastEnforced: boolean | null, + systemNavigationBarColor: number | null, + systemNavigationBarIconBrightness: Brightness | null, + systemNavigationBarDividerColor: number | null, + systemNavigationBarContrastEnforced: boolean | null) { + this.statusBarColor = statusBarColor; + this.statusBarIconBrightness = statusBarIconBrightness; + this.systemStatusBarContrastEnforced = systemStatusBarContrastEnforced; + this.systemNavigationBarColor = systemNavigationBarColor; + this.systemNavigationBarIconBrightness = systemNavigationBarIconBrightness; + this.systemNavigationBarDividerColor = systemNavigationBarDividerColor; + this.systemNavigationBarContrastEnforced = systemNavigationBarContrastEnforced; + } +} + +enum DeviceOrientation { + PORTRAIT_UP = "DeviceOrientation.portraitUp", + PORTRAIT_DOWN = "DeviceOrientation.portraitDown", + LANDSCAPE_LEFT = "DeviceOrientation.landscapeLeft", + LANDSCAPE_RIGHT = "DeviceOrientation.landscapeRight", +} + +class PlatformMethodCallback implements MethodCallHandler { + private static TAG = "PlatformMethodCallback" + platform: PlatformChannel; + + constructor(platform: PlatformChannel) { + this.platform = platform; + } + + onMethodCall(call: MethodCall, result: MethodResult) { + if (this.platform.platformMessageHandler == null) { + Log.w(PlatformMethodCallback.TAG, "platformMessageHandler is null"); + return; + } + + let method: string = call.method; + let args: ESObject = call.args; + Log.d(PlatformMethodCallback.TAG, "Received '" + method + "' message."); + try { + switch (method) { + case "SystemSound.play": + break; + case "HapticFeedback.vibrate": + try { + Log.d(PlatformMethodCallback.TAG, "HapticFeedback: " + args as string); + let feedbackType = this.platform.getFeedbackTypeFromValue(args as string); + this.platform.platformMessageHandler.vibrateHapticFeedback(feedbackType); + result.success(null); + } catch (e) { + Log.e(PlatformMethodCallback.TAG, "HapticFeedback.vibrate error:" + JSON.stringify(e)); + } + break; + case "SystemChrome.setPreferredOrientations": + Log.d(PlatformMethodCallback.TAG, "setPreferredOrientations: " + JSON.stringify(args)); + try { + let ohosOrientation = this.platform.decodeOrientations(args as string[]); + this.platform.platformMessageHandler.setPreferredOrientations(ohosOrientation); + result.success(null); + } catch (err) { + Log.e(PlatformMethodCallback.TAG, "setPreferredOrientations err:" + JSON.stringify(err)); + result.error("error", JSON.stringify(err), null); + } + + break; + case "SystemChrome.setApplicationSwitcherDescription": + Log.d(PlatformMethodCallback.TAG, "setApplicationSwitcherDescription: " + JSON.stringify(args)); + break; + case "SystemChrome.setEnabledSystemUIOverlays": + try { + let overlays: SystemUiOverlay[] = this.decodeSystemUiOverlays(args); + Log.d(PlatformMethodCallback.TAG, "overlays: " + overlays); + this.platform.platformMessageHandler.showSystemOverlays(overlays); + result.success(null); + } catch (err) { + Log.e(PlatformMethodCallback.TAG, "setEnabledSystemUIOverlays err:" + JSON.stringify(err)); + result.error("error", JSON.stringify(err), null); + } + break; + case "SystemChrome.setEnabledSystemUIMode": + try { + Log.d(PlatformMethodCallback.TAG, "setEnabledSystemUIMode args:" + args as string); + let mode: SystemUiMode = this.decodeSystemUiMode(args as string) + this.platform.platformMessageHandler.showSystemUiMode(mode); + } catch (err) { + Log.e(PlatformMethodCallback.TAG, "setEnabledSystemUIMode err:" + JSON.stringify(err)); + result.error("error", JSON.stringify(err), null); + } + break; + case "SystemChrome.setSystemUIChangeListener": + this.platform.platformMessageHandler.setSystemUiChangeListener(); + result.success(null); + break; + case "SystemChrome.restoreSystemUIOverlays": + this.platform.platformMessageHandler.restoreSystemUiOverlays(); + result.success(null); + break; + case "SystemChrome.setSystemUIOverlayStyle": + try { + Log.d(PlatformMethodCallback.TAG, "setSystemUIOverlayStyle asrgs: " + JSON.stringify(args)); + let systemChromeStyle: SystemChromeStyle = this.decodeSystemChromeStyle(args); + this.platform.platformMessageHandler.setSystemUiOverlayStyle(systemChromeStyle); + result.success(null); + } catch (err) { + Log.e(PlatformMethodCallback.TAG, "setSystemUIOverlayStyle err:" + JSON.stringify(err)); + result.error("error", JSON.stringify(err), null); + } + break; + case "SystemNavigator.pop": + this.platform.platformMessageHandler.popSystemNavigator(); + result.success(null); + break; + case "Clipboard.getData": + let pasteBoard = pasteboard.getSystemPasteboard(); + pasteBoard.getData().then((pasteData) => { + let text = pasteData.getPrimaryText(); + let response: ESObject = new Map().set("text", ""); + response.text = text; + result.success(response); + }).catch((err: ESObject) => { + Log.e(PlatformMethodCallback.TAG, "Failed to get PasteData. Cause: " + JSON.stringify(err)); + }); + break; + case "Clipboard.setData": + let clipboardContent: string = args.text; + this.platform.platformMessageHandler.setClipboardData(clipboardContent); + result.success(null); + break; + case "Clipboard.hasStrings": + let hasStrings: boolean = false; + let response: ESObject = new Map().set("value", false); + let systemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.hasData().then((hasData) => { + if (!hasData) { + response.value = hasData; + result.success(response); + } + }).catch((err: ESObject) => { + Log.e(PlatformMethodCallback.TAG, "systemPasteboard.hasData err: " + JSON.stringify(err)); + }) + systemPasteboard.getData().then((pasteData) => { + hasStrings = pasteData.hasType(pasteboard.MIMETYPE_TEXT_PLAIN); + response.value = hasStrings; + result.success(response); + }).catch((err: ESObject) => { + Log.e(PlatformMethodCallback.TAG, "getData err: " + JSON.stringify(err)); + }) + break; + default: + result.notImplemented(); + break; + } + } catch (e) { + result.error("error", JSON.stringify(e), null); + } + } + + private decodeSystemUiOverlays(encodedSystemUiOverlay: string[]): SystemUiOverlay[] { + let overlays: SystemUiOverlay[] = []; + for(let i = 0; i < encodedSystemUiOverlay.length; i++) { + const encodedOverlay = encodedSystemUiOverlay[i]; + const overlay = this.platform.getSystemUiOverlayFromValue(encodedOverlay); + switch (overlay) { + case SystemUiOverlay.TOP_OVERLAYS: + overlays.push(SystemUiOverlay.TOP_OVERLAYS); + break; + case SystemUiOverlay.BOTTOM_OVERLAYS: + overlays.push(SystemUiOverlay.BOTTOM_OVERLAYS); + break; + } + } + return overlays; + } + + private decodeSystemUiMode(encodedSystemUiMode: string): SystemUiMode { + let mode: SystemUiMode = this.platform.getSystemUiModeFromValue(encodedSystemUiMode); + switch (mode) { + case SystemUiMode.LEAN_BACK: + return SystemUiMode.LEAN_BACK; + case SystemUiMode.IMMERSIVE: + return SystemUiMode.IMMERSIVE; + case SystemUiMode.IMMERSIVE_STICKY: + return SystemUiMode.IMMERSIVE_STICKY; + case SystemUiMode.EDGE_TO_EDGE: + default: + return SystemUiMode.EDGE_TO_EDGE; + } + } + + private decodeSystemChromeStyle(encodedStyle: ESObject): SystemChromeStyle { + let statusBarColor: number | null = null; + let statusBarIconBrightness: Brightness | null = null; + let systemStatusBarContrastEnforced: boolean | null = null; + let systemNavigationBarColor: number | null = null; + let systemNavigationBarIconBrightness: Brightness | null = null; + let systemNavigationBarDividerColor: number | null = null; + let systemNavigationBarContrastEnforced: boolean | null = null; + if(encodedStyle.statusBarColor != null) { + statusBarColor = encodedStyle.statusBarColor as number; + } + if(encodedStyle.statusBarIconBrightness != null) { + statusBarIconBrightness = + this.platform.getBrightnessFromValue(encodedStyle.statusBarIconBrightness as string); + } + if(encodedStyle.systemStatusBarContrastEnforced != null) { + systemStatusBarContrastEnforced = encodedStyle.systemStatusBarContrastEnforced as boolean; + } + if(encodedStyle.systemNavigationBarColor != null) { + systemNavigationBarColor = encodedStyle.systemNavigationBarColor as number; + } + if(encodedStyle.systemNavigationBarIconBrightness != null) { + systemNavigationBarIconBrightness = + this.platform.getBrightnessFromValue(encodedStyle.systemNavigationBarIconBrightness as string); + } + if(encodedStyle.systemNavigationBarDividerColor != null) { + systemNavigationBarDividerColor = encodedStyle.systemNavigationBarDividerColor as number; + } + if(encodedStyle.systemNavigationBarContrastEnforced != null) { + systemNavigationBarContrastEnforced = encodedStyle.systemNavigationBarContrastEnforced as boolean; + } + return new SystemChromeStyle( + statusBarColor, + statusBarIconBrightness, + systemStatusBarContrastEnforced, + systemNavigationBarColor, + systemNavigationBarIconBrightness, + systemNavigationBarDividerColor, + systemNavigationBarContrastEnforced + ); + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets new file mode 100644 index 0000000..5da4a68 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/PlatformViewsChannel.ets @@ -0,0 +1,551 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import StandardMethodCodec from '../../../plugin/common/StandardMethodCodec'; +import { ByteBuffer } from '../../../util/ByteBuffer'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +const TAG = "PlatformViewsChannel"; +const NON_TEXTURE_FALLBACK = -2; +export default class PlatformViewsChannel { + private channel: MethodChannel; + private handler: PlatformViewsHandler | null = null; + private parsingHandler = new ParsingCallback(); + + /** + * Constructs a {@code PlatformViewsChannel} that connects Android to the Dart code running in + * {@code dartExecutor}. + * + *

The given {@code dartExecutor} is permitted to be idle or executing code. + * + *

See {@link DartExecutor}. + */ + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, "flutter/platform_views", StandardMethodCodec.INSTANCE); + this.parsingHandler.platformChannel = this; + this.channel.setMethodCallHandler(this.parsingHandler); + } + + /** + * Sets the {@link PlatformViewsHandler} which receives all events and requests that are parsed + * from the underlying platform views channel. + */ + public setPlatformViewsHandler(handler: PlatformViewsHandler | null): void { + this.handler = handler; + this.parsingHandler.handler = handler; + } + + public invokeViewFocused(viewId: number): void { + if (this.channel == null) { + return; + } + this.channel.invokeMethod("viewFocused", viewId); + } + + create(call: MethodCall, result: MethodResult): void { + const createArgs: Map = call.args; + const usesPlatformViewLayer: boolean = createArgs.has("hybrid") && createArgs.get("hybrid") as boolean; + const additionalParams: ByteBuffer = createArgs.has("params") ? createArgs.get("params") : null; + + let direction: Direction = Direction.Ltr; + if (createArgs.get("direction") == 0) { + direction = Direction.Ltr; + } else if (createArgs.get("direction") == 1) { + direction = Direction.Rtl; + } + + try { + if (usesPlatformViewLayer) { + const request: PlatformViewCreationRequest = new PlatformViewCreationRequest( + createArgs.get("id"), + createArgs.get("viewType"), + 0, + 0, + 0, + 0, + direction, + additionalParams, + RequestedDisplayMode.HYBRID_ONLY + ); + this.handler?.createForPlatformViewLayer(request); + result.success(null); + } else { + const hybridFallback: boolean = createArgs.has("hybridFallback") && createArgs.get("hybridFallback"); + const displayMode: RequestedDisplayMode = + hybridFallback ? RequestedDisplayMode.TEXTURE_WITH_HYBRID_FALLBACK + : RequestedDisplayMode.TEXTURE_WITH_VIRTUAL_FALLBACK; + const request: PlatformViewCreationRequest = new PlatformViewCreationRequest( + createArgs.get("id"), + createArgs.get("viewType"), + createArgs.has("top") ? createArgs.get("top") : 0.0, + createArgs.has("left") ? createArgs.get("left") : 0.0, + createArgs.get("width"), + createArgs.get("height"), + direction, + additionalParams, + displayMode + ); + + Log.i(TAG, `Create texture param id:${request.viewId}, + type:${request.viewType}, + w:${request.logicalWidth}, + h:${request.logicalHeight}, + l:${request.logicalLeft}, + t:${request.logicalTop}, + d:${request.direction}`); + + const textureId = this.handler?.createForTextureLayer(request); + if (textureId == NON_TEXTURE_FALLBACK) { + if (!hybridFallback) { + throw new Error( + "Platform view attempted to fall back to hybrid mode when not requested."); + } + + // A fallback to hybrid mode is indicated with a null texture ID. + result.success(null); + } else { + result.success(textureId); + } + } + } catch (err) { + Log.e(TAG, "create failed" + err); + result.error("error", err, null); + } + } + + dispose(call: MethodCall, result: MethodResult): void { + const disposeArgs: Map = call.args; + const viewId: number = disposeArgs.get("id"); + try { + this.handler?.dispose(viewId); + result.success(null); + } catch (err) { + Log.e(TAG, "dispose failed", err); + result.error("error", err, null); + } + } + + resize(call: MethodCall, result: MethodResult): void { + const resizeArgs: Map = call.args; + const resizeRequest: PlatformViewResizeRequest = new PlatformViewResizeRequest( + resizeArgs.get("id"), + resizeArgs.get("width"), + resizeArgs.get("height") + ); + try { + let resizeCallback = new ResizeCallback(); + resizeCallback.result = result; + this.handler?.resize(resizeRequest, resizeCallback); + } catch (err) { + Log.e(TAG, "resize failed", err); + result.error("error", err, null); + } + } + + offset(call: MethodCall, result: MethodResult): void { + const offsetArgs: Map = call.args; + try { + this.handler?.offset( + offsetArgs.get("id"), + offsetArgs.get("top"), + offsetArgs.get("left")); + result.success(null); + } catch (err) { + Log.e(TAG, "offset failed", err); + result.error("error", err, null); + } + } + + touch(call: MethodCall, result: MethodResult): void { + const args: Array = call.args; + let index = 0; + const touch: PlatformViewTouch = new PlatformViewTouch( + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index++], + args[index] + ); + + try { + this.handler?.onTouch(touch); + result.success(null); + } catch (err) { + Log.e(TAG, "offset failed", err); + result.error("error", err, null); + } + } + + setDirection(call: MethodCall, result: MethodResult): void { + const setDirectionArgs: Map = call.args; + const newDirectionViewId: number = setDirectionArgs.get("id"); + const direction: number = setDirectionArgs.get("direction"); + + try { + this.handler?.setDirection(newDirectionViewId, direction); + result.success(null); + } catch (err) { + Log.e(TAG, "setDirection failed", err); + result.error("error", err, null); + } + } + + clearFocus(call: MethodCall, result: MethodResult): void { + const viewId: number = call.args; + try { + this.handler?.clearFocus(viewId); + result.success(null); + } catch (err) { + Log.e(TAG, "clearFocus failed", err); + result.error("error", err, null); + } + } + + synchronizeToNativeViewHierarchy(call: MethodCall, result: MethodResult): void { + const yes: boolean = call.args; + try { + this.handler?.synchronizeToNativeViewHierarchy(yes); + result.success(null); + } catch (err) { + Log.e(TAG, "synchronizeToNativeViewHierarchy failed", err); + result.error("error", err, null); + } + } +} + +/** + * Handler that receives platform view messages sent from Flutter to Ohos through a given + * {@link PlatformViewsChannel}. + * + *

To register a {@code PlatformViewsHandler} with a {@link PlatformViewsChannel}, see {@link + * PlatformViewsChannel#setPlatformViewsHandler(PlatformViewsHandler)}. + */ +export interface PlatformViewsHandler { + /* + * The ID returned by {@code createForTextureLayer} to indicate that the requested texture mode + * was not available and the view creation fell back to {@code PlatformViewLayer} mode. + * + * This can only be returned if the {@link PlatformViewCreationRequest} sets + * {@code TEXTURE_WITH_HYBRID_FALLBACK} as the requested display mode. + */ + + /** + * The Flutter application would like to display a new Ohos {@code View}, i.e., platform + * view. + * + *

The Ohos View is added to the view hierarchy. This view is rendered in the Flutter + * framework by a PlatformViewLayer. + * + * @param request The metadata sent from the framework. + */ + createForPlatformViewLayer(request: PlatformViewCreationRequest): void; + + /** + * The Flutter application would like to display a new Android {@code View}, i.e., platform + * view. + * + *

The Android View is added to the view hierarchy. This view is rendered in the Flutter + * framework by a TextureLayer. + * + * @param request The metadata sent from the framework. + * @return The texture ID. + */ + createForTextureLayer(request: PlatformViewCreationRequest): number; + + /** The Flutter application would like to dispose of an existing Android {@code View}. */ + dispose(viewId: number): void; + + /** + * The Flutter application would like to resize an existing Android {@code View}. + * + * @param request The request to resize the platform view. + * @param onComplete Once the resize is completed, this is the handler to notify the size of the + * platform view buffer. + */ + resize(request: PlatformViewResizeRequest, onComplete: PlatformViewBufferResized): void; + + /** + * The Flutter application would like to change the offset of an existing Android {@code View}. + */ + offset(viewId: number, top: number, left: number): void; + + /** + * The user touched a platform view within Flutter. + * + *

Touch data is reported in {@code touch}. + */ + onTouch(touch: PlatformViewTouch): void; + + /** + * The Flutter application would like to change the layout direction of an existing Android + * {@code View}, i.e., platform view. + */ + setDirection(viewId: number, direction: number): void; + + /** Clears the focus from the platform view with a give id if it is currently focused. */ + clearFocus(viewId: number): void; + + /** + * Whether the render surface of {@code FlutterView} should be converted to a {@code + * FlutterImageView} when a {@code PlatformView} is added. + * + *

This is done to syncronize the rendering of the PlatformView and the FlutterView. Defaults + * to true. + */ + synchronizeToNativeViewHierarchy(yes: boolean): void; +} + +/** Platform view display modes that can be requested at creation time. */ +enum RequestedDisplayMode { + /** Use Texture Layer if possible, falling back to Virtual Display if not. */ + TEXTURE_WITH_VIRTUAL_FALLBACK, + /** Use Texture Layer if possible, falling back to Hybrid Composition if not. */ + TEXTURE_WITH_HYBRID_FALLBACK, + /** Use Hybrid Composition in all cases. */ + HYBRID_ONLY, +} + +/** Request sent from Flutter to create a new platform view. */ +export class PlatformViewCreationRequest { + /** The ID of the platform view as seen by the Flutter side. */ + public viewId: number; + + /** The type of view to create for this platform view. */ + public viewType: string; + + /** The density independent width to display the platform view. */ + public logicalWidth: number; + + /** The density independent height to display the platform view. */ + public logicalHeight: number; + + /** The density independent top position to display the platform view. */ + public logicalTop: number; + + /** The density independent left position to display the platform view. */ + public logicalLeft: number; + + /** + * The layout direction of the new platform view. + */ + public direction: number; + public displayMode: RequestedDisplayMode; + + /** Custom parameters that are unique to the desired platform view. */ + public params: ByteBuffer; + + constructor(viewId: number, viewType: string, logicalTop: number, logicalLeft: number, logicalWidth: number, + logicalHeight: number, direction: Direction, params: ByteBuffer, displayMode?: RequestedDisplayMode) { + this.viewId = viewId; + this.viewType = viewType; + this.logicalTop = logicalTop; + this.logicalLeft = logicalLeft; + this.logicalWidth = logicalWidth; + this.logicalHeight = logicalHeight; + this.direction = direction; + this.displayMode = displayMode ? displayMode : RequestedDisplayMode.TEXTURE_WITH_VIRTUAL_FALLBACK; + this.params = params; + } +} + +/** Request sent from Flutter to resize a platform view. */ +export class PlatformViewResizeRequest { + /** The ID of the platform view as seen by the Flutter side. */ + public viewId: number; + + /** The new density independent width to display the platform view. */ + public newLogicalWidth: number; + + /** The new density independent height to display the platform view. */ + public newLogicalHeight: number; + + constructor(viewId: number, newLogicalWidth: number, newLogicalHeight: number) { + this.viewId = viewId; + this.newLogicalWidth = newLogicalWidth; + this.newLogicalHeight = newLogicalHeight; + } +} + +/** The platform view buffer size. */ +export class PlatformViewBufferSize { + /** The width of the screen buffer. */ + public width: number; + + /** The height of the screen buffer. */ + public height: number; + + constructor(width: number, height: number) { + this.width = width; + this.height = height; + } +} + +/** Allows to notify when a platform view buffer has been resized. */ +export abstract class PlatformViewBufferResized { + abstract run(bufferSize: PlatformViewBufferSize): void; +} + +/** The state of a touch event in Flutter within a platform view. */ +export class PlatformViewTouch { + /** The ID of the platform view as seen by the Flutter side. */ + public viewId: number; + + /** The amount of time that the touch has been pressed. */ + public downTime: number; + + public eventTime: number; + + public action: number; + + /** The number of pointers (e.g, fingers) involved in the touch event. */ + public pointerCount: number; + + /** Properties for each pointer, encoded in a raw format. */ + public rawPointerPropertiesList: ESObject; + + /** Coordinates for each pointer, encoded in a raw format. */ + public rawPointerCoords: ESObject; + + public metaState: number; + + public buttonState: number; + + /** Coordinate precision along the x-axis. */ + public xPrecision: number; + + /** Coordinate precision along the y-axis. */ + public yPrecision: number; + + public deviceId: number; + + public edgeFlags: number; + + public source: number; + + public flags: number; + + public motionEventId: number; + + constructor(viewId: number, + downTime: number, + eventTime: number, + action: number, + pointerCount: number, + rawPointerPropertiesList: ESObject, + rawPointerCoords: ESObject, + metaState: number, + buttonState: number, + xPrecision: number, + yPrecision: number, + deviceId: number, + edgeFlags: number, + source: number, + flags: number, + motionEventId: number) { + this.viewId = viewId; + this.downTime = downTime; + this.eventTime = eventTime; + this.action = action; + this.pointerCount = pointerCount; + this.rawPointerPropertiesList = rawPointerPropertiesList; + this.rawPointerCoords = rawPointerCoords; + this.metaState = metaState; + this.buttonState = buttonState; + this.xPrecision = xPrecision; + this.yPrecision = yPrecision; + this.deviceId = deviceId; + this.edgeFlags = edgeFlags; + this.source = source; + this.flags = flags; + this.motionEventId = motionEventId; + } +} + +class ParsingCallback implements MethodCallHandler { + platformChannel : PlatformViewsChannel | null = null; + handler: PlatformViewsHandler | null = null; + + onMethodCall(call: MethodCall, result: MethodResult) { + if (this.handler == null) { + return; + } + + Log.i(TAG, "Received '" + call.method + "' message."); + switch (call.method) { + case "create": { + this.platformChannel?.create(call, result); + break; + } + case "dispose": { + this.platformChannel?.dispose(call, result); + break; + } + case "resize": { + this.platformChannel?.resize(call, result); + break; + } + case "offset": { + this.platformChannel?.offset(call, result); + break; + } + case "touch": { + this.platformChannel?.touch(call, result); + break; + } + case "setDirection": { + this.platformChannel?.setDirection(call, result); + break; + } + case "clearFocus": { + this.platformChannel?.clearFocus(call, result); + break; + } + case "synchronizeToNativeViewHierarchy": { + this.platformChannel?.synchronizeToNativeViewHierarchy(call, result); + break; + } + default: + result.notImplemented(); + } + } +} + +class ResizeCallback extends PlatformViewBufferResized { + result : MethodResult | null = null; + run(bufferSize: PlatformViewBufferSize) { + if (bufferSize == null) { + this.result?.error("error", "Failed to resize the platform view", null); + } else { + const response: Map = new Map(); + response.set("width", bufferSize.width); + response.set("height", bufferSize.height); + this.result?.success(response); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets new file mode 100644 index 0000000..9ccbd2c --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/RestorationChannel.ets @@ -0,0 +1,175 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import StandardMethodCodec from '../../../plugin/common/StandardMethodCodec'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +/** + * System channel to exchange restoration data between framework and engine. + * + *

The engine can obtain the current restoration data from the framework via this channel to + * store it on disk and - when the app is relaunched - provide the stored data back to the framework + * to recreate the original state of the app. + * + *

The channel can be configured to delay responding to the framework's request for restoration + * data via {@code waitForRestorationData} until the engine-side has provided the data. This is + * useful when the engine is pre-warmed at a point in the application's life cycle where the + * restoration data is not available yet. For example, if the engine is pre-warmed as part of the + * Application before an Activity is created, this flag should be set to true because Android will + * only provide the restoration data to the Activity during the onCreate callback. + * + *

The current restoration data provided by the framework can be read via {@code + * getRestorationData()}. + */ +export default class RestorationChannel { + private static TAG = "RestorationChannel"; + private static CHANNEL_NAME = "flutter/restoration"; + + /** + * Whether the channel delays responding to the framework's initial request for restoration data + * until {@code setRestorationData} has been called. + * + *

If the engine never calls {@code setRestorationData} this flag must be set to false. If set + * to true, the engine must call {@code setRestorationData} either with the actual restoration + * data as argument or null if it turns out that there is no restoration data. + * + *

If the response to the framework's request for restoration data is not delayed until the + * data has been set via {@code setRestorationData}, the framework may intermittently initialize + * itself to default values until the restoration data has been made available. Setting this flag + * to true avoids that extra work. + */ + public waitForRestorationData: boolean = false; + + // Holds the most current restoration data which may have been provided by the engine + // via "setRestorationData" or by the framework via the method channel. This is the data the + // framework should be restored to in case the app is terminated. + private restorationData: Uint8Array = new Uint8Array(); + private channel: MethodChannel | null = null; + private pendingFrameworkRestorationChannelRequest: MethodResult | null = null; + private engineHasProvidedData: boolean = false; + private frameworkHasRequestedData: boolean = false; + private handler: MethodCallHandler = new RestorationChannelMethodCallHandler(this.restorationData); + + constructor(channelOrExecutor: MethodChannel | DartExecutor, waitForRestorationData: boolean) { + if (channelOrExecutor instanceof MethodChannel) { + this.channel = channelOrExecutor; + } else { + this.channel = new MethodChannel(channelOrExecutor, RestorationChannel.CHANNEL_NAME, StandardMethodCodec.INSTANCE); + } + this.waitForRestorationData = waitForRestorationData; + this.channel.setMethodCallHandler(this.handler); + } + + /** Obtain the most current restoration data that the framework has provided. */ + getRestorationData(): Uint8Array { + return this.restorationData; + } + + /** Set the restoration data from which the framework will restore its state. */ + setRestorationData(data: Uint8Array) { + this.engineHasProvidedData = true; + if (this.pendingFrameworkRestorationChannelRequest != null) { + // If their is a pending request from the framework, answer it. + this.pendingFrameworkRestorationChannelRequest.success(RestorationChannelMethodCallHandler.packageData(data)); + this.pendingFrameworkRestorationChannelRequest = null; + this.restorationData = data; + } else if (this.frameworkHasRequestedData) { + // If the framework has previously received the engine's restoration data, push the new data + // directly to it. This case can happen when "waitForRestorationData" is false and the + // framework retrieved the restoration state before it was set via this method. + // Experimentally, this can also be used to restore a previously used engine to another state, + // e.g. when the engine is attached to a new activity. + this.channel?.invokeMethod("push", RestorationChannelMethodCallHandler.packageData(data), { + success: (result: ESObject) :void => { + this.restorationData = data; + }, + + error: (errorCode: string, errorMessage: string, errorDetails: ESObject) :void => { + Log.e(RestorationChannel.TAG, + "Error " + errorCode + " while sending restoration data to framework: " + errorMessage); + }, + + notImplemented: () :void => { + // do nothing + } + }) + } else { + // Otherwise, just cache the data until the framework asks for it. + this.restorationData = data; + } + } + + /** + * Clears the current restoration data. + * + *

This should be called just prior to a hot restart. Otherwise, after the hot restart the + * state prior to the hot restart will get restored. + */ + clearData() { + this.restorationData = new Uint8Array(); + } +} + +class RestorationChannelMethodCallHandler implements MethodCallHandler { + public waitForRestorationData: boolean = false; + private restorationData: Uint8Array; + private engineHasProvidedData: boolean = false; + private frameworkHasRequestedData: boolean = false; + private channel: MethodChannel | null = null; + private pendingFrameworkRestorationChannelRequest: MethodResult | null = null; + + constructor(restorationData: Uint8Array) { + this.restorationData = restorationData; + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + const method = call.method; + const args: ESObject = call.args; + switch (method) { + case "put": { + this.restorationData = args; + result.success(null); + break; + } + case "get": { + this.frameworkHasRequestedData = true; + if (this.engineHasProvidedData || !this.waitForRestorationData) { + result.success(RestorationChannelMethodCallHandler.packageData(this.restorationData)); + // Do not delete the restoration data on the engine side after sending it to the + // framework. We may need to hand this data back to the operating system if the + // framework never modifies the data (and thus doesn't send us any + // data back). + } else { + this.pendingFrameworkRestorationChannelRequest = result; + } + break; + } + default: { + result.notImplemented(); + break; + } + } + } + + static packageData(data: Uint8Array): Map { + const packaged: Map = new Map(); + packaged.set("enabled", true); + packaged.set("data", data); + return packaged; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SettingsChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SettingsChannel.ets new file mode 100644 index 0000000..b40cd55 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SettingsChannel.ets @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import BasicMessageChannel from '../../../plugin/common/BasicMessageChannel'; +import JSONMessageCodec from '../../../plugin/common/JSONMessageCodec'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +export enum PlatformBrightness { + LIGHT = "light", + DARK = "dark" +} + +const TAG = "SettingsChannel"; +const TEXT_SCALE_FACTOR = "textScaleFactor"; +const NATIVE_SPELL_CHECK_SERVICE_DEFINED = "nativeSpellCheckServiceDefined"; +const BRIEFLY_SHOW_PASSWORD = "brieflyShowPassword"; +const ALWAYS_USE_24_HOUR_FORMAT = "alwaysUse24HourFormat"; +const PLATFORM_BRIGHTNESS = "platformBrightness"; +export default class SettingsChannel { + private static CHANNEL_NAME = "flutter/settings"; + + private channel: BasicMessageChannel; + + constructor(dartExecutor: DartExecutor) { + this.channel = new BasicMessageChannel(dartExecutor, SettingsChannel.CHANNEL_NAME, JSONMessageCodec.INSTANCE); + } + + startMessage(): MessageBuilder { + return new MessageBuilder(this.channel); + } +} + +class MessageBuilder { + private channel: BasicMessageChannel; + private message: Map = new Map(); + + constructor(channel: BasicMessageChannel) { + this.channel = channel; + } + + setTextScaleFactor(textScaleFactor: Number): MessageBuilder { + this.message.set(TEXT_SCALE_FACTOR, textScaleFactor); + return this; + } + + setNativeSpellCheckServiceDefined(nativeSpellCheckServiceDefined: boolean): MessageBuilder { + this.message.set(NATIVE_SPELL_CHECK_SERVICE_DEFINED, nativeSpellCheckServiceDefined); + return this; + } + + setBrieflyShowPassword(brieflyShowPassword: boolean): MessageBuilder { + this.message.set(BRIEFLY_SHOW_PASSWORD, brieflyShowPassword); + return this; + } + + setAlwaysUse24HourFormat(alwaysUse24HourFormat: boolean): MessageBuilder { + this.message.set(ALWAYS_USE_24_HOUR_FORMAT, alwaysUse24HourFormat); + return this; + } + + setPlatformBrightness(platformBrightness: PlatformBrightness): MessageBuilder { + this.message.set(PLATFORM_BRIGHTNESS, platformBrightness); + return this; + } + + send(): void { + Log.i(TAG, "Sending message: \n" + + "textScaleFactor: " + + this.message.get(TEXT_SCALE_FACTOR) + + "alwaysUse24HourFormat: " + + this.message.get(ALWAYS_USE_24_HOUR_FORMAT) + + "platformBrightness: " + + this.message.get(PLATFORM_BRIGHTNESS)) + this.channel.send(this.message) + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SystemChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SystemChannel.ets new file mode 100644 index 0000000..9f9ef28 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/SystemChannel.ets @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import BasicMessageChannel from '../../../plugin/common/BasicMessageChannel'; +import JSONMessageCodec from '../../../plugin/common/JSONMessageCodec'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; +const TAG: string = "SystemChannel"; + +/** + * fill in javadoc for SystemChannel. + */ +export default class SystemChannel { + public channel: BasicMessageChannel; + + constructor(dartExecutor: DartExecutor) { + this.channel = new BasicMessageChannel(dartExecutor, "flutter/system", JSONMessageCodec.INSTANCE); + } + + public sendMemoryPressureWarning(): void { + Log.i(TAG, "Sending memory pressure warning to Flutter"); + let message : Map = new Map().set("type", "memoryPressure"); + this.channel.send(message); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TestChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TestChannel.ets new file mode 100644 index 0000000..d54c448 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TestChannel.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import BasicMessageChannel, { MessageHandler, Reply } from '../../../plugin/common/BasicMessageChannel'; +import JSONMessageCodec from '../../../plugin/common/JSONMessageCodec'; +import DartExecutor from '../dart/DartExecutor'; +import Log from '../../../util/Log'; + +const TAG = "TestChannel" + +export default class TestChannel { + private channel: BasicMessageChannel + + constructor(dartExecutor: DartExecutor) { + this.channel = new BasicMessageChannel(dartExecutor, "flutter/test", JSONMessageCodec.INSTANCE); + let callback = new MessageCallback(); + this.channel.setMessageHandler(callback); + } +} + +class MessageCallback implements MessageHandler { + onMessage(message: string, reply: Reply) { + Log.d(TAG, "receive msg = " + message); + reply.reply("收到消息啦:" + message); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets new file mode 100644 index 0000000..97697f6 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/engine/systemchannels/TextInputChannel.ets @@ -0,0 +1,372 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import JSONMethodCodec from '../../../plugin/common/JSONMethodCodec'; +import MethodCall from '../../../plugin/common/MethodCall'; +import MethodChannel, { MethodCallHandler, MethodResult } from '../../../plugin/common/MethodChannel'; +import TextInputPlugin from '../../../plugin/editing/TextInputPlugin'; +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; + +const TAG = "TextInputChannel"; + +export default class TextInputChannel { + private static CHANNEL_NAME = "flutter/textinput"; + public channel: MethodChannel; + textInputMethodHandler: TextInputMethodHandler | null = null; + + constructor(dartExecutor: DartExecutor) { + this.channel = new MethodChannel(dartExecutor, TextInputChannel.CHANNEL_NAME, JSONMethodCodec.INSTANCE); + } + + setTextInputMethodHandler(textInputMethodHandler: TextInputMethodHandler): void { + this.textInputMethodHandler = textInputMethodHandler; + this.channel.setMethodCallHandler(new TextInputCallback(this.textInputMethodHandler)); + } + + requestExistingInputState(): void { + this.channel.invokeMethod("TextInputClient.requestExistingInputState", null); + } + + createEditingStateJSON(text: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): EditingState { + let state: EditingState = { + text: text, + selectionBase: selectionStart, + selectionExtent: selectionEnd, + composingBase: composingStart, + composingExtent: composingEnd + }; + return state; + } + + /** + * Instructs Flutter to update its text input editing state to reflect the given configuration. + */ + updateEditingState(inputClientId: number, + text: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number): void { + Log.d(TAG, "updateEditingState:" + + "Text: " + text + " Selection start: " + selectionStart + " Selection end: " + + selectionEnd + " Composing start: " + composingStart + " Composing end: " + composingEnd); + const state: ESObject = this.createEditingStateJSON(text, selectionStart, selectionEnd, composingStart, composingEnd); + this.channel.invokeMethod('TextInputClient.updateEditingState', [inputClientId, state]); + } + + newline(inputClientId: number): void { + Log.d(TAG, "Sending 'newline' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.newline"]); + } + + go(inputClientId: number): void { + Log.d(TAG, "Sending 'go' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.go"]); + } + + search(inputClientId: number): void { + Log.d(TAG, "Sending 'search' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.search"]); + } + + send(inputClientId: number): void { + Log.d(TAG, "Sending 'send' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.send"]); + } + + done(inputClientId: number): void { + Log.d(TAG, "Sending 'done' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.done"]); + } + + next(inputClientId: number): void { + Log.d(TAG, "Sending 'next' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.next"]); + } + + previous(inputClientId: number): void { + Log.d(TAG, "Sending 'previous' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.previous"]); + } + + unspecifiedAction(inputClientId: number): void { + Log.d(TAG, "Sending 'unspecifiedAction' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.unspecifiedAction"]); + } + + commitContent(inputClientId: number): void { + Log.d(TAG, "Sending 'commitContent' message."); + this.channel.invokeMethod("TextInputClient.performAction", [inputClientId, "TextInputAction.commitContent"]); + } + + performPrivateCommand(inputClientId: number, action: string, data: ESObject) { + + } + +} + +interface EditingState { + text: string; + selectionBase: number; + selectionExtent: number; + composingBase: number; + composingExtent: number; +} + +export interface TextInputMethodHandler { + show(): void; + + hide(): void; + + requestAutofill(): void; + + finishAutofillContext(shouldSave: boolean): void; + + setClient(textInputClientId: number, configuration: Configuration | null): void; + + setPlatformViewClient(id: number, usesVirtualDisplay: boolean): void; + + setEditableSizeAndTransform(width: number, height: number, transform: number[]): void; + + setEditingState(editingState: TextEditState): void; + + clearClient(): void; + +} + +export class Configuration { + obscureText: boolean = false; + autocorrect: boolean = false; + enableSuggestions: boolean = false; + enableIMEPersonalizedLearning: boolean = false; + enableDeltaModel: boolean = false; + textCapitalization: TextCapitalization | null = null; + inputType: InputType | null = null; + inputAction: Number = 0; + actionLabel: String = ""; + contentCommitMimeTypes: String[] = []; + fields: Configuration[] = []; + + constructor(obscureText: boolean, + autocorrect: boolean, + enableSuggestions: boolean, + enableIMEPersonalizedLearning: boolean, + enableDeltaModel: boolean, + inputType: InputType, + inputAction: Number, + actionLabel: String, ) { + } + getTextCapitalizationFromValue(encodedName: string): TextCapitalization { + let textKeys = [ + TextCapitalization.CHARACTERS, TextCapitalization.WORDS, + TextCapitalization.SENTENCES, TextCapitalization.NONE + ]; + for (let i = 0; i < textKeys.length; i++) { + let key = textKeys[i]; + if (TextCapitalization[key] === encodedName) { + return key; + } + } + throw new Error("No such TextCapitalization: " + encodedName); + } +} + +enum TextCapitalization { + CHARACTERS = "TextCapitalization.characters", + WORDS = "TextCapitalization.words", + SENTENCES = "TextCapitalization.sentences", + NONE = "TextCapitalization.none", +} + +export enum TextInputType { + TEXT = "TextInputType.text", + DATETIME = "TextInputType.datetime", + NAME = "TextInputType.name", + POSTAL_ADDRESS = "TextInputType.address", + NUMBER = "TextInputType.number", + PHONE = "TextInputType.phone", + MULTILINE = "TextInputType.multiline", + EMAIL_ADDRESS = "TextInputType.emailAddress", + URL = "TextInputType.url", + VISIBLE_PASSWORD = "TextInputType.visiblePassword", + NONE = "TextInputType.none", +} + +export class InputType { + type: TextInputType; + isSigned: boolean; + isDecimal: boolean; + + constructor(type: TextInputType, isSigned: boolean, isDecimal: boolean) { + this.type = type; + this.isSigned = isSigned; + this.isDecimal = isDecimal; + } + + static fromJson(json: ESObject): InputType { + return new InputType(InputType.getTextInputTypeFromValue(json.name as string), + json.signed as boolean, json.decimal as boolean) + } + + static getTextInputTypeFromValue(encodedName: string): TextInputType { + let textKeys = [ + TextInputType.TEXT, TextInputType.DATETIME, TextInputType.NAME, + TextInputType.POSTAL_ADDRESS, TextInputType.NUMBER, TextInputType.PHONE, + TextInputType.MULTILINE, TextInputType.EMAIL_ADDRESS, TextInputType.URL, + TextInputType.VISIBLE_PASSWORD, TextInputType.NONE + ]; + for (let i = 0; i < textKeys.length; i++) { + let key = textKeys[i]; + if (TextInputType[key] == encodedName) { + return key; + } + } + throw new Error("No such TextInputType: " + encodedName); + } +} + +export class TextEditState { + private static TAG = "TextEditState"; + text: string; + selectionStart: number; + selectionEnd: number; + composingStart: number; + composingEnd: number; + + constructor(text: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number) { + if ((selectionStart != -1 || selectionEnd != -1) + && (selectionStart < 0 || selectionEnd < 0)) { + throw new Error("invalid selection: (" + selectionStart + ", " + selectionEnd + ")"); + } + + if ((composingStart != -1 || composingEnd != -1) + && (composingStart < 0 || composingStart > composingEnd)) { + throw new Error("invalid composing range: (" + composingStart + ", " + composingEnd + ")"); + } + + if (composingEnd > text.length) { + throw new Error("invalid composing start: " + composingStart); + } + + if (selectionStart > text.length) { + throw new Error("invalid selection start: " + selectionStart); + } + + if (selectionEnd > text.length) { + throw new Error("invalid selection end: " + selectionEnd); + } + + this.text = text; + this.selectionStart = selectionStart; + this.selectionEnd = selectionEnd; + this.composingStart = composingStart; + this.composingEnd = composingEnd; + } + + hasSelection(): boolean { + // When selectionStart == -1, it's guaranteed that selectionEnd will also + // be -1. + return this.selectionStart >= 0; + } + + hasComposing(): boolean { + return this.composingStart >= 0 && this.composingEnd > this.composingStart; + } + + static fromJson(textEditState: ESObject): TextEditState { + return new TextEditState( + textEditState.text, + textEditState.selectionBase, + textEditState.selectionExtent, + textEditState.composingBase, + textEditState.composingExtent + ) + } +} + +class TextInputCallback implements MethodCallHandler { + textInputMethodHandler: TextInputMethodHandler; + + constructor(handler: TextInputMethodHandler) { + this.textInputMethodHandler = handler; + } + + onMethodCall(call: MethodCall, result: MethodResult) { + if (this.textInputMethodHandler == null) { + return; + } + let method: string = call.method; + let args: ESObject = call.args; + Log.d(TAG, "Received '" + method + "' message."); + switch (method) { + case "TextInput.show": + this.textInputMethodHandler.show(); + Log.d(TAG, "textInputMethodHandler.show()"); + result.success(null); + break; + case "TextInput.hide": + this.textInputMethodHandler.hide(); + result.success(null); + break; + case "TextInput.setClient": + const textInputClientId: number = args[0] as number; + //TODO: parse configuration + const config: Configuration | null = null; + this.textInputMethodHandler.setClient(textInputClientId, config); + result.success(null); + break; + case "TextInput.requestAutofill": + //TODO: requestAutofill + result.notImplemented(); + break; + case "TextInput.setPlatformViewClient": + //TODO: + result.notImplemented(); + break; + case "TextInput.setEditingState": + this.textInputMethodHandler.setEditingState(TextEditState.fromJson(args)); + result.success(null); + break; + case "TextInput.setEditableSizeAndTransform": + //TODO: + result.notImplemented(); + break; + case "TextInput.clearClient": + this.textInputMethodHandler.clearClient(); + result.success(null); + break; + case "TextInput.sendAppPrivateCommand": + //TODO: + result.notImplemented(); + break; + case "TextInput.finishAutofillContext": + //TODO: + result.notImplemented(); + break; + default: + result.notImplemented(); + break; + } + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/ExclusiveAppComponent.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/ExclusiveAppComponent.ets new file mode 100644 index 0000000..f7ecfc7 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/ExclusiveAppComponent.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export default interface ExclusiveAppComponent { + /** + * Called when another App Component is about to become attached to the {@link + * io.flutter.embedding.engine.FlutterEngine} this App Component is currently attached to. + * + *

This App Component's connections to the {@link io.flutter.embedding.engine.FlutterEngine} + * are still valid at the moment of this call. + */ + detachFromFlutterEngine(): void; + + /** + * Retrieve the App Component behind this exclusive App Component. + * + * @return The app component. + */ + getAppComponent(): T; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbility.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbility.ets new file mode 100644 index 0000000..5e152a6 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbility.ets @@ -0,0 +1,419 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import window from '@ohos.window'; +import { FlutterAbilityDelegate, Host } from './FlutterAbilityDelegate'; +import Log from '../../util/Log'; +import FlutterEngine from '../engine/FlutterEngine'; +import FlutterShellArgs from '../engine/FlutterShellArgs'; +import FlutterAbilityLaunchConfigs from './FlutterAbilityLaunchConfigs'; +import common from '@ohos.app.ability.common'; +import Want from '@ohos.app.ability.Want'; +import display from '@ohos.display'; +import { FlutterPlugin } from '../engine/plugins/FlutterPlugin'; +import { AsyncCallback } from '@ohos.base'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import I18n from '@ohos.i18n' +import { PlatformBrightness } from '../engine/systemchannels/SettingsChannel'; +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; +import { DVModelContainer } from '../../view/DynamicView/dynamicView'; +import { RootDvModeManager } from '../../plugin/platform/RootDvModelManager'; +import { Configuration } from '@ohos.app.ability.Configuration'; + +const TAG = "FlutterAbility"; +const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'; +/** + * flutter ohos基础ability,请在让主ability继承自该类。 + * 该类主要职责: + * 1、持有FlutterAbilityDelegate并初始化; + * 2、生命周期传递; + */ +export class FlutterAbility extends UIAbility implements Host { + private delegate?: FlutterAbilityDelegate | null; + private windowStage?: window.WindowStage; + private mainWindow?: window.Window; + private viewportMetrics = new ViewportMetrics(); + private displayInfo?: display.Display; + + /** + * onCreate + * 1、create and attach delegate + * 2、config windows transparent noNeed? + * 3、lifecycle.onCreate + * 4. setContentView() noNeed + */ + async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + Log.i(TAG, "bundleCodeDir=" + this.context.bundleCodeDir); + // globalThis.flutterAbility = this + this.displayInfo = display.getDefaultDisplaySync(); + this.viewportMetrics.devicePixelRatio = this.displayInfo?.densityPixels + + this.delegate = new FlutterAbilityDelegate(this); + await this?.delegate?.onAttach(this.context); + Log.i(TAG, 'onAttach end'); + this?.delegate?.platformPlugin?.setUIAbilityContext(this.context); + this?.delegate?.onRestoreInstanceState(want); + this?.delegate?.sendSettings(); + + if (this.stillAttachedForEvent("onCreate")) { + this.delegate?.onCreate(); + } + + console.log('MyAbility onCreate'); + // globalThis.applicationContext = this.context.getApplicationContext(); + this.context.eventHub.on(EVENT_BACK_PRESS, () => { + this.delegate?.flutterEngine?.getNavigationChannel()?.popRoute(); + }); + } + + onDestroy() { + this.context.eventHub.off(EVENT_BACK_PRESS); + if (this.stillAttachedForEvent("onDestroy")) { + this?.delegate?.onDestroy(); + } + } + + /** + * window状态改变回调 + * @param windowStage + */ + async onWindowStageCreate(windowStage: window.WindowStage) { + this.windowStage = windowStage + try { + windowStage?.on('windowStageEvent', (data) => { + let stageEventType: window.WindowStageEventType = data; + switch (stageEventType) { + case window.WindowStageEventType.SHOWN: // 切到前台 + Log.i(TAG, 'windowStage foreground.'); + break; + case window.WindowStageEventType.ACTIVE: // 获焦状态 + Log.i(TAG, 'windowStage active.'); + if (this.stillAttachedForEvent("onWindowFocusChanged")) { + this?.delegate?.onWindowFocusChanged(true); + } + break; + case window.WindowStageEventType.INACTIVE: // 失焦状态 + Log.i(TAG, 'windowStage inactive.'); + if (this.stillAttachedForEvent("onWindowFocusChanged")) { + this?.delegate?.onWindowFocusChanged(false); + } + break; + case window.WindowStageEventType.HIDDEN: // 切到后台 + Log.i(TAG, 'windowStage background.'); + break; + default: + break; + } + }); + + this.mainWindow = windowStage?.getMainWindowSync() + this.mainWindow?.on('windowSizeChange', (data) => { + this.onWindowPropertiesUpdated(); + }); + + this.mainWindow?.on('avoidAreaChange', (data) => { + this.onWindowPropertiesUpdated(); + }); + + this.mainWindow?.on('keyboardHeightChange', (data) => { + this.onWindowPropertiesUpdated(); + }); + + this.loadContent(); + this.mainWindow?.setWindowLayoutFullScreen(true); + } catch (exception) { + Log.e(TAG, 'Failed to enable the listener for window stage event changes. Cause:' + JSON.stringify(exception)); + } + } + + loadContent() { + if (this.windowStage != null && this.stillAttachedForEvent("loadContent")) { + Log.i(TAG, 'loadContent'); + this.windowStage?.loadContent('pages/Index', (err, data) => { + if (err.code) { + Log.e(TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + this.onWindowPropertiesUpdated(); + Log.i(TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + if (this.stillAttachedForEvent("onWindowStageCreate")) { + this?.delegate?.onWindowStageCreate(); + } + this?.delegate?.getFlutterNapi()?.updateRefreshRate(this.displayInfo!.refreshRate) + this.onFlutterEngineReady() + } + } + + onFlutterEngineReady(): void { + + } + + private updateViewportMetrics() { + this?.delegate?.getFlutterNapi()?.setViewportMetrics(this.viewportMetrics.devicePixelRatio, + this.viewportMetrics.physicalWidth, + this.viewportMetrics.physicalHeight, + this.viewportMetrics.physicalViewPaddingTop, + this.viewportMetrics.physicalViewPaddingRight, + this.viewportMetrics.physicalViewPaddingBottom, + this.viewportMetrics.physicalViewPaddingLeft, + this.viewportMetrics.physicalViewInsetTop, + this.viewportMetrics.physicalViewInsetRight, + this.viewportMetrics.physicalViewInsetBottom, + this.viewportMetrics.physicalViewInsetLeft, + this.viewportMetrics.systemGestureInsetTop, + this.viewportMetrics.systemGestureInsetRight, + this.viewportMetrics.systemGestureInsetBottom, + this.viewportMetrics.systemGestureInsetLeft, + this.viewportMetrics.physicalTouchSlop, + new Array(0), + new Array(0), + new Array(0)) + } + + onWindowStageDestroy() { + if (this.stillAttachedForEvent("onWindowStageDestroy")) { + this?.delegate?.onWindowStageDestroy(); + } + } + + onForeground() { + if (this.stillAttachedForEvent("onForeground")) { + this?.delegate?.onForeground(); + } + } + + onBackground() { + if (this.stillAttachedForEvent("onBackground")) { + this?.delegate?.onBackground(); + } + } + + release() { + if (this?.delegate != null) { + this?.delegate?.release(); + this.delegate = null; + } + } + + /** + * host所有实现方法开始======start + */ + + getAbility(): UIAbility { + return this; + } + + shouldDispatchAppLifecycleState(): boolean { + return true; + } + + provideFlutterEngine(context: common.Context): FlutterEngine | null { + return null; + } + + configureFlutterEngine(flutterEngine: FlutterEngine) { + + } + + cleanUpFlutterEngine(flutterEngine: FlutterEngine) { + + } + + getFlutterShellArgs(): FlutterShellArgs { + return FlutterShellArgs.fromWant(this.getWant()); + } + + getDartEntrypointArgs(): Array { + if (this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_DART_ENTRYPOINT_ARGS]) { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_DART_ENTRYPOINT_ARGS] as Array; + } + return new Array() + } + + detachFromFlutterEngine() { + if (this?.delegate != null) { + this?.delegate?.onDetach(); + } + } + + popSystemNavigator(): boolean { + return false; + } + + shouldAttachEngineToActivity(): boolean { + return true; + } + + getDartEntrypointLibraryUri(): string { + return ""; + } + + getAppBundlePath(): string { + return ""; + } + + getDartEntrypointFunctionName(): string { + if (this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_DART_ENTRYPOINT]) { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_DART_ENTRYPOINT] as string; + } + return FlutterAbilityLaunchConfigs.DEFAULT_DART_ENTRYPOINT + } + + getInitialRoute(): string { + if (this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_INITIAL_ROUTE]) { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_INITIAL_ROUTE] as string; + } + return "" + } + + getWant(): Want { + return this.launchWant; + } + + shouldDestroyEngineWithHost(): boolean { + return true; + } + + shouldRestoreAndSaveState(): boolean{ + if (this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_CACHED_ENGINE_ID] != undefined) { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_CACHED_ENGINE_ID] as boolean; + } + if (this.getCachedEngineId() != null) { + // Prevent overwriting the existing state in a cached engine with restoration state. + return false; + } + return true; + } + + getCachedEngineId(): string { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_CACHED_ENGINE_ID] as string + } + + getCachedEngineGroupId(): string { + return this.launchWant.parameters![FlutterAbilityLaunchConfigs.EXTRA_CACHED_ENGINE_GROUP_ID] as string + } + + /** + * host所有实现方法结束======end + */ + private stillAttachedForEvent(event: string) { + Log.i(TAG, 'Ability ' + event); + if (this?.delegate == null) { + Log.w(TAG, "FlutterAbility " + event + " call after release."); + return false; + } + if (!this?.delegate?.isAttached) { + Log.w(TAG, "FlutterAbility " + event + " call after detach."); + return false; + } + return true; + } + + addPlugin(plugin: FlutterPlugin): void { + if (this?.delegate != null) { + this?.delegate?.addPlugin(plugin) + } + } + + removePlugin(plugin: FlutterPlugin): void { + if (this?.delegate != null) { + this?.delegate?.removePlugin(plugin) + } + } + + private onWindowPropertiesUpdated(){ + if (this.delegate == null || !this.delegate.isAttached) { + return; + } + let systemAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM); + let gestureAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM_GESTURE); + let keyboardAvoidArea = this.mainWindow?.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD); + const properties = this.mainWindow?.getWindowProperties(); + this.viewportMetrics.physicalWidth = properties!.windowRect.width; + this.viewportMetrics.physicalHeight = properties!.windowRect.height; + + this.viewportMetrics.physicalViewPaddingTop = systemAvoidArea!.topRect.height + this.viewportMetrics.physicalViewPaddingLeft = systemAvoidArea!.leftRect.width + this.viewportMetrics.physicalViewPaddingBottom = systemAvoidArea!.bottomRect.height + this.viewportMetrics.physicalViewPaddingRight = systemAvoidArea!.rightRect.width + + this.viewportMetrics.physicalViewInsetTop = keyboardAvoidArea!.topRect.height + this.viewportMetrics.physicalViewInsetLeft = keyboardAvoidArea!.leftRect.width + this.viewportMetrics.physicalViewInsetBottom = keyboardAvoidArea!.bottomRect.height + this.viewportMetrics.physicalViewInsetRight = keyboardAvoidArea!.rightRect.width + + this.viewportMetrics.systemGestureInsetTop = gestureAvoidArea!.topRect.height + this.viewportMetrics.systemGestureInsetLeft = gestureAvoidArea!.leftRect.width + this.viewportMetrics.systemGestureInsetBottom = gestureAvoidArea!.bottomRect.height + this.viewportMetrics.systemGestureInsetRight = gestureAvoidArea!.rightRect.width + + this.updateViewportMetrics() + } + + onMemoryLevel(level: AbilityConstant.MemoryLevel): void { + Log.i(TAG, 'onMemoryLevel: ' + level); + if (level === AbilityConstant.MemoryLevel.MEMORY_LEVEL_CRITICAL) { + this?.delegate?.onLowMemory(); + } + } + + onConfigurationUpdated(config: Configuration){ + Log.i(TAG, 'onConfigurationUpdated config:' + JSON.stringify(config)); + this?.delegate?.flutterEngine?.getSettingsChannel()?.startMessage() + .setAlwaysUse24HourFormat(I18n.System.is24HourClock()) + .setPlatformBrightness(config.colorMode != ConfigurationConstant.ColorMode.COLOR_MODE_DARK + ? PlatformBrightness.LIGHT : PlatformBrightness.DARK); + } + + getWindowId(callback: AsyncCallback): void { + if (callback === null) { + return; + } + try { + window.getLastWindow(this.context, (error, win) => { + if (error.code) { + callback(error, -1); + return; + } + let windowId = win.getWindowProperties().id; + callback(error, windowId); + }); + } catch (err) { + Log.e(TAG, "get window id error!"); + callback(err, -1); + } + } +} + +export class ViewportMetrics { + devicePixelRatio: number = 1.0; + physicalWidth: number = 0; + physicalHeight: number = 0; + physicalViewPaddingTop: number = 0; + physicalViewPaddingRight: number = 0; + physicalViewPaddingBottom: number = 0; + physicalViewPaddingLeft: number = 0; + physicalViewInsetTop: number = 0; + physicalViewInsetRight: number = 0; + physicalViewInsetBottom: number = 0; + physicalViewInsetLeft: number = 0; + systemGestureInsetTop: number = 0; + systemGestureInsetRight: number = 0; + systemGestureInsetBottom: number = 0; + systemGestureInsetLeft: number = 0; + physicalTouchSlop = -1; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityDelegate.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityDelegate.ets new file mode 100644 index 0000000..af0946c --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityDelegate.ets @@ -0,0 +1,457 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import common from '@ohos.app.ability.common'; +import FlutterEngineConfigurator from './FlutterEngineConfigurator'; +import FlutterEngineProvider from './FlutterEngineProvider'; +import FlutterEngine from '../engine/FlutterEngine'; +import PlatformPlugin, { PlatformPluginDelegate } from '../../plugin/PlatformPlugin'; +import Want from '@ohos.app.ability.Want'; +import FlutterShellArgs from '../engine/FlutterShellArgs'; +import DartExecutor, { DartEntrypoint } from '../engine/dart/DartExecutor'; +import FlutterAbilityLaunchConfigs from './FlutterAbilityLaunchConfigs'; +import Log from '../../util/Log'; +import FlutterInjector from '../../FlutterInjector'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import ExclusiveAppComponent from './ExclusiveAppComponent'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import TextInputPlugin from '../../plugin/editing/TextInputPlugin'; +import { FlutterPlugin } from '../engine/plugins/FlutterPlugin'; +import FlutterEngineCache from '../engine/FlutterEngineCache'; +import FlutterEngineGroupCache from '../engine/FlutterEngineGroupCache'; +import FlutterEngineGroup, { Options } from '../engine/FlutterEngineGroup'; +import MouseCursorPlugin, { MouseCursorViewDelegate } from '../../plugin/mouse/MouseCursorPlugin'; +import Settings from './Settings'; +import FlutterNapi from '../engine/FlutterNapi'; + +const TAG = "FlutterAbilityDelegate"; +const PLUGINS_RESTORATION_BUNDLE_KEY = "plugins"; +const FRAMEWORK_RESTORATION_BUNDLE_KEY = "framework"; + +/** + * 主要职责: + * 1、初始化engine + * 2、处理ability生命周期回调 + */ +class FlutterAbilityDelegate implements ExclusiveAppComponent { + private host?: Host | null; + flutterEngine?: FlutterEngine | null; + platformPlugin?: PlatformPlugin; + private context?: common.Context; + private textInputPlugin?: TextInputPlugin; + private isFlutterEngineFromHost: boolean = false; + private engineGroup?: FlutterEngineGroup; + private settings?: Settings; + + constructor(host: Host) { + this.host = host; + } + + /** + * 是否还attach在ability上 + */ + isAttached = false; + + async onAttach(context: common.Context): Promise { + this.context = context; + this.ensureAlive(); + if (this.flutterEngine == null) { + await this.setupFlutterEngine(); + } + //shouldAttachEngineToActivity + if (this.host?.shouldAttachEngineToActivity()) { + // Notify any plugins that are currently attached to our FlutterEngine that they + // are now attached to an Ability. + Log.d(TAG, "Attaching FlutterEngine to the Ability that owns this delegate."); + this.flutterEngine?.getAbilityControlSurface()?.attachToAbility(this); + } + + //providePlatformPlugin + + //configureFlutterEngine + this.isAttached = true; + Log.d(TAG, "onAttach end start loadcontent") + this.host?.loadContent() + if (this.flutterEngine) { + this.textInputPlugin = new TextInputPlugin(this.flutterEngine.getTextInputChannel()!); + this.platformPlugin = new PlatformPlugin(this.flutterEngine.getPlatformChannel()!, this.context); + this.settings = new Settings(this.flutterEngine.getSettingsChannel()!); + this.flutterEngine.getSystemLanguages(); + } + } + + /** + * 加载app.so资源或者snapshot + */ + private doInitialFlutterViewRun(): void { + let initialRoute = this.host?.getInitialRoute(); + if (initialRoute == null && this.host != null) { + initialRoute = this.maybeGetInitialRouteFromIntent(this.host.getWant()); + if (initialRoute == null) { + initialRoute = FlutterAbilityLaunchConfigs.DEFAULT_INITIAL_ROUTE; + } + } + const libraryUri = this.host?.getDartEntrypointLibraryUri(); + Log.d(TAG, "Executing Dart entrypoint: " + this.host?.getDartEntrypointFunctionName() + ", library uri: " + libraryUri == null ? "\"\"" : libraryUri + ", and sending initial route: " + initialRoute); + + // The engine needs to receive the Flutter app's initial route before executing any + // Dart code to ensure that the initial route arrives in time to be applied. + this.flutterEngine?.getNavigationChannel()?.setInitialRoute(initialRoute ?? ''); + + let appBundlePathOverride = this.host?.getAppBundlePath(); + if (appBundlePathOverride == null || appBundlePathOverride == '') { + appBundlePathOverride = FlutterInjector.getInstance().getFlutterLoader().findAppBundlePath(); + } + + const dartEntrypoint: DartEntrypoint = new DartEntrypoint( + appBundlePathOverride, + this.host?.getDartEntrypointLibraryUri() ?? '', + this.host?.getDartEntrypointFunctionName() ?? '' + ); + this.flutterEngine?.dartExecutor.executeDartEntrypoint(dartEntrypoint, this.host?.getDartEntrypointArgs()); + } + + private maybeGetInitialRouteFromIntent(want: Want): string { + return ''; + } + + + /** + * 通过参数,配置flutterEngine + * @param want + */ + onRestoreInstanceState(want: Want) { + let frameworkState = want.parameters != null + ? want.parameters[FRAMEWORK_RESTORATION_BUNDLE_KEY] as Uint8Array + : new Uint8Array(); + if (this.host?.shouldRestoreAndSaveState()) { + this.flutterEngine?.getRestorationChannel()?.setRestorationData(frameworkState); + } + } + + /** + * 初始化flutterEngine + */ + async setupFlutterEngine() { + // First, check if the host wants to use a cached FlutterEngine. + const cachedEngineId = this.host?.getCachedEngineId(); + Log.d(TAG, "cachedEngineId=" + cachedEngineId); + if (cachedEngineId && cachedEngineId.length > 0) { + this.flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId); + this.isFlutterEngineFromHost = true; + if (this.flutterEngine == null) { + throw new Error( + "The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + + cachedEngineId + + "'"); + } + return; + } + + // Second, defer to subclasses for a custom FlutterEngine. + if (this.host && this.context) { + this.flutterEngine = this.host.provideFlutterEngine(this.context); + } + if (this.flutterEngine != null) { + this.isFlutterEngineFromHost = true; + return; + } + + // Third, check if the host wants to use a cached FlutterEngineGroup + // and create new FlutterEngine using FlutterEngineGroup#createAndRunEngine + const cachedEngineGroupId = this.host?.getCachedEngineGroupId(); + Log.d(TAG, "cachedEngineGroupId=" + cachedEngineGroupId); + if (cachedEngineGroupId != null) { + const flutterEngineGroup = FlutterEngineGroupCache.instance.get(cachedEngineGroupId); + if (flutterEngineGroup == null) { + throw new Error( + "The requested cached FlutterEngineGroup did not exist in the FlutterEngineGroupCache: '" + + cachedEngineGroupId + + "'"); + } + + if (this.context != null) { + this.flutterEngine = await flutterEngineGroup.createAndRunEngineByOptions( + this.addEntrypointOptions(new Options(this.context))); + } + this.isFlutterEngineFromHost = false; + return; + } + + // Our host did not provide a custom FlutterEngine. Create a FlutterEngine to back our + // FlutterView. + Log.d( + TAG, + "No preferred FlutterEngine was provided. Creating a new FlutterEngine for this FlutterAbility."); + + let group = this.engineGroup; + if (group == null && this.context != null && this.host != null) { + group = new FlutterEngineGroup(); + await group.checkLoader(this.context, this.host.getFlutterShellArgs().toArray() ?? []); + this.engineGroup = group; + } + if (this.context) { + this.flutterEngine = await group?.createAndRunEngineByOptions(this.addEntrypointOptions(new Options(this.context) + .setAutomaticallyRegisterPlugins(false) + .setWaitForRestorationData(this.host?.shouldRestoreAndSaveState() || false))); + } + this.isFlutterEngineFromHost = false; + } + + addEntrypointOptions(options: Options): Options { + let appBundlePathOverride = this.host?.getAppBundlePath(); + if (appBundlePathOverride == null || appBundlePathOverride.length == 0) { + appBundlePathOverride = FlutterInjector.getInstance().getFlutterLoader().findAppBundlePath(); + } + + const dartEntrypoint = new DartEntrypoint(appBundlePathOverride ?? '', + '', + this.host?.getDartEntrypointFunctionName() ?? ''); + let initialRoute = this.host?.getInitialRoute(); + if (initialRoute == null && this.host != null) { + initialRoute = this.maybeGetInitialRouteFromIntent(this.host.getWant()); + if (initialRoute == null) { + initialRoute = FlutterAbilityLaunchConfigs.DEFAULT_INITIAL_ROUTE; + } + } + return options + .setDartEntrypoint(dartEntrypoint) + .setInitialRoute(initialRoute ?? '') + .setDartEntrypointArgs(this.host?.getDartEntrypointArgs() ?? []); + } + + /** + * 释放所有持有对象 + */ + release() { + this.host = null; + this.flutterEngine = null; + } + + onDetach() { + if (this.host?.shouldAttachEngineToActivity()) { + // Notify plugins that they are no longer attached to an Activity. + Log.d(TAG, "Detaching FlutterEngine from the Ability"); + this.flutterEngine?.getAbilityControlSurface()?.detachFromAbility(); + } + } + + onLowMemory(): void { + this.getFlutterNapi()?.notifyLowMemoryWarning(); + this.flutterEngine?.getSystemChannel()?.sendMemoryPressureWarning(); + } + + /** + * 生命周期回调 + */ + + onCreate() { + this.ensureAlive(); + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getLifecycleChannel()?.appIsInactive(); + } + } + + onDestroy() { + this.ensureAlive(); + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getLifecycleChannel()?.appIsDetached(); + } + this.textInputPlugin?.detach(); + } + + onWindowStageCreate() { + this.ensureAlive(); + this.doInitialFlutterViewRun(); + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getLifecycleChannel()?.appIsResumed(); + } + } + + onWindowStageDestroy() { + + } + + onWindowFocusChanged(hasFocus: boolean):void { + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getAbilityControlSurface()?.onWindowFocusChanged(hasFocus); + if (hasFocus) { + this.flutterEngine?.getLifecycleChannel()?.aWindowIsFocused(); + } else { + this.flutterEngine?.getLifecycleChannel()?.noWindowsAreFocused(); + } + } + } + + onForeground() { + this.ensureAlive(); + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getLifecycleChannel()?.appIsResumed(); + } + } + + onBackground() { + if (this.shouldDispatchAppLifecycleState()) { + this.flutterEngine?.getLifecycleChannel()?.appIsPaused(); + } + } + + /** + * 生命周期回调结束 + */ + + shouldDispatchAppLifecycleState(): boolean { + if (this.host == null) { + return false; + } + return this.host.shouldDispatchAppLifecycleState() && this.isAttached; + } + + ensureAlive() { + if (this.host == null) { + throw new Error("Cannot execute method on a destroyed FlutterAbilityDelegate."); + } + } + + getFlutterNapi() : FlutterNapi | null { + return this.flutterEngine?.getFlutterNapi() ?? null + } + + detachFromFlutterEngine() { + if (this.host?.shouldDestroyEngineWithHost()) { + // The host owns the engine and should never have its engine taken by another exclusive + // activity. + throw new Error( + "The internal FlutterEngine created by " + + this.host + + " has been attached to by another activity. To persist a FlutterEngine beyond the " + + "ownership of this ablity, explicitly create a FlutterEngine"); + } + + // Default, but customizable, behavior is for the host to call {@link #onDetach} + // deterministically as to not mix more events during the lifecycle of the next exclusive + // activity. + this.host?.detachFromFlutterEngine(); + } + + getAppComponent(): UIAbility { + const ability = this.host?.getAbility(); + if (ability == null) { + throw new Error( + "FlutterActivityAndFragmentDelegate's getAppComponent should only " + + "be queried after onAttach, when the host's ability should always be non-null"); + } + return ability; + } + + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void { + this.ensureAlive() + if (this.flutterEngine != null) { + Log.i(TAG, "Forwarding onNewWant() to FlutterEngine and sending pushRouteInformation message."); + this.flutterEngine?.getAbilityControlSurface()?.onNewWant(want, launchParams); + const initialRoute = this.maybeGetInitialRouteFromIntent(want); + if (initialRoute && initialRoute.length > 0) { + this.flutterEngine?.getNavigationChannel()?.pushRouteInformation(initialRoute); + } + } else { + Log.w(TAG, "onNewIntent() invoked before FlutterFragment was attached to an Activity."); + } + } + + onSaveState(reason: AbilityConstant.StateType, wantParam: Record): AbilityConstant.OnSaveResult { + Log.i(TAG, "onSaveInstanceState. Giving framework and plugins an opportunity to save state."); + this.ensureAlive(); + if (this.host?.shouldRestoreAndSaveState()) { + wantParam[FRAMEWORK_RESTORATION_BUNDLE_KEY] = this.flutterEngine!.getRestorationChannel()!.getRestorationData(); + } + if (this.host?.shouldAttachEngineToActivity()) { + const plugins:Record = {} + const result = this.flutterEngine?.getAbilityControlSurface()?.onSaveState(reason, plugins); + wantParam[PLUGINS_RESTORATION_BUNDLE_KEY] = plugins; + return result ?? AbilityConstant.OnSaveResult.ALL_REJECT + } + return AbilityConstant.OnSaveResult.ALL_REJECT + } + + addPlugin(plugin: FlutterPlugin): void { + this.flutterEngine?.getPlugins()?.add(plugin) + } + + removePlugin(plugin: FlutterPlugin): void { + this.flutterEngine?.getPlugins()?.remove(plugin.getUniqueClassName()) + } + + sendSettings(): void { + this.settings?.sendSettings() + } +} + + +/** + * FlutterAbility句柄 + */ +interface Host extends FlutterEngineProvider, FlutterEngineConfigurator, PlatformPluginDelegate, MouseCursorViewDelegate { + + getAbility(): UIAbility; + + loadContent():void; + + shouldDispatchAppLifecycleState(): boolean; + + detachFromFlutterEngine(); + + shouldAttachEngineToActivity(): boolean; + + getCachedEngineId(): string; + + getCachedEngineGroupId(): string; + + /** + * Returns true if the {@link io.flutter.embedding.engine.FlutterEngine} used in this delegate + * should be destroyed when the host/delegate are destroyed. + */ + shouldDestroyEngineWithHost(): boolean; + + /** Returns the {@link FlutterShellArgs} that should be used when initializing Flutter. */ + getFlutterShellArgs(): FlutterShellArgs; + + /** Returns arguments that passed as a list of string to Dart's entrypoint function. */ + getDartEntrypointArgs(): Array; + + /** + * Returns the URI of the Dart library which contains the entrypoint method (example + * "package:foo_package/main.dart"). If null, this will default to the same library as the + * `main()` function in the Dart program. + */ + getDartEntrypointLibraryUri(): string; + + /** Returns the path to the app bundle where the Dart code exists. */ + getAppBundlePath(): string; + + /** + * Returns the Dart entrypoint that should run when a new {@link + * io.flutter.embedding.engine.FlutterEngine} is created. + */ + getDartEntrypointFunctionName(): string; + + /** Returns the initial route that Flutter renders. */ + getInitialRoute(): string; + + getWant(): Want; + + shouldRestoreAndSaveState(): boolean; +} + +export { Host, FlutterAbilityDelegate } \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityLaunchConfigs.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityLaunchConfigs.ets new file mode 100644 index 0000000..996f455 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterAbilityLaunchConfigs.ets @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** The mode of the background of a Flutter {@code Activity}, either opaque or transparent. */ +enum BackgroundMode { + /** Indicates a FlutterActivity with an opaque background. This is the default. */ + opaque, + /** Indicates a FlutterActivity with a transparent background. */ + transparent +} + +export default class FlutterAbilityLaunchConfigs { + + static DART_ENTRYPOINT_META_DATA_KEY = "io.flutter.Entrypoint"; + static DART_ENTRYPOINT_URI_META_DATA_KEY = "io.flutter.EntrypointUri"; + static INITIAL_ROUTE_META_DATA_KEY = "io.flutter.InitialRoute"; + static SPLASH_SCREEN_META_DATA_KEY = "io.flutter.embedding.android.SplashScreenDrawable"; + static NORMAL_THEME_META_DATA_KEY = "io.flutter.embedding.android.NormalTheme"; + static HANDLE_DEEPLINKING_META_DATA_KEY = "flutter_deeplinking_enabled"; + // Intent extra arguments. + static EXTRA_DART_ENTRYPOINT = "dart_entrypoint"; + static EXTRA_INITIAL_ROUTE = "route"; + static EXTRA_BACKGROUND_MODE = "background_mode"; + static EXTRA_CACHED_ENGINE_ID = "cached_engine_id"; + static EXTRA_DART_ENTRYPOINT_ARGS = "dart_entrypoint_args"; + static EXTRA_CACHED_ENGINE_GROUP_ID = "cached_engine_group_id"; + static EXTRA_DESTROY_ENGINE_WITH_ACTIVITY = "destroy_engine_with_activity"; + static EXTRA_ENABLE_STATE_RESTORATION = "enable_state_restoration"; + + // Default configuration. + static DEFAULT_DART_ENTRYPOINT = "main"; + static DEFAULT_INITIAL_ROUTE = "/"; + static DEFAULT_BACKGROUND_MODE = BackgroundMode.opaque +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineConfigurator.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineConfigurator.ets new file mode 100644 index 0000000..7953cad --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineConfigurator.ets @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterEngine from '../engine/FlutterEngine'; + +export default interface FlutterEngineConfigurator { + + configureFlutterEngine(flutterEngine: FlutterEngine); + + cleanUpFlutterEngine(flutterEngine: FlutterEngine); +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineProvider.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineProvider.ets new file mode 100644 index 0000000..a8eea36 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterEngineProvider.ets @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterEngine from '../engine/FlutterEngine'; +import common from '@ohos.app.ability.common'; + +export default interface FlutterEngineProvider { + provideFlutterEngine(context: common.Context): FlutterEngine | null; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterPage.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterPage.ets new file mode 100644 index 0000000..0569511 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/FlutterPage.ets @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import { PlatformViewWrapper } from '../../plugin/platform/PlatformViewWrapper'; +import { RootDvModeManager } from '../../plugin/platform/RootDvModelManager'; +import { DVModel, + DVModelChildren, + DVModelContainer, + DVModelEvents, + DVModelParameters, DynamicView } from '../../view/DynamicView/dynamicView'; +import { createDVModelFromJson } from '../../view/DynamicView/dynamicViewJson'; + +/** + * 基础page组件,承载XComponent组件 + */ +@Component +export struct FlutterPage { + @State message: string = 'Hello World'; + + @State rootDvModel: DVModelContainer = RootDvModeManager.getRootDvMode(); + + build() { + DynamicView({ + model: this.rootDvModel.model as DVModel, + params: this.rootDvModel.model.params as DVModelParameters, + events: this.rootDvModel.model.events as DVModelEvents, + children: this.rootDvModel.model.children as DVModelChildren, + customBuilder: this.rootDvModel.model.builder as ($$: Record<"params",DVModelParameters >) => void + //customBuilder: this.rootDvModel.model.builder as ($$: { params: DVModelParameters }) => void + }) + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/OhosTouchProcessor.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/OhosTouchProcessor.ets new file mode 100644 index 0000000..53f0f0a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/OhosTouchProcessor.ets @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { TouchEvent } from '@ohos.multimodalInput.touchEvent'; + +export default class OhosTouchProcessor { + private static POINTER_DATA_FIELD_COUNT: number = 35; + + static BYTES_PER_FIELD: number = 8; + + private static POINTER_DATA_FLAG_BATCHED: number = 1; + + public onTouchEvent(event: TouchEvent, transformMatrix: ESObject): void { + + } +} + +export enum PointerChange { + CANCEL = 0, + ADD = 1, + REMOVE = 2, + HOVER = 3, + DOWN = 4, + MOVE = 5, + UP = 6, + PAN_ZOOM_START = 7, + PAN_ZOOM_UPDATE = 8, + PAN_ZOOM_END = 9 +} + +export enum PointerDeviceKind { + TOUCH = 0, + MOUSE = 1, + STYLUS = 2, + INVERTED_STYLUS = 3, + TRACKPAD = 4, + UNKNOWN = 5 +} + +export enum PointerSignalKind { + NONE = 0, + SCROLL = 1, + SCROLL_INERTIA_CANCEL = 2, + SCALE = 3, + UNKNOWN = 4 +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/Settings.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/Settings.ets new file mode 100644 index 0000000..d8ced27 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/Settings.ets @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import SettingsChannel, { PlatformBrightness } from '../engine/systemchannels/SettingsChannel' +import I18n from '@ohos.i18n' + +export default class Settings { + settingsChannel: SettingsChannel | null; + + constructor(settingsChannel: SettingsChannel | null) { + this.settingsChannel = settingsChannel; + } + + sendSettings(): void { + this.settingsChannel?.startMessage() + .setAlwaysUse24HourFormat(I18n.System.is24HourClock()) + .setTextScaleFactor(1.0) + .setNativeSpellCheckServiceDefined(false) + .setBrieflyShowPassword(false) + .setPlatformBrightness(PlatformBrightness.LIGHT) + .send(); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventTracker.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventTracker.ets new file mode 100644 index 0000000..b517431 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/TouchEventTracker.ets @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +/** Tracks the motion events received by the FlutterView. */ +import PlainArray from '@ohos.util.PlainArray'; +import { TouchEvent } from '@ohos.multimodalInput.touchEvent'; +import Queue from '@ohos.util.Queue'; + +export class TouchEventTracker { + private eventById : PlainArray; + private unusedEvents : Queue; + private static INSTANCE:TouchEventTracker; + + public static getInstance(): TouchEventTracker { + if (TouchEventTracker.INSTANCE == null) { + TouchEventTracker.INSTANCE = new TouchEventTracker(); + } + return TouchEventTracker.INSTANCE; + } + + constructor() { + this.eventById = new PlainArray(); + this.unusedEvents = new Queue(); + } + + /** Tracks the event and returns a unique MotionEventId identifying the event. */ + public track(event :TouchEvent) : TouchEventId { + const eventId:TouchEventId = TouchEventId.createUnique(); + this.eventById.add(eventId.getId(), event); + this.unusedEvents.add(eventId.getId()); + return eventId; + } + + /** + * Returns the MotionEvent corresponding to the eventId while discarding all the motion events + * that occurred prior to the event represented by the eventId. Returns null if this event was + * popped or discarded. + */ + public pop(eventId : TouchEventId) : TouchEvent { + // remove all the older events. + while (this.unusedEvents.length != 0 && this.unusedEvents.getFirst() < eventId.getId()) { + this.eventById.remove(this.unusedEvents.pop()); + } + + // remove the current event from the heap if it exists. + if (this.unusedEvents.length != 0 && this.unusedEvents.getFirst() == eventId.getId()) { + this.unusedEvents.pop(); + } + + const event : TouchEvent = this.eventById.get(eventId.getId()); + this.eventById.remove(eventId.getId()); + return event; + } +} + +/** Represents a unique identifier corresponding to a motion event. */ +export class TouchEventId { + private static ID_COUNTER : number = 0; + private id : number; + + constructor(id : number) { + this.id = id; + } + + public static from(id : number) : TouchEventId { + return new TouchEventId(id); + } + + public static createUnique() : TouchEventId { + return new TouchEventId(TouchEventId.ID_COUNTER++); + } + + public getId() : number { + return this.id; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapper.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapper.ets new file mode 100644 index 0000000..ae2c6cf --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/embedding/ohos/WindowInfoRepositoryCallbackAdapterWrapper.ets @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility'; + +export default class WindowInfoRepositoryCallbackAdapterWrapper { + + constructor() { + } + +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/PlatformPlugin.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/PlatformPlugin.ets new file mode 100644 index 0000000..8c757c2 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/PlatformPlugin.ets @@ -0,0 +1,301 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import PlatformChannel, { + AppSwitcherDescription, + Brightness, + ClipboardContentFormat, + HapticFeedbackType, + PlatformMessageHandler, + SoundType, + SystemChromeStyle, + SystemUiMode, + SystemUiOverlay +} from '../embedding/engine/systemchannels/PlatformChannel'; +import pasteboard from '@ohos.pasteboard'; +import Log from '../util/Log'; +import vibrator from '@ohos.vibrator'; +import window from '@ohos.window'; +import common from '@ohos.app.ability.common'; + +/** + * ohos实现platform plugin + */ +export default class PlatformPlugin { + private static TAG = "PlatformPlugin"; + private callback = new PlatformPluginCallback(); + + constructor(platformChannel: PlatformChannel, context: common.Context, platformPluginDelegate?: PlatformPluginDelegate) { + this.callback.platformChannel = platformChannel; + this.callback.context = context; + this.callback.applicationContext = context?.getApplicationContext(); + this.callback.platform = this; + + try { + window.getLastWindow(context, (err, data) => { + if (err.code) { + Log.e(PlatformPlugin.TAG, "Failed to obtain the top window. Cause: " + JSON.stringify(err)); + return; + } + this.callback.windowClass = data; + }); + } catch (err) { + Log.e(PlatformPlugin.TAG, "Failed to obtain the top window. Cause: " + JSON.stringify(err)); + } + this.callback.platformPluginDelegate = platformPluginDelegate ?? null; + this.callback.platformChannel?.setPlatformMessageHandler(this.callback); + } + + + updateSystemUiOverlays(): void { + this.callback.windowClass?.setWindowSystemBarEnable(this.callback.showBarOrNavigation); + if (this.callback.currentTheme != null) { + this.callback.setSystemChromeSystemUIOverlayStyle(this.callback.currentTheme); + } + } + + setUIAbilityContext(context: common.UIAbilityContext): void { + this.callback.uiAbilityContext = context; + } + + setSystemChromeChangeListener(): void { + if (this.callback.callbackId == null && this.callback.applicationContext != null) { + let that = this; + this.callback.callbackId = this.callback.applicationContext?.on('environment', { + onConfigurationUpdated(config) { + Log.d(PlatformPlugin.TAG, "onConfigurationUpdated: " + that.callback.showBarOrNavigation); + that.callback.platformChannel?.systemChromeChanged(that.callback.showBarOrNavigation.includes('status')); + }, + onMemoryLevel(level) { + } + }) + } + } +} + +export interface PlatformPluginDelegate { + popSystemNavigator(): boolean; +} + +class PlatformPluginCallback implements PlatformMessageHandler { + private static TAG = "PlatformPluginCallback"; + platform: PlatformPlugin | null = null; + windowClass: window.Window | null = null; + platformChannel: PlatformChannel | null = null; + platformPluginDelegate: PlatformPluginDelegate | null = null; + context: common.Context | null = null; + showBarOrNavigation: ('status' | 'navigation')[] = ['status', 'navigation']; + uiAbilityContext: common.UIAbilityContext | null = null; + callbackId: number | null = null; + applicationContext: common.ApplicationContext | null = null; + currentTheme: SystemChromeStyle | null = null; + + playSystemSound(soundType: SoundType) { + } + + vibrateHapticFeedback(feedbackType: HapticFeedbackType) { + switch (feedbackType) { + case HapticFeedbackType.STANDARD: + vibrator.startVibration({ type: 'time', duration: 75 }, + { id: 0, usage: 'touch' }); + break; + case HapticFeedbackType.LIGHT_IMPACT: + vibrator.startVibration({ type: 'time', duration: 25 }, + { id: 0, usage: 'touch' }); + break; + case HapticFeedbackType.MEDIUM_IMPACT: + vibrator.startVibration({ type: 'time', duration: 150 }, + { id: 0, usage: 'touch' }); + break; + case HapticFeedbackType.HEAVY_IMPACT: + vibrator.startVibration({ type: 'time', duration: 300 }, + { id: 0, usage: 'touch' }); + break; + case HapticFeedbackType.SELECTION_CLICK: + vibrator.startVibration({ type: 'time', duration: 100 }, + { id: 0, usage: 'touch' }); + break; + } + } + + setPreferredOrientations(ohosOrientation: number) { + Log.d(PlatformPluginCallback.TAG, "ohosOrientation: " + ohosOrientation); + this.windowClass?.setPreferredOrientation(ohosOrientation); + } + + setApplicationSwitcherDescription(description: AppSwitcherDescription) { + // representation described in the given {@code description}. + } + + showSystemOverlays(overlays: SystemUiOverlay[]) { + this.setSystemChromeEnabledSystemUIOverlays(overlays); + } + + showSystemUiMode(mode: SystemUiMode) { + this.setSystemChromeEnabledSystemUIMode(mode); + } + + setSystemUiChangeListener() { + this.platform?.setSystemChromeChangeListener(); + } + + restoreSystemUiOverlays() { + this.platform?.updateSystemUiOverlays(); + } + + setSystemUiOverlayStyle(systemUiOverlayStyle: SystemChromeStyle) { + Log.d(PlatformPluginCallback.TAG, "systemUiOverlayStyle:" + JSON.stringify(systemUiOverlayStyle)); + this.setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle); + } + + popSystemNavigator() { + if (this.platformPluginDelegate != null && this.platformPluginDelegate?.popSystemNavigator()) { + return; + } + if (this.uiAbilityContext != null) { + this.uiAbilityContext.terminateSelf(); + } + } + + getClipboardData(format: ClipboardContentFormat): string { + // todo + return ""; + } + + setClipboardData(text: string) { + let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text); + let clipboard = pasteboard.getSystemPasteboard(); + clipboard.setData(pasteData); + } + + clipboardHasStrings(): boolean { + return false; + } + + setSystemChromeEnabledSystemUIMode(mode: SystemUiMode): void { + Log.d(PlatformPluginCallback.TAG, "mode: " + mode); + let uiConfig: ('status' | 'navigation')[] = []; + if (mode == SystemUiMode.LEAN_BACK) { + //全屏显示,通过点击显示器上的任何位置都可以显示状态和导航栏 + this.windowClass?.setWindowLayoutFullScreen(false); + + } else if (mode == SystemUiMode.IMMERSIVE) { + //全屏显示,通过在显示器边缘的滑动手势可以显示状态和导航栏,应用程序不会接收到此手势 + this.windowClass?.setWindowLayoutFullScreen(true); + + } else if (mode == SystemUiMode.IMMERSIVE_STICKY) { + //全屏显示,通过在显示器边缘的滑动手势可以显示状态和导航栏,此手势由应用程序接收 + this.windowClass?.setWindowLayoutFullScreen(true); + + } else if (mode == SystemUiMode.EDGE_TO_EDGE) { + //全屏显示,在应用程序上呈现状态和导航元素 + this.windowClass?.setWindowLayoutFullScreen(false); + uiConfig = ['status', 'navigation']; + + } else { + return; + } + this.showBarOrNavigation = uiConfig; + this.platform?.updateSystemUiOverlays(); + } + + setSystemChromeSystemUIOverlayStyle(systemChromeStyle: SystemChromeStyle): void { + let isStatusBarLightIconValue: boolean = false; + let statusBarColorValue: string | undefined = undefined; + let statusBarContentColorValue: string | undefined = undefined; + let navigationBarColorValue: string | undefined = undefined; + let isNavigationBarLightIconValue: boolean = false; + let navigationBarContentColorValue: string | undefined = undefined; + if (systemChromeStyle.statusBarIconBrightness != null) { + switch (systemChromeStyle.statusBarIconBrightness) { + case Brightness.DARK: + isStatusBarLightIconValue = false; + break; + case Brightness.LIGHT: + isStatusBarLightIconValue = true; + break; + } + } + + if (systemChromeStyle.statusBarColor != null) { + statusBarColorValue = "#" + systemChromeStyle.statusBarColor.toString(16); + } + + if (systemChromeStyle.systemStatusBarContrastEnforced != null) { + + } + + if (systemChromeStyle.systemNavigationBarIconBrightness != null) { + switch (systemChromeStyle.systemNavigationBarIconBrightness) { + case Brightness.DARK: + isNavigationBarLightIconValue = true; + break; + case Brightness.LIGHT: + isNavigationBarLightIconValue = false; + } + } + + if (systemChromeStyle.systemNavigationBarColor != null) { + navigationBarColorValue = "#" + systemChromeStyle.systemNavigationBarColor.toString(16); + } + + if (systemChromeStyle.systemNavigationBarContrastEnforced != null) { + + } + this.currentTheme = systemChromeStyle; + let systemBarProperties = new SystemBarProperties(); + systemBarProperties.statusBarColor = statusBarColorValue; + systemBarProperties.isStatusBarLightIcon = isStatusBarLightIconValue; + systemBarProperties.statusBarContentColor = statusBarContentColorValue; + systemBarProperties.navigationBarColor = navigationBarColorValue; + systemBarProperties.isNavigationBarLightIcon = isNavigationBarLightIconValue; + systemBarProperties.navigationBarContentColor = navigationBarContentColorValue; + Log.d(PlatformPluginCallback.TAG, "systemBarProperties: " + JSON.stringify(systemBarProperties)); + this.windowClass?.setWindowSystemBarProperties(systemBarProperties); + } + + setSystemChromeEnabledSystemUIOverlays(overlays: SystemUiOverlay[]): void { + let uiConfig: ('status' | 'navigation')[] = []; + if (overlays.length == 0) { + + } + for (let index = 0; index < overlays.length; ++index) { + let overlayToShow = overlays[index]; + switch (overlayToShow) { + case SystemUiOverlay.TOP_OVERLAYS: + uiConfig.push('status'); //hide navigation + break; + case SystemUiOverlay.BOTTOM_OVERLAYS: + uiConfig.push('navigation'); //hide bar + break; + } + } + this.showBarOrNavigation = uiConfig; + this.platform?.updateSystemUiOverlays(); + } +} + +class SystemBarProperties { + statusBarColor?: string; + + isStatusBarLightIcon?: boolean; + + statusBarContentColor?: string; + + navigationBarColor?: string; + + isNavigationBarLightIcon?: boolean; + + navigationBarContentColor?: string; +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel.ets new file mode 100644 index 0000000..796f8ed --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel.ets @@ -0,0 +1,171 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MessageChannelUtils from '../../util/MessageChannelUtils'; +import { BinaryMessageHandler } from './BinaryMessenger'; +import Log from '../../util/Log'; +import { BinaryReply } from './BinaryMessenger'; +import { TaskQueue } from './BinaryMessenger'; +import MessageCodec from './MessageCodec'; +import { BinaryMessenger } from './BinaryMessenger'; +import StringUtils from '../../util/StringUtils'; + +/** + * A named channel for communicating with the Flutter application using basic, asynchronous message + * passing. + * + *

Messages are encoded into binary before being sent, and binary messages received are decoded + * into Java objects. The {@link MessageCodec} used must be compatible with the one used by the + * Flutter application. This can be achieved by creating a BasicMessageChannel + * counterpart of this channel on the Dart side. The static Java type of messages sent and received + * is {@code Object}, but only values supported by the specified {@link MessageCodec} can be used. + * + *

The logical identity of the channel is given by its name. Identically named channels will + * interfere with each other's communication. + */ +export default class BasicMessageChannel { + public static TAG = "BasicMessageChannel#"; + public static CHANNEL_BUFFERS_CHANNEL = "dev.flutter/channel-buffers"; + private messenger: BinaryMessenger; + private name: string; + private codec: MessageCodec; + private taskQueue?: TaskQueue; + + constructor(messenger: BinaryMessenger, name: string, codec: MessageCodec, taskQueue?: TaskQueue) { + this.messenger = messenger + this.name = name + this.codec = codec + this.taskQueue = taskQueue + } + + /** + * Sends the specified message to the Flutter application, optionally expecting a reply. + * + *

Any uncaught exception thrown by the reply callback will be caught and logged. + * + * @param message the message, possibly null. + * @param callback a {@link Reply} callback, possibly null. + */ + send(message: T, callback?: (reply: T)=>void): void { + this.messenger.send(this.name, this.codec.encodeMessage(message), callback == null ? null : new IncomingReplyHandler(callback, this.codec)); + } + + /** + * Registers a message handler on this channel for receiving messages sent from the Flutter + * application. + * + *

Overrides any existing handler registration for (the name of) this channel. + * + *

If no handler has been registered, any incoming message on this channel will be handled + * silently by sending a null reply. + * + * @param handler a {@link MessageHandler}, or null to deregister. + */ + setMessageHandler(handler: MessageHandler): void { + // We call the 2 parameter variant specifically to avoid breaking changes in + // mock verify calls. + // See https://github.com/flutter/flutter/issues/92582. + if (this.taskQueue != null) { + this.messenger.setMessageHandler(this.name, new IncomingMessageHandler(handler, this.codec), this.taskQueue); + } else { + this.messenger.setMessageHandler(this.name, new IncomingMessageHandler(handler, this.codec)); + } + } + + /** + * Adjusts the number of messages that will get buffered when sending messages to channels that + * aren't fully set up yet. For example, the engine isn't running yet or the channel's message + * handler isn't set up on the Dart side yet. + */ + resizeChannelBuffer(newSize: number): void { + MessageChannelUtils.resizeChannelBuffer(this.messenger, this.name, newSize); + } +} + + +export interface Reply { + /** + * Handles the specified message reply. + * + * @param reply the reply, possibly null. + */ + reply: (reply: T) => void; +} + +export interface MessageHandler { + + /** + * Handles the specified message received from Flutter. + * + *

Handler implementations must reply to all incoming messages, by submitting a single reply + * message to the given {@link Reply}. Failure to do so will result in lingering Flutter reply + * handlers. The reply may be submitted asynchronously and invoked on any thread. + * + *

Any uncaught exception thrown by this method, or the preceding message decoding, will be + * caught by the channel implementation and logged, and a null reply message will be sent back + * to Flutter. + * + *

Any uncaught exception thrown during encoding a reply message submitted to the {@link + * Reply} is treated similarly: the exception is logged, and a null reply is sent to Flutter. + * + * @param message the message, possibly null. + * @param reply a {@link Reply} for sending a single message reply back to Flutter. + */ + onMessage(message: T, reply: Reply): void; +} + +class IncomingReplyHandler implements BinaryReply { + private callback: (reply: T)=>void; + private codec: MessageCodec + + constructor(callback:(reply: T)=>void, codec: MessageCodec) { + this.callback = callback + this.codec = codec + } + + reply(reply: ArrayBuffer) { + try { + this.callback(this.codec.decodeMessage(reply)); + } catch (e) { + Log.e(BasicMessageChannel.TAG, "Failed to handle message reply", e); + } + } +} + +class IncomingMessageHandler implements BinaryMessageHandler { + private handler: MessageHandler + private codec: MessageCodec + + constructor(handler: MessageHandler, codec: MessageCodec) { + this.handler = handler; + this.codec = codec + } + + onMessage(message: ArrayBuffer, callback: BinaryReply) { + try { + this.handler.onMessage( + this.codec.decodeMessage(message), + { + reply: (reply: T): void => { + callback.reply(this.codec.encodeMessage(reply)); + } + }); + } catch (e) { + Log.e(BasicMessageChannel.TAG, "Failed to handle message", e); + callback.reply(StringUtils.stringToArrayBuffer("")); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryCodec.ets new file mode 100644 index 0000000..5784364 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryCodec.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MessageCodec from './MessageCodec'; + +/** + * A {@link MessageCodec} using unencoded binary messages, represented as {@link ByteBuffer}s. + * + *

This codec is guaranteed to be compatible with the corresponding BinaryCodec on the + * Dart side. These parts of the Flutter SDK are evolved synchronously. + * + *

On the Dart side, messages are represented using {@code ByteData}. + */ + +export default class BinaryCodec implements MessageCodec { + private returnsDirectByteBufferFromDecoding: boolean = false; + static readonly INSTANCE_DIRECT = new BinaryCodec(true); + + constructor(returnsDirectByteBufferFromDecoding: boolean) { + this.returnsDirectByteBufferFromDecoding = returnsDirectByteBufferFromDecoding; + } + + encodeMessage(message: ArrayBuffer): ArrayBuffer { + return message + } + + decodeMessage(message: ArrayBuffer): ArrayBuffer { + if (message == null) { + return message; + } else if (this.returnsDirectByteBufferFromDecoding) { + return message; + } else { + return message.slice(0, message.byteLength); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger.ets new file mode 100644 index 0000000..e0b5527 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger.ets @@ -0,0 +1,158 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** + * An abstraction over the threading policy used to invoke message handlers. + * + *

These are generated by calling methods like {@link + * BinaryMessenger#makeBackgroundTaskQueue(TaskQueueOptions)} and can be passed into platform + * channels' constructors to control the threading policy for handling platform channels' + * messages. + */ +export interface TaskQueue {} + +/** Options that control how a TaskQueue should operate and be created. */ +export class TaskQueueOptions { + private isSerial = true; + + getIsSerial() { + return this.isSerial; + } + + setIsSerial(isSerial: boolean): TaskQueueOptions { + this.isSerial = isSerial; + return this; + } +} + +/** + * Binary message reply callback. Used to submit a reply to an incoming message from Flutter. Also + * used in the dual capacity to handle a reply received from Flutter after sending a message. + */ +export interface BinaryReply { + /** + * Handles the specified reply. + * + * @param reply the reply payload, a direct-allocated {@link ByteBuffer} or null. Senders of + * outgoing replies must place the reply bytes between position zero and current position. + * Reply receivers can read from the buffer directly. + */ + reply(reply: ArrayBuffer): void; +} + +/** Handler for incoming binary messages from Flutter. */ +export interface BinaryMessageHandler { + /** + * Handles the specified message. + * + *

Handler implementations must reply to all incoming messages, by submitting a single reply + * message to the given {@link BinaryReply}. Failure to do so will result in lingering Flutter + * reply handlers. The reply may be submitted asynchronously. + * + *

Any uncaught exception thrown by this method will be caught by the messenger + * implementation and logged, and a null reply message will be sent back to Flutter. + * + * @param message the message {@link ByteBuffer} payload, possibly null. + * @param reply A {@link BinaryReply} used for submitting a reply back to Flutter. + */ + onMessage(message: ArrayBuffer, reply: BinaryReply): void; +} + +/** + * Facility for communicating with Flutter using asynchronous message passing with binary messages. + * The Flutter Dart code should use BinaryMessages to + * participate. + * + *

{@code BinaryMessenger} is expected to be utilized from a single thread throughout the + * duration of its existence. If created on the main thread, then all invocations should take place + * on the main thread. If created on a background thread, then all invocations should take place on + * that background thread. + * + * @see BasicMessageChannel , which supports message passing with Strings and semi-structured + * messages. + * @see MethodChannel , which supports communication using asynchronous method invocation. + * @see EventChannel , which supports communication using event streams. + */ +export interface BinaryMessenger { + makeBackgroundTaskQueue(options?: TaskQueueOptions): TaskQueue; + + /** + * Sends a binary message to the Flutter application. + * + * @param channel the name {@link String} of the logical channel used for the message. + * @param message the message payload, a direct-allocated {@link ByteBuffer} with the message + * bytes between position zero and current position, or null. + */ + send(channel: String, message: ArrayBuffer): void; + + /** + * Sends a binary message to the Flutter application, optionally expecting a reply. + * + *

Any uncaught exception thrown by the reply callback will be caught and logged. + * + * @param channel the name {@link String} of the logical channel used for the message. + * @param message the message payload, a direct-allocated {@link ByteBuffer} with the message + * bytes between position zero and current position, or null. + * @param callback a {@link BinaryReply} callback invoked when the Flutter application responds to + * the message, possibly null. + */ + send(channel: String, message: ArrayBuffer, callback?: BinaryReply | null): void; + + /** + * Registers a handler to be invoked when the Flutter application sends a message to its host + * platform. + * + *

Registration overwrites any previous registration for the same channel name. Use a null + * handler to deregister. + * + *

If no handler has been registered for a particular channel, any incoming message on that + * channel will be handled silently by sending a null reply. + * + * @param channel the name {@link String} of the channel. + * @param handler a {@link BinaryMessageHandler} to be invoked on incoming messages, or null. + * @param taskQueue a {@link BinaryMessenger.TaskQueue} that specifies what thread will execute + * the handler. Specifying null means execute on the platform thread. + */ + //setMessageHandler(channel: String, handler: BinaryMessageHandler) + setMessageHandler(channel: String, handler: BinaryMessageHandler, taskQueue?: TaskQueue): void; + // { + // if (taskQueue != null) { + // throw new Error("setMessageHandler called with nonnull taskQueue is not supported.") + // } + // } + + /** + * Enables the ability to queue messages received from Dart. + * + *

This is useful when there are pending channel handler registrations. For example, Dart may + * be initialized concurrently, and prior to the registration of the channel handlers. This + * implies that Dart may start sending messages while plugins are being registered. + */ + enableBufferingIncomingMessages(): void; + // { + // throw new Error("enableBufferingIncomingMessages not implemented."); + // } + + /** + * Disables the ability to queue messages received from Dart. + * + *

This can be used after all pending channel handlers have been registered. + */ + disableBufferingIncomingMessages(): void; + // { + // throw new Error("disableBufferingIncomingMessages not implemented."); + // } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel.ets new file mode 100644 index 0000000..166659a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel.ets @@ -0,0 +1,263 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + + +/** + * A named channel for communicating with the Flutter application using asynchronous event streams. + * + *

Incoming requests for event stream setup are decoded from binary on receipt, and Java + * responses and events are encoded into binary before being transmitted back to Flutter. The {@link + * MethodCodec} used must be compatible with the one used by the Flutter application. This can be + * achieved by creating an EventChannel + * counterpart of this channel on the Dart side. The Java type of stream configuration arguments, + * events, and error details is {@code Object}, but only values supported by the specified {@link + * MethodCodec} can be used. + * + *

The logical identity of the channel is given by its name. Identically named channels will + * interfere with each other's communication. + */ +import Log from '../../util/Log'; +import { BinaryMessageHandler, BinaryMessenger, BinaryReply, TaskQueue } from './BinaryMessenger'; +import MethodCodec from './MethodCodec'; +import StandardMethodCodec from './StandardMethodCodec'; + +const TAG = "EventChannel#"; + +export default class EventChannel { + private messenger: BinaryMessenger; + private name: string; + private codec: MethodCodec; + private taskQueue: TaskQueue; + + constructor(messenger: BinaryMessenger, name: string, codec?: MethodCodec, taskQueue?: TaskQueue) { + this.messenger = messenger + this.name = name + this.codec = codec ? codec : StandardMethodCodec.INSTANCE + this.taskQueue = taskQueue + } + + + /** + * Registers a stream handler on this channel. + * + *

Overrides any existing handler registration for (the name of) this channel. + * + *

If no handler has been registered, any incoming stream setup requests will be handled + * silently by providing an empty stream. + * + * @param handler a {@link StreamHandler}, or null to deregister. + */ + setStreamHandler(handler: StreamHandler): void { + // We call the 2 parameter variant specifically to avoid breaking changes in + // mock verify calls. + // See https://github.com/flutter/flutter/issues/92582. + if (this.taskQueue != null) { + this.messenger.setMessageHandler( + this.name, handler == null ? null : new IncomingStreamRequestHandler(handler, this.name, this.codec, this.messenger), this.taskQueue); + } else { + this.messenger.setMessageHandler( + this.name, handler == null ? null : new IncomingStreamRequestHandler(handler, this.name, this.codec, this.messenger)); + } + } +} + +/** + * Handler of stream setup and teardown requests. + * + *

Implementations must be prepared to accept sequences of alternating calls to {@link + * #onListen(Object, EventChannel.EventSink)} and {@link #onCancel(Object)}. Implementations + * should ideally consume no resources when the last such call is not {@code onListen}. In typical + * situations, this means that the implementation should register itself with platform-specific + * event sources {@code onListen} and deregister again {@code onCancel}. + */ +export interface StreamHandler { + /** + * Handles a request to set up an event stream. + * + *

Any uncaught exception thrown by this method will be caught by the channel implementation + * and logged. An error result message will be sent back to Flutter. + * + * @param arguments stream configuration arguments, possibly null. + * @param events an {@link EventSink} for emitting events to the Flutter receiver. + */ + onListen(args: ESObject, events: EventSink): void; + + /** + * Handles a request to tear down the most recently created event stream. + * + *

Any uncaught exception thrown by this method will be caught by the channel implementation + * and logged. An error result message will be sent back to Flutter. + * + *

The channel implementation may call this method with null arguments to separate a pair of + * two consecutive set up requests. Such request pairs may occur during Flutter hot restart. Any + * uncaught exception thrown in this situation will be logged without notifying Flutter. + * + * @param arguments stream configuration arguments, possibly null. + */ + onCancel(args: ESObject): void; +} + +/** + * Event callback. Supports dual use: Producers of events to be sent to Flutter act as clients of + * this interface for sending events. Consumers of events sent from Flutter implement this + * interface for handling received events (the latter facility has not been implemented yet). + */ +export interface EventSink { + /** + * Consumes a successful event. + * + * @param event the event, possibly null. + */ + success(event: ESObject): void; + + /** + * Consumes an error event. + * + * @param errorCode an error code String. + * @param errorMessage a human-readable error message String, possibly null. + * @param errorDetails error details, possibly null + */ + error(errorCode: string, errorMessage: string, errorDetails: ESObject): void; + + /** + * Consumes end of stream. Ensuing calls to {@link #success(Object)} or {@link #error(String, + * String, Object)}, if any, are ignored. + */ + endOfStream(): void; +} + +class IncomingStreamRequestHandler implements BinaryMessageHandler { + private handler: StreamHandler; + private activeSink = new AtomicReference(null); + private codec: MethodCodec; + private name: string; + private messenger: BinaryMessenger; + + constructor(handler: StreamHandler, name: string, codec: MethodCodec, messenger: BinaryMessenger) { + this.handler = handler; + this.codec = codec; + this.name = name; + this.messenger = messenger; + } + + onMessage(message: ArrayBuffer, reply: BinaryReply): void { + const call = this.codec.decodeMethodCall(message); + if (call.method == "listen") { + this.onListen(call.args, reply); + } else if (call.method == "cancel") { + this.onCancel(call.args, reply); + } else { + reply.reply(null); + } + } + + onListen(args: ESObject, callback: BinaryReply): void { + const eventSink = new EventSinkImplementation(this.activeSink, this.name, this.codec, this.messenger); + const oldSink = this.activeSink.getAndSet(eventSink); + if (oldSink != null) { + // Repeated calls to onListen may happen during hot restart. + // We separate them with a call to onCancel. + try { + this.handler.onCancel(null); + } catch (e) { + Log.e(TAG + this.name, "Failed to close existing event stream", e); + } + } + try { + this.handler.onListen(args, eventSink); + callback.reply(this.codec.encodeSuccessEnvelope(null)); + } catch (e) { + this.activeSink.set(null); + Log.e(TAG + this.name, "Failed to open event stream", e); + callback.reply(this.codec.encodeErrorEnvelope("error", e.getMessage(), null)); + } + } + + onCancel(args: ESObject, callback: BinaryReply): void { + const oldSink = this.activeSink.getAndSet(null); + if (oldSink != null) { + try { + this.handler.onCancel(args); + callback.reply(this.codec.encodeSuccessEnvelope(null)); + } catch (e) { + Log.e(TAG + this.name, "Failed to close event stream", e); + callback.reply(this.codec.encodeErrorEnvelope("error", e.getMessage(), null)); + } + } else { + callback.reply(this.codec.encodeErrorEnvelope("error", "No active stream to cancel", null)); + } + } +} + +class EventSinkImplementation implements EventSink { + private hasEnded = false; + private activeSink: AtomicReference; + private messenger: BinaryMessenger; + private codec: MethodCodec; + private name: string; + + constructor(activeSink: AtomicReference, name: string, codec: MethodCodec, messenger: BinaryMessenger) { + this.activeSink = activeSink; + this.codec = codec; + this.name = name; + this.messenger = messenger; + } + + success(event: ESObject): void { + if (this.hasEnded || this.activeSink.get() != this) { + return; + } + this.messenger.send(this.name, this.codec.encodeSuccessEnvelope(event)); + } + + error(errorCode: string, errorMessage: string, errorDetails: ESObject) { + if (this.hasEnded || this.activeSink.get() != this) { + return; + } + this.messenger.send( + this.name, this.codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails)); + } + + endOfStream(): void { + if (this.hasEnded || this.activeSink.get() != this) { + return; + } + this.hasEnded = true; + this.messenger.send(this.name, null); + } +} + +class AtomicReference { + private value: T; + + constructor(value: T) { + this.value = value + } + + get(): T { + return this.value; + } + + set(newValue: T): void { + this.value = newValue; + } + + getAndSet(newValue: T) { + const oldValue = this.value; + this.value = newValue; + return oldValue; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets new file mode 100644 index 0000000..204dd8e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/FlutterException.ets @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export default class FlutterException implements Error { + stack?: string; + message: string; + name: string = ""; + code: string; + details: ESObject + + constructor(code: string, message: string, details: ESObject) { + this.message = message; + this.code = code; + this.details =details; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets new file mode 100644 index 0000000..6224740 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMessageCodec.ets @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import StringUtils from '../../util/StringUtils'; + +import MessageCodec from './MessageCodec'; +import MethodCodec from './MethodCodec'; +import StringCodec from './StringCodec'; + +/** + * A {@link MethodCodec} using UTF-8 encoded JSON method calls and result envelopes. + * + *

This codec is guaranteed to be compatible with the corresponding JSONMethodCodec on + * the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + *

On the Dart side, JSON messages are handled by the JSON facilities of the dart:convert package. + */ +export default class JSONMessageCodec implements MessageCodec { + static INSTANCE = new JSONMessageCodec(); + + encodeMessage(message: ESObject): ArrayBuffer { + if (message == null) { + return StringUtils.stringToArrayBuffer(""); + } + return StringCodec.INSTANCE.encodeMessage(JSON.stringify(message)); + } + + decodeMessage(message: ArrayBuffer): ESObject { + if (message == null) { + return null; + } + try { + const jsonStr = StringCodec.INSTANCE.decodeMessage(message); + return JSON.parse(jsonStr); + } catch (e) { + throw new Error("Invalid JSON"); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets new file mode 100644 index 0000000..7b5bf1d --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/JSONMethodCodec.ets @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import Log from '../../util/Log'; + +import ToolUtils from '../../util/ToolUtils'; +import FlutterException from './FlutterException'; +import JSONMessageCodec from './JSONMessageCodec'; +import MethodCall from './MethodCall'; +import MethodCodec from './MethodCodec'; + +/** + * A {@link MethodCodec} using UTF-8 encoded JSON method calls and result envelopes. + * + *

This codec is guaranteed to be compatible with the corresponding JSONMethodCodec on + * the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + *

Values supported as methods arguments and result payloads are those supported by {@link + * JSONMessageCodec}. + */ +export default class JSONMethodCodec implements MethodCodec { + static INSTANCE = new JSONMethodCodec(); + + encodeMethodCall(methodCall: MethodCall): ArrayBuffer { + try { + const map: Record = { + "method": methodCall.method, "args": methodCall.args + } + + return JSONMessageCodec.INSTANCE.encodeMessage(map); + } catch (e) { + throw new Error("Invalid JSON"); + } + } + + decodeMethodCall(message: ArrayBuffer): MethodCall { + try { + const json: ESObject = JSONMessageCodec.INSTANCE.decodeMessage(message); + if (ToolUtils.isObj(json)) { + const method: string = json["method"]; + const args: ESObject = json["args"]; + if (typeof method == 'string') { + return new MethodCall(method, args); + } + } + throw new Error("Invalid method call: " + json); + } catch (e) { + throw new Error("Invalid JSON:" + JSON.stringify(e)); + } + } + + encodeSuccessEnvelope(result: ESObject): ArrayBuffer { + return JSONMessageCodec.INSTANCE.encodeMessage([result]); + } + + encodeErrorEnvelope(errorCode: ESObject, errorMessage: string, errorDetails: ESObject) { + return JSONMessageCodec.INSTANCE.encodeMessage([errorCode, errorMessage, errorDetails]); + } + + encodeErrorEnvelopeWithStacktrace(errorCode: string, errorMessage: string, errorDetails: ESObject, errorStacktrace: string): ArrayBuffer { + return JSONMessageCodec.INSTANCE.encodeMessage([errorCode, errorMessage, errorDetails, errorStacktrace]) + } + + decodeEnvelope(envelope: ArrayBuffer): ESObject { + try { + const json: ESObject = JSONMessageCodec.INSTANCE.decodeMessage(envelope); + if (json instanceof Array) { + if (json.length == 1) { + return json[0]; + } + if (json.length == 3) { + const code: string = json[0]; + const message: string = json[1]; + const details: ESObject = json[2]; + if (typeof code == 'string' && (message == null || typeof message == 'string')) { + throw new FlutterException(code, message, details); + } + } + } + throw new Error("Invalid envelope: " + json); + } catch (e) { + throw new Error("Invalid JSON"); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec.ets new file mode 100644 index 0000000..663d57a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec.ets @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +/** + * A message encoding/decoding mechanism. + */ +export default interface MessageCodec { + /** + * Encodes the specified message into binary. + */ + encodeMessage(message: T) : ArrayBuffer; + + /** + * Decodes the specified message from binary. + * + */ + decodeMessage(message: ArrayBuffer): T; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets new file mode 100644 index 0000000..0042c25 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall.ets @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import ToolUtils from '../../util/ToolUtils'; +/** Command object representing a method call on a {@link MethodChannel}. */ +export default class MethodCall { + /** The name of the called method. */ + method: string; + + /** + * Arguments for the call. + * + *

Consider using {@link #arguments()} for cases where a particular run-time type is expected. + * Consider using {@link #argument(String)} when that run-time type is {@link Map} or {@link + * JSONObject}. + */ + args: ESObject; + + constructor(method: string, args: ESObject) { + this.method = method + this.args = args + } + + argument(key: string): ESObject { + if (this.args == null) { + return null; + } else if (this.args instanceof Map) { + return (this.args as Map).get(key); + } else if (ToolUtils.isObj(this.args)) { + return this.args[key] + } else { + throw new Error("ClassCastException"); + } + } + + hasArgument(key: string): boolean { + if (arguments == null) { + return false; + } else if (arguments instanceof Map) { + return (this.args as Map).has(key); + } else if (ToolUtils.isObj(this.args)) { + return this.args.hasOwnProperty(key); + } else { + throw new Error("ClassCastException"); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets new file mode 100644 index 0000000..31da9ff --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel.ets @@ -0,0 +1,217 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '../../util/Log'; +import MessageChannelUtils from '../../util/MessageChannelUtils'; +import StringUtils from '../../util/StringUtils'; +import { BinaryMessageHandler, BinaryMessenger, BinaryReply, TaskQueue } from './BinaryMessenger'; +import MethodCall from './MethodCall'; +import MethodCodec from './MethodCodec'; +import StandardMethodCodec from './StandardMethodCodec'; +/** + * A named channel for communicating with the Flutter application using asynchronous method calls. + * + *

Incoming method calls are decoded from binary on receipt, and Java results are encoded into + * binary before being transmitted back to Flutter. The {@link MethodCodec} used must be compatible + * with the one used by the Flutter application. This can be achieved by creating a MethodChannel + * counterpart of this channel on the Dart side. The Java type of method call arguments and results + * is {@code Object}, but only values supported by the specified {@link MethodCodec} can be used. + * + *

The logical identity of the channel is given by its name. Identically named channels will + * interfere with each other's communication. + */ + +export default class MethodChannel { + static TAG = "MethodChannel#"; + private messenger: BinaryMessenger; + private name: string; + private codec: MethodCodec; + private taskQueue?: TaskQueue; + + constructor(messenger: BinaryMessenger, name: string, codec: MethodCodec = StandardMethodCodec.INSTANCE, taskQueue?: TaskQueue) { + this.messenger = messenger + this.name = name + this.codec = codec + this.taskQueue = taskQueue + } + + /** + * Invokes a method on this channel, optionally expecting a result. + * + *

Any uncaught exception thrown by the result callback will be caught and logged. + * + * @param method the name String of the method. + * @param arguments the arguments for the invocation, possibly null. + * @param callback a {@link Result} callback for the invocation result, or null. + */ + invokeMethod(method: string, args: ESObject, callback?: MethodResult): void { + this.messenger.send(this.name, this.codec.encodeMethodCall(new MethodCall(method, args)), callback == null ? null : new IncomingResultHandler(callback, this.codec)); + } + + /** + * Registers a method call handler on this channel. + * + *

Overrides any existing handler registration for (the name of) this channel. + * + *

If no handler has been registered, any incoming method call on this channel will be handled + * silently by sending a null reply. This results in a MissingPluginException + * on the Dart side, unless an OptionalMethodChannel + * is used. + * + * @param handler a {@link MethodCallHandler}, or null to deregister. + */ + setMethodCallHandler(handler: MethodCallHandler): void { + // We call the 2 parameter variant specifically to avoid breaking changes in + // mock verify calls. + // See https://github.com/flutter/flutter/issues/92582. + if (this.taskQueue != null) { + this.messenger.setMessageHandler( + this.name, new IncomingMethodCallHandler(handler, this.codec), this.taskQueue); + } else { + this.messenger.setMessageHandler( + this.name, new IncomingMethodCallHandler(handler, this.codec)); + } + } + + /** + * Adjusts the number of messages that will get buffered when sending messages to channels that + * aren't fully set up yet. For example, the engine isn't running yet or the channel's message + * handler isn't set up on the Dart side yet. + */ + resizeChannelBuffer(newSize: number): void { + MessageChannelUtils.resizeChannelBuffer(this.messenger, this.name, newSize); + } +} + +/** A handler of incoming method calls. */ +export interface MethodCallHandler { + /** + * Handles the specified method call received from Flutter. + * + *

Handler implementations must submit a result for all incoming calls, by making a single + * call on the given {@link Result} callback. Failure to do so will result in lingering Flutter + * result handlers. The result may be submitted asynchronously and on any thread. Calls to + * unknown or unimplemented methods should be handled using {@link Result#notImplemented()}. + * + *

Any uncaught exception thrown by this method will be caught by the channel implementation + * and logged, and an error result will be sent back to Flutter. + * + *

The handler is called on the platform thread (Android main thread) by default, or + * otherwise on the thread specified by the {@link BinaryMessenger.TaskQueue} provided to the + * associated {@link MethodChannel} when it was created. See also Threading in + * the Flutter Engine. + * + * @param call A {@link MethodCall}. + * @param result A {@link Result} used for submitting the result of the call. + */ + onMethodCall(call: MethodCall, result: MethodResult): void; +} + +/** + * Method call result callback. Supports dual use: Implementations of methods to be invoked by + * Flutter act as clients of this interface for sending results back to Flutter. Invokers of + * Flutter methods provide implementations of this interface for handling results received from + * Flutter. + * + *

All methods of this class can be invoked on any thread. + */ +export interface MethodResult { + /** + * Handles a successful result. + * + * @param result The result, possibly null. The result must be an Object type supported by the + * codec. For instance, if you are using {@link StandardMessageCodec} (default), please see + * its documentation on what types are supported. + */ + success: (result: ESObject) => void; + + /** + * Handles an error result. + * + * @param errorCode An error code String. + * @param errorMessage A human-readable error message String, possibly null. + * @param errorDetails Error details, possibly null. The details must be an Object type + * supported by the codec. For instance, if you are using {@link StandardMessageCodec} + * (default), please see its documentation on what types are supported. + */ + error: (errorCode: string, errorMessage: string, errorDetails: ESObject) => void; + + /** Handles a call to an unimplemented method. */ + notImplemented: () => void; +} + +class IncomingResultHandler implements BinaryReply { + private callback: MethodResult; + private codec: MethodCodec; + + constructor(callback: MethodResult, codec: MethodCodec) { + this.callback = callback; + this.codec = codec + } + + reply(reply: ArrayBuffer): void { + try { + if (reply == null) { + this.callback.notImplemented(); + } else { + try { + this.callback.success(this.codec.decodeEnvelope(reply)); + } catch (e) { + this.callback.error(e.code, e.getMessage(), e.details); + } + } + } catch (e) { + Log.e(MethodChannel.TAG, "Failed to handle method call result", e); + } + } +} + +class IncomingMethodCallHandler implements BinaryMessageHandler { + private handler: MethodCallHandler; + private codec: MethodCodec; + + constructor(handler: MethodCallHandler, codec: MethodCodec) { + this.handler = handler; + this.codec = codec + } + + onMessage(message: ArrayBuffer, reply: BinaryReply): void { + const call = this.codec.decodeMethodCall(message); + try { + this.handler.onMethodCall( + call, { + success: (result: ESObject): void => { + reply.reply(this.codec.encodeSuccessEnvelope(result)); + }, + + error: (errorCode: string, errorMessage: string, errorDetails: ESObject): void => { + reply.reply(this.codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails)); + }, + + notImplemented: (): void => { + Log.w(MethodChannel.TAG,"method not implemented"); + reply.reply(StringUtils.stringToArrayBuffer("")); + } + }); + } catch (e) { + Log.e(MethodChannel.TAG, "Failed to handle method call", e); + reply.reply(this.codec.encodeErrorEnvelopeWithStacktrace("error", e.getMessage(), null, e)); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets new file mode 100644 index 0000000..86ed92a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCodec.ets @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MethodCall from './MethodCall'; +/** + * A codec for method calls and enveloped results. + * + *

Method calls are encoded as binary messages with enough structure that the codec can extract a + * method name String and an arguments Object. These data items are used to populate a {@link + * MethodCall}. + * + *

All operations throw {@link IllegalArgumentException}, if conversion fails. + */ +export default interface MethodCodec { + /** + * Encodes a message call into binary. + * + * @param methodCall a {@link MethodCall}. + * @return a {@link ByteBuffer} containing the encoding between position 0 and the current + * position. + */ + encodeMethodCall(methodCall: MethodCall): ArrayBuffer; + + /** + * Decodes a message call from binary. + * + * @param methodCall the binary encoding of the method call as a {@link ByteBuffer}. + * @return a {@link MethodCall} representation of the bytes between the given buffer's current + * position and its limit. + */ + decodeMethodCall(methodCall: ArrayBuffer): MethodCall; + + /** + * Encodes a successful result into a binary envelope message. + * + * @param result The result value, possibly null. + * @return a {@link ByteBuffer} containing the encoding between position 0 and the current + * position. + */ + encodeSuccessEnvelope(result: ESObject): ArrayBuffer; + + /** + * Encodes an error result into a binary envelope message. + * + * @param errorCode An error code String. + * @param errorMessage An error message String, possibly null. + * @param errorDetails Error details, possibly null. Consider supporting {@link Throwable} in your + * codec. This is the most common value passed to this field. + * @return a {@link ByteBuffer} containing the encoding between position 0 and the current + * position. + */ + encodeErrorEnvelope(errorCode: string, errorMessage: string, errorDetails: ESObject): ArrayBuffer; + + /** + * Encodes an error result into a binary envelope message with the native stacktrace. + * + * @param errorCode An error code String. + * @param errorMessage An error message String, possibly null. + * @param errorDetails Error details, possibly null. Consider supporting {@link Throwable} in your + * codec. This is the most common value passed to this field. + * @param errorStacktrace Platform stacktrace for the error. possibly null. + * @return a {@link ByteBuffer} containing the encoding between position 0 and the current + * position. + */ + encodeErrorEnvelopeWithStacktrace(errorCode: string, errorMessage: string, errorDetails: ESObject, errorStacktrace: string): ArrayBuffer + + /** + * Decodes a result envelope from binary. + * + * @param envelope the binary encoding of a result envelope as a {@link ByteBuffer}. + * @return the enveloped result Object. + * @throws FlutterException if the envelope was an error envelope. + */ + decodeEnvelope(envelope: ArrayBuffer): ESObject +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/PluginRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/PluginRegistry.ets new file mode 100644 index 0000000..cb92c8e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/PluginRegistry.ets @@ -0,0 +1,14 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets new file mode 100644 index 0000000..d9b52ff --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec.ets @@ -0,0 +1,331 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { ByteBuffer } from '../../util/ByteBuffer'; +import StringUtils from '../../util/StringUtils'; +import MessageCodec from './MessageCodec'; + +/** + * MessageCodec using the Flutter standard binary encoding. + * + *

This codec is guaranteed to be compatible with the corresponding StandardMessageCodec + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + *

Supported messages are acyclic values of these forms: + * + *

    + *
  • null + *
  • Booleans + *
  • number + *
  • BigIntegers (see below) + *
  • Int8Array, Int32Array, Float32Array, Float64Array + *
  • Strings + *
  • Array[] + *
  • Lists of supported values + *
  • Maps with supported keys and values + *
+ * + *

On the Dart side, these values are represented as follows: + * + *

    + *
  • null: null + *
  • Boolean: bool + *
  • Byte, Short, Integer, Long: int + *
  • Float, Double: double + *
  • String: String + *
  • byte[]: Uint8List + *
  • int[]: Int32List + *
  • long[]: Int64List + *
  • float[]: Float32List + *
  • double[]: Float64List + *
  • List: List + *
  • Map: Map + *
+ * + *

BigIntegers are represented in Dart as strings with the hexadecimal representation of the + * integer's value. + * + *

To extend the codec, overwrite the writeValue and readValueOfType methods. + */ +export default class StandardMessageCodec implements MessageCodec { + private static TAG = "StandardMessageCodec#"; + static INSTANCE = new StandardMessageCodec(); + + encodeMessage(message: ESObject): ArrayBuffer { + const stream = ByteBuffer.from(new ArrayBuffer(1024)) + this.writeValue(stream, message); + return stream.buffer + } + + decodeMessage(message: ArrayBuffer): ESObject { + if (message == null) { + return null + } + const buffer = ByteBuffer.from(message) + return this.readValue(buffer) + } + + private static NULL = 0; + private static TRUE = 1; + private static FALSE = 2; + private static INT32 = 3; + private static INT64 = 4; + private static BIGINT = 5; + private static FLOAT64 = 6; + private static STRING = 7; + private static UINT8_ARRAY = 8; + private static INT32_ARRAY = 9; + private static INT64_ARRAY = 10; + private static FLOAT64_ARRAY = 11; + private static LIST = 12; + private static MAP = 13; + private static FLOAT32_ARRAY = 14; + + + writeValue(stream: ByteBuffer, value: ESObject): ESObject { + if (value == null || value == undefined) { + stream.writeInt8(StandardMessageCodec.NULL) + } else if (typeof value === "boolean") { + stream.writeInt8(value ? StandardMessageCodec.TRUE : StandardMessageCodec.FALSE) + } else if (typeof value === "number") { + if (Number.isInteger(value)) { //整型 + if (-0x7fffffff - 1 <= value && value <= 0x7fffffff) { //int32 + stream.writeInt8(StandardMessageCodec.INT32) + stream.writeInt32(value, true) + } else if(Number.MIN_SAFE_INTEGER <= value && value <= Number.MAX_SAFE_INTEGER) { //int64 number整型取值范围 + stream.writeInt8(StandardMessageCodec.INT64) + stream.writeBigInt64(BigInt(value), true) + } else { //被判为整型的double型 + stream.writeInt8(StandardMessageCodec.FLOAT64) + this.writeAlignment(stream, 8); + stream.writeFloat64(value, true) + } + } else { //浮点型 + stream.writeInt8(StandardMessageCodec.FLOAT64) + this.writeAlignment(stream, 8); + stream.writeFloat64(value, true) + } + }else if (typeof value === "bigint") { + stream.writeInt8(StandardMessageCodec.INT64) + stream.writeBigInt64(value, true) + } else if (typeof value === "string") { + stream.writeInt8(StandardMessageCodec.STRING) + let stringBuff = StringUtils.stringToArrayBuffer(value) + this.writeBytes(stream, new Uint8Array(stringBuff)) + } else if (value instanceof Uint8Array) { + stream.writeInt8(StandardMessageCodec.UINT8_ARRAY) + this.writeBytes(stream, value) + } else if (value instanceof Int32Array) { + stream.writeInt8(StandardMessageCodec.INT32_ARRAY) + this.writeSize(stream, value.length); + this.writeAlignment(stream, 4); + value.forEach(item => stream.writeInt32(item, true)) + } else if(value instanceof BigInt64Array) { + stream.writeInt8(StandardMessageCodec.INT64_ARRAY) + this.writeSize(stream, value.length); + this.writeAlignment(stream, 8); + value.forEach(item => stream.writeBigInt64(item, true)) + } else if (value instanceof Float32Array) { + stream.writeInt8(StandardMessageCodec.FLOAT32_ARRAY) + this.writeSize(stream, value.length); + this.writeAlignment(stream, 4); + value.forEach(item => stream.writeFloat32(item, true)) + } else if (value instanceof Float64Array) { + stream.writeInt8(StandardMessageCodec.FLOAT64_ARRAY) + this.writeSize(stream, value.length); + this.writeAlignment(stream, 8); + value.forEach(item => stream.writeFloat64(item, true)) + } else if (value instanceof Array || value instanceof Int8Array || value instanceof Int16Array + || value instanceof Uint16Array || value instanceof Uint32Array) { + stream.writeInt8(StandardMessageCodec.LIST) + this.writeSize(stream, value.length); + value.forEach((item: ESObject): void => this.writeValue(stream, item)) + } else if (value instanceof Map) { + stream.writeInt8(StandardMessageCodec.MAP) + this.writeSize(stream, value.size); + value.forEach((value: ESObject, key: ESObject) => { + this.writeValue(stream, key); + this.writeValue(stream, value); + }) + } else if (typeof value == 'object') { + let map: Map = new Map(); + Object.keys(value).forEach(key => { + map.set(key, value[key]); + }); + this.writeValue(stream, map); + } else { + throw new Error("Unsupported value: " + value); + stream.writeInt8(StandardMessageCodec.NULL); + } + return stream + } + + writeAlignment(stream: ByteBuffer, alignment: number) { + let mod: number = stream.byteOffset % alignment; + if (mod != 0) { + for (let i = 0; i < alignment - mod; i++) { + stream.writeInt8(0); + } + } + } + + writeSize(stream: ByteBuffer, value: number) { + if (value < 254) { + stream.writeInt8(value); + } else if (value <= 0xffff) { + stream.writeInt8(254); + stream.writeInt16(value, true); + } else { + stream.writeInt8(255); + stream.writeInt32(value, true); + } + } + + writeBytes(stream: ByteBuffer, bytes: Uint8Array) { + this.writeSize(stream, bytes.length) + stream.writeUint8Array(bytes); + } + + readSize(buffer: ByteBuffer) { + let value = buffer.readInt8() & 0xff; + if (value < 254) { + return value; + } else if (value == 254) { + return buffer.readInt16(true); + } else { + return buffer.readInt32(true); + } + } + + readAlignment(buffer: ByteBuffer, alignment: number) { + let mod = buffer.byteOffset % alignment; + if (mod != 0) { + buffer.skip(alignment - mod); + } + } + + readValue(buffer: ByteBuffer): ESObject { + let type = buffer.readInt8() + return this.readValueOfType(type, buffer); + } + + readBytes(buffer: ByteBuffer): Uint8Array { + let length = this.readSize(buffer); + let bytes = new Uint8Array(length) + for (let i = 0; i < length; i++) { + bytes[i] = buffer.readUint8() + } + return bytes; + } + + readValueOfType(type: number, buffer: ByteBuffer): ESObject { + let result: ESObject; + switch (type) { + case StandardMessageCodec.NULL: + result = null; + break; + case StandardMessageCodec.TRUE: + result = true; + break; + case StandardMessageCodec.FALSE: + result = false; + break; + case StandardMessageCodec.INT32: + result = buffer.readInt32(true); + break; + case StandardMessageCodec.INT64: + result = buffer.readInt64(true); + break; + case StandardMessageCodec.BIGINT: + result = buffer.readBigInt64(true) + break; + case StandardMessageCodec.FLOAT64: + this.readAlignment(buffer, 8); + result = buffer.readFloat64(true) + break; + case StandardMessageCodec.STRING: { + let bytes = this.readBytes(buffer); + result = StringUtils.arrayBufferToString(bytes.buffer); + break; + } + case StandardMessageCodec.UINT8_ARRAY: { + result = this.readBytes(buffer); + break; + } + case StandardMessageCodec.INT32_ARRAY: { + let length = this.readSize(buffer); + let array = new Int32Array(length) + this.readAlignment(buffer, 4); + for (let i = 0; i < length; i++) { + array[i] = buffer.readInt32(true) + } + result = array; + break; + } + case StandardMessageCodec.INT64_ARRAY: { + let length = this.readSize(buffer); + let array = new BigInt64Array(length) + this.readAlignment(buffer, 8); + for (let i = 0; i < length; i++) { + array[i] = buffer.readBigInt64(true) + } + result = array; + break; + } + case StandardMessageCodec.FLOAT64_ARRAY: { + let length = this.readSize(buffer); + let array = new Float64Array(length) + this.readAlignment(buffer, 8); + for (let i = 0; i < length; i++) { + array[i] = buffer.readFloat64(true) + } + result = array; + break; + } + case StandardMessageCodec.LIST: { + let length = this.readSize(buffer); + let array: Array = new Array(length) + for (let i = 0; i < length; i++) { + array[i] = this.readValue(buffer) + } + result = array; + break; + } + case StandardMessageCodec.MAP: { + let size = this.readSize(buffer); + let map: Map = new Map() + for (let i = 0; i < size; i++) { + map.set(this.readValue(buffer), this.readValue(buffer)); + } + result = map; + break; + } + case StandardMessageCodec.FLOAT32_ARRAY: { + let length = this.readSize(buffer); + let array = new Float32Array(length); + this.readAlignment(buffer, 4); + for (let i = 0; i < length; i++) { + array[i] = buffer.readFloat32(true) + } + result = array; + break; + } + default: + throw new Error("Message corrupted"); + } + return result; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets new file mode 100644 index 0000000..d4417c5 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec.ets @@ -0,0 +1,116 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { ByteBuffer } from '../../util/ByteBuffer'; +import FlutterException from './FlutterException'; +import MethodCall from './MethodCall'; +import MethodCodec from './MethodCodec'; +import StandardMessageCodec from './StandardMessageCodec'; + +/** + * A {@link MethodCodec} using the Flutter standard binary encoding. + * + *

This codec is guaranteed to be compatible with the corresponding StandardMethodCodec + * on the Dart side. These parts of the Flutter SDK are evolved synchronously. + * + *

Values supported as method arguments and result payloads are those supported by {@link + * StandardMessageCodec}. + */ +export default class StandardMethodCodec implements MethodCodec { + private static TAG = "StandardMethodCodec"; + public static INSTANCE = new StandardMethodCodec(StandardMessageCodec.INSTANCE); + + private messageCodec: StandardMessageCodec; + + /** Creates a new method codec based on the specified message codec. */ + constructor(messageCodec: StandardMessageCodec) { + this.messageCodec = messageCodec; + } + + encodeMethodCall(methodCall: MethodCall): ArrayBuffer { + const stream = ByteBuffer.from(new ArrayBuffer(1024)); + this.messageCodec.writeValue(stream, methodCall.method); + this.messageCodec.writeValue(stream, methodCall.args); + return stream.buffer; + } + + decodeMethodCall(methodCall: ArrayBuffer): MethodCall { + const buffer = ByteBuffer.from(methodCall); + const method: ESObject = this.messageCodec.readValue(buffer); + const args: ESObject = this.messageCodec.readValue(buffer); + if (typeof method == 'string' && !buffer.hasRemaining()) { + return new MethodCall(method, args); + } + throw new Error("Method call corrupted"); + } + + encodeSuccessEnvelope(result: ESObject): ArrayBuffer { + const stream = ByteBuffer.from(new ArrayBuffer(1024)); + stream.writeInt8(0); + this.messageCodec.writeValue(stream, result); + return stream.buffer; + } + + encodeErrorEnvelope(errorCode: string, errorMessage: string, errorDetails: ESObject): ArrayBuffer { + const stream = ByteBuffer.from(new ArrayBuffer(1024)); + stream.writeInt8(1); + this.messageCodec.writeValue(stream, errorCode); + this.messageCodec.writeValue(stream, errorMessage); + if (errorDetails instanceof Error) { + this.messageCodec.writeValue(stream, errorDetails.stack); + } else { + this.messageCodec.writeValue(stream, errorDetails); + } + return stream.buffer; + } + + encodeErrorEnvelopeWithStacktrace(errorCode: string, errorMessage: string, errorDetails: ESObject, errorStacktrace: string): ArrayBuffer { + const stream = ByteBuffer.from(new ArrayBuffer(1024)); + stream.writeInt8(1); + this.messageCodec.writeValue(stream, errorCode); + this.messageCodec.writeValue(stream, errorMessage); + if (errorDetails instanceof Error) { + this.messageCodec.writeValue(stream, errorDetails.stack); + } else { + this.messageCodec.writeValue(stream, errorDetails); + } + this.messageCodec.writeValue(stream, errorStacktrace); + return stream.buffer; + } + + decodeEnvelope(envelope: ArrayBuffer): ESObject { + const buffer = ByteBuffer.from(envelope); + const flag = buffer.readInt8(); + switch (flag) { + case 0: { + const result: ESObject = this.messageCodec.readValue(buffer); + if (!buffer.hasRemaining()) { + return result; + } + // Falls through intentionally. + } + case 1: { + const code: ESObject = this.messageCodec.readValue(buffer); + const message: ESObject = this.messageCodec.readValue(buffer); + const details: ESObject = this.messageCodec.readValue(buffer); + if (typeof code == 'string' && (message == null || typeof message == 'string') && !buffer.hasRemaining()) { + throw new FlutterException(code, message, details); + } + } + } + throw new Error("Envelope corrupted"); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StringCodec.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StringCodec.ets new file mode 100644 index 0000000..b824ac1 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/common/StringCodec.ets @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import StringUtils from '../../util/StringUtils'; +import MessageCodec from './MessageCodec'; + +/** + * A {@link MessageCodec} using UTF-8 encoded String messages. + * + *

This codec is guaranteed to be compatible with the corresponding StringCodec on the + * Dart side. These parts of the Flutter SDK are evolved synchronously. + */ +export default class StringCodec implements MessageCodec { + static readonly INSTANCE = new StringCodec(); + + encodeMessage(message: string): ArrayBuffer { + if (message == null) { + return StringUtils.stringToArrayBuffer(""); + } + return StringUtils.stringToArrayBuffer(message); + } + + decodeMessage(message: ArrayBuffer): string { + if (message == null) { + return ""; + } + return StringUtils.arrayBufferToString(message); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/ListenableEditingState.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/ListenableEditingState.ets new file mode 100644 index 0000000..1ea2049 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/ListenableEditingState.ets @@ -0,0 +1,263 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { TextEditState } from '../../embedding/engine/systemchannels/TextInputChannel'; +import Log from '../../util/Log'; +import inputMethod from '@ohos.inputMethod'; +import ArrayList from '@ohos.util.ArrayList'; +import { TextEditingDelta } from './TextEditingDelta'; + +const TAG = "ListenableEditingState"; +export class ListenableEditingState { + //Cache used to storage software keyboard input action + private mStringCache: string; + private mSelectionStartCache: number = 0; + private mSelectionEndCache: number = 0; + private mComposingStartCache: number = 0; + private mComposingEndCache: number = 0; + //used to compare with Cache + + private mListeners: ArrayList = new ArrayList(); + private mPendingListeners: ArrayList = new ArrayList(); + private mBatchTextEditingDeltas: ArrayList = new ArrayList(); + private mChangeNotificationDepth: number = 0; + private mBatchEditNestDepth: number = 0; + + private mTextWhenBeginBatchEdit: string; + private mSelectionStartWhenBeginBatchEdit: number = 0; + private mSelectionEndWhenBeginBatchEdit: number = 0; + private mComposingStartWhenBeginBatchEdit: number = 0; + private mComposingEndWhenBeginBatchEdit: number = 0; + + + constructor() { + this.mStringCache = ""; + this.mTextWhenBeginBatchEdit = ""; + this.mSelectionStartCache = 0; + this.mSelectionEndCache = 0; + this.mComposingStartCache = -1; + this.mComposingEndCache = -1; + } + + + getSelectionStart(): number { + return this.mSelectionStartCache; + } + + getSelectionEnd(): number { + return this.mSelectionEndCache; + } + + getComposingStart(): number { + return this.mComposingStartCache; + } + + getComposingEnd(): number { + return this.mComposingEndCache; + } + + getStringCache(): string { + return this.mStringCache; + } + + setSelectionStart(newSelectionStart: number): void { + this.mSelectionStartCache = newSelectionStart; + } + + setSelectionEnd(newSelectionEnd: number): void { + this.mSelectionEndCache = newSelectionEnd; + } + + setComposingStart(newComposingStart: number): void { + this.mComposingStartCache = newComposingStart; + } + + setComposingEnd(newComposingEnd: number): void { + this.mComposingEndCache = newComposingEnd; + } + + setStringCache(newStringCache: string): void { + this.mStringCache = newStringCache; + } + + notifyListener(listener: EditingStateWatcher, + textChanged: boolean, + selectionChanged: boolean, + composingChanged: boolean): void { + this.mChangeNotificationDepth++; + listener.didChangeEditingState(textChanged, selectionChanged, composingChanged); + this.mChangeNotificationDepth--; + } + + notifyListenersIfNeeded(textChanged: boolean, selectionChanged: boolean, composingChanged: boolean) { + if (textChanged || selectionChanged || composingChanged) { + for(const listener of this.mListeners) { + this.notifyListener(listener, textChanged, selectionChanged, composingChanged); + } + + } + } + + handleInsertTextEvent(text: string): void { + if(this.mStringCache.length == this.mSelectionStartCache) { + //Insert text one by one + this.mStringCache += text; + this.setSelectionStart(this.mStringCache.length); + this.setSelectionEnd(this.mStringCache.length); + + } else if(this.mStringCache.length > this.mSelectionStartCache) { + //Insert text in the middle of string + let tempStr: string = this.mStringCache.substring(0, this.mSelectionStartCache) + text + this.mStringCache.substring(this.mSelectionStartCache); + this.mStringCache = tempStr; + this.mSelectionStartCache += text.length; + this.mSelectionEndCache = this.mSelectionStartCache; + } + if(this.mListeners == null) { + Log.e(TAG, "mListeners is null"); + return; + } + this.notifyListenersIfNeeded(true, true, false); + } + + updateTextInputState(state: TextEditState): void { + this.beginBatchEdit(); + this.setStringCache(state.text); + if(state.hasSelection()) { + this.setSelectionStart(state.selectionStart); + this.setSelectionEnd(state.selectionEnd); + } else { + this.setSelectionStart(0); + this.setSelectionEnd(0); + } + this.endBatchEdit(); + } + + beginBatchEdit(): void { + this.mBatchEditNestDepth++; + if(this.mChangeNotificationDepth > 0) { + Log.e(TAG, "editing state should not be changed in a listener callback"); + } + if(this.mBatchEditNestDepth == 1 && !this.mListeners.isEmpty()) { + this.mTextWhenBeginBatchEdit = this.getStringCache(); + this.mSelectionStartWhenBeginBatchEdit = this.getSelectionStart(); + this.mSelectionEndWhenBeginBatchEdit = this.getSelectionEnd(); + this.mComposingStartWhenBeginBatchEdit = this.getComposingStart(); + this.mComposingEndWhenBeginBatchEdit = this.getComposingEnd(); + } + } + + endBatchEdit(): void { + if (this.mBatchEditNestDepth == 0) { + Log.e(TAG, "endBatchEdit called without a matching beginBatchEdit"); + return; + } + if(this.mBatchEditNestDepth == 1) { + Log.d(TAG,"mBatchEditNestDepth == 1"); + for(const listener of this.mPendingListeners) { + this.notifyListener(listener, true, true, true); + } + + if(!this.mListeners.isEmpty()) { + Log.d(TAG, "didFinishBatchEdit with " + this.mListeners.length + " listener(s)"); + const textChanged = !(this.mStringCache == this.mTextWhenBeginBatchEdit); + const selectionChanged = this.mSelectionStartWhenBeginBatchEdit != this.getSelectionStart() + || this.mSelectionEndWhenBeginBatchEdit != this.getSelectionEnd(); + const composingRegionChanged = this.mComposingStartWhenBeginBatchEdit != this.getComposingStart() + || this.mComposingEndWhenBeginBatchEdit != this.getComposingEnd(); + Log.d(TAG,"textChanged: " + textChanged + " selectionChanged: " + selectionChanged + + " composingRegionChanged: " + composingRegionChanged); + this.notifyListenersIfNeeded(textChanged, selectionChanged, composingRegionChanged); + } + } + for(const listener of this.mPendingListeners) { + this.mListeners.add(listener); + } + this.mPendingListeners.clear(); + this.mBatchEditNestDepth--; + + } + + addEditingStateListener(listener: EditingStateWatcher): void { + if(this.mChangeNotificationDepth > 0) { + Log.e(TAG, "adding a listener " + JSON.stringify(listener) + " in a listener callback"); + } + if(this.mBatchEditNestDepth > 0) { + Log.d(TAG, "a listener was added to EditingState while a batch edit was in progress"); + this.mPendingListeners.add(listener); + } else { + this.mListeners.add(listener); + } + } + + removeEditingStateListener(listener: EditingStateWatcher): void { + if(this.mChangeNotificationDepth > 0) { + Log.e(TAG, "removing a listener " + JSON.stringify(listener) + " in a listener callback"); + } + this.mListeners.remove(listener); + if(this.mBatchEditNestDepth > 0) { + this.mPendingListeners.remove(listener); + } + } + + handleDeleteEvent(leftOrRight: boolean, length: number): void { + if(leftOrRight == false) { + //delete left + if(this.mSelectionStartCache == 0) { + return; + } + this.mSelectionStartCache -= length; + let tempStr: string = this.mStringCache.slice(0, this.mSelectionStartCache) + this.mStringCache.slice(this.mSelectionStartCache + length); + this.mStringCache = tempStr; + this.mSelectionEndCache = this.mSelectionStartCache; + } else if(leftOrRight == true) { + //delete right + if(this.mSelectionStartCache == this.mStringCache.length) { + return; + } + this.mSelectionEndCache += length; + let tempStr: string = this.mStringCache.slice(0,this.mSelectionStartCache) + this.mStringCache.slice(this.mSelectionEndCache); + this.mStringCache = tempStr; + this.mSelectionStartCache = this.mSelectionEndCache; + } + this.notifyListenersIfNeeded(true, true, false); + } + + handleFunctionKey(functionKey: inputMethod.FunctionKey): void { + switch (functionKey.enterKeyType) { + case inputMethod.EnterKeyType.PREVIOUS: + case inputMethod.EnterKeyType.UNSPECIFIED: + case inputMethod.EnterKeyType.NONE: + case inputMethod.EnterKeyType.GO: + case inputMethod.EnterKeyType.SEARCH: + case inputMethod.EnterKeyType.SEND: + case inputMethod.EnterKeyType.NEXT: + case inputMethod.EnterKeyType.DONE: + + } + } + + handleSelectByRange(range: inputMethod.Range): void { + Log.d(TAG, "handleSelectByRange start: " + range.start +" end: " + range.end); + } + + + +} + +export interface EditingStateWatcher { + // Changing the editing state in a didChangeEditingState callback may cause unexpected + // behavior. + didChangeEditingState(textChanged: boolean, selectionChanged: boolean, composingRegionChanged: boolean); +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextEditingDelta.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextEditingDelta.ets new file mode 100644 index 0000000..1aa1b2d --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextEditingDelta.ets @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '../../util/Log'; + +export class TextEditingDelta { + private static TAG = "TextEditingDelta"; + private oldText: string = ""; + private deltaText: string = ""; + private deltaStart: number = 0; + private deltaEnd: number = 0; + private newSelectionStart: number; + private newSelectionEnd: number; + private newComposingStart: number; + private newComposingEnd: number; + + constructor(oldEditable: string, + selectionStart: number, + selectionEnd: number, + composingStart: number, + composingEnd: number, + replacementDestinationStart?: number, + replacementDestinationEnd?: number, + replacementSource?: string,) { + this.newSelectionStart = selectionStart; + this.newSelectionEnd = selectionEnd; + this.newComposingStart = composingStart; + this.newComposingEnd = composingEnd; + if(replacementDestinationStart === undefined || + replacementDestinationEnd === undefined || + replacementSource === undefined) { + this.setDeltas(oldEditable, "", -1, -1); + } else { + this.setDeltas( + oldEditable, + replacementSource, + replacementDestinationStart, + replacementDestinationEnd); + } + + } + + setDeltas(oldText: string, newText: string, newStart: number, newExtent: number): void { + this.oldText = oldText; + this.deltaText = newText; + this.deltaStart = newStart; + this.deltaEnd = newExtent; + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets new file mode 100644 index 0000000..16aa44a --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/editing/TextInputPlugin.ets @@ -0,0 +1,264 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import TextInputChannel, { Configuration, TextEditState, + TextInputMethodHandler, + TextInputType } from '../../embedding/engine/systemchannels/TextInputChannel'; +import inputMethod from '@ohos.inputMethod'; +import Log from '../../util/Log'; +import { EditingStateWatcher, ListenableEditingState } from './ListenableEditingState'; + +export default class TextInputPlugin implements EditingStateWatcher{ + private static TAG = "TextInputPlugin"; + private textInputChannel: TextInputChannel; + private mTextInputHandler: TextInputMethodHandlerImpl; + + constructor(textInputChannel: TextInputChannel) { + this.textInputChannel = textInputChannel; + this.mTextInputHandler = new TextInputMethodHandlerImpl(this); + this.textInputChannel.setTextInputMethodHandler(this.mTextInputHandler); + } + + public clearTextInputClient() { + this.textInputChannel.textInputMethodHandler?.clearClient(); + } + + setTextInputEditingState(state: TextEditState) { + + } + + didChangeEditingState(textChanged: boolean, selectionChanged: boolean, composingRegionChanged: boolean): void { + let editable = this.mTextInputHandler.mEditable; + let inputTarget = this.mTextInputHandler.inputTarget; + this.textInputChannel.updateEditingState(inputTarget.id, editable.getStringCache(), + editable.getSelectionStart(), editable.getSelectionEnd(), + editable.getComposingStart(), editable.getComposingEnd()) + } + + detach(): void { + this.mTextInputHandler.inputMethodController.detach((err) => { + if(err) { + Log.e(TextInputPlugin.TAG, "Failed to detach: " + JSON.stringify(err)); + } + }) + } + +} + +class TextInputMethodHandlerImpl implements TextInputMethodHandler { + private static TAG = "TextInputMethodHandlerImpl"; + private textConfig: inputMethod.TextConfig; + inputMethodController: inputMethod.InputMethodController; + inputTarget: InputTarget; + private configuration: Configuration | null = null; + mEditable: ListenableEditingState; + private mRestartInputPending: boolean = false; + private plugin: EditingStateWatcher; + + private imcFlag: boolean = false; + + constructor(plugin: TextInputPlugin) { + this.textConfig = { + inputAttribute: { + textInputType: 0, + enterKeyType: 1 + }}; + this.plugin = plugin; + this.mEditable = new ListenableEditingState(); + this.inputMethodController = inputMethod.getController(); + this.inputTarget = new InputTarget(Type.NO_TARGET, 0); + } + + show(): void { + this.showTextInput(); + } + + hide(): void { + this.hideTextInput(); + } + + requestAutofill(): void { + + } + + finishAutofillContext(shouldSave: boolean): void { + + } + + setClient(textInputClientId: number, configuration: Configuration | null): void { + Log.d(TextInputMethodHandlerImpl.TAG,"textInputClientId: " + textInputClientId); + this.setTextInputClient(textInputClientId, configuration); + } + + setPlatformViewClient(id: number, usesVirtualDisplay: boolean): void { + + } + + setEditableSizeAndTransform(width: number, height: number, transform: number[]): void { + + } + + setEditingState(editingState: TextEditState): void { + Log.d(TextInputMethodHandlerImpl.TAG, "text:" + editingState.text +" selectionStart:" + editingState.selectionStart + " selectionEnd:" + + editingState.selectionEnd + " composingStart:" + editingState.composingStart + " composingEnd" + editingState.composingEnd); + this.mEditable.updateTextInputState(editingState); + } + + clearClient(): void { + this.clearTextInputClient(); + } + + private async showTextInput(): Promise { + await this.attach(true); + if(this.imcFlag != true) { + this.listenKeyBoardEvent(); + } + this.inputMethodController.showTextInput().then(()=> { + Log.d(TextInputMethodHandlerImpl.TAG, "Succeeded in showing softKeyboard"); + }).catch((err: ESObject) => { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to show softKeyboard:" + JSON.stringify(err)); + }); + } + + private async hideTextInput(): Promise { + this.inputMethodController.hideTextInput().then(() => { + Log.d(TextInputMethodHandlerImpl.TAG, "Succeeded in hide softKeyboard"); + }).catch((err: ESObject) => { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to hide softKeyboard:" + JSON.stringify(err)); + }) + } + + async attach(showKeyboard: boolean): Promise { + try { + await this.inputMethodController.attach(showKeyboard, this.textConfig); + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to attach:" + JSON.stringify(err)); + } + } + + setTextInputClient(client: number, configuration: Configuration | null): void { + this.configuration = configuration; + if(this.canShowTextInput()) { + this.inputTarget = new InputTarget(Type.FRAMEWORK_CLIENT, client); + } else { + this.inputTarget = new InputTarget(Type.NO_TARGET, client); + } + this.mEditable.removeEditingStateListener(this.plugin); + this.mEditable = new ListenableEditingState(); + + this.mRestartInputPending = true; + this.mEditable.addEditingStateListener(this.plugin); + } + + canShowTextInput(): boolean { + if(this.configuration == null || this.configuration.inputType == null) { + return true; + } + return this.configuration.inputType.type != TextInputType.NONE; + } + + listenKeyBoardEvent(): void { + try { + this.inputMethodController.on('insertText', (text) => { + Log.d(TextInputMethodHandlerImpl.TAG, "insertText: " + text); + this.mEditable.handleInsertTextEvent(text); + }); + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to subscribe insertText:" + JSON.stringify(err)); + this.cancelListenKeyBoardEvent(); + return; + } + + try { + this.inputMethodController.on('deleteLeft', (length) => { + this.mEditable.handleDeleteEvent(false, length); + }) + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to subscribe deleteLeft:" + JSON.stringify(err)); + this.cancelListenKeyBoardEvent(); + return; + } + + try { + this.inputMethodController.on('deleteRight', (length) => { + this.mEditable.handleDeleteEvent(true, length); + }) + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to subscribe deleteRight:" + JSON.stringify(err)); + this.cancelListenKeyBoardEvent(); + return; + } + + try { + this.inputMethodController.on('sendFunctionKey', (functionKey) => { + this.mEditable.handleFunctionKey(functionKey); + }) + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to subscribe sendFunctionKey:" + JSON.stringify(err)); + this.cancelListenKeyBoardEvent(); + return; + } + + try { + this.inputMethodController.on('selectByRange', (range: inputMethod.Range) => { + this.mEditable.handleSelectByRange(range); + }) + } catch (err) { + Log.e(TextInputMethodHandlerImpl.TAG, "Failed to subscribe selectByRange:" + JSON.stringify(err)); + this.cancelListenKeyBoardEvent(); + return; + } + Log.d(TextInputMethodHandlerImpl.TAG, "listenKeyBoardEvent success"); + this.imcFlag = true; + } + + cancelListenKeyBoardEvent(): void { + this.inputMethodController.off('insertText'); + this.inputMethodController.off('deleteLeft'); + this.inputMethodController.off('deleteRight'); + this.inputMethodController.off('sendFunctionKey'); + this.inputMethodController.off('selectByRange'); + } + + public clearTextInputClient(): void { + if(this.inputTarget.type == Type.VIRTUAL_DISPLAY_PLATFORM_VIEW) { + return; + } + this.mEditable.removeEditingStateListener(this.plugin); + this.configuration = null; + this.inputTarget = new InputTarget(Type.NO_TARGET, 0); + } +} + +enum Type { + NO_TARGET, + // InputConnection is managed by the TextInputPlugin, and events are forwarded to the Flutter + // framework. + FRAMEWORK_CLIENT, + // InputConnection is managed by a platform view that is presented on a virtual display. + VIRTUAL_DISPLAY_PLATFORM_VIEW, + PHYSICAL_DISPLAY_PLATFORM_VIEW, +} + +export class InputTarget { + type: Type; + id: number; + + constructor(type: Type, id: number) { + this.type = type; + this.id = id; + } + +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/localization/LocalizationPlugin.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/localization/LocalizationPlugin.ets new file mode 100644 index 0000000..78ed1c7 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/localization/LocalizationPlugin.ets @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import LocalizationChannel, { LocalizationMessageHandler } from '../../embedding/engine/systemchannels/LocalizationChannel' +import common from '@ohos.app.ability.common'; +import intl from '@ohos.intl'; +import Log from '../../util/Log'; +import i18n from '@ohos.i18n'; + +const TAG = "LocalizationPlugin"; +export default class LocalizationPlugin { + private localizationChannel:LocalizationChannel; + private context: common.Context; + + localeFromString(localeString: string): intl.Locale { + localeString = localeString.replace('_','-'); + let parts: string[] = localeString.split('-',-1); + let languageCode = parts[0]; + let scriptCode = ""; + let countryCode = ""; + let index: number = 1; + + if (parts.length > index && parts[index].length == 4) { + scriptCode = parts[index]; + index++; + } + + if (parts.length > index && parts[index].length >= 2 && parts[index].length <= 3) { + countryCode = parts[index]; + index++; + } + return new intl.Locale(languageCode+'-'+ countryCode +'-' + scriptCode); + } + + private localizationMessageHandler: LocalizationMessageHandler =new enterGetStringResource(()=>{ + Log.i(TAG, "getResource enter"); + return "" + }) + constructor(context: common.Context, localizationChannel: LocalizationChannel) { + this.context = context; + this.localizationChannel = localizationChannel; + this.localizationChannel.setLocalizationMessageHandler(this.localizationMessageHandler); + } + + sendLocaleToFlutter(): void { + let systemLanguages = i18n.System.getSystemLanguages(); + this.localizationChannel.sendLocales(systemLanguages); + } +} +class enterGetStringResource{ + getStringResource : (key: string, localeString: string)=>string + + constructor(getStringResource: (key: string, localeString: string)=>string) { + this.getStringResource = getStringResource + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/mouse/MouseCursorPlugin.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/mouse/MouseCursorPlugin.ets new file mode 100644 index 0000000..0f8bf87 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/mouse/MouseCursorPlugin.ets @@ -0,0 +1,129 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MouseCursorChannel, { MouseCursorMethodHandler } from '../../embedding/engine/systemchannels/MouseCursorChannel'; +import pointer from '@ohos.multimodalInput.pointer'; +import HashMap from '@ohos.util.HashMap'; +import Log from '../../util/Log'; +import { AsyncCallback } from '@ohos.base'; + +const TAG: string = "MouseCursorPlugin"; +export default class MouseCursorPlugin implements MouseCursorMethodHandler{ + private mView: MouseCursorViewDelegate; + + private mouseCursorChannel: MouseCursorChannel; + + private systemCursorConstants: HashMap | null = null; + + constructor(mouseCursorView: MouseCursorViewDelegate, mouseCursorChannel: MouseCursorChannel) { + this.mView = mouseCursorView; + this.mouseCursorChannel = mouseCursorChannel; + this.mouseCursorChannel.setMethodHandler(this); + } + + activateSystemCursor(kind: string): void { + this.mView.getWindowId((error, windowId) => { + if (windowId < 0) { + Log.w(TAG, "set point style failed windowId is invalid"); + return; + } + let pointStyle: pointer.PointerStyle = this.resolveSystemCursor(kind); + try { + pointer.setPointerStyle(windowId, pointStyle, (err: ESObject) => { + Log.i(TAG, "set point style success kind : " + kind); + }) + } catch (e) { + Log.e(TAG, "set point style failed : " + kind + " " + JSON.stringify(e)); + } + }); + } + + /** + * Return mouse cursor point style + * + *

This method guarantees to return a non-null object. + * + * @param kind mouse cursor type + * @returns point style + */ + private resolveSystemCursor(kind: string): pointer.PointerStyle { + if (this.systemCursorConstants == null) { + this.systemCursorConstants = new HashMap(); + this.systemCursorConstants.set("alias", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("allScroll", pointer.PointerStyle.MOVE); + this.systemCursorConstants.set("basic", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("cell", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("click", pointer.PointerStyle.HAND_POINTING); + this.systemCursorConstants.set("contextMenu", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("copy", pointer.PointerStyle.CURSOR_COPY); + this.systemCursorConstants.set("forbidden", pointer.PointerStyle.CURSOR_FORBID); + this.systemCursorConstants.set("grab", pointer.PointerStyle.HAND_OPEN); + this.systemCursorConstants.set("grabbing", pointer.PointerStyle.HAND_GRABBING); + this.systemCursorConstants.set("help", pointer.PointerStyle.HELP); + this.systemCursorConstants.set("move", pointer.PointerStyle.MOVE); + this.systemCursorConstants.set("none", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("noDrop", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("precise", pointer.PointerStyle.CROSS); + this.systemCursorConstants.set("text", pointer.PointerStyle.TEXT_CURSOR); + this.systemCursorConstants.set("resizeColum", pointer.PointerStyle.NORTH_SOUTH); + this.systemCursorConstants.set("resizeDown", pointer.PointerStyle.SOUTH); + this.systemCursorConstants.set("resizeUpLeft", pointer.PointerStyle.NORTH_WEST); + this.systemCursorConstants.set("resizeDownRight", pointer.PointerStyle.SOUTH_EAST); + this.systemCursorConstants.set("resizeLeft", pointer.PointerStyle.WEST); + this.systemCursorConstants.set("resizeLeftRight", pointer.PointerStyle.RESIZE_LEFT_RIGHT); + this.systemCursorConstants.set("resizeRight", pointer.PointerStyle.EAST); + this.systemCursorConstants.set("resizeRow", pointer.PointerStyle.WEST_EAST); + this.systemCursorConstants.set("resizeUp", pointer.PointerStyle.NORTH); + this.systemCursorConstants.set("resizeUpDown", pointer.PointerStyle.RESIZE_UP_DOWN); + this.systemCursorConstants.set("resizeUpLeft", pointer.PointerStyle.NORTH_WEST); + this.systemCursorConstants.set("resizeUpRight", pointer.PointerStyle.NORTH_EAST); + this.systemCursorConstants.set("resizeUpLeftDownRight", pointer.PointerStyle.MOVE); + this.systemCursorConstants.set("resizeUpRightDownLeft", pointer.PointerStyle.MOVE); + this.systemCursorConstants.set("verticalText", pointer.PointerStyle.TEXT_CURSOR); + this.systemCursorConstants.set("wait", pointer.PointerStyle.DEFAULT); + this.systemCursorConstants.set("zoomIn", pointer.PointerStyle.ZOOM_IN); + this.systemCursorConstants.set("zoomOut", pointer.PointerStyle.ZOOM_OUT); + } + let pointStyle:pointer.PointerStyle = this.systemCursorConstants.get(kind); + if (pointStyle === null) { + return pointer.PointerStyle.DEFAULT; + } + return pointStyle; + } + + /** + * Detaches the text input plugin from the platform views controller; + * + *

The MouseCursorPlugin instance should not be used after call this. + */ + destroy(): void { + this.mouseCursorChannel.setMethodHandler(null); + } +} + +/** + * Delegate interface for requesting the system to display a pointer icon object. + * + *

Typically implemented by an component, such as a{@code FlutterView} + */ +export interface MouseCursorViewDelegate { + /** + * get window id to set mouse style + *

component need to implement this interface to get windowId + * + * @param callback windowId + * */ + getWindowId(callback: AsyncCallback): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets new file mode 100644 index 0000000..ea9450d --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/AccessibilityEventsDelegate.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import AccessibilityBridge from '../../view/AccessibilityBridge'; + +export class AccessibilityEventsDelegate { + private accessibilityBridge: AccessibilityBridge | null = null; + + requestSendAccessibilityEvent(accessibilityBridge: AccessibilityBridge): boolean { + if (accessibilityBridge == null) { + return false; + } + return true; + } + + onAccessibilityHoverEvent(accessibilityBridge: AccessibilityBridge): boolean { + if (accessibilityBridge == null) { + return false; + } + return true; + } + + setAccessibilityBridge (accessibilityBridge: AccessibilityBridge): void { + this.accessibilityBridge = accessibilityBridge; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformOverlayView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformOverlayView.ets new file mode 100644 index 0000000..64e8c7f --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformOverlayView.ets @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { AccessibilityEventsDelegate } from './AccessibilityEventsDelegate'; + +export class PlatformOverlayView { + private accessibilityEventsDelegate: AccessibilityEventsDelegate; + + constructor(context: Context, width: Number, height: Number, accessibilityEventsDelegate: AccessibilityEventsDelegate) { + this.accessibilityEventsDelegate= accessibilityEventsDelegate; + } + + public onHoverEvent(): boolean { + return false; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView.ets new file mode 100644 index 0000000..ddf5f59 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView.ets @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { DVModel, DynamicView } from '../../view/DynamicView/dynamicView' + +/** A handle to an DynamicView to be embedded in the Flutter hierarchy. */ +export default abstract class PlatformView { + /** Returns the DynamicView to be embedded in the Flutter hierarchy. */ + abstract getView(): DVModel; + + /** + * Called by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code + * PlatformView} when the DynamicView responsible for rendering a Flutter UI is + * associated with the {@link io.flutter.embedding.engine.FlutterEngine}. + * + *

This means that our associated {@link io.flutter.embedding.engine.FlutterEngine} can now + * render a UI and interact with the user. + * + *

Some platform views may have unusual dependencies on the {@link View} that renders Flutter + * UIs, such as unique keyboard interactions. That {@link View} is provided here for those + * purposes. Use of this {@link View} should be avoided if it is not absolutely necessary, because + * depending on this {@link View} will tend to make platform view code more brittle to future + * changes. + */ + onFlutterViewAttached(dvModel: DVModel): void {} + + /** + * Called by the {@link io.flutter.embedding.engine.FlutterEngine} that owns this {@code + * PlatformView} when the DynamicView responsible for rendering a Flutter UI is detached + * and disassociated from the {@link io.flutter.embedding.engine.FlutterEngine}. + * + *

This means that our associated {@link io.flutter.embedding.engine.FlutterEngine} no longer + * has a rendering surface, or a user interaction surface of any kind. + * + *

This platform view must release any references related to the DynamicView that was + * provided in {@link #onFlutterViewAttached(View)}. + */ + onFlutterViewDetached(): void {} + + /** + * Dispose this platform view. + * + *

The {@link PlatformView} object is unusable after this method is called. + * + *

Plugins implementing {@link PlatformView} must clear all references to the View object and + * the PlatformView after this method is called. Failing to do so will result in a memory leak. + * + *

References related to the DynamicView attached in {@link + * #onFlutterViewAttached(View)} must be released in {@code dispose()} to avoid memory leaks. + */ + abstract dispose(): void; + + /** + * Callback fired when the platform's input connection is locked, or should be used. + * + *

This hook only exists for rare cases where the plugin relies on the state of the input + * connection. This probably doesn't need to be implemented. + */ + onInputConnectionLocked(): void {} + + /** + * Callback fired when the platform input connection has been unlocked. + * + *

This hook only exists for rare cases where the plugin relies on the state of the input + * connection. This probably doesn't need to be implemented. + */ + onInputConnectionUnlocked(): void {} +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets new file mode 100644 index 0000000..373a7ea --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory.ets @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import MessageCodec from '../common/MessageCodec'; +import PlatformView from './PlatformView' +import common from '@ohos.app.ability.common'; + +export default abstract class PlatformViewFactory { + private createArgsCodec: MessageCodec; + + /** @param createArgsCodec the codec used to decode the args parameter of {@link #create}. */ + constructor(createArgsCodec: MessageCodec) { + this.createArgsCodec = createArgsCodec; + } + + /** + * Creates a new Dynamic be embedded in the Flutter hierarchy. + * + * @param context the context to be used when creating the view, this is different than + * FlutterView's context. + * @param viewId unique identifier for the created instance, this value is known on the Dart side. + * @param args arguments sent from the Flutter app. The bytes for this value are decoded using the + * createArgsCodec argument passed to the constructor. This is null if createArgsCodec was + * null, or no arguments were sent from the Flutter app. + */ + public abstract create(context: common.Context, viewId: number, args: ESObject): PlatformView; + + /** Returns the codec to be used for decoding the args parameter of {@link #create}. */ + getCreateArgsCodec(): MessageCodec { + return this.createArgsCodec; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistry.ets new file mode 100644 index 0000000..2c49f5e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistry.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import PlatformViewFactory from './PlatformViewFactory' + +/** + * Registry for platform view factories. + * + *

Plugins can register factories for specific view types. + */ +export default interface PlatformViewRegistry { + /** + * Registers a factory for a platform view. + * + * @param viewTypeId unique identifier for the platform view's type. + * @param factory factory for creating platform views of the specified type. + * @return true if succeeded, false if a factory is already registered for viewTypeId. + */ + registerViewFactory(viewTypeId: string, factory: PlatformViewFactory): boolean; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistryImpl.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistryImpl.ets new file mode 100644 index 0000000..98cb247 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistryImpl.ets @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import HashMap from '@ohos.util.HashMap'; +import PlatformViewFactory from './PlatformViewFactory' +import PlatformViewRegistry from './PlatformViewRegistry' + +export default class PlatformViewRegistryImpl implements PlatformViewRegistry { + // Maps a platform view type id to its factory. + private viewFactories: HashMap; + + constructor() { + this.viewFactories = new HashMap(); + } + + registerViewFactory(viewTypeId: string, factory: PlatformViewFactory): boolean { + if (this.viewFactories.hasKey(viewTypeId)) { + return false; + } + + this.viewFactories.set(viewTypeId, factory); + return true; + } + + getFactory(viewTypeId: string): PlatformViewFactory { + return this.viewFactories.get(viewTypeId); + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets new file mode 100644 index 0000000..dcd5707 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewWrapper.ets @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import OhosTouchProcessor from '../../embedding/ohos/OhosTouchProcessor'; +import { DVModel, DVModelParameters } from '../../view/DynamicView/dynamicView'; +import { createDVModelFromJson } from '../../view/DynamicView/dynamicViewJson'; +import { RootDvModeManager } from './RootDvModelManager'; +import matrix4 from '@ohos.matrix4' +import Log from '../../util/Log'; + +const TAG: string = "PlatformViewWrapper"; +export class PlatformViewWrapper { + private prevLeft: number = 0; + private prevTop: number = 0; + private left: number = 0; + private top: number = 0; + private bufferWidth: number = 0; + private bufferHeight: number = 0; + private touchProcessor: OhosTouchProcessor | null = null; + + + private model : DVModel = createDVModelFromJson( new DVModelParam("Column", [])); + + public setTouchProcessor(newTouchProcessor: OhosTouchProcessor): void { + this.touchProcessor = newTouchProcessor; + } + + constructor() { + } + + public getDvModel(): DVModel { + return this.model; + } + + setParams: (params: DVModelParameters, key: string, element: ESObject ) => void = (params: DVModelParameters, key: string, element: ESObject): void => { + let params2 = params as Record; + params2[key] =element; + } + + getParams: (params: DVModelParameters, element: string) => string | ESObject = (params: DVModelParameters, element: string): string | ESObject => { + let params2 = params as Record; + return params2[element]; + } + + public setLayoutParams(parameters : DVModelParameters): void { + if (!this.model) { + return; + } + if (this.model.params == null) { + this.model.params = new DVModelParameters(); + } + this.setParams(this.model.params, "marginLeft", this.getParams(parameters, "marginLeft")); + this.setParams(this.model.params, "marginTop", this.getParams(parameters, "marginTop")); + this.left = this.getParams(parameters, "marginLeft"); + this.top = this.getParams(parameters, "marginTop"); + + this.setParams(this.model.params, "width", this.getParams(parameters, "width")); + this.setParams(this.model.params, "height", this.getParams(parameters, "height")); + + // this.model.params.marginLeft = parameters.marginLeft; + // this.model.params.marginTop = parameters.marginTop; + // this.left = parameters.marginLeft; + // this.top = parameters.marginTop;; + + // this.model.params.width = parameters.width; + // this.model.params.height = parameters.height; + } + + public addDvModel(model: DVModel): void { + this.model?.children.push(model); + } +} + +class DVModelParam { + compType: string + children: [] + + constructor(compType: string, children: []) { + this.compType = compType; + this.children = children; + } +}; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsAccessibilityDelegate.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsAccessibilityDelegate.ets new file mode 100644 index 0000000..6288804 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsAccessibilityDelegate.ets @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import AccessibilityBridge from '../../view/AccessibilityBridge'; + +export interface PlatformViewsAccessibilityDelegate { + /** + * Returns the root of the view hierarchy for the platform view with the requested id, or null if + * there is no corresponding view. + */ + getPlatformViewById(viewId: number): Object; + + /** Returns true if the platform view uses virtual displays. */ + usesVirtualDisplay(id: number): boolean; + + /** + * Attaches an accessibility bridge for this platform views accessibility delegate. + * + *

Accessibility events originating in platform views belonging to this delegate will be + * delegated to this accessibility bridge. + */ + attachAccessibilityBridge(accessibilityBridge: AccessibilityBridge): void; + + /** + * Detaches the current accessibility bridge. + * + *

Any accessibility events sent by platform views belonging to this delegate will be ignored + * until a new accessibility bridge is attached. + */ + detachAccessibilityBridge(): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets new file mode 100644 index 0000000..0d244a9 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewsController.ets @@ -0,0 +1,505 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { PlatformViewsAccessibilityDelegate } from './PlatformViewsAccessibilityDelegate'; +import PlatformViewsChannel, { + PlatformViewBufferResized, + PlatformViewCreationRequest, + PlatformViewResizeRequest, + PlatformViewsHandler, PlatformViewTouch, PlatformViewBufferSize +} from '../../../ets/embedding/engine/systemchannels/PlatformViewsChannel'; +import PlatformView from './PlatformView'; +import { DVModel, DVModelContainer, DVModelParameters, DynamicView } from '../../view/DynamicView/dynamicView'; +import display from '@ohos.display'; +import { FlutterView } from '../../view/FlutterView'; +import { TextureRegistry } from '../../view/TextureRegistry'; +import TextInputPlugin from '../editing/TextInputPlugin'; +import { PlatformOverlayView } from './PlatformOverlayView'; +import { PlatformViewWrapper } from './PlatformViewWrapper'; +import { FlutterOverlaySurface } from '../../embedding/engine/FlutterOverlaySurface'; +import HashSet from '@ohos.util.HashSet'; +import PlatformViewRegistry from './PlatformViewRegistry'; +import PlatformViewRegistryImpl from './PlatformViewRegistryImpl'; +import DartExecutor from '../../embedding/engine/dart/DartExecutor'; +import { AccessibilityEventsDelegate } from './AccessibilityEventsDelegate'; +import AccessibilityBridge from '../../view/AccessibilityBridge'; +import { RootDvModeManager } from './RootDvModelManager'; +import { FlutterMutatorView } from '../../embedding/engine/mutatorsstack/FlutterMutatorView'; +import common from '@ohos.app.ability.common'; +import Log from '../../util/Log' +import OhosTouchProcessor from '../../embedding/ohos/OhosTouchProcessor' +import PlatformViewFactory from './PlatformViewFactory' +import { ByteBuffer } from '../../util/ByteBuffer'; + +const TAG = "PlatformViewsController" + +export default class PlatformViewsController implements PlatformViewsAccessibilityDelegate, PlatformViewsHandler { + private registry: PlatformViewRegistryImpl; + private context: Context | null = null; + private flutterView: FlutterView | null = null; + private textureRegistry: TextureRegistry | null = null; + private textInputPlugin: TextInputPlugin | null = null; + private platformViewsChannel: PlatformViewsChannel | null = null; + private accessibilityEventsDelegate: AccessibilityEventsDelegate; + private nextOverlayLayerId: number = 0; + private usesSoftwareRendering: boolean = false; + + private platformViews: Map; + private overlayLayerViews: Map; + private viewWrappers: Map; + private currentFrameUsedOverlayLayerIds: HashSet; + private currentFrameUsedPlatformViewIds: HashSet; + private rootDvModel: DVModelContainer | null = RootDvModeManager.getRootDvMode(); + private platformViewParent: Map; + + constructor() { + this.registry = new PlatformViewRegistryImpl(); + this.accessibilityEventsDelegate = new AccessibilityEventsDelegate(); + this.overlayLayerViews = new Map(); + this.currentFrameUsedOverlayLayerIds = new HashSet(); + this.currentFrameUsedPlatformViewIds = new HashSet(); + this.viewWrappers = new Map(); + this.platformViews = new Map(); + this.platformViewParent = new Map(); + } + + + getPlatformViewById(viewId: number): Object { + throw new Error('Method not implemented.'); + } + + usesVirtualDisplay(id: number): boolean { + throw new Error('Method not implemented.'); + } + + attachAccessibilityBridge(accessibilityBridge: AccessibilityBridge): void { + throw new Error('Method not implemented.'); + } + + detachAccessibilityBridge(): void { + throw new Error('Method not implemented.'); + } + + createForPlatformViewLayer(request: PlatformViewCreationRequest): void { + Log.i(TAG, "Enter createForPlatformViewLayer"); + this.ensureValidRequest(request); + + let platformView: PlatformView = this.createPlatformView(request, false); + + this.configureForHybridComposition(platformView, request); + } + + dispose(viewId: number): void { + let platformView: PlatformView | null = this.platformViews.get(viewId) || null; + if (platformView == null) { + Log.e(TAG, "Disposing unknown platform view with id: " + viewId); + return; + } + this.platformViews.delete(viewId); + + try { + platformView.dispose(); + } catch (err) { + Log.e(TAG, "Disposing platform view threw an exception", err); + } + + let viewWrapper: PlatformViewWrapper | null = this.viewWrappers.get(viewId) || null; + if (viewWrapper != null) { + let children = viewWrapper.getDvModel().children; + let index = RootDvModeManager.getRootDvMode().model.children.indexOf(viewWrapper.getDvModel()); + children.splice(0, children.length); + RootDvModeManager.getRootDvMode().model.children.splice(index, 1); + this.viewWrappers.delete(viewId); + } + + let parentView: FlutterMutatorView | null = this.platformViewParent.get(viewId) || null; + if (parentView != null) { + this.platformViewParent.delete(viewId); + } + } + + setParams: (params: DVModelParameters, key: string, element: ESObject ) => void = (params: DVModelParameters, key: string, element: ESObject): void => { + let params2 = params as Record; + params2[key] =element; + } + + resize(request: PlatformViewResizeRequest, onComplete: PlatformViewBufferResized): void { + let physicalWidth: number = this.toPhysicalPixels(request.newLogicalWidth); + let physicalHeight: number = this.toPhysicalPixels(request.newLogicalHeight); + let viewId: number = request.viewId; + Log.i(TAG, `Resize viewId ${viewId}, pw:${physicalWidth}, ph:${physicalHeight},lw:${request.newLogicalWidth}, lh:${request.newLogicalHeight}`); + + let platformView: PlatformView | null = this.platformViews.get(viewId) || null; + let viewWrapper: PlatformViewWrapper | null = this.viewWrappers.get(viewId) || null; + if (platformView == null || viewWrapper == null) { + Log.e(TAG, "Resizing unknown platform view with id: " + viewId); + return; + } + + let viewWrapperLayoutParams: DVModelParameters | undefined = viewWrapper.getDvModel()?.getLayoutParams(); + if (physicalWidth && viewWrapperLayoutParams) { + this.setParams(viewWrapperLayoutParams, "width", physicalWidth); + // viewWrapperLayoutParams.width = physicalWidth; + } + + if (physicalHeight && viewWrapperLayoutParams) { + this.setParams(viewWrapperLayoutParams, "height", physicalHeight); + // viewWrapperLayoutParams.height = physicalHeight; + } + + let embeddedView: DVModel = platformView.getView(); + if (embeddedView != null) { + let embeddedViewLayoutParams = embeddedView.getLayoutParams(); + if (physicalWidth) { + this.setParams(embeddedViewLayoutParams, "width", physicalWidth); + // embeddedViewLayoutParams.width = physicalWidth; + } + + if (physicalHeight) { + this.setParams(embeddedViewLayoutParams, "height", physicalHeight); + // embeddedViewLayoutParams.height = physicalHeight; + } + } + + onComplete.run(new PlatformViewBufferSize(request.newLogicalWidth, request.newLogicalHeight)); + } + + offset(viewId: number, top: number, left: number): void { + Log.i(TAG, `Offset is id${viewId}, t:${top}, l:${left}`); + let viewWrapper: PlatformViewWrapper | null = this.viewWrappers.get(viewId) || null; + if (viewWrapper == null) { + Log.e(TAG, "Setting offset for an unknown platform view with id: " + viewId); + return; + } + + let physicalTop = this.toPhysicalPixels(top); + let physicalLeft = this.toPhysicalPixels(left); + let params = viewWrapper.getDvModel()!.params; + this.setParams(params!, "marginTop", physicalTop); + this.setParams(params!, "marginLeft", physicalLeft); + viewWrapper.setLayoutParams(params!); + } + + onTouch(touch: PlatformViewTouch): void { + let viewId: number = touch.viewId; + let density: number = display.getDefaultDisplaySync().densityDPI; + + let platformView: PlatformView | null = this.platformViews.get(viewId) ?? null; + if (platformView == null) { + Log.e(TAG, "Sending touch to an unknown platform view with id: " + viewId); + return; + } + let dvModel: DVModel = platformView.getView(); + if (dvModel == null) { + Log.e(TAG, "Sending touch to a null dv model with id: " + viewId); + } + Log.e(TAG, "Sending touch to a dv model with id: " + viewId.toString()); + sendEventByKey(viewId.toString(), 10, ""); + } + + setDirection(viewId: number, direction: number): void { + if (!this.validateDirection(direction)) { + throw new Error("Trying to set unknown direction value: " + + direction + + "(view id: " + + viewId + + ")"); + } + + const platformView = this.platformViews.get(viewId); + if (platformView == null) { + Log.e(TAG, "Setting direction to an unknown view with id: " + viewId); + return; + } + const embeddedView = platformView.getView(); + if (embeddedView == null) { + Log.e(TAG, "Setting direction to a null view with id: " + viewId); + return; + } + this.setParams(embeddedView.params, "direction", direction); + // embeddedView.params.direction = direction; + } + + validateDirection(direction:number):boolean { + return direction == Direction.Ltr || direction == Direction.Rtl || direction == Direction.Auto; + } + + clearFocus(viewId: number): void { + const platformView = this.platformViews.get(viewId); + if (platformView == null) { + Log.e(TAG, "Setting direction to an unknown view with id: " + viewId); + return; + } + const embeddedView = platformView.getView(); + if (embeddedView == null) { + Log.e(TAG, "Setting direction to a null view with id: " + viewId); + return; + } + focusControl.requestFocus("flutterXComponent"); + } + synchronizeToNativeViewHierarchy(yes: boolean): void { + throw new Error('Method not implemented.'); + } + + public createForTextureLayer(request: PlatformViewCreationRequest): number { + Log.i(TAG, "Enter createForTextureLayer"); + this.ensureValidRequest(request); + + let viewId: number = request.viewId; + if (this.viewWrappers.get(request.viewId) != null) { + throw new Error( + "Trying to create an already created platform view, view id: " + viewId); + } + + let platformView: PlatformView = this.createPlatformView(request, true); + let dynamicView: DVModel = platformView.getView(); + return this.configureForTextureLayerComposition(platformView, request); + } + + private ensureValidRequest(request: PlatformViewCreationRequest): void { + if (!this.validateDirection(request.direction)) { + throw new Error("Trying to create a view with unknown direction value: " + + request.direction + + "(view id: " + + request.viewId + + ")") + } + } + + private createPlatformView(request: PlatformViewCreationRequest, wrapContext: boolean): PlatformView { + Log.i(TAG, "Enter createPlatformView"); + const viewFactory: PlatformViewFactory = this.registry.getFactory(request.viewType); + if (viewFactory == null) { + throw new Error("Trying to create a platform view of unregistered type: " + request.viewType) + } + + let createParams: ESObject = null; + if (request.params != null) { + let byteParas : ByteBuffer = request.params as ByteBuffer; + createParams = viewFactory.getCreateArgsCodec().decodeMessage(byteParas.buffer); + } + + if (this.context == null) { + throw new Error('PlatformView#context is null.'); + } + let platformView = viewFactory.create(this.context, request.viewId, createParams); + + let embeddedView: DVModel = platformView.getView(); + if (embeddedView == null) { + throw new Error("PlatformView#getView() returned null, but an dynamic view reference was expected."); + } + + this.setParams(embeddedView.params, "direction", request.direction); + // embeddedView.params.direction = request.direction; + + this.platformViews.set(request.viewId, platformView); + return platformView; + } + + // Configures the view for Hybrid Composition mode. + private configureForHybridComposition(platformView: PlatformView, request: PlatformViewCreationRequest): void { + Log.i(TAG, "Using hybrid composition for platform view: " + request.viewId); + } + + private configureForTextureLayerComposition(platformView: PlatformView, request: PlatformViewCreationRequest): number { + Log.i(TAG, "Hosting view in view hierarchy for platform view: " + request.viewId); + + let viewWrapper: PlatformViewWrapper = new PlatformViewWrapper(); + let textureId: number = 0; + + let physicalTop: number = this.toPhysicalPixels(request.logicalTop); + let physicalLeft: number = this.toPhysicalPixels(request.logicalLeft); + + Log.i(TAG, `View pW:${request.logicalWidth}, pH:${request.logicalHeight}, pT:${physicalTop}, pL:${physicalLeft}`); + + let param: DVModelParameters = new DVModelParameters(); + + this.setParams(param, "marginLeft", physicalLeft); + this.setParams(param, "marginTop", physicalTop); + // param.marginLeft = physicalLeft; + // param.marginTop = physicalTop; + + let model = platformView.getView(); + if (request.logicalWidth != null) { + let physicalWidth: number = this.toPhysicalPixels(request.logicalWidth); + this.setParams(model.params, "width", physicalWidth); + this.setParams(param, "width", physicalWidth); + // model.params.width = physicalWidth; + // param.width = physicalWidth; + } + + if (request.logicalHeight != null) { + let physicalHeight: number = this.toPhysicalPixels(request.logicalHeight); + this.setParams(model.params, "height", physicalHeight); + this.setParams(param, "height", physicalHeight); + // model.params.height = physicalHeight; + // param.height = physicalHeight; + } + + viewWrapper.setLayoutParams(param); + viewWrapper.addDvModel(model); + + RootDvModeManager.addDvModel(viewWrapper.getDvModel()!); + this.viewWrappers.set(request.viewId, viewWrapper); + Log.i(TAG, "Create platform view success"); + + return textureId; + } + + public attach(context: Context, textureRegistry: TextureRegistry | null, dartExecutor: DartExecutor): void { + if (this.context != null) { + + } + this.context = context; + this.textureRegistry = textureRegistry; + this.platformViewsChannel = new PlatformViewsChannel(dartExecutor); + this.platformViewsChannel.setPlatformViewsHandler(this); + } + + public detach(): void { + if (this.platformViewsChannel != null) { + this.platformViewsChannel.setPlatformViewsHandler(null); + } + this.destroyOverlaySurfaces(); + this.platformViewsChannel = null; + this.context = null; + this.textureRegistry = null; + } + + public attachToView() { + for (let wrapper of this.viewWrappers.values()) { + this.rootDvModel?.model.children.push(wrapper.getDvModel()!); + } + for (let mutator of this.platformViewParent.values()) { + this.rootDvModel?.model.children.push(mutator.getDvModel()!); + } + for (let platformView of this.platformViews.values()) { + platformView.onFlutterViewAttached(this.rootDvModel!.model); + } + } + + public detachFromView(): void { + for (let index = 0; index < this.viewWrappers.size; index++) { + this.rootDvModel?.model.children.pop(); + } + for (let index = 0; index < this.platformViewParent.size; index++) { + this.rootDvModel?.model.children.pop(); + } + this.destroyOverlaySurfaces(); + this.removeOverlaySurfaces(); + this.rootDvModel = null; + + for (let platformView of this.platformViews.values()) { + platformView.onFlutterViewDetached(); + } + } + + public attachTextInputPlugin(textInputPlugin: TextInputPlugin): void { + this.textInputPlugin = textInputPlugin; + } + + public detachTextInputPlugin(): void { + this.textInputPlugin = null; + } + + public getRegistry(): PlatformViewRegistry { + return this.registry; + } + + public onDetachedFromNapi(): void { + this.diposeAllViews(); + } + + public onPreEngineRestart(): void { + this.diposeAllViews(); + } + + private getDisplayDensity(): number { + return display.getDefaultDisplaySync().densityPixels; + } + private toPhysicalPixels(logicalPixels: number): number { + return Math.round(px2vp(logicalPixels * this.getDisplayDensity())); + } + + private toLogicalPixelsByDensity(physicalPixels: number, displayDensity: number): number { + return Math.round(physicalPixels / displayDensity); + } + + private toLogicalPixels(physicalPixels: number): number { + return this.toLogicalPixelsByDensity(physicalPixels, this.getDisplayDensity()); + } + + + private diposeAllViews(): void { + } + + private initializeRootImageViewIfNeeded(): void { + } + + initializePlatformViewIfNeeded(viewId: number): void { + let platformView: PlatformView = this.platformViews[viewId]; + if (platformView == null) { + throw new Error("Platform view hasn't been initialized from the platform view channel."); + } + if (this.platformViewParent[viewId] == null) { + return; + } + let dvModel: DVModel = platformView.getView(); + if (dvModel == null) { + throw new Error("PlatformView#getView() returned null, but an ohos dv model reference was expected."); + } + let parentView: FlutterMutatorView = new FlutterMutatorView(); + parentView.setOnDescendantFocusChangeListener(() => { + this.platformViewsChannel?.invokeViewFocused(viewId); + }, () => { + if (this.textInputPlugin != null) { + this.textInputPlugin.clearTextInputClient(); + } + }); + } + + public onDisplayOverlaySurface(id: number, x: number, y: number, width: number, height: number): void { + } + + public onBeginFrame(): void { + this.currentFrameUsedOverlayLayerIds.clear(); + this.currentFrameUsedPlatformViewIds.clear(); + } + + public onEndFrame(): void { + } + + private finishFrame(isFrameRenderedUsingImageReaders: boolean): void { + } + + public createOverlaySurfaceByPlatformOverlayView(imageView: PlatformOverlayView) { + let id = this.nextOverlayLayerId++; + this.overlayLayerViews.set(id, imageView); + return new FlutterOverlaySurface(this.nextOverlayLayerId++); + } + + public createOverlaySurface(): FlutterOverlaySurface { + return new FlutterOverlaySurface(this.nextOverlayLayerId++); + } + + private destroyOverlaySurfaces(): void { + } + + private removeOverlaySurfaces(): void { + if (!(this.flutterView instanceof FlutterView)) { + return; + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets new file mode 100644 index 0000000..eec92e8 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/plugin/platform/RootDvModelManager.ets @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import { DVModel, + DVModelContainer, + DVModelParameters } from '../../view/DynamicView/dynamicView'; +import { createDVModelFromJson } from '../../view/DynamicView/dynamicViewJson'; + +@Component +struct XComponentStruct { + private context:ESObject; + + build() { + XComponent({ id: 'flutterXComponent', type: 'texture', libraryname: 'flutter' }) + .onLoad((context) => { + this.context = context; + }) + .onDestroy(() => { + }) + } +} +interface $$type{ + param: DVModelParameters +} +@Builder function BuildXComponentStruct($$: $$type) { + XComponentStruct(); +} + +class DVModelJson{ + compType: string + children:Array + attributes:ESObject + + constructor(compType:string , children:Array , attributes:ESObject) { + this.compType = compType + this.children = children + this.attributes = attributes + } +} +export class RootDvModeManager { + private static xComponentModel:ESObject = + { + compType: "xComponent", + build: BuildXComponentStruct + }; + + private static model: DVModel = createDVModelFromJson(new DVModelJson("Stack", [RootDvModeManager.xComponentModel], {alignContent: Alignment.TopStart},) + + ); + + private static container : DVModelContainer = new DVModelContainer(RootDvModeManager.model); + + public static getRootDvMode(): DVModelContainer { + return RootDvModeManager.container; + } + + public static addDvModel(model: DVModel): void { + RootDvModeManager.container.model.children.push(model); + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ByteBuffer.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ByteBuffer.ets new file mode 100644 index 0000000..38d652b --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ByteBuffer.ets @@ -0,0 +1,818 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import util from '@ohos.util' +import StringUtils from './StringUtils' + +/** + * A byte buffer. + * + * Supports the following data types: + * - Bool + * - Int (8, 16, 32, 64) + * - Uint (8, 16, 32, 64) + * - BigInt (64) + * - String (utf8, utf16, and delimited) + * - TypedArray + * + */ +export class ByteBuffer { + + /** + * Creates a byte buffer. + * @param source The data source. + * @param byteOffset The byte offset. + * @param byteLength The byte length. + * @returns A byte buffer. + */ + static from(source: ArrayBuffer, byteOffset?: number, byteLength?: number): ByteBuffer { + // if (ArrayBuffer.isView(source)) { + // byteOffset = source.byteOffset + (byteOffset || 0) + // } + const byteBuffer = new ByteBuffer() + byteBuffer.dataView = byteLength === undefined ? new DataView(source, byteOffset) : new DataView(source, byteOffset, Math.min(source.byteLength, byteLength)) + byteBuffer.mByteOffset = byteBuffer.dataView.byteOffset + return byteBuffer + } + + /** + * The dataView. + */ + private dataView?: DataView + + /** + * The byte offset. + */ + mByteOffset: number = 0 + + /** + * The byte offset. + * @returns The byte offset. + */ + get byteOffset(): number { + return this.mByteOffset + } + + /** + * The byte offset. + * @returns The byte offset. + */ + get byteLength(): number { + return this.dataView?.byteLength ?? 0 + } + + /** + * The number of remaining bytes. + * @returns The number of bytes remaining. + */ + get bytesRemaining(): number { + return this.dataView ? this.dataView.byteLength - this.mByteOffset : 0; + } + + hasRemaining(): boolean { + return this.dataView != undefined && this.mByteOffset < this.dataView.byteLength; + } + + get buffer(): ArrayBuffer { + const dataBuffer = new DataView(new ArrayBuffer(this.mByteOffset)); + for (let i = 0; i < this.mByteOffset; i++) { + dataBuffer.setUint8(i, this.dataView!.getUint8(i)); + } + return dataBuffer.buffer + } + + /** + * Skips the byte offset. + * @param byteLength The byte length. + */ + skip(byteLength: number): void { + this.mByteOffset += byteLength + } + + /** + * Resets the byte offset. + */ + reset(): void { + this.mByteOffset = this.dataView?.byteOffset ?? 0 + } + + /** + * Clears the byte buffer. + */ + clear(): void { + this.getUint8Array(0).fill(0) + } + + /** + * check buffer capacity. + */ + checkWriteCapacity(slen: number): void { + if (this.mByteOffset + slen > this.dataView!.byteLength) { + let checkBuffer = new DataView(new ArrayBuffer(this.dataView!.byteLength + slen + 512)); + for (let i = 0; i < this.mByteOffset; i++) { + checkBuffer.setUint8(i, this.dataView!.getUint8(i)); + } + this.dataView = checkBuffer; + } + } + + /** + * Gets a boolean. + * @param byteOffset The byte offset. + */ + getBool(byteOffset: number): boolean { + return this.getInt8(byteOffset) !== 0 + } + + /** + * Reads the next boolean. + */ + readBool(): boolean { + return this.getInt8(this.mByteOffset++) !== 0 + } + + /** + * Sets a boolean. + * @param byteOffset The byte offset. + * @param value The value. + */ + setBool(byteOffset: number, value: boolean): void { + this.dataView?.setInt8(byteOffset, value ? 1 : 0) + } + + /** + * Writes the next boolean. + * @param value The value. + */ + writeBool(value: boolean): void { + this.checkWriteCapacity(1) + this.setInt8(this.mByteOffset++, value ? 1 : 0) + } + + /** + * Gets an signed byte. + * @param byteOffset The byte offset. + * @returns The value. + */ + getInt8(byteOffset: number): number { + return this.dataView?.getInt8(byteOffset) || 0 + } + + /** + * Reads the next signed byte. + * @returns The value. + */ + readInt8(): number { + return this.getInt8(this.mByteOffset++) + } + + /** + * Sets a signed byte. + * @param byteOffset The byte offset. + * @param value The value. + */ + setInt8(byteOffset: number, value: number): void { + this.dataView?.setInt8(byteOffset, value) + } + + /** + * Writes the next signed byte. + * @param value The value. + */ + writeInt8(value: number): void { + this.checkWriteCapacity(1) + this.setInt8(this.mByteOffset++, value) + } + + /** + * Gets an unsigned byte. + * @param byteOffset The byte offset. + * @returns The value. + */ + getUint8(byteOffset: number): number { + return this.dataView?.getUint8(byteOffset) || 0 + } + + /** + * Reads the next unsigned byte. + * @returns The value. + */ + readUint8(): number { + return this.getUint8(this.mByteOffset++) + } + + /** + * Sets an unsigned byte. + * @param byteOffset The byte offset. + * @param value The value. + */ + setUint8(byteOffset: number, value: number): void { + this.dataView?.setUint8(byteOffset, value) + } + + /** + * Writes the next signed byte. + * @param value The value. + */ + writeUint8(value: number): void { + this.checkWriteCapacity(1) + this.setUint8(this.mByteOffset++, value) + } + + /** + * Gets an signed short. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getInt16(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getInt16(byteOffset, littleEndian) || 0 + } + + /** + * Reads the next signed short. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readInt16(littleEndian?: boolean): number { + const value = this.getInt16(this.mByteOffset, littleEndian) + this.mByteOffset += 2 + return value + } + + /** + * Sets a signed short. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setInt16(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setInt16(byteOffset, value, littleEndian) + } + + /** + * Writes the next signed short. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeInt16(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(2) + this.setInt16(this.mByteOffset, value, littleEndian) + this.mByteOffset += 2 + } + + /** + * Gets an unsigned short. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getUint16(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getUint16(byteOffset, littleEndian) || 0 + } + + /** + * Reads the next unsigned short. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readUint16(littleEndian?: boolean): number { + const value = this.getUint16(this.mByteOffset, littleEndian) + this.mByteOffset += 2 + return value + } + + /** + * Sets an unsigned short. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setUint16(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setUint16(byteOffset, value, littleEndian) + } + + /** + * Writes the next signed short. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeUint16(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(2) + this.setUint16(this.mByteOffset, value, littleEndian) + this.mByteOffset += 2 + } + + /** + * Gets an signed integer. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getInt32(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getInt32(byteOffset, littleEndian) ?? 0 + } + + /** + * Reads the next signed integer. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readInt32(littleEndian?: boolean): number { + const value = this.getInt32(this.mByteOffset, littleEndian) + this.mByteOffset += 4 + return value + } + + /** + * Sets a signed integer. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setInt32(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setInt32(byteOffset, value, littleEndian) + } + + /** + * Writes the next signed integer. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeInt32(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(4) + this.setInt32(this.mByteOffset, value, littleEndian) + this.mByteOffset += 4 + } + + /** + * Gets an unsigned integer. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getUint32(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getUint32(byteOffset, littleEndian) ?? 0 + } + + /** + * Reads the next unsigned integer. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readUint32(littleEndian?: boolean): number { + const value = this.getUint32(this.mByteOffset, littleEndian) + this.mByteOffset += 4 + return value + } + + /** + * Sets an unsigned integer. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setUint32(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setUint32(byteOffset, value, littleEndian) + } + + /** + * Writes the next signed integer. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeUint32(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(4) + this.setUint32(this.mByteOffset, value, littleEndian) + this.mByteOffset += 4 + } + + /** + * Gets a float. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getFloat32(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getFloat32(byteOffset, littleEndian) ?? 0 + } + + /** + * Reads the next float. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readFloat32(littleEndian?: boolean): number { + const value = this.getFloat32(this.mByteOffset, littleEndian) + this.mByteOffset += 4 + return value + } + + /** + * Sets a float. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setFloat32(byteOffset, value, littleEndian) + } + + /** + * Writes the next float. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeFloat32(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(4) + this.setFloat32(this.mByteOffset, value, littleEndian) + this.mByteOffset += 4 + } + + /** + * Gets a double. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getFloat64(byteOffset: number, littleEndian?: boolean): number { + return this.dataView?.getFloat64(byteOffset, littleEndian) ?? 0 + } + + /** + * Reads the next double. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readFloat64(littleEndian?: boolean): number { + const value = this.getFloat64(this.mByteOffset, littleEndian) + this.mByteOffset += 8 + return value + } + + /** + * Sets a double. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void { + this.dataView?.setFloat64(byteOffset, value, littleEndian) + } + + /** + * Writes the next double. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeFloat64(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(8) + this.setFloat64(this.mByteOffset, value, littleEndian) + this.mByteOffset += 8 + } + + /** + * Gets an signed long. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getBigInt64(byteOffset: number, littleEndian?: boolean): bigint { + return this.dataView?.getBigInt64(byteOffset, littleEndian) ?? BigInt(0) + } + + /** + * Reads the next signed long. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readBigInt64(littleEndian?: boolean): bigint { + const value = this.getBigInt64(this.mByteOffset, littleEndian) + this.mByteOffset += 8 + return value + } + + /** + * Sets a signed long. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void { + this.dataView?.setBigInt64(byteOffset, value, littleEndian) + } + + /** + * Writes the next signed long. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeBigInt64(value: bigint, littleEndian?: boolean): void { + this.checkWriteCapacity(8) + this.setBigInt64(this.mByteOffset, value, littleEndian) + this.mByteOffset += 8 + } + + /** + * Gets an unsigned long. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getBigUint64(byteOffset: number, littleEndian?: boolean): bigint { + return this.dataView?.getBigUint64(byteOffset, littleEndian) ?? BigInt(0) + } + + /** + * Reads the next unsigned long. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readBigUint64(littleEndian?: boolean): bigint { + const value = this.getBigUint64(this.mByteOffset, littleEndian) + this.mByteOffset += 8 + return value + } + + /** + * Sets an unsigned long. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void { + this.dataView?.setBigUint64(byteOffset, value, littleEndian) + } + + /** + * Writes the next unsigned long. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeBigUint64(value: bigint, littleEndian?: boolean): void { + this.checkWriteCapacity(8) + this.setBigUint64(this.mByteOffset, value, littleEndian) + this.mByteOffset += 8 + } + + /** + * Gets an signed long. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getInt64(byteOffset: number, littleEndian?: boolean): bigint { + return this.getBigInt64(byteOffset, littleEndian) + } + + /** + * Reads the next signed long. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readInt64(littleEndian?: boolean): bigint { + const value = this.getInt64(this.mByteOffset, littleEndian) + this.mByteOffset += 8 + return value + } + + /** + * Sets a signed long. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setInt64(byteOffset: number, value: number, littleEndian?: boolean): void { + this.setBigInt64(byteOffset, BigInt(value), littleEndian) + } + + /** + * Writes the next signed long. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeInt64(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(8) + this.setInt64(this.mByteOffset, value, littleEndian) + this.mByteOffset += 8 + } + + /** + * Gets an unsigned long. + * @param byteOffset The byte offset. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + getUint64(byteOffset: number, littleEndian?: boolean): number { + return Number(this.getBigUint64(byteOffset, littleEndian)) + } + + /** + * Reads the next unsigned long. + * @param littleEndian If the value is little endian. + * @returns The value. + */ + readUint64(littleEndian?: boolean): number { + const value = this.getUint64(this.mByteOffset, littleEndian) + this.mByteOffset += 8 + return value + } + + /** + * Sets an unsigned long. + * @param byteOffset The byte offset. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + setUint64(byteOffset: number, value: number, littleEndian?: boolean): void { + this.setBigUint64(byteOffset, BigInt(value), littleEndian) + } + + /** + * Writes the next signed long. + * @param value The value. + * @param littleEndian If the value is little endian. + */ + writeUint64(value: number, littleEndian?: boolean): void { + this.checkWriteCapacity(8) + this.setUint64(this.mByteOffset, value, littleEndian) + this.mByteOffset += 8 + } + + /** + * Gets an array of unsigned bytes. + * @param byteOffset The byte offset. + * @param byteLength The byte length. + * @returns The value. + */ + getUint8Array(byteOffset: number, byteLength?: number): Uint8Array { + return this.dataView == null + ? new Uint8Array(StringUtils.stringToArrayBuffer(""), byteOffset, byteLength) + : new Uint8Array(this.dataView?.buffer, this.dataView?.byteOffset + byteOffset, byteLength) + } + + /** + * Reads the next array of unsigned bytes. + * @param byteLength The byte length. + * @returns The value. + */ + readUint8Array(byteLength?: number): Uint8Array { + const value = this.getUint8Array(this.mByteOffset, byteLength) + this.mByteOffset += value.byteLength + return value + } + + /** + * Sets an array of unsigned bytes. + * @param byteOffset The byte offset. + * @param value The value. + */ + setUint8Array(byteOffset: number, value: Uint8Array): void { + const byteLength = value.byteLength + this.getUint8Array(byteOffset, byteLength).set(value) + } + + /** + * Writes the next array of unsigned bytes. + * @param value The value. + */ + writeUint8Array(value: Uint8Array): void { + this.checkWriteCapacity(value.byteLength) + this.setUint8Array(this.mByteOffset, value) + this.mByteOffset += value.byteLength + } + + /** + * Gets an array of unsigned shorts. + * @param byteOffset The byte offset. + * @param byteLength The byte length. + * @returns The value. + */ + getUint16Array(byteOffset: number, byteLength?: number): Uint16Array { + if (byteLength !== undefined) { + byteLength = Math.floor(byteLength / 2) + } + return this.dataView == null + ? new Uint16Array(StringUtils.stringToArrayBuffer(""), byteOffset, byteLength) + : new Uint16Array(this.dataView.buffer, this.dataView.byteOffset + byteOffset, byteLength) + } + + /** + * Reads the next array of unsigned shorts. + * @param byteLength The byte length. + * @returns The value. + */ + readUint16Array(byteLength?: number): Uint16Array { + const value = this.getUint16Array(this.mByteOffset, byteLength) + this.mByteOffset += value.byteLength + return value + } + + /** + * Sets an array of unsigned bytes. + * @param byteOffset The byte offset. + * @param value The value. + */ + setUint16Array(byteOffset: number, value: Uint16Array): void { + const byteLength = value.byteLength + this.getUint16Array(byteOffset, byteLength).set(value) + } + + /** + * Writes the next array of unsigned bytes. + * @param value The value. + */ + writeUint16Array(value: Uint16Array): void { + this.checkWriteCapacity(value.byteLength) + this.setUint16Array(this.mByteOffset, value) + this.mByteOffset += value.byteLength + } + + /** + * Gets a string. + * @param byteOffset The byte offset. + * @param byteLength The byte length. + * @param byteEncoding The byte encoding. + * @returns The value. + */ + getString(byteOffset: number, byteLength?: number, byteEncoding?: string): string { + const decoder = new util.TextDecoder(byteEncoding || "utf-8") + const encoded = this.getUint8Array(byteOffset, byteLength) + return decoder.decode(encoded) + } + + /** + * Reads the next string. + * @param byteLength The byte length. + * @param byteEncoding The byte encoding. + * @returns The value. + */ + readString(byteLength?: number, byteEncoding?: string): string { + const value = this.getString(this.mByteOffset, byteLength, byteEncoding) + if (byteLength === undefined) { + this.mByteOffset = this.dataView?.byteLength ?? 0 + } else { + this.mByteOffset += byteLength + } + return value + } + + /** + * Sets a string. + * @param byteOffset The byte offset. + * @param value The string. + * @param byteEncoding The byte encoding. + * @returns The byte length. + */ + setString(byteOffset: number, value: string, byteEncoding?: string, write?: boolean): number { + if (byteEncoding && byteEncoding !== "utf-8") { + throw new TypeError("String encoding '" + byteEncoding + "' is not supported") + } + const encoder = new util.TextEncoder() + const byteLength = Math.min(this.dataView!.byteLength - byteOffset, value.length * 4) + if (write) { + this.checkWriteCapacity(byteLength) + } + const destination = this.getUint8Array(byteOffset, byteLength) + const written = encoder.encodeInto(value, destination).written + return written || 0 + } + + /** + * Writes the next a string. + * @param value The string. + * @param byteEncoding The byte encoding. + */ + writeString(value: string, byteEncoding?: string): void { + const byteLength = this.setString(this.mByteOffset, value, byteEncoding, true) + this.mByteOffset += byteLength + } + + /** + * Formats to a string. + * @param format The string format. + * @returns The string. + */ + toString(format?: string): string { + return [...this.getUint8Array(0)].map((byte: number) => { + switch(format) { + case "hex": + return ("00" + byte.toString(16)).slice(-2) + default: + return byte.toString(10) + } + }).join(" ") + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets new file mode 100644 index 0000000..437b52f --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/Log.ets @@ -0,0 +1,122 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import HiLog from '@ohos.hilog'; + +const DOMAIN: number = 0x00FF; +const TAG = "Flutter"; +const SYMBOL = " --> "; +// const FILTER_KEYS = [ +// new RegExp('hide', "gi") +// ] + +// export function filterKey(target: any, propKey: string, descriptor: PropertyDescriptor) { +// const original = descriptor.value; +// descriptor.value = function (...args: string[]) { +// let filterResult = args.map((str) => { +// let tempStr = str +// FILTER_KEYS.forEach((filterKey) => tempStr = tempStr.replace(filterKey, "**")) +// return tempStr +// }); +// const result = original.call(this, ...filterResult); +// return result; +// }; +// } + +/** + * Basic log class + */ +export default class Log { + /** + * Outputs debug-level logs. + * + * @param tag Identifies the log tag. + * @param format Indicates the log format string. + * @param args Indicates the log parameters. + * @since 7 + */ + static d(tag: string, format: string, ...args: ESObject[]) { + if (Log.isLoggable(HiLog.LogLevel.DEBUG)) { + HiLog.debug(DOMAIN, TAG, tag + SYMBOL + format, args); + } + } + + /** + * Outputs info-level logs. + * + * @param tag Identifies the log tag. + * @param format Indicates the log format string. + * @param args Indicates the log parameters. + * @since 7 + */ + static i(tag: string, format: string, ...args: ESObject[]) { + if (Log.isLoggable(HiLog.LogLevel.INFO)) { + HiLog.info(DOMAIN, TAG, tag + SYMBOL + format, args); + } + } + + /** + * Outputs warning-level logs. + * + * @param tag Identifies the log tag. + * @param format Indicates the log format string. + * @param args Indicates the log parameters. + * @since 7 + */ + static w(tag: string, format: string, ...args: ESObject[]) { + if (Log.isLoggable(HiLog.LogLevel.WARN)) { + HiLog.warn(DOMAIN, TAG, tag + SYMBOL + format, args); + } + } + + /** + * Outputs error-level logs. + * + * @param tag Identifies the log tag. + * @param format Indicates the log format string. + * @param args Indicates the log parameters. + * @since 7 + */ + static e(tag: string, format: string, ...args: ESObject[]) { + if (Log.isLoggable(HiLog.LogLevel.ERROR)) { + HiLog.error(DOMAIN, TAG, tag + SYMBOL + format, args); + } + } + + /** + * Outputs fatal-level logs. + * + * @param tag Identifies the log tag. + * @param format Indicates the log format string. + * @param args Indicates the log parameters. + * @since 7 + */ + static f(tag: string, format: string, ...args: ESObject[]) { + if (Log.isLoggable(HiLog.LogLevel.FATAL)) { + HiLog.fatal(DOMAIN, TAG, tag + SYMBOL + format, args); + } + } + + /** + * Checks whether logs of the specified tag, and level can be printed. + * + * @param tag Identifies the log tag. + * @param level log level + * @since 7 + */ + private static isLoggable(level: HiLog.LogLevel): boolean { + return HiLog.isLoggable(DOMAIN, TAG, level); + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/MessageChannelUtils.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/MessageChannelUtils.ets new file mode 100644 index 0000000..1899f74 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/MessageChannelUtils.ets @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import BasicMessageChannel from '../plugin/common/BasicMessageChannel'; +import { BinaryMessenger } from '../plugin/common/BinaryMessenger'; +import StringUtils from './StringUtils'; + +export default class MessageChannelUtils { + static resizeChannelBuffer(messenger: BinaryMessenger, channel: string, newSize: number) { + const dataStr = `resize\r${channel}\r${newSize}` + messenger.send(BasicMessageChannel.CHANNEL_BUFFERS_CHANNEL, StringUtils.stringToArrayBuffer(dataStr)); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/PathUtils.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/PathUtils.ets new file mode 100644 index 0000000..691ea0f --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/PathUtils.ets @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ +import common from '@ohos.app.ability.common'; +import fs from '@ohos.file.fs'; +import Log from './Log'; + +/** + * ohos路径获取工具 + */ +const TAG: string = "PathUtils"; + +export default class PathUtils { + static getFilesDir(context: common.Context): string { + return context.filesDir; + } + + static getCacheDirectory(context: common.Context): string { + return context.cacheDir; + } + + static getDataDirectory(context: common.Context): string { + const name = "flutter"; + const flutterDir = context.filesDir + "/" + name; + if (!fs.accessSync(flutterDir)) { + try { + fs.mkdirSync(flutterDir); + } catch (err) { + Log.e(TAG, "mkdirSync failed err:" + err); + return null; + } + } + return flutterDir; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/StringUtils.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/StringUtils.ets new file mode 100644 index 0000000..595f870 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/StringUtils.ets @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import util from '@ohos.util' + +/** + * 默认字符串工具 + */ +export default class StringUtils { + static stringToArrayBuffer(str: string): ArrayBuffer { + let textEncoder = new util.TextEncoder("utf-8"); + return textEncoder.encodeInto(str).buffer; + } + + static arrayBufferToString(buffer: ArrayBuffer): string { + let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM : true }) + return textDecoder.decode(new Uint8Array(buffer)) + } + + static isNotEmpty(str: string): boolean { + return str != null && str.length > 0; + } + + static isEmpty(str: string): boolean { + return (!str) || str.length == 0; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ToolUtils.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ToolUtils.ets new file mode 100644 index 0000000..c3879f4 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/ToolUtils.ets @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export default class ToolUtils { + static isObj(object: Object): boolean { + return object && typeof (object) == 'object'; + } + + static implementsInterface(obj: ESObject, method: string): boolean { + return Reflect.has(obj, method) && typeof obj[method] === 'function' + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/TraceSection.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/TraceSection.ets new file mode 100644 index 0000000..3caaade --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/util/TraceSection.ets @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import hiTraceMeter from '@ohos.hiTraceMeter' + +export class TraceSection { + + static taskId: number = 1; + + private static cropSectionName(sectionName: string): string { + return sectionName.length < 124 ? sectionName : sectionName.substring(0, 124) + "..."; + } + + /** + * Wraps Trace.beginSection to ensure that the line length stays below 127 code units. + * + * @param sectionName The string to display as the section name in the trace. + */ + public static begin(sectionName: string): void { + hiTraceMeter.startTrace(TraceSection.cropSectionName(sectionName), TraceSection.taskId++); + } + + /** Wraps Trace.endSection. */ + public static end(sectionName: string): void { + hiTraceMeter.finishTrace(TraceSection.cropSectionName(sectionName), TraceSection.taskId); + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/AccessibilityBridge.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/AccessibilityBridge.ets new file mode 100644 index 0000000..0e08f41 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/AccessibilityBridge.ets @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export default class AccessibilityBridge { + constructor(){ + + } +} + +export enum Action { + TAP = 1 << 0, + LONG_PRESS = 1 << 1, + SCROLL_LEFT = 1 << 2, + SCROLL_RIGHT = 1 << 3, + SCROLL_UP = 1 << 4, + SCROLL_DOWN = 1 << 5, + INCREASE = 1 << 6, + DECREASE = 1 << 7, + SHOW_ON_SCREEN = 1 << 8, + MOVE_CURSOR_FORWARD_BY_CHARACTER = 1 << 9, + MOVE_CURSOR_BACKWARD_BY_CHARACTER = 1 << 10, + SET_SELECTION = 1 << 11, + COPY = 1 << 12, + CUT = 1 << 13, + PASTE = 1 << 14, + DID_GAIN_ACCESSIBILITY_FOCUS = 1 << 15, + DID_LOSE_ACCESSIBILITY_FOCUS = 1 << 16, + CUSTOM_ACTION = 1 << 17, + DISMISS = 1 << 18, + MOVE_CURSOR_FORWARD_BY_WORD = 1 << 19, + MOVE_CURSOR_BACKWARD_BY_WORD = 1 << 20, + SET_NEXT = 1 << 21, +}; \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets new file mode 100644 index 0000000..1c5f696 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView.ets @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ +import matrix4 from '@ohos.matrix4'; +import Log from '../../util/Log'; + +/** + * Dynamic View creation + * from a recursive data structure + * + * exported @Component: DynamicView + * exported view model classes: + * - DVModelContainer + * - DVModel + * - DVModelParameters + * - DVModelEvents + * - DVModelChildren + * + * The purpose of exporting the DVModel classes + * is to make them available to the converter from + * JD's XML format and the expression parser. These + * components are expected to generate and update the + * DVModel. + * + * An application written by JS should only import + * DynamicView, DVModelContainer to be used in their own ArkUI + * container view. + */ + +/** + * View Model classes + */ + +@Observed +export class DVModelParameters extends Object { + /* empty, just get any instance wrapped inside an ObservedObject + with the help of the decoration */ +} + +@Observed +export class DVModelEvents extends Object { + /* empty, just get any instance wrapped inside an ObservedObject + with the help of the decoration */ +} + +@Observed +export class DVModelChildren extends Array { + /* empty, just get any instance wrapped inside an ObservedObject + with the help of the decoration */ +} + +let nextId: number = 1; + +@Observed +export class DVModel { + id_: number; + compType: string; + params: DVModelParameters; + events: DVModelEvents; + children: DVModelChildren; + builder: ESObject; + + constructor(compType: string, params: DVModelParameters, events: DVModelEvents, children: DVModelChildren, builder?: ESObject) { + this.id_ = nextId++; + this.compType = compType; + this.params = params ?? new DVModelParameters; + this.events = events; + this.children = children; + this.builder = builder; + } + + public getLayoutParams(): DVModelParameters { + return this.params; + } +} + +// includes the root DVModel objects. +export class DVModelContainer { + model: DVModel; + + constructor(model: DVModel) { + this.model = model; + } +} + +/** + DynamicView is the @Component that does all the work: + + The following 4 features are the key solution elements for dynamic View + construction and update: + + 1. The if statement decides which framework component to create. + We can not use a factory function here, because that would requite calling + a regular function inside build() or a @Builder function. + + 2. Take note of the @Builder for Row, Column containers: + These functions create DynamicView Views inside a DynamicView + view. This behaviour is why we talk about DynamicView as a 'recursive' View. + All @Builder functions are member functions of the DynamicView @Component to + retain access ('this.xyz') to its decorated state variables. + + 3. The @Extend functions execute attribute and event handler registration functions + for all attributes and events permissable on the framework component, irrespective + if DVModelParameters or DVModelEvents objects includes a value or not. If not + the attribute or event is set to 'undefined' by intention. This is required to unset + any previously set value. + + 4. The scope ('this') of any lambda registered as an event hander function, e.g. for onClick, + is the @Component, in which the DVModel object is initialized. This said, it is advised to initialize + the DVModel object in the @Component that is parent to outmost DynamicView. Thereby, + any event handler function is able to mutate decorated state variables of that @Component + + */ + +@Component +export struct DynamicView { + @ObjectLink model: DVModel; + @ObjectLink children: DVModelChildren; + @ObjectLink params: DVModelParameters; + @ObjectLink events: DVModelEvents; + @BuilderParam customBuilder?: ($$: BuilderParams) => void; + + + getParams: (params: DVModelParameters, element: string) => string | ESObject = (params: DVModelParameters, element: string): string | ESObject => { + let params2 = params as Record; + return params2[element]; + } + + getEvents: (events: DVModelEvents, element: string) => ESObject = (events: DVModelEvents, element: string): ESObject => { + let events2 = events as Record; + return events2[element]; + } + /* + we use this @Styles member function to set all common attributes and event handlers + and set component specific attribute and event handler functions in the @Builder function + */ + @Styles common_attrs() { + .width(this.getParams(this.params, "width")) + .height(this.getParams(this.params, "height")) + .backgroundColor(this.getParams(this.params, "backgroundColor")) + .onClick(this.getEvents(this.events, "onClick")) + .margin({ + left: this.getParams(this.params, "marginLeft"), + right: this.getParams(this.params, "marginRight"), + top: this.getParams(this.params, "marginTop"), + bottom: this.getParams(this.params, "marginBottom") + }) + .onTouch(this.getEvents(this.events, "onTouch")) + .onFocus(this.getEvents(this.events, "onFocus")) + .onBlur(this.getEvents(this.events, "onBlur")) + .translate({ + x: this.getParams(this.params, "translateX"), + y: this.getParams(this.params, "translateY"), + z: this.getParams(this.params, "translateZ") + }) + .transform(this.getParams(this.params, "matrix")) + .direction(this.getParams(this.params, "direction")) + } + + @Styles clip_attrs() { + .clip(this.getParams(this.params, "rectWidth") ? new Rect({ + width: this.getParams(this.params, "rectWidth"), + height: this.getParams(this.params, "rectHeight"), + radius: this.getParams(this.params, "rectRadius") + }) : null) + .clip(this.getParams(this.params, "pathWidth") ? new Path({ + width: this.getParams(this.params, "pathWidth"), + height: this.getParams(this.params, "pathHeight"), + commands: this.getParams(this.params, "pathCommands") + }) : null) + } + + @Builder buildChildren() { + ForEach(this.children, + (child: ESObject) => { + DynamicView({ + model: child as DVModel, + params: child.params, + events: child.events, + children: child.children, + customBuilder: child.builder + }) + }, + (child: ESObject) => `${child.id_}` + ) + } + + @Builder buildRow() { + Row() { + this.buildChildren() + } + .common_attrs() + .clip_attrs() + } + + @Builder buildColumn() { + Column() { + this.buildChildren() + } + .common_attrs() + .clip_attrs() + } + + @Builder buildStack() { + Stack() { + this.buildChildren() + } + .common_attrs() + .clip_attrs() + .alignContent(this.getParams(this.params, "alignContent")) + } + + @Builder buildText() { + Text(`${this.getParams(this.params, "value")}`) + .common_attrs() + .fontColor(this.getParams(this.params, "fontColor")) + } + + @Builder buildImage() { + Image(this.getParams(this.params, "src")) + .common_attrs() + } + + // Button with label + @Builder buildButton() { + Button(this.getParams(this.params, "value")) + .common_attrs() + } + + @Builder buildCustom() { + if (this.customBuilder) { + this.customBuilder(new BuilderParams(this.params)); + } + } + + build() { + if (this.model.compType == "Column") { + this.buildColumn() + } else if (this.model.compType == "Row") { + this.buildRow() + } else if (this.model.compType == "Stack") { + this.buildStack() + } else if (this.model.compType == "Text") { + this.buildText() + } else if (this.model.compType == "Image") { + this.buildImage() + } else if (this.model.compType == "Button") { + this.buildButton() + } else { + this.buildCustom() + } + } +} + +export class BuilderParams { + params: DVModelParameters; + + constructor(params: DVModelParameters) { + this.params = params; + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets new file mode 100644 index 0000000..40b0529 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson.ets @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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. + */ + +import { DVModel, DVModelParameters, DVModelEvents, DVModelChildren } from "./dynamicView"; + +export function createDVModelFromJson(json: Object): DVModel { + + /* private use helper functions */ + let createChildrenFrom: (children: Array) => DVModelChildren = (children: Array): DVModelChildren => { + let result = new DVModelChildren(); + if (Array.isArray(children)) { + (children as Array).forEach(child => { + const childView = createDVModelFromJson(child); + if (childView != undefined) { + result.push(childView); + } + }); + } + return result; + } + + let setParams: (result: DVModelParameters | DVModelEvents, key: ESObject, element: Object ) => void = (result: DVModelParameters, key: ESObject, element: ESObject): void => { + let newResult = result as Record; + newResult[key] = element[key]; + } + + let createAttributesFrom: (attributes: Object) => DVModelParameters = (attributes: Object): DVModelParameters => { + let result = new DVModelParameters(); + if ((typeof attributes == "object") && (!Array.isArray(attributes))) { + Object.keys(attributes).forEach(k => {setParams(result, k, attributes)}); + } + return result; + } + + let createEventsFrom: (events: Object) => DVModelEvents = (events: Object): DVModelEvents => { + let result = new DVModelEvents(); + if ((typeof events == "object") && (!Array.isArray(events))) { + Object.keys(events).forEach(k => {setParams(result, k, events)}); + } + return result; + } + + if (typeof json !== 'object') { + console.error("createDVModelFromJson: input is not JSON"); + return new DVModel("", "", "", createChildrenFrom([])); + } + + let jsonObject = json as Record; + return new DVModel( + jsonObject["compType"], + createAttributesFrom(jsonObject["attributes"]), + createEventsFrom(jsonObject["events"]), + createChildrenFrom(jsonObject["children"]), + jsonObject["build"] + ); +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterCallbackInformation.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterCallbackInformation.ets new file mode 100644 index 0000000..2620272 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterCallbackInformation.ets @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import FlutterNapi from '../embedding/engine/FlutterNapi'; + +export class FlutterCallbackInformation { + callbackName: string; + callbackClassName: string; + callbackLibraryPath: string; + + /** + * Get callback information for a given handle. + * + * @param handle the handle for the callback, generated by `PluginUtilities.getCallbackHandle` in + * `dart:ui`. + * @return an instance of FlutterCallbackInformation for the provided handle. + */ + static lookupCallbackInformation(handle: number): FlutterCallbackInformation | null { + return FlutterNapi.nativeLookupCallbackInformation(handle); + } + + constructor(callbackName: string, callbackClassName: string, callbackLibraryPath: string) { + this.callbackName = callbackName; + this.callbackClassName = callbackClassName; + this.callbackLibraryPath = callbackLibraryPath; + } +} diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterNativeView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterNativeView.ets new file mode 100644 index 0000000..9138ad7 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterNativeView.ets @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import common from '@ohos.app.ability.common'; +import DartExecutor from '../embedding/engine/dart/DartExecutor'; +import { EngineLifecycleListener } from '../embedding/engine/FlutterEngine'; +import FlutterNapi from '../embedding/engine/FlutterNapi'; +import Log from '../util/Log'; +import FlutterPluginRegistry from '../app/FlutterPluginRegistry'; +import FlutterRunArguments from './FlutterRunArguments'; +import { FlutterView } from './FlutterView'; + +const TAG: string = "FlutterNativeView"; + +export default class FlutterNativeView { + private mContext: common.Context; + private mPluginRegistry: FlutterPluginRegistry; + private mFlutterNapi: FlutterNapi; + private dartExecutor: DartExecutor; + private mFlutterView: FlutterView; + private applicationIsRunning: boolean; + + constructor(context: common.Context, isBackgroundView?: boolean) { + if (isBackgroundView) { + Log.i(TAG, "isBackgroundView is no longer supported and will be ignored"); + } + this.mContext = context; + this.mPluginRegistry = new FlutterPluginRegistry(); + this.mFlutterNapi = new FlutterNapi(); + //this.mFlutterNapi.addIsDisplayingFlutterUiListener(this.flutterUiDisplayListener); + this.dartExecutor = new DartExecutor(this.mFlutterNapi, this.mContext.resourceManager); + this.mFlutterNapi.addEngineLifecycleListener(new EngineLifecycleListenerImpl(this.mFlutterView, this.mPluginRegistry)); + this.attach(this.mFlutterNapi, this.dartExecutor); + this.assertAttached(this.mFlutterNapi); + } + + attach(flutterNapi: FlutterNapi, dartExecutor: DartExecutor): void { + flutterNapi.attachToNative(); + dartExecutor.onAttachedToNAPI(); + } + + assertAttached(flutterNapi: FlutterNapi): void { + if (!this.isAttached(flutterNapi)) { + throw new Error('Platform View is not attached'); + } + } + + isAttached(flutterNapi: FlutterNapi): boolean { + return flutterNapi.isAttached(); + } + + detachFromFlutterView(): void { + this.mPluginRegistry.detach(); + this.mFlutterView = null; + } + + destroy(): void { + this.mPluginRegistry.destroy(); + this.dartExecutor.onDetachedFromNAPI(); + this.mFlutterView = null; + //this.mFlutterNapi.removeIsDisplayingFlutterUiListener(this.flutterUiDisplayListener); + this.applicationIsRunning = false; + } + + getDartExecutor(): DartExecutor { + return this.dartExecutor; + } + + getPluginRegistry(): FlutterPluginRegistry { + return this.mPluginRegistry; + } + + attachViewAndAbility(flutterView: FlutterView, context: common.Context): void { + this.mFlutterView = flutterView; + this.mPluginRegistry.attach(flutterView, context); + } + + runFromBundle(args: FlutterRunArguments): void { + if (args.entrypoint == null) { + throw new Error("an entrypoint must be specific"); + } + this.assertAttached(this.mFlutterNapi); + if (this.applicationIsRunning) { + throw new Error("this flutter engine instance is already running an application"); + } + this.mFlutterNapi.runBundleAndSnapshotFromLibrary(args.bundlePath, args.entrypoint, args.libraryPath, this.mContext.resourceManager, null); + this.applicationIsRunning = true; + } + + isApplicationRunning(): boolean { + return this.applicationIsRunning; + } + + // getObservatoryUri(): string { + // return this.mFlutterNapi.getObservatoryUri(); + // } +} + +class EngineLifecycleListenerImpl implements EngineLifecycleListener { + private flutterView: FlutterView; + private pluginRegistry: FlutterPluginRegistry; + + onPreEngineRestart(): void { + if (this.flutterView != null) { + //this.flutterView.resetAccessibilityTree(); + } + + if (this.pluginRegistry == null) { + return; + } + + this.pluginRegistry.onPreEngineRestart(); + } + + onEngineWillDestroy(): void { + + } + + constructor(flutterView: FlutterView, pluginRegistry: FlutterPluginRegistry) { + this.flutterView = flutterView; + this.pluginRegistry = pluginRegistry; + } +} + + diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterRunArguments.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterRunArguments.ets new file mode 100644 index 0000000..d17ec28 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterRunArguments.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export default class FlutterRunArguments { + public bundlePath: string; + public entrypoint: string; + public libraryPath: string; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterView.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterView.ets new file mode 100644 index 0000000..cf38a74 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/FlutterView.ets @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export class FlutterView { + +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/TextureRegistry.ets b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/TextureRegistry.ets new file mode 100644 index 0000000..a37ab97 --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/ets/view/TextureRegistry.ets @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export interface TextureRegistry { + + createSurfaceTexture(): SurfaceTextureEntry; + registerSurfaceTexture(): SurfaceTextureEntry; + + onTrimMemory(level: number) : void; +} + +interface SurfaceTextureEntry { + id(): number; + + release(): void; +} + +interface OnFrameConsumedListener { + onFrameConsumed(): void; +} + +interface OnTrimMemoryListener { + onTrimMemory(level: number) : void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/module.json b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/module.json new file mode 100644 index 0000000..776528e --- /dev/null +++ b/sqflite/ohos/sqflite/oh_modules/.ohpm/@ohos+flutter_ohos@9dd5beymeoxhsmtiwsbnrq8f9h8=/oh_modules/@ohos/flutter_ohos/src/main/module.json @@ -0,0 +1,20 @@ +{ + "app": { + "bundleName": "com.example.config", + "debug": true, + "versionCode": 1000000, + "versionName": "1.0.0", + "minAPIVersion": 40000010, + "targetAPIVersion": 40000010, + "apiReleaseType": "Release", + "compileSdkVersion": "4.0.0.40", + "compileSdkType": "HarmonyOS" + }, + "module": { + "name": "flutter", + "type": "har", + "deviceTypes": [ + "default" + ] + } +} diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets new file mode 100644 index 0000000..4668bdf --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Messages.ets @@ -0,0 +1,422 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import BasicMessageChannel from '@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; +import { SqlHelper } from './sql_helper'; + + +const TAG: string = "Message"; + +export default class Messages { + static wrapError(exception: Error): Array { + const errorList: Array = new Array(); + if (exception instanceof FlutterError) { + const error = exception; + errorList.push(error.code); + errorList.push(error.message); + errorList.push(error.details); + } else { + errorList.push(exception.name); + errorList.push(exception.message); + errorList.push(exception.stack); + } + return errorList; + } +} + +export class FlutterError extends Error { + code: string; + details: ESObject; + + constructor(code: string, message: string, details: ESObject) { + super(message); + this.code = code; + this.details = details; + } +} + +export abstract class SqfliteApi { + abstract getPlatformVersion(): string; + + /// 打开数据库 + abstract options(data: Map): Promise; + + /// 获取数据库存储的基本路径 + abstract getDatabasesPath(): string; + + /// 打开数据库 + abstract openDatabase(dataBaseName: string): Promise; + + /// 增加数据 + abstract insert(data: Map): Promise; + + /// 查询数据 + abstract query(data: Map): Promise>; + + /// 修改数据 + abstract update(data: Map): Promise; + + /// 关闭数据库 + abstract closeDatabase(dataBaseName: string): Promise; + + /// 删除数据库 + abstract deleteDatabase(dataBaseName: string): Promise; + + /// 执行sql语句 + abstract execute(data: Map): Promise; + + /// 检查数据库是否存在 + abstract databaseExists(dataBaseName: string): Promise; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: SqfliteApi) { + Log.i(TAG, "鸿蒙setup成功 "); + { + Log.i(TAG, "鸿蒙options初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.options", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用options成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 options 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + await api.options(message as Map); + wrapped.push(null); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙getPlatformVersion初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.getPlatformVersion", + SqfliteApi.getCodec()); + if (api != null) { + + channel.setMessageHandler({ + onMessage: (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用getPlatformVersion成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 getPlatformVersion 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + const output = api.getPlatformVersion(); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙getDatabasesPath初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.getDatabasesPath", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用getDatabasesPath成功 "); + let wrapped: Array = new Array(); + try { + const output = api.getDatabasesPath(); + Log.i(TAG, "getDatabasesPath 通道获取的数据: " + output as string); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙openDatabase初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.openDatabase", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用openDatabase成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 openDatabase 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + let dbName: string = SqlHelper.getLastPathName((message as Map).get('path')!.toString()); + const output = await api.openDatabase(dbName); + if (output >= 0) { + let returnMap = new Map(); + returnMap.set('id', output); + // todo 这里是不是需要自己写json返回去 + wrapped.push('{"id":1}'); + // wrapped.push(returnMap); + Log.i(TAG, "鸿蒙 openDatabase 通道创建数据库成功, 数据库id: " + output); + } else { + wrapped.push(null); + Log.i(TAG, "鸿蒙 openDatabase 通道创建数据库失败"); + } + } catch (err) { + Log.i(TAG, "鸿蒙 openDatabase 通道创建数据库在message出现异常: " + err); + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙insert初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.insert", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用insert成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 insert 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + const output = await api.insert(message as Map); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙query初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.query", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用query成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 query 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + const output = await api.query(message as Map); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + + { + Log.i(TAG, "鸿蒙update初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.update", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用update成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 update 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + const output = await api.update(message as Map); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + { + Log.i(TAG, "鸿蒙closeDatabase初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.closeDatabase", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用closeDatabase成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 closeDatabase 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + let dbName: string = SqlHelper.getLastPathName((message as Map).get('path') as string); + const output = await api.closeDatabase(dbName); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + + { + Log.i(TAG, "鸿蒙deleteDatabase初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.deleteDatabase", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用deleteDatabase成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 deleteDatabase 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + let dbName: string = SqlHelper.getLastPathName((message as Map).get('path') as string); + const output = await api.deleteDatabase(dbName); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + + { + Log.i(TAG, "鸿蒙execute初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.execute", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用execute成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 execute 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + const output = await api.execute(message as Map); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + + { + Log.i(TAG, "鸿蒙databaseExists初始化成功"); + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.SqfliteApi.databaseExists", + SqfliteApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: async (message: ESObject, reply: ESObject) => { + Log.i(TAG, "鸿蒙调用databaseExists成功 "); + let wrapped: Array = new Array(); + try { + Log.i(TAG, "鸿蒙 databaseExists 通道接收的数据: " + SqlHelper.mapToJson(message as Map)); + let dbName: string = SqlHelper.getLastPathName((message as Map).get('path') as string); + const output = await api.databaseExists(dbName); + wrapped.push(output); + } catch (err) { + const wrappedError: Array = Messages.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped); + } + }) + } else { + Log.i(TAG, "鸿蒙返回null "); + channel.setMessageHandler(null); + } + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets new file mode 100644 index 0000000..4484b22 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets @@ -0,0 +1,454 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import common from '@ohos.app.ability.common'; +import AbilityAware from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware'; +import { + AbilityPluginBinding +} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding'; +import { + FlutterPlugin, + FlutterPluginBinding +} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import MethodChannel, { + MethodCallHandler, + MethodResult +} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { SqfliteApi } from './Messages'; +import { SqfLiteHelper } from './sqflite_helper'; +import relationalStore from '@ohos.data.relationalStore'; +import { ValueType } from '@ohos.data.ValuesBucket'; +import { SqlHelper } from './sql_helper'; +import { Constant } from './constant'; +import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; + +const TAG: string = "SqflitePlugin"; + +export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, AbilityAware, MethodCallHandler { + private pluginBinding: FlutterPluginBinding | null = null; + private abilityPluginBinding: AbilityPluginBinding | null = null; + private context: common.Context | null = null; + private channel: MethodChannel | null = null; + + constructor(context?: common.Context) { + super(); + if (context) { + this.context = context; + } + } + + getUniqueClassName(): string { + return "SqflitePlugin"; + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + this.pluginBinding = binding; + this.channel = new MethodChannel(binding.getBinaryMessenger(), Constant.PLUGIN_KEY); + this.channel.setMethodCallHandler(this); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + this.pluginBinding = null; + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + Log.d(TAG, '-----onMethodCall step in ---' + call.method) + switch (call.method) { + case Constant.METHOD_OPEN_DATABASE: + this.handleOpenDatabaseCall(call, result); + break; + case Constant.METHOD_GET_DATABASES_PATH: + this.handleGetDatabasesPathCall(call, result); + break; + case Constant.METHOD_DATABASE_EXISTS: + this.handleDatabaseExistsCall(call, result); + break; + case Constant.METHOD_EXECUTE: + this.handleExecuteCall(call, result); + break; + case Constant.METHOD_INSERT: + this.handleInsertCall(call, result); + break; + case Constant.METHOD_QUERY: + this.handleQueryCall(call, result); + break; + case Constant.METHOD_UPDATE: + this.handleUpdateCall(call, result); + break; + case Constant.METHOD_BATCH: + this.handleBatchCall(call, result); + break; + case Constant.METHOD_OPTIONS: + this.handleOptionsCall(call, result); + break; + case Constant.METHOD_DEBUG_MODE: + this.handleDebugModeCall(call, result); + break; + case Constant.METHOD_GET_PLATFORM_VERSION: + this.handleGetPlatformVersionCall(call, result); + break; + case Constant.METHOD_CLOSE_DATABASE: + this.handleCloseDatabaseCall(call, result); + break; + case Constant.METHOD_DELETE_DATABASE: + this.handleDeleteDatabaseCall(call, result); + break; + default: + result.notImplemented(); + break; + } + } + + onAttachedToAbility(binding: AbilityPluginBinding): void { + Log.i(TAG, "flutter-sqflite-onAttachedToAbility"); + this.setup(this.pluginBinding!.getBinaryMessenger(), this.pluginBinding!.getApplicationContext()); + this.abilityPluginBinding = binding; + this.channel?.setMethodCallHandler(this); + } + + onDetachedFromAbility(): void { + } + + static registerWith(): void { + } + + setup(messenger: BinaryMessenger, context: common.Context) { + try { + SqfliteApi.setup(messenger, this); + } catch (err) { + Log.e(TAG, "Received exception while setting up SqflitePlugin", err); + } + this.context = context; + } + + async options(data: Map): Promise { + data.forEach((value, key) => { + Log.i(TAG, 'options收到数据: ' + key + ' -> ' + value); + }) + } + + getPlatformVersion(): string { + Log.i(TAG, "HarmonyOS 通信正常"); + return "HarmonyOS 通信正常"; + } + + //----------begin + ///打开数据库 + async handleOpenDatabaseCall(call: MethodCall, result: MethodResult): Promise { + let daPath: string = call.argument(Constant.PARAM_PATH); + await SqfLiteHelper.getDataBase(this.context!, daPath, result); + } + + ///获取数据库路径 + handleGetDatabasesPathCall(call: MethodCall, result: MethodResult) { + let appContext = this.context!.getApplicationContext(); + let path: string = appContext.databaseDir; + result.success(path); + } + + ///检查数据库是否存在 + async handleDatabaseExistsCall(call: MethodCall, result: MethodResult): Promise { + let daPath: string = call.argument(Constant.PARAM_PATH); + let isExist: boolean = await SqfLiteHelper.checkDatabaseExisted(daPath); + result.success(isExist); + } + + ///执行Sql + async handleExecuteCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + + let sql: string = call.argument(Constant.PARAM_SQL); + let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); + SqfLiteHelper.execute(sql, sqlArguments, call, result, rdbStore); + } + + ///插入数据 + async handleInsertCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + let sql: string = call.argument(Constant.PARAM_SQL); + let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); + await SqfLiteHelper.insertSql(sql, sqlArguments, call, result, rdbStore); + } + + ///查询数据 + async handleQueryCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + let sql: string = call.argument(Constant.PARAM_SQL); + let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); + let cursorPageSize: number | undefined = call.argument(Constant.PARAM_CURSOR_PAGE_SIZE); + await SqfLiteHelper.querySql(sql, sqlArguments, call, result, rdbStore, cursorPageSize); + } + + ///更新(包括删除)数据 + async handleUpdateCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + let sql: string = call.argument(Constant.PARAM_SQL); + let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); + await SqfLiteHelper.updateSql(sql, sqlArguments, call, result, rdbStore); + } + + ///batch操作 + async handleBatchCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + SqfLiteHelper.batch(call, result, rdbStore); + } + + ///Options操作,设置LogLevel,仅限开发,已废弃 + async handleOptionsCall(call: MethodCall, result: MethodResult): Promise { + SqfLiteHelper.options(call, result); + } + + ///设置debug模式,已废弃 + async handleDebugModeCall(call: MethodCall, result: MethodResult): Promise { + SqfLiteHelper.debugMode(call, result); + } + + ///获取设备信息 + async handleGetPlatformVersionCall(call: MethodCall, result: MethodResult): Promise { + SqfLiteHelper.getPlatformVersion(call, result); + } + + ///关闭数据库 + async handleCloseDatabaseCall(call: MethodCall, result: MethodResult): Promise { + let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); + if (rdbStore == null) { + return; + } + SqfLiteHelper.closeDataBase(call, result); + + } + + ///删除数据库 + async handleDeleteDatabaseCall(call: MethodCall, result: MethodResult): Promise { + let dataBaseName: string = call.argument(Constant.PARAM_PATH); + let res = await SqfLiteHelper.deleteDataBase(this.context!, dataBaseName); + if (res) { + result.success(null); + }else { + result.error('-1', 'Delete database faile', ''); + } + } + + //----------end + + /// 获取数据库的路径 + getDatabasesPath(): string { + let path: string = this.context!.getApplicationContext().databaseDir; + Log.i(TAG, "鸿蒙 获取数据库路径:" + path); + /// EL1 + return path; + } + + /// 打开数据库 + async openDatabaseByInvoke(call: MethodCall, result: MethodResult): Promise { + let dataBaseName: string = call.argument("path"); + // let id = await SqfLiteHelper.getDataBase(this.context!, dataBaseName) ?? -1; + // Log.i(TAG, "invoke鸿蒙 打开数据库结果:" + id); + result.success(-1); + } + + /// 打开数据库 + async openDatabase(dataBaseName: string): Promise { + // let id = await SqfLiteHelper.getDataBase(this.context!, dataBaseName) ?? -1; + // Log.i(TAG, "鸿蒙 打开数据库结果:" + id); + // result.success(id); + return -1; + } + + /// 插入数据 + async insert(data: Map): Promise { + Log.i(TAG, "鸿蒙 开始插入数据"); + + let rowId: number = -1; + let dbName: string = SqfLiteHelper.dBIdList.get(data.get('id')! as number) ?? ''; + Log.i(TAG, "鸿蒙 插入数据获取数据库名 :" + dbName); + let dataName: string[] = SqlHelper.getSqlDataName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 插入数据获取插入数据列 :" + dataName); + let tableName: string = SqlHelper.getInsertSqlTableName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 插入数据获取表名 :" + tableName); + + try { + Log.i(TAG, "鸿蒙 取到的arguments 1:" + JSON.stringify(data).toString()); + let txt: string = (data.get('arguments')! as string); + Log.i(TAG, "鸿蒙 取到的arguments 2:" + txt); + // let list: string[] = txt.split(",") as string[]; + // todo 这里的数据需要使用flutter传过来的才行 + let list: ValueType[] = [2, 'hi', 2000]; + Log.i(TAG, "鸿蒙 插入数据获取到的值:" + list.toString()); + const valuesBucket: relationalStore.ValuesBucket = {} + dataName.forEach((value, index) => { + valuesBucket[value] = list[index]; + }) + rowId = await SqfLiteHelper.insertData(dbName, tableName, valuesBucket); + Log.i(TAG, "鸿蒙 插入数据返回的行id:" + rowId); + } catch (e) { + Log.i(TAG, "鸿蒙 插入数据解析arguments出现异常" + e + rowId); + } + return rowId; + } + + /// 查询数据 + async query(data: Map): Promise> { + let returnMap: Map = new Map(); + let dbName: string = SqfLiteHelper.dBIdList.get(data.get('id')! as number) ?? ''; + Log.i(TAG, "鸿蒙 查询数据获取数据库名字 :" + dbName); + + if (dbName.length <= 0) { + Log.i(TAG, "鸿蒙 查询功能没有获取到数据库名字"); + return returnMap; + } + + if ((data.get('sql')! as string).includes('WHERE') == true) { + Log.i(TAG, "鸿蒙 开始查询数据"); + let tableName: string = SqlHelper.getQuerySqlTableName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 查询数据获取表名 :" + tableName); + let queryWhere: string[] = SqlHelper.getQuerySqlWhereName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 查询数据获取查询数据 :" + queryWhere); + // let querySELECT: string[] = SqfLiteHelper.getQuerySqlSELECTName(data.get('sql')! as string); + // Log.i(TAG, "鸿蒙 查询数据获取查询咧 :" + querySELECT); + let txt: string = (data.get('arguments')! as string); + // let list: string[] = txt.split(","); + // todo 这里的数据需要使用flutter传过来的才行 + let list: ValueType[] = [2]; + Log.i(TAG, "鸿蒙 查询数据获取查询值 :" + list.toString()); + Log.i(TAG, "鸿蒙 查询数据获取值完毕"); + Log.i(TAG, "鸿蒙 查询数据传入的数据queryWhere: " + queryWhere[0] + ", list:" + list[0]); + + // querySELECT 先不传 ,list[0] 很奇怪 + // let result = await rdb.query(predicates, querySELECT); + let result = await SqfLiteHelper.readOneData(dbName, tableName, queryWhere[0], list[0]); + if (result == null) return returnMap; + let rowsData: Object[] = []; + + result.forEach((value, key) => { + let row: Object[] = []; + value.forEach((v, k) => { + row.push(v); + }) + rowsData.push(row); + }) + + returnMap.set('columns', queryWhere); + returnMap.set('rows', rowsData); + Log.i(TAG, "鸿蒙 查询数据完毕"); + } else { + Log.i(TAG, "鸿蒙 开始检查表"); + const tableName = (data.get('sql')! as string).split(" FROM ")[1]; + Log.i(TAG, "鸿蒙 检查表, 表名 :" + tableName, '%{public}s'); + let result = await SqfLiteHelper.checkTable(dbName, tableName); + returnMap.set('checkTable', result); + } + return returnMap; + } + + /// 更新数据 + async update(data: Map): Promise { + Log.i(TAG, "鸿蒙 开始修改数据"); + let rowId: number = -1; + if ((data.get('sql') as string).includes('UPDATE')) { + let dbName: string = SqfLiteHelper.dBIdList.get(data.get('id')! as number) ?? ''; + Log.i(TAG, "鸿蒙 更新数据获取数据库名:" + dbName); + let tableName: string = SqlHelper.getUpdateSqlTableName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 更新数据获取表名:" + tableName); + let queryWhere: string[] = SqlHelper.getUpdateSqlWhereName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 更新数据获取where:" + queryWhere); + let querySET: string[] = SqlHelper.getUpdateSqlSETName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 更新数据获取列:" + querySET); + + let txt: string = (data.get('arguments')! as string); + // let list: string[] = txt.split(","); + // todo 这里的数据需要使用flutter传过来的才行 + let list: ValueType[] = ['hello', 2023, 2]; + Log.i(TAG, "鸿蒙 修改数据获取到的值:" + list.toString()); + const valuesBucket: relationalStore.ValuesBucket = {} + querySET.forEach((value, index) => { + valuesBucket[value] = list[index]; + }) + + /// todo where的参数在list的后面, 要根据那个where输入的长度来动态获取 + rowId = await SqfLiteHelper.updateData(dbName, tableName, queryWhere[0], list[list.length-1], valuesBucket); + Log.i(TAG, "鸿蒙 修改数据成功的行id:" + rowId); + } else { + rowId = await this.delete(data); + Log.i(TAG, "鸿蒙 删除数据成功的行id:" + rowId); + } + return rowId; + } + + /// 删除数据 + async delete(data: Map): Promise { + let rowId: number = -1; + + let dbName: string = SqfLiteHelper.dBIdList.get(data.get('id')! as number) ?? ''; + Log.i(TAG, "鸿蒙 删除数据获取数据库名:" + dbName); + let tableName: string = SqlHelper.getDeleteSqlTableName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 删除数据获取表名:" + tableName); + let queryWhere: string[] = SqlHelper.getDeleteSqlWhereName(data.get('sql')! as string); + Log.i(TAG, "鸿蒙 删除数据获取where:" + queryWhere); + + let txt: string = (data.get('arguments')! as string); + // let list: string[] = txt.split(","); + // todo 这里的数据需要使用flutter传过来的才行 + let list: ValueType[] = [2]; + Log.i(TAG, "鸿蒙 删除数据获取值:" + list.toString()); + rowId = await SqfLiteHelper.deleteData(dbName, tableName, queryWhere[0], list[0]); + + return rowId; + } + + /// 关闭一个数据库 + async closeDatabase(dataBaseName: string): Promise { + // SqfLiteHelper.closeDataBase(dataBaseName); + Log.i(TAG, "鸿蒙 关闭数据库成功"); + } + + /// 删除数据库 + async deleteDatabase(dataBaseName: string): Promise { + let result = await SqfLiteHelper.deleteDataBase(this.context!, dataBaseName); + Log.i(TAG, "鸿蒙 删除数据库成功"); + return result; + } + + /// 执行sql语句 + async execute(data: Map): Promise { + let dbName: string = SqfLiteHelper.dBIdList.get(data.get('id')! as number) ?? ''; + // await SqfLiteHelper.execute(dbName, data.get('sql')! as string); + Log.i(TAG, "鸿蒙 执行sql语句成功"); + } + + /// 检查数据库是否存在 + async databaseExists(dataBaseName: string): Promise { + let result: boolean = SqfLiteHelper.databaseExists(dataBaseName); + Log.i(TAG, "鸿蒙 查询数据库是否存在成功, 结果:" + result.toString()); + return result; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/constant.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/constant.ets new file mode 100644 index 0000000..c39b849 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/constant.ets @@ -0,0 +1,79 @@ +export class Constant { + // Can be used as the name MethodChannel or to register with + static PLUGIN_KEY: string = "com.tekartik.sqflite"; + + static METHOD_GET_PLATFORM_VERSION: string = "getPlatformVersion"; + static METHOD_GET_DATABASES_PATH: string = "getDatabasesPath"; + static METHOD_DEBUG: string = "debug"; + static METHOD_OPTIONS: string = "options"; + static METHOD_OPEN_DATABASE: string = "openDatabase"; + static METHOD_CLOSE_DATABASE: string = "closeDatabase"; + static METHOD_INSERT: string = "insert"; + static METHOD_EXECUTE: string = "execute"; + static METHOD_QUERY: string = "query"; + static METHOD_QUERY_CURSOR_NEXT: string = "queryCursorNext"; + static METHOD_UPDATE: string = "update"; + static METHOD_BATCH: string = "batch"; + static METHOD_DELETE_DATABASE: string = "deleteDatabase"; + static METHOD_DATABASE_EXISTS: string = "databaseExists"; + // true when entering, false when leaving, null otherwise, should be named inTransactionChange instead + static PARAM_IN_TRANSACTION_CHANGE: string = "inTransaction"; + // Set for calls within a transaction + static PARAM_TRANSACTION_ID: string = "transactionId"; + // Special transaction id used for recovering a locked database. + public TRANSACTION_ID_FORCE: number = -1; + // Result when opening a database + public PARAM_RECOVERED: string = "recovered"; + // Result when opening a database + public PARAM_RECOVERED_IN_TRANSACTION: string = "recoveredInTransaction"; + static PARAM_SQL: string = "sql"; + static PARAM_SQL_ARGUMENTS: string = "arguments"; + static PARAM_NO_RESULT: string = "noResult"; + static PARAM_CONTINUE_OR_ERROR: string = "continueOnError"; + static PARAM_COLUMNS: string = "columns"; + static PARAM_ROWS: string = "rows"; + // For query to use a cursor.Integer. + static PARAM_CURSOR_PAGE_SIZE: string = "cursorPageSize"; + // For queryCursorNext. Integer + static PARAM_CURSOR_ID: string = "cursorId"; + // For queryCursorNext. Integer + public PARAM_CANCEL: string = "cancel"; + // in each operation + static PARAM_METHOD: string = "method"; + // Batch operation results + public static PARAM_RESULT: string = "result"; + public static PARAM_ERROR: string = "error"; + // map with code/message/data + public static PARAM_ERROR_CODE: string = "code"; + public static PARAM_ERROR_MESSAGE: string = "message"; + public static PARAM_ERROR_DATA: string = "data"; + // android log tag + static TAG: string = "Sqflite"; + // Obsolete since 1.17 + static METHOD_DEBUG_MODE: string = "debugMode"; + static METHOD_ANDROID_SET_LOCALE: string = "androidSetLocale"; + // Locale tag + static PARAM_LOCALE: string = "locale"; + // public static final String[] + // static EMPTY_STRING_ARRAY = new String[0]; + static PARAM_ID: string = "id"; + static PARAM_PATH: string = "path"; + // when opening a database + static PARAM_READ_ONLY: string = "readOnly";// boolean + static PARAM_SINGLE_INSTANCE: string = "singleInstance";// boolean + static PARAM_LOG_LEVEL: string = "logLevel";// int + static PARAM_THREAD_PRIORITY: string = "androidThreadPriority";// int + static PARAM_THREAD_COUNT: string = "androidThreadCount";// int + + //debugMode + static PARAM_CMD: string = "cmd";// debugMode cmd:get/set + static CMD_GET: string = "get"; + // in batch + static PARAM_OPERATIONS: string = "operations"; + static SQLITE_ERROR: string = "sqlite_error";// code + static ERROR_BAD_PARAM: string = "bad_param";// internal only + static ERROR_OPEN_FAILED: string = "open_failed";// msg + static ERROR_DATABASE_CLOSED: string = "database_closed";// msg + // memory database path + static MEMORY_DATABASE_PATH: string = ":memory:"; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets new file mode 100644 index 0000000..84a7a74 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets @@ -0,0 +1,939 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import relationalStore from '@ohos.data.relationalStore'; +import common from '@ohos.app.ability.common'; +import MethodChannel, { + MethodCallHandler, + MethodResult +} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import { Tools } from './tools'; +import { BusinessError } from '@ohos.base'; +import { Constant } from './constant'; +import deviceInfo from '@ohos.deviceInfo'; +import { ValueType } from '@ohos.data.ValuesBucket'; +import { SqlHelper } from './sql_helper'; +import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; +import fs from '@ohos.file.fs'; + +const TAG: string = "SqfLiteHelper"; + +type HandleCallback = (x: Object) => void; + +export class SqfLiteHelper { + /// 已加载的数据库 + public static dataBaseList: Map = new Map(); + /// 加载的数据库的list + public static dBIdList: Map = new Map(); + /// 加载的数据库的list + private static databaseId: number = 0; + private static lastTransactionId: number = 0; + private static currentTransactionId: number | null; + private static transactionDepth: number = 0; + private static noResult: boolean; + private static insertResult: number = -1; + private static updateResult: number = -1; + private static queryResult: Map = new Map(); + private static operationError: OperationError; + + /// 创建一个数据库 + public static async getDataBase(context: common.Context, dbPath: string, result: MethodResult): Promise { + let id: number = -1; + let dbPathNameList: string[] = dbPath.split('/'); + let dbName: string = dbPathNameList[dbPathNameList.length - 1]; + let endWithDb: boolean = Tools.stringEndWith(dbName, '.db'); + + if (!endWithDb) { + dbName = dbName + '.db'; + } + + const isExisted: boolean = await SqfLiteHelper.checkDatabaseExisted(dbPath); + if (isExisted) { + // 从已有的数据库里面获取 + let local: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dbName); + if (local != null) { + Log.d(TAG, '~~createDatabase from local: ' + local); + SqfLiteHelper.dBIdList.forEach((value, key) => { + if (dbName == value) { + Log.d(TAG, '~~createDatabase from local DBId: ' + key); + id = key + } + }) + let map: Record = { + 'id': id, + 'recovered': false, + 'recoveredInTransaction': false, + } + result.success(map); + return id; + } + } + + // 自定义数据库路径 + let customDir: string = ''; + for (let index = 5; index < dbPathNameList.length - 1; index++) { + if (customDir.length > 0) { + customDir = customDir + '/' + dbPathNameList[index]; + } else { + customDir = dbPathNameList[index]; + } + } + + Log.i(TAG, '~~custom db Dir:' + customDir + ' system version:' + deviceInfo.osFullName, ''); + + // 从系统中获取 + let config: relationalStore.StoreConfig; + if (customDir.length > 0) { + config = { + name: dbName, // 数据库文件名 + securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别 + customDir: customDir, + }; + } else { + config = { + name: dbName, // 数据库文件名 + securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别 + } + } + + try { + let rdbStore = await relationalStore.getRdbStore(context, config); + Log.d(TAG, '~~createDatabase success' + dbName + ' 正常', '%{public}s'); + + SqfLiteHelper.dataBaseList.set(dbName, rdbStore); + SqfLiteHelper.databaseId = SqfLiteHelper.databaseId + 1; + id = SqfLiteHelper.databaseId; + SqfLiteHelper.dBIdList.set(id, dbName); + let map: Record = { + 'id': id, + 'recovered': false, + 'recoveredInTransaction': false, + } + result.success(map); + } catch (err) { + let code = (err as BusinessError).code; + let message = (err as BusinessError).message; + result.error(Constant.SQLITE_ERROR, message + '' + code, 'open database failed'); + Log.d(TAG, '~~createDatabase failed: ' + err + ' system version:' + deviceInfo.osFullName + '---api version:' + deviceInfo.sdkApiVersion + 'major version:' + deviceInfo.majorVersion + '--osReleaseType:' + deviceInfo.osReleaseType + 'displayVersion:' + deviceInfo.displayVersion + 'buildVersion:' + deviceInfo.buildVersion, '%{public}s'); + } + // result.error(Constant.SQLITE_ERROR, Constant.SQLITE_OPEN_FAILED + "" + path, null); + return id; + } + + /// 检查数据库是否存在 + public static async checkDatabaseExisted(dbPath: string): Promise { + let dbPathNameList: Array = dbPath.split('/'); + let dbName: string = dbPathNameList[dbPathNameList.length - 1]; + let endWithDb: boolean = Tools.stringEndWith(dbName, '.db'); + + // //获取应用的bundleName + // let bundleName: string = (await bundleManager.getBundleInfoForSelf(1)).name; + // Log.i(TAG, "Begin check databases exists bundleName:" + bundleName + '~~~'); + + let trueDbPath: string = ''; + if (dbPathNameList.length > 6) { + Log.i(TAG, "handleDatabaseExistsCall length > 5"); + for (let index = 0; index < dbPathNameList.length; index++) { + const element = dbPathNameList[index] as string; + if ((index < 5) || (index > 5 && index != dbPathNameList.length - 1)) { + trueDbPath = trueDbPath + element + '/'; + } else if (index == 5) { + trueDbPath = trueDbPath + 'rdb' + '/'; + trueDbPath = trueDbPath + element + '/'; + } else { + if (!endWithDb) { + trueDbPath = trueDbPath + element + '.db'; + } else { + trueDbPath = trueDbPath + element; + } + } + } + } else { + Log.i(TAG, "handleDatabaseExistsCall length <= 5"); + for (let index = 0; index < dbPathNameList.length; index++) { + const element = dbPathNameList[index] as string; + if (index != dbPathNameList.length - 1) { + trueDbPath = trueDbPath + element + '/'; + } else { + trueDbPath = trueDbPath + 'rdb' + '/'; + if (!endWithDb) { + trueDbPath = trueDbPath + element + '.db'; + } else { + trueDbPath = trueDbPath + element; + } + } + } + } + Log.i(TAG, "End check databases exists result:" + trueDbPath + ' ---length:' + dbPathNameList.toString() + '--:' + dbPathNameList.length); + let isExists: boolean = await fs.access(trueDbPath); + return isExists; + } + + /// 从已加载的列表里获取一个数据库 + private static getOnlyLocal(dataBaseName: string): relationalStore.RdbStore | null { + if (SqfLiteHelper.dataBaseList.has(dataBaseName)) { + return SqfLiteHelper.dataBaseList.get(dataBaseName) as relationalStore.RdbStore | null; + } + Log.i(TAG, '没有加载这个数据库', '%{public}s'); + return null; + } + + /// 从已加载的列表里获取一个数据库 + public static getDatabaseOrError(call: MethodCall, result: MethodResult): relationalStore.RdbStore | null { + let dataBaseId: number = call.argument("id"); + let databaseName: string | undefined = SqfLiteHelper.dBIdList.get(dataBaseId); + if (typeof databaseName == undefined) { + result.error('sqlite_error', "database_closed" + "" + dataBaseId, null); + return null; + } + let rdbStore = SqfLiteHelper.getOnlyLocal(databaseName as string); + if (rdbStore != null) { + return rdbStore; + } else { + result.error('sqlite_error', "database_closed" + "" + dataBaseId, null); + return null; + } + Log.i(TAG, '没有加载这个数据库', '%{public{}s'); + return null; + } + + /// 关闭一个数据库 + public static closeDataBase(call: MethodCall, result: MethodResult): void { + let databaseId: number = call.argument(Constant.PARAM_ID); + let dataBaseName: string | undefined = SqfLiteHelper.dBIdList.get(databaseId); + if (dataBaseName == undefined) return; + if (SqfLiteHelper.dataBaseList.has(dataBaseName)) { + SqfLiteHelper.dataBaseList.delete(dataBaseName); + let id: number = -1; + SqfLiteHelper.dBIdList.forEach((value, key) => { + if (dataBaseName == value) { + id = key; + } + }) + if (id > -1) { + SqfLiteHelper.dBIdList.delete(id); + result.success(null); + Log.i(TAG, '-----database close:' + dataBaseName + 'closed', ''); + return; + } + } + result.error('sqlite_error', "close database failed, database is not exist, can not close" + " " + databaseId, null); + } + + /// 删除一个数据库 + public static async deleteDataBase(context: common.Context, dataBaseName: string): Promise { + let result: boolean = false; + let dbNameList: string[] = dataBaseName.split('/'); + let dbName: string = dbNameList[dbNameList.length - 1]; + let endWithDb: boolean = Tools.stringEndWith(dbName, '.db'); + Log.i(TAG, 'step:-1 delete asction, got database name:' + dataBaseName + 'endWithDb:' + endWithDb); + if (!endWithDb) { + dbName = dbName + '.db'; + } + dataBaseName = dbName; + Log.i(TAG, 'step:0 delete action, got database name:' + dataBaseName + 'endWithDb:' + endWithDb); + if (SqfLiteHelper.dataBaseList.has(dataBaseName)) { + Log.i(TAG, 'step:1 already loaded database, trying delete' + dataBaseName); + SqfLiteHelper.dataBaseList.delete(dataBaseName); + let id: number = -1; + SqfLiteHelper.dBIdList.forEach((value, key) => { + if (dataBaseName == value) { + id = key; + } + }) + if (id > -1) { + SqfLiteHelper.dBIdList.delete(id); + await relationalStore.deleteRdbStore(context, dataBaseName); + Log.i(TAG, 'step:2 already deleted ' + dataBaseName + ' 数据库', '%{public}s'); + result = true; + } + } else { + Log.i(TAG, 'step:3 unload database, trying delete' + dataBaseName); + try { + // todo 这里需要注意一下 + if (await SqfLiteHelper.checkTable(dataBaseName, 'defaultTable') == true) { + await SqfLiteHelper.deleteTable(dataBaseName, 'defaultTable'); + } + await relationalStore.deleteRdbStore(context, dataBaseName); + Log.i(TAG, 'step:4 already deleted ' + dataBaseName + ' 数据库', '%{public}s'); + result = true; + } catch (e) { + Log.i(TAG, 'step:5 deleted database error' + e, '%{public}s'); + } + } + // Log.i(TAG, 'can not found this database, delete faired', '%{public}s'); + return result; + } + + public static async insert(call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise { + + let rowId: number = -1; + let list: ValueType[] = call.argument(Constant.PARAM_SQL_ARGUMENTS); + let sqlString: string = call.argument(Constant.PARAM_SQL)! as string; + Log.i(TAG, "insert data, get sqlString:" + sqlString + '--------' + arguments); + + if (list == undefined || list.length < 1) { + + try { + // let tableName: string = SqlHelper.getRawInsertSqlTableName(sqlString); + // Log.i(TAG, "insert data, get tableName1:" + tableName); + // + // let dataNames: string[] = SqlHelper.getRawSqlDataName(sqlString); + // Log.i(TAG, "insert data, get dataName1:" + dataNames); + // + // let dataValues: string[] = SqlHelper.getRawSqlDataValues(sqlString); + // Log.i(TAG, "insert data, get dataValues:" + dataValues); + + const valuesBucket: relationalStore.ValuesBucket = {} + // dataNames.forEach((value, index) => { + // valuesBucket[value] = dataValues[index]; + // }) + + // rowId = await dataBase.insert(tableName, valuesBucket); + // Log.i(TAG, "insert data, return row id:" + rowId); + // result.success(rowId); + } catch (err) { + let code = (err as BusinessError).code; + let message = (err as BusinessError).message; + result.error(Constant.SQLITE_ERROR, message + '' + code, 'insert data, failed'); + } + } else { + try { + let dataName: string[] = SqlHelper.getSqlDataName(sqlString); + let tableName: string = SqlHelper.getInsertSqlTableName(sqlString); + + const valuesBucket: relationalStore.ValuesBucket = {} + dataName.forEach((value, index) => { + valuesBucket[value] = list[index]; + }) + + rowId = await dataBase.insert(tableName, valuesBucket); + Log.i(TAG, "insert data, return row id:" + rowId); + result.success(rowId); + } catch (err) { + let code = (err as BusinessError).code; + let message = (err as BusinessError).message; + result.error(Constant.SQLITE_ERROR, message + '' + code, 'insert data, failed'); + } + } + + return rowId; + } + + /// 插入一条数据 + public static async insertSql(sql: string, sqlArguments: ValueType[] | undefined, call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise { + + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + String + let tableName: string = SqlHelper.getInsertSqlTableName(sql); + Log.i(TAG, "insertSql data: get tableName :" + tableName + databaseName); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if (tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table:' + tableName, ''); + return false; + } + + return await SqfLiteHelper.execute(sql, sqlArguments, call, result, dataBase, (rows) => { + SqfLiteHelper.insertResult = rows as number; + result.success(rows); + }); + } + + /// 执行一个sql语句 + public static async execute(sql: string, sqlArguments: ValueType[] | undefined, call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore, callback?: HandleCallback): Promise { + Log.i(TAG, "lz execute" + ' sql:' + sql + '---sqlArguments:' + sqlArguments); + + let inTransactionChange: Boolean = SqfLiteHelper.getInTransactionChange(call); + let enteringTransaction: boolean = (inTransactionChange == true && SqfLiteHelper.hasNullTransactionId(call)); + if (enteringTransaction) { + SqfLiteHelper.currentTransactionId = ++(SqfLiteHelper.lastTransactionId); + } + if (!SqfLiteHelper.executeOrError(sql, sqlArguments, call, result, dataBase)) { + // Revert if needed + if (enteringTransaction) { + SqfLiteHelper.currentTransactionId = null; + } + return false; + } else if (enteringTransaction) { + /// Return the transaction id + if (SqfLiteHelper.currentTransactionId != null) { + let res: Map = new Map(); + res.set(Constant.PARAM_TRANSACTION_ID, SqfLiteHelper.currentTransactionId); + result.success(res); + } else { + result.success(null); + } + } else { + if (inTransactionChange == false) { + SqfLiteHelper.currentTransactionId = null; + } + + if (callback != undefined) { + callback(1); + } else { + result.success(null); + } + } + return true; + } + + /// 读取一条数据 + public static async querySql(sql: string, sqlArguments: ValueType[] | undefined, call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore, cursorPageSize: number | undefined): Promise { + + if(sql == 'PRAGMA user_version') { + let results: Map = new Map(); + results.set(Constant.PARAM_COLUMNS, ['user_version']); + results.set(Constant.PARAM_ROWS, [[dataBase.version]]); + result.success(results); + return true; + } + + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + let tableName: string = SqlHelper.getQuerySqlTableName(sql); + Log.i(TAG, "querySql data: get tableName :" + tableName + databaseName); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if(tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table: ' + tableName, ''); + return false; + } + + let suc: boolean = false; + if(sqlArguments != undefined && sqlArguments.length > 0) { + try{ + await dataBase.querySql(sql, sqlArguments, (err, resultSet) => { + suc = SqfLiteHelper.handleQuerySql1(result, err, resultSet, cursorPageSize); + }); + return suc; + } catch(err) { + SqfLiteHelper.handleSqliteError(result, err); + return false; + } + } else { + try{ + await dataBase.querySql(sql, (err, resultSet) => { + suc = SqfLiteHelper.handleQuerySql1(result, err, resultSet, cursorPageSize); + }) + return suc; + } catch(err) { + SqfLiteHelper.handleSqliteError(result, err); + return false; + } + } + } + + private static handleQuerySql1(result: MethodResult, err: BusinessError, resultSet: relationalStore.ResultSet, cursorPageSize: number | undefined): boolean { + if (err) { + SqfLiteHelper.handleSqliteError(result, err); + return false; + } + let results: Map = new Map(); + let rows: Array> = new Array>(); + let columns: Array | null = null; + let columnCount: number = 0; + + // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。 + while (resultSet.goToNextRow()) { + if (columns == null) { + columnCount = resultSet.columnCount; + columns = new Array(); + rows = new Array>(); + for (let i = 0; i < columnCount; i++) { + columns.push(resultSet.getColumnName(i)); + } + results.set(Constant.PARAM_COLUMNS, columns); + results.set(Constant.PARAM_ROWS, rows); + } + + let row = SqfLiteHelper.cursorRowToList(resultSet, columnCount); + rows.push(row); + if (cursorPageSize != null) { + if (rows.length >= cursorPageSize) { + break; + } + } + } + + let str = JSON.stringify(results) + Log.d(TAG, "query data result: " + str.toString()); + + SqfLiteHelper.queryResult = results; + result.success(results); + // 释放数据集的内存 + resultSet.close(); + return true; + } + + static cursorRowToList(cursor: relationalStore.ResultSet, length: number): Array { + let list = new Array(); + + for (let i = 0; i < length; i++) { + let value: Object = SqfLiteHelper.cursorValue(cursor, i); + // let value: Object = 'cursorValue(cursor, i)'; + // if(Debug.EXTRA_LOGV){ + // String type = null; + // if(value != null){ + // if(value.getClass().isArray()) { + // type = "array(" + value.getClass().getComponentType().getName() + ")"; + // } else { + // type = value.getCalss().getName(); + // } + // } + // Log.d(TAG, "column " + i + "" + cursor.getType(i) + ": " + value + (type == null ? "" : "(" + type + ")")); + // } + list.push(value); + } + return list; + } + + static cursorValue(cursor: relationalStore.ResultSet, index: number): string { + return cursor.getString(index); + } + + /// 更新/删除数据--使用Sql方式 + public static async updateSql(sql: string, sqlArguments: ValueType[] | undefined, call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise { + + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + let tableName: string = SqlHelper.getUpdateSqlTableName(sql); + Log.i(TAG, "updataSql data: get tableName:" + tableName + databaseName); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if (tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table:' + tableName, ''); + return false; + } + + return SqfLiteHelper.execute(sql, sqlArguments, call, result, dataBase, (rows) => { + SqfLiteHelper.updateResult = rows as number; + result.success(rows); + }); + } + + /// batch操作 + public static async batch(call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise { + + result.error(Constant.SQLITE_ERROR, 'ohos does not currently support batch operations', '') + return; + // let noResult: boolean = SqfLiteHelper.getNoResult(call); + // SqfLiteHelper.noResult = noResult; + // let continueOnError: boolean = SqfLiteHelper.getContinueOnError(call); + // + // let operations: Array> = SqfLiteHelper.getAragument(call, Constant.PARAM_OPERATIONS) as Array>; + // let results: Array> = new Array(); + // + // for(let index = 0; index < operations.length; index++) { + // const map: Map = operations[index]; + // const method: string = map.get(Constant.PARAM_METHOD) as string; + // + // let sql: string = map.get(Constant.PARAM_SQL) as string; + // let sqlArguments: ValueType[] | undefined = map.get(Constant.PARAM_SQL_ARGUMENTS) as (ValueType[] | undefined); + // let cursorPageSize: number | undefined = call.argument(Constant.PARAM_CURSOR_PAGE_SIZE); + // + // Log.i(TAG, "hanle batch:" + method + '----' + sql + ' map:' + map.toString() + 'operations:' + operations.toString()); + // + // switch(method) { + // case Constant.METHOD_EXECUTE: + // if(await SqfLiteHelper.execute(sql, sqlArguments, call, result, dataBase)) { + // SqfLiteHelper.handleSuccess(results, ''); + // } else if(continueOnError) { + // SqfLiteHelper.handleErrorContinue(results); + // } else { + // return; + // } + // break; + // case Constant.METHOD_INSERT: + // if(await SqfLiteHelper.insertSql(sql, sqlArguments, call, result, dataBase)) { + // SqfLiteHelper.handleSuccess(results, SqfLiteHelper.insertResult); + // } else if(continueOnError) { + // SqfLiteHelper.handleErrorContinue(results); + // } else { + // SqfLiteHelper.handleError(result); + // return; + // } + // break; + // case Constant.METHOD_QUERY: + // if(await SqfLiteHelper.querySql(sql, sqlArguments, call, result, dataBase, cursorPageSize)) { + // SqfLiteHelper.handleSuccess(results, SqfLiteHelper.queryResult); + // } else if(continueOnError) { + // SqfLiteHelper.handleErrorContinue(results); + // } else { + // SqfLiteHelper.handleError(result); + // return; + // } + // break; + // case Constant.METHOD_UPDATE: + // if(await SqfLiteHelper.updataSql(sql, sqlArguments, call, result, dataBase)) { + // SqfLiteHelper.handleSuccess(results, SqfLiteHelper.updataResult); + // } else if(continueOnError) { + // SqfLiteHelper.handleErrorContinue(results); + // } else { + // SqfLiteHelper.handleError(result); + // return; + // } + // break; + // default: + // result.error(Constant.ERROR_BAD_PARAM, "Batch method" + method + "no supported", null); + // return; + // } + // } + // Log.d(TAG, "handle batch result data SUCCESS:" + typeof results + '-----' + results + '------q:' + JSON.stringify(results) + 'noResult:' + noResult); + // if(noResult) { + // result.success(null); + // } else { + // result.success(results); + // } + //SqfLiteHelper.execute(call, result, dataBase, (rows) => result.success(rows)); + } + + /// Options操作,设置LogLevel,仅限开发,已被废弃 + public static async options(call: MethodCall, result: MethodResult): Promise { + let logLevel: number | undefined = call.argument(Constant.PARAM_LOG_LEVEL); + Log.i(TAG, "handle options:" + logLevel); + result.success(null); + } + + /// 设置debug模式,查看SQL查询,已弃用 + public static async debugMode(call: MethodCall, result: MethodResult): Promise { + let on: boolean = call.args; + Log.i(TAG, "debugMode:" + on); + result.success(null); + } + + /// 获取设备版本信息 + public static async getPlatformVersion(call: MethodCall, result: MethodResult): Promise { + result.success('ohos' + deviceInfo.osFullName); + } + + + private static async executeOrError(sql: string, sqlArguments: ValueType[] | undefined, call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise { + + let operationInTransaction: boolean = SqfLiteHelper.getInTransactionChange(call); + try { + if (sqlArguments == undefined || sqlArguments.length < 1) { + await dataBase.executeSql(sql); + } else { + await dataBase.executeSql(sql, sqlArguments); + } + SqfLiteHelper.enterOrLeaveInTransaction(operationInTransaction); + return true; + } catch (err) { + let code = (err as BusinessError).code; + let message = (err as BusinessError).message; + result.error(Constant.SQLITE_ERROR, message + '' + code + sql, sql); + SqfLiteHelper.operationError = new OperationError(code.toString(), message, sql); + Log.i(TAG, "lz execute error: " + message + '--sql:' + sql + '--code:' + code); + return false; + } + // try{ + // getWritableDatabase().execSQL(command.getSql(), command.getSqlArguments()); + // enterOrLeaveInTransaction(operationInTransaction); + // return true; + // } catch(Exception exception) { + // handleException(exception, operation); + // return false; + // } + } + + private static enterOrLeaveInTransaction(value: boolean): void { + if (value == true) { + SqfLiteHelper.transactionDepth++; + } else if (value == false) { + SqfLiteHelper.transactionDepth--; + } + } + + private static hasNullTransactionId(call: MethodCall): boolean { + let rawId: object = call.argument(Constant.PARAM_TRANSACTION_ID); + if (rawId == null || rawId == undefined) { + return true; + } + return false; + } + + private static getInTransactionChange(call: MethodCall): boolean { + let inTransactionChange: object = call.argument(Constant.PARAM_IN_TRANSACTION_CHANGE); + Log.i(TAG, 'inTransactionChange' + 'type:' + typeof inTransactionChange); + if (inTransactionChange instanceof Boolean) { + return inTransactionChange.valueOf(); + } + return false; + } + + private static getTransactionId(call: MethodCall): Number | undefined { + let rawId: object = call.argument(Constant.PARAM_TRANSACTION_ID); + if (rawId instanceof Number) { + return rawId; + } + return undefined; + } + + /// Sqlite错误处理 + private static handleSqliteError(result: MethodResult, err: BusinessError) { + let code = err.code; + let message = err.message; + result.error(Constant.SQLITE_ERROR, message + '' + code, ''); + } + + private static getNoResult(call: MethodCall): boolean { + let noResult: boolean = call.argument(Constant.PARAM_NO_RESULT); + return noResult; + } + + private static getContinueOnError(call: MethodCall): boolean { + let noResult: boolean = call.argument(Constant.PARAM_CONTINUE_OR_ERROR); + return noResult; + } + + private static getArgument(call: MethodCall, key: string): object { + return call.argument(key); + } + + public static handleError(result: MethodResult) { + result.error(SqfLiteHelper.operationError.errorCode, SqfLiteHelper.operationError.errorMessage, SqfLiteHelper.operationError.errorData); + } + + private static handleErrorContinue(results: Array>) { + if (!SqfLiteHelper.noResult) { + let error: Map = new Map(); + let errorDetail: Map = new Map(); + errorDetail.set(Constant.PARAM_ERROR_CODE, SqfLiteHelper.operationError.errorCode); + errorDetail.set(Constant.PARAM_ERROR_MESSAGE, SqfLiteHelper.operationError.errorMessage); + errorDetail.set(Constant.PARAM_ERROR_DATA, SqfLiteHelper.operationError.errorData); + + error.set(Constant.PARAM_ERROR_DATA, errorDetail); + results.push(error); + } + } + + + /// 检查数据库 + public static databaseExists(dataBaseName: string): boolean { + // let sql: string = "SHOW DATABASES LIKE " + dataBaseName; + // + // let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + // if (dataBase == null) return success; + + // todo 这里还没有实现 + return true; + } + + /// 检查表 + public static async checkTable(dataBaseName: string, tableName: string): Promise { + let success: boolean = false; + + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return success; + try { + let predicates = new relationalStore.RdbPredicates(tableName); + predicates.isNull('id'); + let result = await dataBase.query(predicates); + if (result.columnCount > 0) { + Log.i(TAG, '检查表' + tableName + '已存在', '%{public}s'); + success = true; + } else { + Log.i(TAG, '检查表' + tableName + '不存在', '%{public}s'); + } + } catch (e) { + Log.i(TAG, '检查表' + tableName + '出现异常: ' + e, '%{public}s'); + } + + return success; + } + + /// 创建表 + public static async createTable(dataBaseName: string, tableName: string, data: string = ''): Promise { + let success: boolean = false; + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return success; + + try { + await dataBase.executeSql('CREATE TABLE IF NOT EXISTS ' + tableName + '(' + data + ')') + Log.i(TAG, '创建表' + tableName + '成功', '%{public}s'); + success = true; + } catch (e) { + Log.i(TAG, '创建表' + tableName + '出现异常: ' + e, '%{public}s'); + } + return success; + } + + /// 删除表 + public static async deleteTable(dataBaseName: string, tableName: string): Promise { + let success: boolean = false; + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return success; + let checkTableSql = 'DROP TABLE ' + tableName; + try { + await dataBase.executeSql(checkTableSql); + Log.i(TAG, '删除表' + tableName + '成功', '%{public}s'); + success = true; + } catch (e) { + Log.i(TAG, '删除表' + tableName + '出现异常: ' + e, '%{public}s'); + } + return success; + } + + /// 插入一条数据 + public static async insertData(dataBaseName: string, tableName: string, valuesBucket: relationalStore.ValuesBucket): Promise { + let rowId: number = -1; + + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return rowId; + + try { + rowId = await dataBase.insert(tableName, valuesBucket); + if (rowId >= 0) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表插入数据成功, 行id: ' + rowId, '%{public}s'); + } else { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表插入数据返回值不正常: ' + rowId, '%{public}s'); + } + } catch (e) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表插入数据出现异常: ' + e.code + '---' + e.message, '%{public}s'); + } + return rowId; + } + + /// 读取一条数据 + /// [columns] 查询的咧 + /// [queryColumnName] 对应的列的名称 + /// [queryColumnData] 对应的列的值 + public static async readOneData(dataBaseName: string, tableName: string, queryColumnName: string, queryColumnData: relationalStore.ValueType, columns: Array = []): Promise> | null> { + let maps: Map> = new Map>(); + try { + Log.i(TAG, "新的>查询数据执行readOneData"); + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return null; + let predicates = new relationalStore.RdbPredicates(tableName); + predicates.equalTo(queryColumnName, queryColumnData); + + let resultSet = await dataBase.query(predicates, columns); + Log.i(TAG, "新的>鸿蒙查询数据成功"); + while (resultSet.goToNextRow()) { + let map: Map = new Map(); + for (let i = 0; i < resultSet.columnCount; i++) { + let key = resultSet.getColumnName(i); + let value = resultSet.getString(i); + map.set(key, value); + } + Log.i(TAG, '取出的值 -> ' + map, '%{public}s'); + maps.set(maps.size.toString(), map); + } + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表读取数据成功: ', '%{public}s'); + return maps; + } catch (e) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表读取数据出现异常: ' + e.code + '---' + e.message, '%{public}s'); + } + return null; + } + + /// 更新一条数据 + public static async updateData(dataBaseName: string, tableName: string, queryColumnName: string, queryColumnData: relationalStore.ValueType, valuesBucket: relationalStore.ValuesBucket): Promise { + let rowId: number = 0; + try { + Log.i(TAG, "新的>更新数据执行updateData"); + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return rowId; + + let predicates = new relationalStore.RdbPredicates(tableName); + predicates.equalTo(queryColumnName, queryColumnData); + + rowId = await dataBase.update(valuesBucket, predicates); + Log.i(TAG, "新的>鸿蒙更新数据成功"); + if (rowId > 0) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表更新数据成功, 影响行数: ' + rowId, '%{public}s'); + } else { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表更新数据成功, 返回值不正常: ' + rowId, '%{public}s'); + } + } catch (e) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表更新数据出现异常: ' + e.code + '---' + e.message, '%{public}s'); + } + return rowId; + } + + /// 删除一条数据 + public static async deleteData(dataBaseName: string, tableName: string, queryColumnName: string, queryColumnData: relationalStore.ValueType): Promise { + let rowId: number = -1; + + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return rowId; + + try { + let predicates = new relationalStore.RdbPredicates(tableName); + predicates.equalTo(queryColumnName, queryColumnData); + rowId = await dataBase.delete(predicates); + if (rowId >= 0) { + // todo 这里删除0行暂时视为成功 + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表删除数据成功, 影响行数: ' + rowId, '%{public}s'); + } else { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表删除数据失败, 影响行数: ' + rowId, '%{public}s'); + } + } catch (err) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表删除数据出现异常: ' + err.message, '%{public}s'); + } + return rowId; + } + + /// 为一个表添加一个新的属性 + public static async addNewProperty(dataBaseName: string, tableName: string, propertyName: string): Promise { + let success: boolean = false; + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return false; + + try { + await dataBase.executeSql('ALTER TABLE ' + tableName + ' ADD ' + propertyName); + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表添加属性成功', '%{public}s'); + success = true; + } catch (err) { + Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表添加属性出现异常: ' + err.message, '%{public}s'); + } + return success; + } + + /// 为一个表删除一个的属性 + public static async deleteProperty(dataBaseName: string, tableName: string, propertyName: string): Promise { + let success: boolean = false; + let dataBase: relationalStore.RdbStore | null = SqfLiteHelper.getOnlyLocal(dataBaseName); + if (dataBase == null) return false; + + try { + await dataBase.executeSql('ALTER TABLE ' + tableName + ' DROP COLUMN ' + propertyName); + success = true; + // Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表删除属性成功', '%{public}s'); + } catch (err) { + // Log.i(TAG, dataBaseName + ' 的 ' + tableName + ' 表删除属性出现异常: ' + err.message, '%{public}s'); + } + return success; + } +} + +class OperationError { + public errorCode: string; + public errorMessage: string; + public errorData: string; + + constructor(errorCode: string, errorMessage: string, errorData: string) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.errorData = errorData; + } +} + + + + diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sql_helper.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sql_helper.ets new file mode 100644 index 0000000..494bbff --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sql_helper.ets @@ -0,0 +1,216 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* 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. +*/ + +export class SqlHelper { + /// 分离sql的属性部分 + public static getSqlDataName(jsonStr: string): string[] { + // 提取属性部分 + // let pattern = new RegExp('INSERT INTO (\\w+) \\(([^()]+)\\)'); + let pattern = new RegExp('INSERT OR REPLACE INTO (\\w+) \\(([^()]+)\\)'); + const propertiesMatch = pattern.exec(jsonStr); + const propertiesStr = propertiesMatch ? propertiesMatch[2] : ''; // 提取属性部分的字符串 + const properties = propertiesStr.split(',').map(prop => prop.trim()); // 将属性部分字符串拆分为数组 + return properties; + } + + /// 分离sql的值部分 + public static getSqlData(jsonStr: string): string[] { + // 提取值部分 + const valuesRegex = '/VALUES \(([^)]+)\)/'; // 匹配VALUES括号内的值部分 + const valuesMatch = jsonStr.match(valuesRegex); + const valuesStr = valuesMatch ? valuesMatch[1] : ''; // 提取值部分的字符串 + const values = valuesStr.split(',') + .map(val => val.trim()) + .map(val => val.replace('/\?/g', '')); // 将值部分字符串拆分为数组,并去掉问号 + return values; + } + + /// 分离sql的表名部分 + public static getInsertSqlTableName(jsonStr: string): string { + // 提取表名 + let firstMatch: number = jsonStr.search('INSERT OR REPLACE INTO'); + let pattern: RegExp; + if (firstMatch >= 0) { + pattern = new RegExp('INSERT OR REPLACE INTO (\\w+) \\(([^()]+)\\)'); + }else { + pattern = new RegExp('INSERT INTO (\\w+)'); + } + // let pattern = new RegExp('INSERT INTO (\\w+) \\(([^()]+)\\)'); + const propertiesMatch = pattern.exec(jsonStr); + const propertiesStr = propertiesMatch ? propertiesMatch[1] : ''; // 提取属性部分的字符串 + return propertiesStr; + } + + /// 分离sql的表名部分 + public static getQuerySqlTableName(jsonStr: string): string { + // 提取表名 + let pattern = new RegExp("FROM\\s+(\\w+)") + let match = pattern.exec(jsonStr) + if (match == null) return ''; + return match[1]; + } + + /// 分离sql的Where部分 + public static getQuerySqlWhereName(jsonStr: string): string[] { + + // 提取表名 + let pattern = new RegExp("SELECT \\* FROM (\\w+) WHERE (\\w+ = \\?)(?: AND (\\w+ = \\?))*") + let match = pattern.exec(jsonStr) + if (match == null) return []; + const whereClauses: string[] = match.slice(2).filter((clause: string) => clause !== undefined); + + const whereColumns: string[] = whereClauses.filter((clause) => clause.includes('=')) + .map((clause) => clause.split('=')[0].trim()); + return whereColumns; + } + + /// 分离sql的SELECT部分 + public static getQuerySqlSELECTName(jsonStr: string): string[] { + // 提取SELECT后面的参数 + const selectParamsRegex = '/SELECT\s+([^\s]+)\s+FROM/'; // 正则表达式匹配SELECT和FROM之间的参数 + const selectParamsMatch = jsonStr.match(selectParamsRegex); + const selectParams = selectParamsMatch ? selectParamsMatch[1].split(',') : []; // 将参数按逗号分隔成数组 + return selectParams; + } + + /// 分离sql的表名部分 + public static getUpdateSqlTableName(jsonStr: string): string { + let firstMatch:number = jsonStr.search('UPDATE'); + let pattern: RegExp; + if (firstMatch >= 0) { + pattern = new RegExp('UPDATE\\s+(\\w+)'); + }else { + pattern = new RegExp('DELETE FROM\\s+(\\w+)'); + } + + let match = pattern.exec(jsonStr); + if (match == null) return ''; + return match[1]; + } + + /// 分离sql的Where部分 + public static getUpdateSqlWhereName(jsonStr: string): string[] { + // 提取WHERE后面的参数 + const wherePattern: RegExp = new RegExp('WHERE\\s+([^]+?)\\s*$'); // 匹配WHERE后面的值 + const whereMatch = jsonStr.match(wherePattern); + if (whereMatch == null) return []; + const whereValues = whereMatch[1].split(',').map((clause) => clause.split('=')[0].trim()); + return whereValues; + } + + /// 分离sql的SELECT部分 + public static getUpdateSqlSETName(jsonStr: string): string[] { + // 提取SET后面的参数 + const setPattern: RegExp = new RegExp('SET +([^]+?) +WHERE'); // 匹配SET后面的值 + const setMatch = jsonStr.match(setPattern); + if (setMatch == null) return []; + const setValues = setMatch[1].split(',').map((clause) => clause.split('=')[0].trim()); + return setValues; + } + + /// 分离sql的表名部分 + public static getDeleteSqlTableName(jsonStr: string): string { + // 提取表名 + let pattern = new RegExp("DELETE FROM (\\w+)"); + let match = pattern.exec(jsonStr); + if (match == null) return ''; + return match[1]; + } + + /// 分离sql的Where部分 + public static getDeleteSqlWhereName(jsonStr: string): string[] { + // 提取WHERE后面的参数 + const wherePattern: RegExp = new RegExp('WHERE +([^]+?) *$'); // 匹配WHERE后面的值 + const whereMatch = jsonStr.match(wherePattern); + if (whereMatch == null) return []; + const whereValues = whereMatch[1].split(',').map((clause) => clause.split('=')[0].trim()); + return whereValues; + } + + /// 获取数据库路径上的最后一项作为数据库名 + public static getLastPathName(path: string): string { + // 通过split方法将路径分割成数组 + const pathParts = path.split('/'); + + // 获取最后一个元素 + return pathParts[pathParts.length - 1]; + } + + /// map转化为json + public static mapToJson(jsonStr: Map): string { + if (jsonStr.size <= 0) return '{}'; + let result: string = '{'; + jsonStr.forEach((value, key) => { + result += key + ":" + value.toString() + ","; + }) + // 可以选择去掉最后一个逗号 + // result = result.slice(0, -1); + result += '}'; + return result; + } + + // /// json转化为map + // public static parseJsonString(jsonStr: string): Map { + // // 去除字符串两端的空格 + // jsonStr = jsonStr.trim(); + // + // // 检查字符串是否以 '{' 开头和以 '}' 结尾 + // if (jsonStr[0] !== '{' || jsonStr[jsonStr.length - 1] !== '}') { + // throw new Error('Invalid JSON string format'); + // } + // + // // 创建一个空的Map对象 + // const map = new Map(); + // + // // 去除首尾的 {} 后,将字符串按 ',' 分割为键值对数组 + // const keyValuePairs = jsonStr.slice(1, -1).split(','); + // + // // 遍历键值对数组 + // for (const keyValuePair of keyValuePairs) { + // // 使用 ':' 分割键和值 + // const list: Array = keyValuePair.split(':'); + // + // // 去除键和值两端的空格 + // // const trimmedKey = list[0].trim(); + // // const trimmedValue = list[1].trim(); + // + // // 将键和值添加到Map中 + // if (list[0] != '') { + // map.set(list[0], list[1]); + // } + // } + // return map; + // } + + /// 获取map的keys + // public static getMapKeys(jsonStr: Map): string { + // let result: string = ''; + // jsonStr.forEach((value, key) => { + // result += key + ', '; + // }) + // result = result.slice(0, result.length - 2); + // return result; + // } + + /// 获取map的values + // public static getMapValues(jsonStr: Map): string { + // let result: string = ''; + // jsonStr.forEach((value, key) => { + // result += value + ', '; + // }) + // result = result.slice(0, result.length - 2); + // return result; + // } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/tools.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/tools.ets new file mode 100644 index 0000000..2fb57ca --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/tools.ets @@ -0,0 +1,13 @@ +export class Tools { + static stringEndWith(origin:string, endString:string): boolean { + if (origin.length < endString.length) return false; + + let originEndString:string = ''; + for (let index = 0; index < endString.length; index++) { + originEndString = originEndString + origin[origin.length - endString.length + index]; + } + + return originEndString == endString; + } +} + diff --git a/sqflite/ohos/sqflite/src/main/module.json5 b/sqflite/ohos/sqflite/src/main/module.json5 new file mode 100644 index 0000000..676c73a --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/module.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +{ + "module": { + "name": "sqflite", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/resources/base/element/string.json b/sqflite/ohos/sqflite/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/sqflite/ohos/sqflite/src/main/resources/en_US/element/string.json b/sqflite/ohos/sqflite/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/resources/en_US/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/sqflite/ohos/sqflite/src/main/resources/zh_CN/element/string.json b/sqflite/ohos/sqflite/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/sqflite/ohos/sqflite/src/test/List.test.ets b/sqflite/ohos/sqflite/src/test/List.test.ets new file mode 100644 index 0000000..4340a28 --- /dev/null +++ b/sqflite/ohos/sqflite/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest() +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/test/LocalUnit.test.ets b/sqflite/ohos/sqflite/src/test/LocalUnit.test.ets new file mode 100644 index 0000000..5633114 --- /dev/null +++ b/sqflite/ohos/sqflite/src/test/LocalUnit.test.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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. + */ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', function () { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(function () { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(function () { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(function () { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(function () { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, function () { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index c1a0c08..480af56 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -3,12 +3,12 @@ repository: https://github.com/tekartik/sqflite/tree/master/sqflite issue_tracker: https://github.com/tekartik/sqflite/issues description: Flutter plugin for SQLite, a self-contained, high-reliability, embedded, SQL database engine. -version: 2.3.0 +version: 2.2.8+3 funding: - https://github.com/sponsors/alextekartik environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=2.18.0 <4.0.0' flutter: ">=3.3.0" flutter: @@ -22,15 +22,26 @@ flutter: pluginClass: SqflitePlugin dartPluginClass: SqflitePlugin macos: + package: com.tekartik.sqflite + pluginClass: SqflitePlugin + dartPluginClass: SqflitePlugin + ohos: + package: io.flutter.plugins.sqflite pluginClass: SqflitePlugin dartPluginClass: SqflitePlugin dependencies: flutter: sdk: flutter - sqflite_common: '>=2.5.0-1 <4.0.0' + # sqflite_common: '>=2.4.5-3 <4.0.0' path: '>=1.8.0 <3.0.0' + # sqflite_ohos: + # path: sqflite_ohos +dependency_overrides: + sqflite_common: + path: tripartite/sqflite_common + dev_dependencies: flutter_lints: '>=1.0.0' process_run: '>=0.12.0' @@ -38,4 +49,4 @@ dev_dependencies: flutter_test: sdk: flutter test_api: '>=0.2.19' - pub_semver: '>=2.0.0' + pub_semver: '>=2.0.0' \ No newline at end of file diff --git a/sqflite/test/sqlite_api_test.dart b/sqflite/test/sqlite_api_test.dart index 4425f84..c49a9e3 100644 --- a/sqflite/test/sqlite_api_test.dart +++ b/sqflite/test/sqlite_api_test.dart @@ -24,10 +24,6 @@ void main() { ]) { expect(value, isNotNull); } - try { - // ignore: unnecessary_cast - SqfliteDatabaseExecutorExt((null as Database?)!).getVersion(); - } catch (_) {} }); }); } diff --git a/sqflite/test/src_mixin_test.dart b/sqflite/test/src_mixin_test.dart index a2041ea..81d36cd 100644 --- a/sqflite/test/src_mixin_test.dart +++ b/sqflite/test/src_mixin_test.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:path/path.dart'; @@ -152,16 +151,6 @@ class MockInvalidFactory extends DatabaseFactory { Future setDatabasesPath(String path) { throw UnimplementedError(); } - - @override - Future readDatabaseBytes(String path) { - throw UnimplementedError(); - } - - @override - Future writeDatabaseBytes(String path, Uint8List bytes) { - throw UnimplementedError(); - } } final MockDatabaseFactory mockDatabaseFactory = MockDatabaseFactory(); diff --git a/sqflite/tripartite/sqflite_common/.gitignore b/sqflite/tripartite/sqflite_common/.gitignore new file mode 100644 index 0000000..1d294b8 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/.gitignore @@ -0,0 +1,19 @@ +.DS_Store +.packages +.pub/ +ios/.generated/ +packages +pubspec.lock + +# Directory created by dartdoc +doc/api/ + +# Local folder +.local/ + +# Conventional directory for build outputs +build/ +coverage/ + +# flutter +.metadata \ No newline at end of file diff --git a/sqflite/tripartite/sqflite_common/CHANGELOG.md b/sqflite/tripartite/sqflite_common/CHANGELOG.md new file mode 100644 index 0000000..ea82971 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/CHANGELOG.md @@ -0,0 +1,69 @@ +## 2.4.5 + +* Add global API from sqflite (openDatabase, deleteDatabase, databaseFactory...) from sqflite + +## 2.4.4 + +* Dart 3 support + +## 2.4.3 + +* add minimum support for SQLite uri (https://www.sqlite.org/uri.html) + +## 2.4.2+2 + +* add experimental logger support. + +## 2.4.1 + +* add support for `Batch.length` to help finding the last added operation index. +* strict-casts and sdk 2.18 support + +## 2.4.0+2 + +* add support for `Database.queryCursor()` and `Database.rawQueryCursor()` +* base experimental web support +* Support for transaction v2 + +## 2.3.0 + +- Add `apply()` method to `Batch`. It will execute statements in that batch + without starting a new transaction. + +## 2.2.1+1 + +* Add debug tag to database factory + +## 2.2.0 + +* Export `Object? result` in `DatabaseException` +* Export deprecated `DatabaseFactory.debugSetLogLevel` for quick logging. + +## 2.1.0 + +* Requires dart sdk 2.15 + +## 2.0.1+1 + +* Truncate arguments in exception + +## 2.0.0+2 + +* `nnbd` support +* Fix transaction ref counting on begin transaction failure + +## 1.0.3+2 + +* Don't lock globally during open but lock per database full path. + +## 1.0.2+1 + +* Don't create a transaction during openDatabase if not needed. + +## 1.0.1 + +* Export `DatabaseException.getResultCode()`. + +## 1.0.0+1 + +* Initial revision from sqflite 1.2.2+1 diff --git a/sqflite/tripartite/sqflite_common/LICENSE b/sqflite/tripartite/sqflite_common/LICENSE new file mode 100644 index 0000000..5385068 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2019, Alexandre Roux Tekartik +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sqflite/tripartite/sqflite_common/README.md b/sqflite/tripartite/sqflite_common/README.md new file mode 100644 index 0000000..4d782cd --- /dev/null +++ b/sqflite/tripartite/sqflite_common/README.md @@ -0,0 +1,15 @@ +# sqflite common + +This package is not intended for direct use. +* See [sqflite](https://pub.dev/packages/sqflite) for flutter mobile +* See [sqflite_common_ffi](https://pub.dev/packages/sqflite_common_ffi) for Desktop +and unit test + +One exception to import `sqflite_common/sqlite_api.dart` is that you have logic +which is shared across Flutter apps and desktop binaries, and you want to make +your shared logic platform-agnostic. In this case, you can import the +`sqflite_common/sqlite_api.dart` directly in your Dart package for shared logic +and import it in your platform-dependent packages (e.g. using +[sqflite](https://pub.dev/packages/sqflite) for Flutter apps and +[sqflite_common_ffi](https://pub.dev/packages/sqflite_common_ffi) for desktop +binaries). diff --git a/sqflite/tripartite/sqflite_common/analysis_options.yaml b/sqflite/tripartite/sqflite_common/analysis_options.yaml new file mode 100644 index 0000000..25cf80a --- /dev/null +++ b/sqflite/tripartite/sqflite_common/analysis_options.yaml @@ -0,0 +1,112 @@ +include: package:lints/recommended.yaml + +# Until there are meta linter rules, each desired lint must be explicitly enabled. +# See: https://github.com/dart-lang/linter/issues/288 +# +# For a list of lints, see: http://dart-lang.github.io/linter/lints/ +# See the configuration guide for more +# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer +# +# NOTE: Please keep this file in sync with +# https://github.com/flutter/flutter/blob/master/analysis_options.yaml + +analyzer: + # Strong mode is sometimes harder to keep + language: + strict-casts: true + strict-inference: true + + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: warning + # treat missing returns as a warning (not a hint) + missing_return: warning + # allow having TODOs in the code + todo: ignore + # Ignore errors like + # 'super_goes_last' is a deprecated lint rule and should not be used • included_file_warning + included_file_warning: ignore + +linter: + rules: + - always_declare_return_types + - avoid_dynamic_calls + - avoid_empty_else + - avoid_relative_lib_imports + - avoid_shadowing_type_parameters + - avoid_slow_async_io + - avoid_types_as_parameter_names + - await_only_futures + - camel_case_extensions + - camel_case_types + - cancel_subscriptions + - curly_braces_in_flow_control_structures + - depend_on_referenced_packages + - directives_ordering + - empty_catches + - hash_and_equals + - iterable_contains_unrelated_type + - library_private_types_in_public_api + - list_remove_unrelated_type + - no_adjacent_strings_in_list + - no_duplicate_case_values + - no_leading_underscores_for_library_prefixes + - no_leading_underscores_for_local_identifiers + - non_constant_identifier_names + - null_check_on_nullable_type_parameter + - omit_local_variable_types + - package_api_docs + - package_prefixed_library_names + - prefer_generic_function_type_aliases + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_iterable_whereType + - prefer_single_quotes + - prefer_typing_uninitialized_variables + - sort_child_properties_last + - test_types_in_equals + - throw_in_finally + - unawaited_futures + - unnecessary_constructor_name + # - unnecessary_import + - unnecessary_late + - unnecessary_null_aware_assignments + - unnecessary_nullable_for_final_variable_declarations + - unnecessary_statements + # - unnecessary_type_check + - unrelated_type_equality_checks + - unsafe_html + - use_full_hex_values_for_flutter_colors + - valid_regexps + + - constant_identifier_names + - control_flow_in_finally + - empty_statements + - implementation_imports + - overridden_fields + - package_names + - prefer_const_constructors + - prefer_initializing_formals + - prefer_void_to_null + # + - always_require_non_null_named_parameters + - annotate_overrides + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_return_types_on_setters + - empty_constructor_bodies + - library_names + - library_prefixes + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_contains + - slash_for_doc_comments + - type_init_formals + - unnecessary_const + - unnecessary_new + - unnecessary_null_in_if_null_operators + - use_rethrow_when_possible + + # === doc rules === + - public_member_api_docs diff --git a/sqflite/tripartite/sqflite_common/doc/method_call_protocol.md b/sqflite/tripartite/sqflite_common/doc/method_call_protocol.md new file mode 100644 index 0000000..f00bef0 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/doc/method_call_protocol.md @@ -0,0 +1,110 @@ +# Method call protocol + +This protocol is used in a similar way for: +- sqflite plugin +- sqflite_common_ffi isolate communication +- sqflite_common_ffi_web web worker communication + +## Methods + +### openDatabase + +``` +in: + path: database path (String) + readOnly: + singleInstance: + +out: + id: database id (int) + clientId: + recoveredInTransaction: +``` + +### query + +`SELECT` method + +``` +in: + sql: select query (String) + arguments: [, ...] (binding parameters) + cursorPageSize: new in 2022-10-17 if non null the cursor is kept + +out: + columns: [, ...] + rows: [ + [row1 value1, row2 value2, ...] + [row2 value1, row2 value2, ...] + ... + ] + cursorId: optional cursor id for queryNext, null if end is reached +``` + +### queryCursorNext + +Added in 2022-10-17 to support pages queries + +``` +in: + cursorId: + cancel: true if the query should be cancelled + +out: + columns: [, ...] + rows: [ + [row1 value1, row2 value2, ...] + [row2 value1, row2 value2, ...] + ... + ] + cursorId: optional cursor id for queryNext, null if end is reached +``` + +### Transaction + +#### Transaction v1 + +Up to 2022-10-21 + +``` +in: + BEGIN TRANSACTION: + inTransaction: true +``` + +``` +in: + +``` + +``` +in: + END TRANSACTION: + inTransaction: false +``` + +#### Transaction v2 + +As of 2022-10-21 a new transaction mechanism is added, being compatible with the existing + +``` +in: + BEGIN TRANSACTION: + 'inTransaction': true + 'transactionId': null // This tells +out: + // This tells that the implementation supports the new transaction model + transactionId: +``` + +``` +in: + +``` + +``` +in: + END TRANSACTION: + transactionId: + inTransaction: false +``` \ No newline at end of file diff --git a/sqflite/tripartite/sqflite_common/example/main.dart b/sqflite/tripartite/sqflite_common/example/main.dart new file mode 100644 index 0000000..eb073b1 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/example/main.dart @@ -0,0 +1,5 @@ +Future main() async { + /// This package is not intended for direct use. + /// + /// See [sqflite](https://pub.dev/packages/sqflite) +} diff --git a/sqflite/tripartite/sqflite_common/lib/sqflite.dart b/sqflite/tripartite/sqflite_common/lib/sqflite.dart new file mode 100644 index 0000000..5abe3e9 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/sqflite.dart @@ -0,0 +1,114 @@ +import 'dart:async'; + +import 'package:sqflite_common/src/sqflite_database_factory.dart'; + +import 'sqlite_api.dart'; + +export 'package:sqflite_common/src/sqflite_database_factory.dart' show databaseFactory, databaseFactoryOrNull; + +export 'sqlite_api.dart'; + +/// +/// Open the database at a given path +/// +/// [version] (optional) specifies the schema version of the database being +/// opened. This is used to decide whether to call [onCreate], [onUpgrade], +/// and [onDowngrade] +/// +/// The optional callbacks are called in the following order: +/// +/// 1. [onConfigure] +/// 2. [onCreate] or [onUpgrade] or [onDowngrade] +/// 5. [onOpen] +/// +/// [onConfigure] is the first callback invoked when opening the database. It +/// allows you to perform database initialization such as enabling foreign keys +/// or write-ahead logging +/// +/// If [version] is specified, [onCreate], [onUpgrade], and [onDowngrade] can +/// be called. These functions are mutually exclusive — only one of them can be +/// called depending on the context, although they can all be specified to +/// cover multiple scenarios. If specified, it must be a 32-bits integer greater +/// than 0. +/// +/// [onCreate] is called if the database did not exist prior to calling +/// [openDatabase]. You can use the opportunity to create the required tables +/// in the database according to your schema +/// +/// [onUpgrade] is called if either of the following conditions are met: +/// +/// 1. [onCreate] is not specified +/// 2. The database already exists and [version] is higher than the last +/// database version +/// +/// In the first case where [onCreate] is not specified, [onUpgrade] is called +/// with its [oldVersion] parameter as `0`. In the second case, you can perform +/// the necessary migration procedures to handle the differing schema +/// +/// [onDowngrade] is called only when [version] is lower than the last database +/// version. This is a rare case and should only come up if a newer version of +/// your code has created a database that is then interacted with by an older +/// version of your code. You should try to avoid this scenario +/// +/// [onOpen] is the last optional callback to be invoked. It is called after +/// the database version has been set and before [openDatabase] returns +/// +/// When [readOnly] (false by default) is true, all other parameters are +/// ignored and the database is opened as-is +/// +/// When [singleInstance] is true (the default), a single database instance is +/// returned for a given path. Subsequent calls to [openDatabase] with the +/// same path will return the same instance, and will discard all other +/// parameters such as callbacks for that invocation. +/// +Future openDatabase(String path, + {int? version, + OnDatabaseConfigureFn? onConfigure, + OnDatabaseCreateFn? onCreate, + OnDatabaseVersionChangeFn? onUpgrade, + OnDatabaseVersionChangeFn? onDowngrade, + OnDatabaseOpenFn? onOpen, + bool? readOnly = false, + bool? singleInstance = true}) { + print("步骤1:${StackTrace.current.toString()}"); + final options = OpenDatabaseOptions( + version: version, + onConfigure: onConfigure, + onCreate: onCreate, + onUpgrade: onUpgrade, + onDowngrade: onDowngrade, + onOpen: onOpen, + readOnly: readOnly, + singleInstance: singleInstance); + return databaseFactory.openDatabase(path, options: options); +} + +/// +/// Open the database at a given path in read only mode +/// +Future openReadOnlyDatabase(String path, {bool? singleInstance = true}) => + openDatabase(path, readOnly: true, singleInstance: singleInstance); + +/// +/// Get the default databases location. +/// +/// On Android, it is typically data/data//databases +/// +/// On iOS and MacOS, it is the Documents directory. +/// +/// Note for iOS and non-Android platforms: Using `path_provider` is recommended to get the +/// databases directory. The most appropriate location on iOS would be +/// the Library directory that you could get from the [`path_provider` package] +/// (https://pub.dev/documentation/path_provider/latest/path_provider/getLibraryDirectory.html). +/// +Future getDatabasesPath() => databaseFactory.getDatabasesPath(); + +/// +/// Delete the database at the given path. +/// +Future deleteDatabase(String path) => databaseFactory.deleteDatabase(path); + +/// +/// Check if a database exists at a given path. +/// +Future databaseExists(String path) => databaseFactory.databaseExists(path); diff --git a/sqflite/tripartite/sqflite_common/lib/sqflite_dev.dart b/sqflite/tripartite/sqflite_common/lib/sqflite_dev.dart new file mode 100644 index 0000000..f98d171 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/sqflite_dev.dart @@ -0,0 +1,28 @@ +/// To be deprecated +library sqflite_common_sqflite_dev; + +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/mixin/import_mixin.dart'; + +/// Dev extension +/// +/// Please prefer using SqfliteDatabaseFactoryDebug which is exported by default. +extension SqfliteDatabaseFactoryDev on DatabaseFactory { + /// Change the log level if you want to see the SQL query + /// executed natively. + /// + /// Deprecated for temp usage only + @Deprecated('Dev only') + Future setLogLevel(int logLevel) async { + await setOptions(SqfliteOptions(logLevel: logLevel)); + } + + /// Testing only. + /// + /// deprecated on purpose to remove from code. + @Deprecated('Dev only') + Future setOptions(SqfliteOptions options) async { + await (this as SqfliteInvokeHandler) + .invokeMethod(methodOptions, options.toMap()); + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/sqflite_logger.dart b/sqflite/tripartite/sqflite_common/lib/sqflite_logger.dart new file mode 100644 index 0000000..80e68bd --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/sqflite_logger.dart @@ -0,0 +1,22 @@ +export 'src/logger/sqflite_logger.dart' + show + SqfliteDatabaseFactoryLogger, + SqfliteDatabaseFactoryLoggerType, + SqfliteLoggerOptions, + SqfliteLoggerSqlEvent, + SqfliteLoggerDatabaseOpenEvent, + SqfliteLoggerDatabaseCloseEvent, + SqfliteLoggerDatabaseDeleteEvent, + SqfliteLoggerInvokeEvent, + SqfliteLoggerBatchEvent, + SqfliteLoggerBatchOperation, + SqfliteLoggerEvent, + SqfliteLoggerSqlCommandExecute, + SqfliteLoggerSqlCommandInsert, + SqfliteLoggerSqlCommandUpdate, + SqfliteLoggerSqlCommandDelete, + SqfliteLoggerSqlCommandQuery, + SqfliteLoggerEventExt, + DatabaseFactoryLoggerDebugExt; + +export 'src/sql_command.dart' show SqliteSqlCommandType; diff --git a/sqflite/tripartite/sqflite_common/lib/sql.dart b/sqflite/tripartite/sqflite_common/lib/sql.dart new file mode 100644 index 0000000..6a03532 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/sql.dart @@ -0,0 +1,6 @@ +// Only export: +// * [ConflictAlgorithm] +// * [escapeName] +// * [unescapeName] +export 'package:sqflite_common/src/sql_builder.dart' + show ConflictAlgorithm, escapeName, unescapeName; diff --git a/sqflite/tripartite/sqflite_common/lib/sqlite_api.dart b/sqflite/tripartite/sqflite_common/lib/sqlite_api.dart new file mode 100644 index 0000000..91e82d0 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/sqlite_api.dart @@ -0,0 +1,588 @@ +import 'dart:async'; + +import 'package:sqflite_common/sql.dart' show ConflictAlgorithm; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/database_mixin.dart'; +import 'package:sqflite_common/src/open_options.dart' as impl; +import 'package:sqflite_common/src/transaction.dart'; + +export 'package:sqflite_common/sql.dart' show ConflictAlgorithm; +export 'package:sqflite_common/src/constant.dart' + show + inMemoryDatabasePath, + sqfliteLogLevelNone, + sqfliteLogLevelSql, + sqfliteLogLevelVerbose; +export 'package:sqflite_common/src/exception.dart' show DatabaseException; +export 'package:sqflite_common/src/sqflite_debug.dart' + show SqfliteDatabaseFactoryDebug, DatabaseFactoryLoggerDebugExt; + +/// Basic databases operations +abstract class DatabaseFactory { + /// Open a database at [path] with the given [OpenDatabaseOptions]`options` + /// + /// ``` + /// var databasesPath = await getDatabasesPath(); + /// String path = join(databasesPath, 'demo.db'); + /// Database database = await openDatabase(path, version: 1, + /// onCreate: (Database db, int version) async { + /// // When creating the db, create the table + /// await db.execute( + /// 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); + /// }); + ///``` + /// Notice, `join` is a part of the [path](https://pub.dev/packages/path) package + Future openDatabase(String path, {OpenDatabaseOptions? options}); + + /// Get the default databases location path. + /// + /// When using sqfliteFactory: + /// * On Android, it is typically data/data//databases + /// * On iOS and MacOS, it is the Documents directory + /// + /// For other implementation (ffi), the location is a default location + /// that makes mainly sense for debug/testing and you'd better rely on a + /// custom strategy using package such as `path_provider`. + Future getDatabasesPath(); + + /// Set the default databases location path + Future setDatabasesPath(String path); + + /// Delete a database if it exists + Future deleteDatabase(String path); + + /// Check if a database exists + Future databaseExists(String path); +} + +/// +/// Common API for [Database] and [Transaction] to execute SQL commands +/// +abstract class DatabaseExecutor { + /// Execute an SQL query with no return value. + /// + /// ``` + /// await db.execute( + /// 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); + /// ``` + Future execute(String sql, [List? arguments]); + + /// Executes a raw SQL INSERT query and returns the last inserted row ID. + /// + /// ``` + /// int id1 = await database.rawInsert( + /// 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)'); + /// ``` + /// + /// 0 could be returned for some specific conflict algorithms if not inserted. + Future rawInsert(String sql, [List? arguments]); + + /// This method helps insert a map of [values] + /// into the specified [table] and returns the + /// id of the last inserted row. + /// + /// ``` + /// var value = { + /// 'age': 18, + /// 'name': 'value' + /// }; + /// int id = await db.insert( + /// 'table', + /// value, + /// conflictAlgorithm: ConflictAlgorithm.replace, + /// ); + /// ``` + /// + /// 0 could be returned for some specific conflict algorithms if not inserted. + Future insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}); + + /// This is a helper to query a table and return the items found. All optional + /// clauses and filters are formatted as SQL queries + /// excluding the clauses' names. + /// + /// [table] contains the table names to compile the query against. + /// + /// [distinct] when set to true ensures each row is unique. + /// + /// The [columns] list specify which columns to return. Passing null will + /// return all columns, which is discouraged. + /// + /// [where] filters which rows to return. Passing null will return all rows + /// for the given URL. '?'s are replaced with the items in the + /// [whereArgs] field. + /// + /// [groupBy] declares how to group rows. Passing null + /// will cause the rows to not be grouped. + /// + /// [having] declares which row groups to include in the cursor, + /// if row grouping is being used. Passing null will cause + /// all row groups to be included, and is required when row + /// grouping is not being used. + /// + /// [orderBy] declares how to order the rows, + /// Passing null will use the default sort order, + /// which may be unordered. + /// + /// [limit] limits the number of rows returned by the query. + /// + /// [offset] specifies the starting index. + /// + /// ``` + /// List maps = await db.query(tableTodo, + /// columns: ['columnId', 'columnDone', 'columnTitle'], + /// where: 'columnId = ?', + /// whereArgs: [id]); + /// ``` + Future>> query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}); + + /// Executes a raw SQL SELECT query and returns a list + /// of the rows that were found. + /// + /// ``` + /// List list = await database.rawQuery('SELECT * FROM Test'); + /// ``` + Future>> rawQuery(String sql, + [List? arguments]); + + /// Executes a raw SQL SELECT with a cursor. + /// + /// Returns a cursor, that must either be closed when reaching the end or + /// that must be closed manually. You have to do [QueryCursor.moveNext] to + /// navigate (forward) in the cursor. + /// + /// Since its implementation cache rows for efficiency, [bufferSize] specified the + /// number of rows to cache (100 being the default) + /// + /// ``` + /// var cursor = await database.rawQueryCursor('SELECT * FROM Test'); + /// ``` + Future rawQueryCursor(String sql, List? arguments, + {int? bufferSize}); + + /// See [DatabaseExecutor.rawQueryCursor] for details about the argument [bufferSize] + /// See [DatabaseExecutor.query] for the other arguments. + Future queryCursor(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset, + int? bufferSize}); + + /// Executes a raw SQL UPDATE query and returns + /// the number of changes made. + /// + /// ``` + /// int count = await database.rawUpdate( + /// 'UPDATE Test SET name = ?, value = ? WHERE name = ?', + /// ['updated name', '9876', 'some name']); + /// ``` + Future rawUpdate(String sql, [List? arguments]); + + /// Convenience method for updating rows in the database. Returns + /// the number of changes made + /// + /// Update [table] with [values], a map from column names to new column + /// values. null is a valid value that will be translated to NULL. + /// + /// [where] is the optional WHERE clause to apply when updating. + /// Passing null will update all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a + /// conflict. See [ConflictAlgorithm] docs for more details + /// + /// ``` + /// int count = await db.update(tableTodo, todo.toMap(), + /// where: '$columnId = ?', whereArgs: [todo.id]); + /// ``` + Future update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}); + + /// Executes a raw SQL DELETE query and returns the + /// number of changes made. + /// + /// ``` + /// int count = await database + /// .rawDelete('DELETE FROM Test WHERE name = ?', ['another name']); + /// ``` + Future rawDelete(String sql, [List? arguments]); + + /// Convenience method for deleting rows in the database. + /// + /// Delete from [table] + /// + /// [where] is the optional WHERE clause to apply when updating. Passing null + /// will delete all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// Returns the number of rows affected. + /// ``` + /// int count = await db.delete(tableTodo, where: 'columnId = ?', whereArgs: [id]); + /// ``` + Future delete(String table, {String? where, List? whereArgs}); + + /// Creates a batch, used for performing multiple operation + /// in a single atomic operation. + /// + /// A batch can either be committed atomically with [Batch.commit], or non- + /// atomically by calling [Batch.apply]. For details on the two methods, see + /// their documentation. + /// In general, it is recommended to finish batches with [Batch.commit]. + /// + /// When committed with [Batch.commit], sqflite will manage a transaction to + /// execute statements in the batch. If this [batch] method has been called on + /// a [Transaction], committing the batch is deferred to when the transaction + /// completes (but [Batch.apply] or [Batch.commit] still need to be called). + Batch batch(); + + /// Get the database. + Database get database; +} + +/// Database transaction +/// to use during a transaction +abstract class Transaction implements DatabaseExecutor {} + +/// +/// Database to send sql commands, created during [openDatabase] +/// +abstract class Database implements DatabaseExecutor { + /// The path of the database + String get path; + + /// Close the database. Cannot be accessed anymore + Future close(); + + /// Calls in action must only be done using the transaction object + /// using the database will trigger a dead-lock. + /// + /// ``` + /// await database.transaction((txn) async { + /// // Ok + /// await txn.execute('CREATE TABLE Test1 (id INTEGER PRIMARY KEY)'); + /// + /// // DON'T use the database object in a transaction + /// // this will deadlock! + /// await database.execute('CREATE TABLE Test2 (id INTEGER PRIMARY KEY)'); + /// }); + Future transaction(Future Function(Transaction txn) action, + {bool? exclusive}); + + /// Tell if the database is open, returns false once close has been called + bool get isOpen; + + /// testing only + @Deprecated('Dev only') + Future devInvokeMethod(String method, [Object? arguments]); + + /// testing only + @Deprecated('Dev only') + Future devInvokeSqlMethod(String method, String sql, + [List? arguments]); +} + +/// Helpers +extension SqfliteDatabaseExecutorExt on DatabaseExecutor { + SqfliteDatabase get _db => (this as SqfliteDatabaseExecutor).db; + SqfliteTransaction? get _txn => (this as SqfliteDatabaseExecutor).txn; + + /// + /// Set the database inner version + /// Used internally for open helpers and automatic versioning + /// + Future setVersion(int version) { + _db.checkNotClosed(); + return _db.txnSetVersion(_txn, version); + } + + /// + /// Get the database inner version + /// + Future getVersion() { + _db.checkNotClosed(); + return _db.txnGetVersion(_txn); + } +} + +/// Prototype of the function called when the version has changed. +/// +/// Schema migration (adding column, adding table, adding trigger...) +/// should happen here. +typedef OnDatabaseVersionChangeFn = FutureOr Function( + Database db, int oldVersion, int newVersion); + +/// Prototype of the function called when the database is created. +/// +/// Database intialization (creating tables, views, triggers...) +/// should happen here. +typedef OnDatabaseCreateFn = FutureOr Function(Database db, int version); + +/// Prototype of the function called when the database is open. +/// +/// Post initialization should happen here. +typedef OnDatabaseOpenFn = FutureOr Function(Database db); + +/// Prototype of the function called before calling [onCreate]/[onUpdate]/[onOpen] +/// when the database is open. +/// +/// Post initialization should happen here. +typedef OnDatabaseConfigureFn = FutureOr Function(Database db); + +/// to specify during [openDatabase] for [onDowngrade] +/// Downgrading will always fail +Future onDatabaseVersionChangeError( + Database db, int oldVersion, int newVersion) async { + throw ArgumentError("can't change version from $oldVersion to $newVersion"); +} + +Future __onDatabaseDowngradeDelete( + Database db, int oldVersion, int newVersion) async { + // Implementation is hidden implemented in openDatabase._onDatabaseDowngradeDelete +} + +/// Downgrading will delete the database and open it again. +/// +/// To set in [onDowngrade] if you want to delete everything on downgrade. +final OnDatabaseVersionChangeFn onDatabaseDowngradeDelete = + __onDatabaseDowngradeDelete; + +/// +/// Options for opening the database +/// see [openDatabase] for details +/// +abstract class OpenDatabaseOptions { + /// Open the database at a given path + /// + /// [version] (optional) specifies the schema version of the database being + /// opened. This is used to decide whether to call [onCreate], [onUpgrade], + /// and [onDowngrade]. If specified, it must be a 32-bits integer greater than + /// 0. + /// + /// The optional callbacks are called in the following order: + /// + /// 1. [onConfigure] + /// 2. [onCreate] or [onUpgrade] or [onDowngrade] + /// 5. [onOpen] + /// + /// [onConfigure] is the first callback invoked when opening the database. It + /// allows you to perform database initialization such as enabling foreign keys + /// or write-ahead logging + /// + /// If [version] is specified, [onCreate], [onUpgrade], and [onDowngrade] can + /// be called. These functions are mutually exclusive — only one of them can be + /// called depending on the context, although they can all be specified to + /// cover multiple scenarios + /// + /// [onCreate] is called if the database did not exist prior to calling + /// [openDatabase]. You can use the opportunity to create the required tables + /// in the database according to your schema + /// + /// [onUpgrade] is called if either of the following conditions are met: + /// + /// 1. [onCreate] is not specified + /// 2. The database already exists and [version] is higher than the last + /// database version + /// + /// In the first case where [onCreate] is not specified, [onUpgrade] is called + /// with its [oldVersion] parameter as `0`. In the second case, you can perform + /// the necessary migration procedures to handle the differing schema + /// + /// [onDowngrade] is called only when [version] is lower than the last database + /// version. This is a rare case and should only come up if a newer version of + /// your code has created a database that is then interacted with by an older + /// version of your code. You should try to avoid this scenario + /// + /// [onOpen] is the last optional callback to be invoked. It is called after + /// the database version has been set and before [openDatabase] returns + /// + /// When [readOnly] (false by default) is true, all other parameters are + /// ignored and the database is opened as-is + /// + /// When [singleInstance] is true (the default), a single database instance is + /// returned for a given path. Subsequent calls to [openDatabase] with the + /// same path will return the same instance, and will discard all other + /// parameters such as callbacks for that invocation. You could set it to + /// false for in memory database (it is forced to false for `:memory:` path) + /// but not for uri. + /// + factory OpenDatabaseOptions( + {int? version, + OnDatabaseConfigureFn? onConfigure, + OnDatabaseCreateFn? onCreate, + OnDatabaseVersionChangeFn? onUpgrade, + OnDatabaseVersionChangeFn? onDowngrade, + OnDatabaseOpenFn? onOpen, + bool? readOnly = false, + bool? singleInstance = true}) { + return impl.SqfliteOpenDatabaseOptions( + version: version, + onConfigure: onConfigure, + onCreate: onCreate, + onUpgrade: onUpgrade, + onDowngrade: onDowngrade, + onOpen: onOpen, + readOnly: readOnly, + singleInstance: singleInstance); + } + + /// Specify the expected version. + int? version; + + /// called right after opening the database. + OnDatabaseConfigureFn? onConfigure; + + /// Called when the database is created. + OnDatabaseCreateFn? onCreate; + + /// Called when the database is upgraded. + OnDatabaseVersionChangeFn? onUpgrade; + + /// Called when the database is downgraded. + /// + /// Use [onDatabaseDowngradeDelete] for re-creating the database + OnDatabaseVersionChangeFn? onDowngrade; + + /// Called after all other callbacks have been called. + OnDatabaseOpenFn? onOpen; + + /// Open the database in read-only mode (no callback called). + late bool readOnly; + + /// The existing single-instance (hot-restart) + late bool singleInstance; +} + +/// +/// A batch is used to perform multiple operation as a single atomic unit. +/// A Batch object can be acquired by calling [Database.batch]. It provides +/// methods for adding operation. None of the operation will be +/// executed (or visible locally) until commit() is called. +/// +/// +/// ``` +/// batch = db.batch(); +/// batch.insert('Test', {'name': 'item'}); +/// batch.update('Test', {'name': 'new_item'}, where: 'name = ?', whereArgs: ['item']); +/// batch.delete('Test', where: 'name = ?', whereArgs: ['item']); +/// results = await batch.commit(); +/// ``` +abstract class Batch { + /// Commits all of the operations in this batch as a single atomic unit + /// The result is a list of the result of each operation in the same order + /// if [noResult] is true, the result list is empty (i.e. the id inserted + /// the count of item changed is not returned. + /// + /// The batch is stopped if any operation failed + /// If [continueOnError] is true, all the operations in the batch are executed + /// and the failure are ignored (i.e. the result for the given operation will + /// be a DatabaseException) + /// + /// During [Database.onCreate], [Database.onUpgrade], [Database.onDowngrade] + /// (we are already in a transaction) or if the batch was created in a + /// transaction it will only be commited when + /// the transaction is commited ([exclusive] is not used then). + /// + /// Otherwise, sqflite will start a transaction to commit this batch. In rare + /// cases where you don't need an atomic operation, or where you are manually + /// managing the transaction without using sqflite APIs, you can also use + /// [apply] to run statements in this batch without a transaction managed by + /// sqflite. + Future> commit({ + bool? exclusive, + bool? noResult, + bool? continueOnError, + }); + + /// Runs all statements in this batch non-atomically. + /// + /// Unlike [commit], which starts a transaction to commit statements in this + /// batch atomically, [apply] will simply run the statements without starting + /// a transaction internally. + /// + /// This can be useful in the rare cases where you don't need a sqflite + /// transaction, for instance because you are manually starting a transaction + /// or because you simply don't need the batch to be applied atomically. + /// + /// In general, prefer [commit] to run batches over this method. + Future> apply({bool? noResult, bool? continueOnError}); + + /// See [Database.rawInsert] + void rawInsert(String sql, [List? arguments]); + + /// See [Database.insert] + void insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}); + + /// See [Database.rawUpdate] + void rawUpdate(String sql, [List? arguments]); + + /// See [Database.update] + void update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}); + + /// See [Database.rawDelete] + void rawDelete(String sql, [List? arguments]); + + /// See [Database.delete] + void delete(String table, {String? where, List? whereArgs}); + + /// See [Database.execute]; + void execute(String sql, [List? arguments]); + + /// See [Database.query]; + void query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}); + + /// See [Database.query]; + void rawQuery(String sql, [List? arguments]); + + /// Current batch size + int get length; +} + +/// Cursor for query by page cursor. +abstract class QueryCursor { + /// Move to the next row. + /// + /// If false is returned, the cursor is closed and is no longer valid. + Future moveNext(); + + /// Current row data. + Map get current; + + /// Close the current cursor. + /// + /// Not needed when reaching the end of the cursor (moveNext returning false. + Future close(); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/arg_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/arg_utils.dart new file mode 100644 index 0000000..e3e0d0b --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/arg_utils.dart @@ -0,0 +1,29 @@ +import 'dart:typed_data'; + +String? _argumentToStringTruncate(Object? argument) { + if (argument == null) { + return null; + } + var text = argument.toString(); + if (text.length > 50) { + return '${text.substring(0, 50)}...'; + } + return text; +} + +/// Convert an sql argument to a printable string, truncating if necessary +String? argumentToString(Object? argument) { + if (argument is Uint8List) { + return 'Blob(${argument.length})'; + } + return _argumentToStringTruncate(argument); +} + +/// Convert sql arguments to a printable string, truncating if necessary +String argumentsToString(List arguments) => + '[${arguments.map((e) => argumentToString(e)).join(', ')}]'; + +/// Sql command and arguments formatted for logs +String sqlArgumentsToString(String sql, List? arguments) { + return '$sql${(arguments?.isNotEmpty ?? false) ? ' ${argumentsToString(arguments!)}' : ''}'; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/batch.dart b/sqflite/tripartite/sqflite_common/lib/src/batch.dart new file mode 100644 index 0000000..93cd83e --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/batch.dart @@ -0,0 +1,190 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/sql_builder.dart'; +import 'package:sqflite_common/src/sql_command.dart'; +import 'package:sqflite_common/src/transaction.dart'; +import 'package:sqflite_common/src/utils.dart'; + +/// Batch mixin. +mixin SqfliteBatchMixin implements Batch { + @override + void insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { + final builder = SqlBuilder.insert(table, values, + nullColumnHack: nullColumnHack, conflictAlgorithm: conflictAlgorithm); + return rawInsert(builder.sql, builder.arguments); + } + + @override + void query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + final builder = SqlBuilder.query(table, + distinct: distinct, + columns: columns, + where: where, + whereArgs: whereArgs, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset); + return rawQuery(builder.sql, builder.arguments); + } + + @override + void update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) { + final builder = SqlBuilder.update(table, values, + where: where, + whereArgs: whereArgs, + conflictAlgorithm: conflictAlgorithm); + return rawUpdate(builder.sql, builder.arguments); + } + + @override + void delete(String table, {String? where, List? whereArgs}) { + final builder = + SqlBuilder.delete(table, where: where, whereArgs: whereArgs); + return rawDelete(builder.sql, builder.arguments); + } +} + +/// Internal batch operation. +class SqfliteBatchOperation extends SqfliteSqlCommand { + /// Protocol method for each operation. + final String method; + + Map _getOperationParam() { + var map = { + paramMethod: method, + paramSql: sql, + if (arguments != null) paramSqlArguments: arguments + }; + // Handle in transaction change if needed + if (type == SqliteSqlCommandType.execute) { + // Check for begin/end transaction + final inTransaction = getSqlInTransactionArgument(sql); + if (inTransaction != null) { + map[paramInTransaction] = inTransaction; + } + } + return map; + } + + /// Internal batch operation. + SqfliteBatchOperation(super.type, this.method, super.sql, super.arguments); +} + +/// Batch implementation +abstract class SqfliteBatch with SqfliteBatchMixin implements Batch { + /// Get the list of operation as parameter for batch. + List> getOperationsParam() => + operations.map((e) => e._getOperationParam()).toList(); + + /// List of operations + final operations = []; + + @override + void rawInsert(String sql, [List? arguments]) { + operations.add(SqfliteBatchOperation( + SqliteSqlCommandType.insert, methodInsert, sql, arguments)); + } + + @override + void rawQuery(String sql, [List? arguments]) { + operations.add(SqfliteBatchOperation( + SqliteSqlCommandType.query, methodQuery, sql, arguments)); + } + + @override + void rawUpdate(String sql, [List? arguments]) { + operations.add(SqfliteBatchOperation( + SqliteSqlCommandType.update, methodUpdate, sql, arguments)); + } + + @override + void rawDelete(String sql, [List? arguments]) { + operations.add(SqfliteBatchOperation( + SqliteSqlCommandType.delete, methodUpdate, sql, arguments)); + } + + @override + void execute(String sql, [List? arguments]) { + operations.add(SqfliteBatchOperation( + SqliteSqlCommandType.execute, methodExecute, sql, arguments)); + } + + /// Batch size + @override + int get length => operations.length; +} + +/// Batch on a given database +class SqfliteDatabaseBatch extends SqfliteBatch { + /// Create a batch in a database + SqfliteDatabaseBatch(this.database); + + /// Our database + final SqfliteDatabase database; + + @override + Future> commit({ + bool? exclusive, + bool? noResult, + bool? continueOnError, + }) { + database.checkNotClosed(); + + return database.transaction>((Transaction txn) { + final sqfliteTransaction = txn as SqfliteTransaction; + return database.txnApplyBatch(sqfliteTransaction, this, + noResult: noResult, continueOnError: continueOnError); + }, exclusive: exclusive); + } + + @override + Future> apply({bool? noResult, bool? continueOnError}) { + return database.txnApplyBatch(null, this, + noResult: noResult, continueOnError: continueOnError); + } +} + +/// Batch on a given transaction +class SqfliteTransactionBatch extends SqfliteBatch { + /// Create a batch in a transaction + SqfliteTransactionBatch(this.transaction); + + /// Our transaction + final SqfliteTransaction transaction; + + @override + Future> commit({ + bool? exclusive, + bool? noResult, + bool? continueOnError, + }) { + if (exclusive != null) { + throw ArgumentError.value(exclusive, 'exclusive', + 'must not be set when commiting a batch in a transaction'); + } + + return apply(noResult: noResult, continueOnError: continueOnError); + } + + @override + Future> apply({bool? noResult, bool? continueOnError}) { + return transaction.database.txnApplyBatch(transaction, this, + noResult: noResult, continueOnError: continueOnError); + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/collection_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/collection_utils.dart new file mode 100644 index 0000000..4254223 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/collection_utils.dart @@ -0,0 +1,217 @@ +import 'dart:collection'; + +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/constant.dart' as constant; +import 'package:sqflite_common/src/exception.dart'; + +export 'dart:async'; + +/// Native result wrapper +class Rows extends PluginList> { + /// Wrap the native list as a raw + Rows.from(List list) : super.from(list); + + @override + Map operator [](int index) { + final item = rawList[index] as Map; + return item.cast(); + } +} + +/// Unpack the native results +QueryResultSet queryResultSetFromMap(Map queryResultSetMap) { + final columns = queryResultSetMap['columns'] as List?; + final rows = queryResultSetMap['rows'] as List?; + return QueryResultSet(columns, rows); +} + +/// Native exception wrapper +DatabaseException databaseExceptionFromOperationError( + Map errorMap) { + final message = errorMap[paramErrorMessage] as String?; + return SqfliteDatabaseException(message, errorMap[paramErrorData], + resultCode: errorMap[paramErrorResultCode] as int?); +} + +/// A batch operation result is either +/// {'result':...} +/// or +/// {'error':...} +dynamic fromRawOperationResult(Map rawOperationResultMap) { + final errorMap = + rawOperationResultMap[constant.paramError] as Map?; + if (errorMap != null) { + return databaseExceptionFromOperationError(errorMap); + } + final dynamic successResult = rawOperationResultMap[constant.paramResult]; + if (successResult is Map) { + return queryResultToList(successResult); + } else if (successResult is List) { + return queryResultToList(successResult); + } + + // This could be just an int (insert) + return successResult; +} + +/// Native result to a map list as expected by the sqflite API +List> queryResultToList(dynamic queryResult) { + if (queryResult is Map) { + return queryResultSetFromMap(queryResult); + } + // dart1 + // dart2 support <= 0.7.0 - this is a list + // to remove once done on iOS and Android + if (queryResult is List) { + final rows = Rows.from(queryResult); + return rows; + } + + throw UnsupportedError('Unsupported queryResult type $queryResult'); +} + +/// Native result to a map list as expected by the sqflite API +int? queryResultCursorId(dynamic queryResult) { + if (queryResult is Map) { + return queryResult[paramCursorId] as int?; + } + throw UnsupportedError('Unsupported queryResult type $queryResult'); +} + +/// Query native result +class QueryResultSet extends ListBase> { + /// Creates a result set from a native column/row values + QueryResultSet(List? rawColumns, List? rawRows) { + _columns = rawColumns?.cast(); + _rows = rawRows?.cast>(); + + if (_columns != null) { + _columnIndexMap = {}; + + for (var i = 0; i < _columns!.length; i++) { + _columnIndexMap[_columns![i]] = i; + } + } + } + + List>? _rows; + List? _columns; + List? _keys; + late Map _columnIndexMap; + + @override + int get length => _rows?.length ?? 0; + + @override + Map operator [](int index) { + return QueryRow(this, _rows![index]); + } + + @override + void operator []=(int index, Map value) { + throw UnsupportedError('read-only'); + } + + @override + set length(int newLength) { + throw UnsupportedError('read-only'); + } + + /// Get the column index for a give column name + int? columnIndex(String? name) { + return _columnIndexMap[name!]; + } + + /// Remove duplicated + List get keys => _keys ??= _columns!.toSet().toList(growable: false); +} + +/// Query Row wrapper +class QueryRow extends MapBase { + /// Create a row from a result set information and a list of values + QueryRow(this.queryResultSet, this.row); + + /// Our result set + final QueryResultSet queryResultSet; + + /// Our row values + final List row; + + @override + dynamic operator [](Object? key) { + final stringKey = key as String?; + final columnIndex = queryResultSet.columnIndex(stringKey); + if (columnIndex != null) { + return row[columnIndex]; + } + return null; + } + + @override + void operator []=(String key, dynamic value) { + throw UnsupportedError('read-only'); + } + + @override + void clear() { + throw UnsupportedError('read-only'); + } + + @override + Iterable get keys => queryResultSet.keys; + + @override + dynamic remove(Object? key) { + throw UnsupportedError('read-only'); + } +} + +/// Single batch operation results. +class BatchResult { + /// Wrap a batch operation result. + BatchResult(this.result); + + /// Our operation result + final dynamic result; +} + +/// Batch results. +class BatchResults extends PluginList { + /// Creates a batch result from a native list. + BatchResults.from(List list) : super.from(list); + + @override + dynamic operator [](int index) { + // New in 0.13 + // It is always a Map and can be either a result or an error + final rawMap = _list[index] as Map; + return fromRawOperationResult(rawMap); + } +} + +/// Helper to handle a native list. +abstract class PluginList extends ListBase { + /// Creates a types list from a native list. + PluginList.from(List list) : _list = list; + + final List _list; + + /// Our raw native list. + List get rawList => _list; + + /// Get a raw element. + dynamic rawElementAt(int index) => _list[index]; + + @override + int get length => _list.length; + + @override + set length(int newLength) { + throw UnsupportedError('read-only'); + } + + @override + void operator []=(int index, T value) { + throw UnsupportedError('read-only'); + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/compat.dart b/sqflite/tripartite/sqflite_common/lib/src/compat.dart new file mode 100644 index 0000000..9b4e5ee --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/compat.dart @@ -0,0 +1,66 @@ +import 'factory_mixin.dart'; + +/// +/// internal options. +/// +/// Used internally. +/// +/// deprecated since 1.1.1 +/// +@Deprecated('Dev only') +class SqfliteOptions { + /// deprecated + SqfliteOptions({this.logLevel}); + + // true =<0.7.0 + /// deprecated + @Deprecated('remove usage') + bool? queryAsMapList; + + /// deprecated + int? androidThreadPriority; + + /// deprecated + int? androidThreadCount; + + /// deprecated + int? logLevel; + + /// deprecated + Map toMap() { + final map = {}; + if (queryAsMapList != null) { + map['queryAsMapList'] = queryAsMapList; + } + if (androidThreadPriority != null) { + map['androidThreadPriority'] = androidThreadPriority; + } + if (androidThreadCount != null) { + map['androidThreadCount'] = androidThreadCount; + } + if (logLevel != null) { + map[paramLogLevel] = logLevel; + } + return map; + } + + /// deprecated + void fromMap(Map map) { + final dynamic queryAsMapList = map['queryAsMapList']; + if (queryAsMapList is bool) { + this.queryAsMapList = queryAsMapList; + } + final dynamic androidThreadPriority = map['androidThreadPriority']; + if (androidThreadPriority is int) { + this.androidThreadPriority = androidThreadPriority; + } + final dynamic androidThreadCount = map['androidThreadCount']; + if (androidThreadCount is int) { + this.androidThreadCount = androidThreadCount; + } + final dynamic logLevel = map[paramLogLevel]; + if (logLevel is int) { + this.logLevel = logLevel; + } + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/constant.dart b/sqflite/tripartite/sqflite_common/lib/src/constant.dart new file mode 100644 index 0000000..209dd42 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/constant.dart @@ -0,0 +1,182 @@ +// +// Native methods to use +// + +/// Native sql INSERT. +const String methodInsert = 'insert'; + +/// Native batch. +const String methodBatch = 'batch'; + +/// Native debug method. +const String methodDebug = 'debug'; + +/// Native options method. +const String methodOptions = 'options'; + +/// Native close database method. +const String methodCloseDatabase = 'closeDatabase'; + +/// Native open database method. +const String methodOpenDatabase = 'openDatabase'; + +/// Native sql execute. +const String methodExecute = 'execute'; + +/// Native sql UPDATE or DELETE method. +const String methodUpdate = 'update'; + +/// Native sql SELECT method. +const String methodQuery = 'query'; + +/// Native sql SELECT method. +const String methodQueryCursorNext = 'queryCursorNext'; + +/// deprecated. +const String methodGetPlatformVersion = 'getPlatformVersion'; + +/// Native getDatabasePath method. +const String methodGetDatabasesPath = 'getDatabasesPath'; + +/// Native database exists method. +const String methodDatabaseExists = 'databaseExists'; + +/// Native database delete method. +const String methodDeleteDatabase = 'deleteDatabase'; + +/// Native batch operations parameter. +const String paramOperations = 'operations'; + +/// Native batch 'no result' flag. +/// +/// if true the result of each batch operation is not filled +const String paramNoResult = 'noResult'; + +/// Native batch 'continue on error' flag. +/// +/// if true all the operation in the batch are executed even if on failed. +const String paramContinueOnError = 'continueOnError'; + +/// Batch operation method (insert/execute/query/update +const String paramMethod = 'method'; + +/// Batch operation result. +const String paramResult = 'result'; + +/// Error. +const String paramError = 'error'; + +/// Error code. +const String paramErrorCode = 'code'; + +/// Error message. +const String paramErrorMessage = 'message'; + +/// Error message. +const String paramErrorResultCode = 'resultCode'; + +/// Error data. +const String paramErrorData = 'data'; + +/// Open database 'recovered' flag. +/// +/// True if a single instance was recovered from the native world. +const String paramRecovered = 'recovered'; + +/// Open database 'recovered in transaction' flag. +/// +/// True if a single instance was recovered from the native world +/// while in a transaction. +const String paramRecoveredInTransaction = 'recoveredInTransaction'; + +/// The database path (string). +const String paramPath = 'path'; + +/// The database version (int). +const String paramVersion = 'version'; + +/// The database id (int) +const String paramId = 'id'; + +/// True if the database is in a transaction +const String paramInTransaction = 'inTransaction'; + +/// For beginTransaction, set it to null +/// Returned by beingTransaction for new implementation +/// +/// Transaction param, to set in all calls during a transaction. +/// +/// To set to null when beginning a transaction, it tells the implementation +/// that transactionId is supported by the client (compared to a raw BEGIN calls) +const String paramTransactionId = 'transactionId'; + +/// Special transaction id to force even if a transaction is running. +const int paramTransactionIdValueForce = -1; + +/// True when opening the database (bool) +const String paramReadOnly = 'readOnly'; + +/// True if opened as a single instance (bool) +const String paramSingleInstance = 'singleInstance'; + +/// SQL query (insert/execute/update/select). +/// +/// String. +const String paramSql = 'sql'; + +/// SQL query parameters. +/// +/// List. +const String paramSqlArguments = 'arguments'; + +/// SQL query cursorId parameter. +/// +/// Integer. +const String paramCursorId = 'cursorId'; + +/// SQL query cursor page size parameter. +/// +/// If null to cursor is used +/// +/// Integer. +const String paramCursorPageSize = 'cursorPageSize'; + +/// SQL query cursor next cancel parameter. +/// +/// true or false +/// +/// boolean. +const String paramCursorCancel = 'cancel'; + +/// SQLite error code +const String sqliteErrorCode = 'sqlite_error'; + +/// Special database name opened in memory +const String inMemoryDatabasePath = ':memory:'; + +/// Default duration before printing a lock warning if a database call hangs. +/// +/// Non final for changing it during testing. +/// +/// If a database called is delayed by this duration, a print will happen. +const Duration lockWarningDurationDefault = Duration(seconds: 10); + +// +// Log levels +// +/// No logs +final sqfliteLogLevelNone = 0; + +/// Log native sql commands +final sqfliteLogLevelSql = 1; + +/// Log native verbose +final sqfliteLogLevelVerbose = 2; + +// deprecated since 1.1.6 +// @deprecated +/// deprecated +const String methodSetDebugModeOn = 'debugMode'; + +/// Default buffer size for queryCursor +const int queryCursorBufferSizeDefault = 100; diff --git a/sqflite/tripartite/sqflite_common/lib/src/cursor.dart b/sqflite/tripartite/sqflite_common/lib/src/cursor.dart new file mode 100644 index 0000000..85a7759 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/cursor.dart @@ -0,0 +1,36 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/transaction.dart'; + +/// Sqflite query cursor wrapper. +class SqfliteQueryCursor implements QueryCursor { + final SqfliteDatabase _database; + + /// Current transaction if any + final SqfliteTransaction? txn; // transaction if any + + /// True when closed. moveNext should fail but current row remains ok + var closed = false; + + /// The native cursor id, null if not supported or if closed + int? cursorId; + + /// The current result list + List> resultList; + + /// The current index + int currentIndex = -1; + + /// Sqflite query cursor wrapper. + SqfliteQueryCursor(this._database, this.txn, this.cursorId, this.resultList); + + @override + Map get current => + _database.txnQueryCursorGetCurrent(txn, this); + + @override + Future moveNext() => _database.txnQueryCursorMoveNext(txn, this); + + @override + Future close() => _database.txnQueryCursorClose(txn, this); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/database.dart b/sqflite/tripartite/sqflite_common/lib/src/database.dart new file mode 100644 index 0000000..d6f9668 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/database.dart @@ -0,0 +1,132 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/batch.dart'; +import 'package:sqflite_common/src/factory.dart'; +import 'package:sqflite_common/src/transaction.dart'; + +import 'cursor.dart'; + +/// Base database executor. +abstract class SqfliteDatabaseExecutor implements DatabaseExecutor { + /// Executor transaction if any. + SqfliteTransaction? get txn; + + /// Executor database. + SqfliteDatabase get db; +} + +/// Open helper. +class SqfliteDatabaseOpenHelper { + /// Creates a database helper. + SqfliteDatabaseOpenHelper(this.factory, this.path, this.options); + + /// Our database factory + final SqfliteDatabaseFactory factory; + + /// Open options + final OpenDatabaseOptions? options; + + /// Our database pathy + final String path; + + /// The database once opened. + SqfliteDatabase? sqfliteDatabase; + + /// Creates a new database object. + SqfliteDatabase newDatabase(String path) => factory.newDatabase(this, path); + + /// True if the database is opened + bool get isOpen => sqfliteDatabase != null; + + // Future get databaseReady => _completer.future; + + /// Open or return the one opened. + Future openDatabase() async { + if (!isOpen) { + final database = newDatabase(path); + await database.doOpen(options!); + sqfliteDatabase = database; + } + return sqfliteDatabase!; + } + + /// Open the database if opened. + Future closeDatabase(SqfliteDatabase sqfliteDatabase) async { + if (!isOpen) { + return; + } + await sqfliteDatabase.doClose(); + this.sqfliteDatabase = null; + } +} + +/// Internal database interface. +abstract class SqfliteDatabase extends SqfliteDatabaseExecutor + implements Database { + /// Actually open the database. + Future doOpen(OpenDatabaseOptions options); + + /// Actually close the database. + Future doClose(); + + /// Database internal id. + int? id; + + /// Open options. + OpenDatabaseOptions? options; + + /// Begin a transaction. + Future beginTransaction({bool? exclusive}); + + /// Ends a transaction. + Future endTransaction(SqfliteTransaction txn); + + /// Commit a batch. + Future> txnApplyBatch( + SqfliteTransaction? txn, SqfliteBatch batch, + {bool? noResult, bool? continueOnError}); + + /// Execute a command. + Future txnExecute( + SqfliteTransaction? txn, String sql, List? arguments, + {bool? beginTransaction}); + + /// Execute a raw INSERT command. + Future txnRawInsert( + SqfliteTransaction? txn, String sql, List? arguments); + + /// Execute a raw SELECT command. + Future>> txnRawQuery( + SqfliteTransaction? txn, String sql, List? arguments); + + /// Execute a raw SELECT command by page. + Future txnRawQueryCursor(SqfliteTransaction? txn, + String sql, List? arguments, int pageSize); + + /// Cursor move next. + Future txnQueryCursorMoveNext( + SqfliteTransaction? txn, SqfliteQueryCursor cursor); + + /// Cursor current row. + Map txnQueryCursorGetCurrent( + SqfliteTransaction? txn, SqfliteQueryCursor cursor); + + /// Close the cursor. + Future txnQueryCursorClose( + SqfliteTransaction? txn, SqfliteQueryCursor cursor); + + /// Execute a raw UPDATE command. + Future txnRawUpdate( + SqfliteTransaction? txn, String sql, List? arguments); + + /// Execute a raw DELETE command. + Future txnRawDelete( + SqfliteTransaction? txn, String sql, List? arguments); + + /// Check if a database is not closed. + /// + /// Throw an exception if closed. + void checkNotClosed(); + + /// Allow database overriding. + Future invokeMethod(String method, [Object? arguments]); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/database_mixin.dart b/sqflite/tripartite/sqflite_common/lib/src/database_mixin.dart new file mode 100644 index 0000000..8427630 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/database_mixin.dart @@ -0,0 +1,927 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/batch.dart'; +import 'package:sqflite_common/src/collection_utils.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/cursor.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/exception.dart'; +import 'package:sqflite_common/src/factory.dart'; +import 'package:sqflite_common/src/path_utils.dart'; +import 'package:sqflite_common/src/sql_builder.dart'; +import 'package:sqflite_common/src/transaction.dart'; +import 'package:sqflite_common/src/utils.dart'; +import 'package:sqflite_common/src/utils.dart' as utils; +import 'package:sqflite_common/src/value_utils.dart'; +import 'package:sqflite_common/utils/utils.dart'; +import 'package:synchronized/synchronized.dart'; + +/// Base database implementation +class SqfliteDatabaseBase with SqfliteDatabaseMixin, SqfliteDatabaseExecutorMixin { + /// ctor + SqfliteDatabaseBase(SqfliteDatabaseOpenHelper openHelper, String path, {OpenDatabaseOptions? options}) { + this.openHelper = openHelper; + this.path = path; + } +} + +/// Common database/transaction implementation +mixin SqfliteDatabaseExecutorMixin implements SqfliteDatabaseExecutor { + @override + SqfliteTransaction? get txn; + + @override + SqfliteDatabase get db; + + /// Execute an SQL query with no return value + @override + Future execute(String sql, [List? arguments]) { + db.checkNotClosed(); + return db.txnExecute(txn, sql, arguments); + } + + /// Execute a raw SQL INSERT query + /// + /// Returns the last inserted record id + @override + Future rawInsert(String sql, [List? arguments]) { + db.checkNotClosed(); + return db.txnRawInsert(txn, sql, arguments); + } + + /// Insert a row into a table, where the keys of [values] correspond to + /// column names + @override + Future insert(String table, Map values, {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { + final builder = SqlBuilder.insert(table, values, nullColumnHack: nullColumnHack, conflictAlgorithm: conflictAlgorithm); + return rawInsert(builder.sql, builder.arguments); + } + + /// Helper to query a table + /// + /// @param distinct true if you want each row to be unique, false otherwise. + /// @param table The table names to compile the query against. + /// @param columns A list of which columns to return. Passing null will + /// return all columns, which is discouraged to prevent reading + /// data from storage that isn't going to be used. + /// @param where A filter declaring which rows to return, formatted as an SQL + /// WHERE clause (excluding the WHERE itself). Passing null will + /// return all rows for the given URL. + /// @param groupBy A filter declaring how to group rows, formatted as an SQL + /// GROUP BY clause (excluding the GROUP BY itself). Passing null + /// will cause the rows to not be grouped. + /// @param having A filter declare which row groups to include in the cursor, + /// if row grouping is being used, formatted as an SQL HAVING + /// clause (excluding the HAVING itself). Passing null will cause + /// all row groups to be included, and is required when row + /// grouping is not being used. + /// @param orderBy How to order the rows, formatted as an SQL ORDER BY clause + /// (excluding the ORDER BY itself). Passing null will use the + /// default sort order, which may be unordered. + /// @param limit Limits the number of rows returned by the query, + /// @param offset starting index, + /// + /// @return the items found + /// + @override + Future>> query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + final builder = SqlBuilder.query(table, + distinct: distinct, + columns: columns, + where: where, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset, + whereArgs: whereArgs); + return rawQuery(builder.sql, builder.arguments); + } + + /// Execute a raw SQL SELECT query + /// + /// Returns a list of rows that were found + @override + Future>> rawQuery(String sql, [List? arguments]) { + checkRawArgs(arguments); + return _rawQuery(sql, arguments); + } + + Future>> _rawQuery(String sql, [List? arguments]) { + db.checkNotClosed(); + return db.txnRawQuery(txn, sql, arguments); + } + + @override + Future queryCursor(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset, + int? bufferSize}) { + final builder = SqlBuilder.query(table, + distinct: distinct, + columns: columns, + where: where, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset, + whereArgs: whereArgs); + return _rawQueryCursor(builder.sql, builder.arguments, bufferSize); + } + + @override + Future rawQueryCursor(String sql, List? arguments, {int? bufferSize}) { + checkRawArgs(arguments); + return _rawQueryCursor(sql, arguments, bufferSize); + } + + Future _rawQueryCursor(String sql, List? arguments, int? pageSize) { + pageSize ??= queryCursorBufferSizeDefault; + db.checkNotClosed(); + return db.txnRawQueryCursor(txn, sql, arguments, pageSize); + } + + /// Execute a raw SQL UPDATE query + /// + /// Returns the number of changes made + @override + Future rawUpdate(String sql, [List? arguments]) { + checkRawArgs(arguments); + return _rawUpdate(sql, arguments); + } + + /// Execute a raw SQL UPDATE query + /// + /// Returns the number of changes made + Future _rawUpdate(String sql, [List? arguments]) { + db.checkNotClosed(); + return db.txnRawUpdate(txn, sql, arguments); + } + + /// Convenience method for updating rows in the database. + /// + /// Update [table] with [values], a map from column names to new column + /// values. null is a valid value that will be translated to NULL. + /// + /// [where] is the optional WHERE clause to apply when updating. + /// Passing null will update all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a + /// conflict. See [ConflictResolver] docs for more details + @override + Future update(String table, Map values, + {String? where, List? whereArgs, ConflictAlgorithm? conflictAlgorithm}) { + final builder = SqlBuilder.update(table, values, where: where, whereArgs: whereArgs, conflictAlgorithm: conflictAlgorithm); + return rawUpdate(builder.sql, builder.arguments); + } + + /// Executes a raw SQL DELETE query + /// + /// Returns the number of changes made + @override + Future rawDelete(String sql, [List? arguments]) { + checkRawArgs(arguments); + return _rawDelete(sql, arguments); + } + + /// Execute a raw SQL UPDATE query + /// + /// Returns the number of changes made + Future _rawDelete(String sql, [List? arguments]) { + db.checkNotClosed(); + return db.txnRawDelete(txn, sql, arguments); + } + + /// Convenience method for deleting rows in the database. + /// + /// Delete from [table] + /// + /// [where] is the optional WHERE clause to apply when updating. Passing null + /// will update all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a + /// conflict. See [ConflictResolver] docs for more details + /// + /// Returns the number of rows affected if a whereClause is passed in, 0 + /// otherwise. To remove all rows and get a count pass '1' as the + /// whereClause. + @override + Future delete(String table, {String? where, List? whereArgs}) { + final builder = SqlBuilder.delete(table, where: where, whereArgs: whereArgs); + return _rawDelete(builder.sql, builder.arguments); + } +} + +/// Common extension +extension SqfliteDatabaseMixinExt on SqfliteDatabase { + /// + /// Get the database inner version + /// + Future txnGetVersion(SqfliteTransaction? txn) async { + final rows = await txnRawQuery(txn, 'PRAGMA user_version', null); + return firstIntValue(rows) ?? 0; + } + + /// Set the database inner version + /// Used internally for open helpers and automatic versioning + /// + Future txnSetVersion(SqfliteTransaction? txn, int version) async { + await txnExecute(txn, 'PRAGMA user_version = $version', null); + } + + /// Base database map parameter. + Map getBaseDatabaseMethodArguments(SqfliteTransaction? txn) { + final map = { + paramId: id, + // transaction v2 + if (txn?.transactionId != null) paramTransactionId: txn?.transactionId + }; + return map; + } + + /// v1 and v2 support + /// Base database map parameter in transaction. + Map getBaseDatabaseMethodArgumentsInTransactionChange(SqfliteTransaction? txn, bool? inTransaction) { + final map = getBaseDatabaseMethodArguments(txn); + addInTransactionChangeParam(map, inTransaction); + return map; + } + + /// v1 and v2 support + /// Base database map parameter in transaction. + void addInTransactionChangeParam(Map map, bool? inTransaction) { + if (inTransaction != null) { + map[paramInTransaction] = inTransaction; + } + } + + Map _txnGetSqlMethodArguments(SqfliteTransaction? txn, String sql, List? sqlArguments) { + var methodArguments = { + paramSql: sql, + if (sqlArguments != null) paramSqlArguments: sqlArguments, + }..addAll(getBaseDatabaseMethodArguments(txn)); + return methodArguments; + } + + SqfliteDatabaseMixin get _mixin => this as SqfliteDatabaseMixin; + + /// try if open in read-only mode. + bool get readOnly => _mixin.openHelper?.options?.readOnly ?? false; + + /// for Update sql query + /// returns the update count + Future _txnRawUpdateOrDelete(SqfliteTransaction? txn, String sql, List? arguments) { + return _mixin.txnWriteSynchronized(txn, (_) async { + final result = await _mixin.safeInvokeMethod(methodUpdate, + {paramSql: sql, paramSqlArguments: arguments}..addAll(getBaseDatabaseMethodArguments(txn))); + return result ?? 0; + }); + } + + /// Run transaction. + Future _txnTransaction(Transaction? txn, Future Function(Transaction txn) action, {bool? exclusive}) async { + bool? successfull; + var transactionStarted = txn == null; + if (transactionStarted) { + txn = await beginTransaction(exclusive: exclusive); + } + T result; + try { + result = await action(txn); + successfull = true; + } finally { + if (transactionStarted) { + final sqfliteTransaction = txn as SqfliteTransaction; + sqfliteTransaction.successful = successfull; + await endTransaction(sqfliteTransaction); + } + } + return result; + } + + /// Begin a transaction. + Future txnBeginTransaction(SqfliteTransaction txn, {bool? exclusive}) async { + Object? response; + // never create transaction in read-only mode + if (readOnly != true) { + if (exclusive == true) { + response = await txnExecute(txn, 'BEGIN EXCLUSIVE', null, beginTransaction: true); + } else { + response = await txnExecute(txn, 'BEGIN IMMEDIATE', null, beginTransaction: true); + } + } + // Transaction v2 support, save the transaction id + if (response is Map) { + var transactionId = response[paramTransactionId]; + if (transactionId is int) { + txn.transactionId = transactionId; + } + } + } +} + +/// Sqflite database mixin. +mixin SqfliteDatabaseMixin implements SqfliteDatabase { + /// Invoke native method and wrap exception. + Future safeInvokeMethod(String method, [Object? arguments]) => + factory.wrapDatabaseException(() => invokeMethod(method, arguments)); + + /// Invoke the native method of the factory. + @override + Future invokeMethod(String method, [Object? arguments]) => _mixin.factory.invokeMethod(method, arguments); + + /// Keep our open helper for proper closing. + SqfliteDatabaseOpenHelper? openHelper; + @override + OpenDatabaseOptions? options; + + /// The factory. + SqfliteDatabaseFactory get factory => openHelper!.factory; + + @override + SqfliteDatabase get database => db; + + @override + SqfliteDatabase get db => this; + + /// True once the client called close. It should no longer invoke native + /// code + bool isClosed = false; + + @override + bool get isOpen => openHelper!.isOpen; + + @override + late String path; + + /// Special transaction created during open. + /// + /// Only not null during opening. + SqfliteTransaction? openTransaction; + + @override + SqfliteTransaction? get txn => openTransaction; + + /// Non-reentrant lock. + final Lock _rawLock = Lock(); + + // Its internal id + @override + int? id; + + /// Set when parsing BEGIN and COMMIT/ROLLBACK + bool inTransaction = false; + + /// Set internally for testing + bool doNotUseSynchronized = false; + + /// Base database map parameter. + /* + Map get getBaseDatabaseMethodArguments(txn) => + getBaseDatabaseMethodArguments(txn)(id!);*/ + + @override + Batch batch() { + return SqfliteDatabaseBatch(this); + } + + @override + void checkNotClosed() { + if (isClosed) { + throw SqfliteDatabaseException('error database_closed', null); + } + } + + @override + Future devInvokeMethod(String method, [Object? arguments]) { + return invokeMethod(method, arguments); + } + + @override + Future devInvokeSqlMethod(String method, String sql, [List? arguments]) { + return devInvokeMethod(method, {paramSql: sql, paramSqlArguments: arguments}..addAll( + // Handle the open transactin if any, but this is just for testing + getBaseDatabaseMethodArguments(txn))); + } + + /// synchronized call to the database + /// not re-entrant + /// Ugly compatibility step to not support older synchronized + /// mechanism + Future txnSynchronized(Transaction? txn, Future Function(Transaction? txn) action) async { + // If in a transaction, execute right away + if (txn != null || doNotUseSynchronized) { + return await action(txn); + } else { + // Simple timeout warning if we cannot get the lock after XX seconds + final handleTimeoutWarning = (utils.lockWarningDuration != null && utils.lockWarningCallback != null); + late Completer timeoutCompleter; + if (handleTimeoutWarning) { + timeoutCompleter = Completer(); + } + + // Grab the lock + final operation = _rawLock.synchronized(() { + if (handleTimeoutWarning) { + timeoutCompleter.complete(); + } + return action(txn); + }); + // Simply warn the developer as this could likely be a deadlock + if (handleTimeoutWarning) { + // ignore: unawaited_futures + timeoutCompleter.future.timeout(utils.lockWarningDuration!, onTimeout: () { + utils.lockWarningCallback!(); + }); + } + return await operation; + } + } + + /// synchronized call to the database + /// not re-entrant + Future txnWriteSynchronized(Transaction? txn, Future Function(Transaction? txn) action) => + txnSynchronized(txn, action); + + /// for sql without return values + /// + /// [beginTransaction] is true when beginning a transaction. + @override + Future txnExecute(SqfliteTransaction? txn, String sql, List? arguments, {bool? beginTransaction}) { + return txnWriteSynchronized(txn, (_) { + var inTransactionChange = getSqlInTransactionArgument(sql); + + if (inTransactionChange ?? false) { + inTransactionChange = true; + inTransaction = true; + } else if (inTransactionChange == false) { + inTransactionChange = false; + inTransaction = false; + } + return invokeExecute(txn, sql, arguments, inTransactionChange: inTransactionChange, beginTransaction: beginTransaction); + }); + } + + /// [inTransactionChange] is true when entering a transaction, false when leaving + /// should be set by parsing the sql command for all commands + /// + /// [beginTransaction] is true when entering a transaction and should clear + /// the transaction param. + Future invokeExecute(SqfliteTransaction? txn, String sql, List? arguments, + {bool? inTransactionChange, bool? beginTransaction}) { + var methodArguments = _txnGetSqlMethodArguments(txn, sql, arguments); + // Transaction v2, tell our support for transaction id + if (beginTransaction == true) { + methodArguments[paramTransactionId] = null; + } + addInTransactionChangeParam(methodArguments, inTransactionChange); + return safeInvokeMethod(methodExecute, methodArguments); + } + + /// for INSERT sql query + /// returns the last inserted record id + /// + /// 0 returned instead of null + @override + Future txnRawInsert(SqfliteTransaction? txn, String sql, List? arguments) { + return txnWriteSynchronized(txn, (_) async { + // The value could be null (for insert ignore). Return 0 in this case + return await safeInvokeMethod(methodInsert, _txnGetSqlMethodArguments(txn, sql, arguments)) ?? 0; + }); + } + + @override + Future>> txnRawQuery(SqfliteTransaction? txn, String sql, List? arguments) { + return txnSynchronized(txn, (_) async { + final dynamic result = await safeInvokeMethod(methodQuery, _txnGetSqlMethodArguments(txn, sql, arguments)); + return queryResultToList(result); + }); + } + + @override + Future txnRawQueryCursor(SqfliteTransaction? txn, String sql, List? arguments, int pageSize) { + return txnSynchronized(txn, (_) async { + var methodArguments = _txnGetSqlMethodArguments(txn, sql, arguments); + methodArguments[paramCursorPageSize] = pageSize; + dynamic result = await safeInvokeMethod(methodQuery, methodArguments); + + var cursorId = queryResultCursorId(result); + var resultList = queryResultToList(result); + return SqfliteQueryCursor(this, txn, cursorId, resultList); + }); + } + + /// Cursor current row. + @override + Map txnQueryCursorGetCurrent(SqfliteTransaction? txn, SqfliteQueryCursor cursor) { + if (cursor.closed) { + throw StateError('Cursor is closed, cannot get current row'); + } + if (cursor.currentIndex < 0 || cursor.currentIndex >= cursor.resultList.length) { + throw StateError('You must have a successful moveNext() before getting the current row'); + } + return cursor.resultList[cursor.currentIndex]; + } + + Future _closeCursor(SqfliteQueryCursor cursor) async { + if (!cursor.closed) { + cursor.closed = true; + var cursorId = cursor.cursorId; + if (cursorId != null) { + cursor.cursorId = null; + await safeInvokeMethod(methodQueryCursorNext, + {paramCursorId: cursorId, paramCursorCancel: true}..addAll(getBaseDatabaseMethodArguments(txn))); + } + } + } + + @override + Future txnQueryCursorMoveNext(SqfliteTransaction? txn, SqfliteQueryCursor cursor) async { + if (cursor.closed) { + return false; + } + if (cursor.currentIndex < cursor.resultList.length - 1) { + cursor.currentIndex++; + return true; + } + var cursorId = cursor.cursorId; + if (cursorId == null) { + // At end, let's quit + await txnQueryCursorClose(txn, cursor); + return false; + } else { + return txnSynchronized(txn, (_) async { + if (cursor.closed) { + return false; + } + var cursorId = cursor.cursorId; + if (cursorId == null) { + // At end, let's quit + await _closeCursor(cursor); + return false; + } + // Ok let's fetch the next batch of data + var result = await safeInvokeMethod( + methodQueryCursorNext, + { + paramCursorId: cursorId, + }..addAll(getBaseDatabaseMethodArguments(txn))); + var updatedCursorId = queryResultCursorId(result); + cursor.cursorId = updatedCursorId; + cursor.currentIndex = 0; + cursor.resultList = queryResultToList(result); + if (cursor.resultList.isEmpty) { + // cursor id should be null, but who knows... + await _closeCursor(cursor); + return false; + } else { + return true; + } + }); + } + } + + @override + Future txnQueryCursorClose(SqfliteTransaction? txn, SqfliteQueryCursor cursor) async { + if (!cursor.closed) { + if (cursor.cursorId != null) { + return txnSynchronized(txn, (_) async { + await _closeCursor(cursor); + }); + } else { + cursor.closed = true; + } + } + } + + /// for Update sql query + /// returns the update count + @override + Future txnRawUpdate(SqfliteTransaction? txn, String sql, List? arguments) => + _txnRawUpdateOrDelete(txn, sql, arguments); + + /// for Delete sql query + /// returns the delete count + @override + Future txnRawDelete(SqfliteTransaction? txn, String sql, List? arguments) => + _txnRawUpdateOrDelete(txn, sql, arguments); + + @override + Future> txnApplyBatch(SqfliteTransaction? txn, SqfliteBatch batch, {bool? noResult, bool? continueOnError}) { + return txnWriteSynchronized(txn, (_) async { + final arguments = {paramOperations: batch.getOperationsParam()} + ..addAll(getBaseDatabaseMethodArguments(txn)); + if (noResult == true) { + arguments[paramNoResult] = noResult; + } + if (continueOnError == true) { + arguments[paramContinueOnError] = continueOnError; + } + final results = await safeInvokeMethod?>(methodBatch, arguments); + + // Typically when noResult is true + if (results == null) { + return []; + } + // dart2 - wrap if we need to support more results than just int + return BatchResults.from(results); + }); + } + + /// New transaction. + SqfliteTransaction newTransaction() { + final txn = SqfliteTransaction(this); + return txn; + } + + @override + Future beginTransaction({bool? exclusive}) async { + final txn = newTransaction(); + await txnBeginTransaction(txn, exclusive: exclusive); + return txn; + } + + @override + Future endTransaction(SqfliteTransaction txn) async { + // never commit transaction in read-only mode + if (readOnly != true) { + if (txn.successful == true) { + await txnExecute(txn, 'COMMIT', null); + } else { + await txnExecute(txn, 'ROLLBACK', null); + } + } + } + + @override + Future transaction(Future Function(Transaction txn) action, {bool? exclusive}) { + checkNotClosed(); + return txnWriteSynchronized(txn, (Transaction? txn) async { + return _txnTransaction(txn, action, exclusive: exclusive); + }); + } + + /// Close the database. Cannot be access anymore + @override + Future close() => factory.closeDatabase(this); + + /// Close the database. Cannot be access anymore + @override + Future doClose() => _closeDatabase(id); + + @override + String toString() { + return '$id $path'; + } + + /// Open a database and returns its id. + /// + /// id does not run any callback calls + Future openDatabase() async { + final params = {paramPath: path}; + if (readOnly == true) { + params[paramReadOnly] = true; + } + // Single instance? never for standard inMemoryDatabase + final singleInstance = (options?.singleInstance ?? false) && !isInMemoryDatabasePath(path); + + params[paramSingleInstance] = singleInstance; + + // Version up to 1.1.5 returns an int + // Now it returns some database information + // the one being about being recovered from the native world + // where we are going to revert + // doing first on Android without breaking ios + final openResult = await safeInvokeMethod(methodOpenDatabase, params); + if (openResult is int) { + return openResult; + } else if (openResult is Map) { + final id = openResult[paramId] as int?; + // Recover means we found an instance in the native world + final recoveredInTransaction = openResult[paramRecoveredInTransaction] == true; + // in this case, we are going to rollback any changes in case a transaction + // was in progress. This catches hot-restart scenario + if (recoveredInTransaction) { + // Don't do it for read-only + if (readOnly != true) { + // We are not yet open so invoke the plugin directly + try { + await safeInvokeMethod(methodExecute, { + paramSql: 'ROLLBACK', + paramId: id, + + /// Force the action even if we are in a transaction. + paramTransactionId: paramTransactionIdValueForce, + paramInTransaction: false + }); + } catch (e) { + print('ignore recovered database ROLLBACK error $e'); + } + } + } + return id!; + } else { + throw 'unsupported result $openResult (${openResult?.runtimeType})'; + } + } + + final Lock _closeLock = Lock(); + + /// rollback any pending transaction if needed + Future _closeDatabase(int? databaseId) async { + await _closeLock.synchronized(() async { + // devPrint('_closeDatabase closing $databaseId inTransaction $inTransaction isClosed $isClosed readOnly $readOnly'); + if (!isClosed) { + // Mark as closed now + isClosed = true; + + if (readOnly != true && inTransaction) { + // Grab lock to prevent future access + // At least we know no other request will be ran + try { + await txnWriteSynchronized(txn, (Transaction? txn) async { + // Special trick to cancel any pending transaction + try { + await invokeExecute( + + /// Force if needed + (txn as SqfliteTransaction?) ?? getForcedSqfliteTransaction(this), + 'ROLLBACK', + null, + inTransactionChange: false); + } catch (_) { + // devPrint('rollback error $_'); + } + }); + } catch (e) { + print('Error $e before rollback'); + } + } + + // close for good + // Catch exception, close should never fail + try { + await safeInvokeMethod(methodCloseDatabase, {paramId: databaseId}); + } catch (e) { + print('error $e closing database $databaseId'); + } + } + }); + } + + // To call during open + // not exported + @override + Future doOpen(OpenDatabaseOptions options) async { + if (options.version != null) { + if (options.version == 0) { + throw ArgumentError('version cannot be set to 0 in openDatabase'); + } + } else { + if (options.onCreate != null) { + throw ArgumentError('onCreate must be null if no version is specified'); + } + if (options.onUpgrade != null) { + throw ArgumentError('onUpgrade must be null if no version is specified'); + } + if (options.onDowngrade != null) { + throw ArgumentError('onDowngrade must be null if no version is specified'); + } + } + this.options = options; + var databaseId = await openDatabase(); + + try { + // Special on downgrade delete database + if (options.onDowngrade == onDatabaseDowngradeDelete) { + // Downgrading will delete the database and open it again + Future onDatabaseDowngradeDoDelete(Database database, int oldVersion, int newVersion) async { + final db = database as SqfliteDatabase; + // This is tricky as we are in the middle of opening a database + // need to close what is being done and restart + await db.doClose(); + // But don't mark it as closed + isClosed = false; + + await factory.deleteDatabase(db.path); + + // get a new database id after open + db.id = databaseId = await openDatabase(); + + try { + // Since we deleted the database re-run the needed first steps: + // onConfigure then onCreate + if (options.onConfigure != null) { + await options.onConfigure!(db); + } + } catch (e) { + // This exception is sometimes hard te catch + // during development + print(e); + + // create a transaction just to make the current transaction happy + openTransaction = await db.beginTransaction(exclusive: true); + rethrow; + } + + // Recreate a new transaction + // no end transaction it will be done later before calling then onOpen + openTransaction = await db.beginTransaction(exclusive: true); + if (options.onCreate != null) { + await options.onCreate!(db, options.version!); + } + } + + options.onDowngrade = onDatabaseDowngradeDoDelete; + } + + id = databaseId; + + // first configure it + if (options.onConfigure != null) { + await options.onConfigure!(this); + } + + if (options.version != null) { + // Check the version outside of the transaction + // And only create the transaction if needed (https://github.com/tekartik/sqflite/issues/459) + final oldVersion = await getVersion(); + if (oldVersion != options.version) { + try { + await transaction((Transaction txn) async { + // Set the current transaction as the open one + // to allow direct database call during open and allowing + // creating a fake transaction (since we are already in a transaction) + final sqfliteTransaction = txn as SqfliteTransaction; + openTransaction = sqfliteTransaction; + + // We read again the version to be safe regarding edge cases + final oldVersion = await txnGetVersion(txn); + if (oldVersion == 0) { + if (options.onCreate != null) { + await options.onCreate!(this, options.version!); + } else if (options.onUpgrade != null) { + await options.onUpgrade!(this, 0, options.version!); + } + } else if (options.version! > oldVersion) { + if (options.onUpgrade != null) { + await options.onUpgrade!(this, oldVersion, options.version!); + } + } else if (options.version! < oldVersion) { + if (options.onDowngrade != null) { + await options.onDowngrade!(this, oldVersion, options.version!); + // Check and reuse transaction if if needed + // in case downgrade delete was called + if (openTransaction!.transactionId != txn.transactionId) { + txn.transactionId = openTransaction!.transactionId; + } + } + } + if (oldVersion != options.version) { + await setVersion(options.version!); + } + }, exclusive: true); + } finally { + // clean up open transaction + openTransaction = null; + } + } + } + + if (options.onOpen != null) { + await options.onOpen!(this); + } + + return this; + } catch (e) { + print('error $e during open, closing...'); + await _closeDatabase(databaseId); + rethrow; + } finally { + // clean up open transaction + openTransaction = null; + } + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/dev_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/dev_utils.dart new file mode 100644 index 0000000..6d62eb3 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/dev_utils.dart @@ -0,0 +1,12 @@ +/// Deprecated to prevent keeping the code used. +@Deprecated('Dev only') +void devPrint(Object? object) { + print(object); +} + +/// Deprecated to prevent keeping the code used. +/// +/// Can be use as a todo for weird code. int value = devWarning(myFunction()); +/// The function is always called +@Deprecated('Dev only') +T devWarning(T value) => value; diff --git a/sqflite/tripartite/sqflite_common/lib/src/env_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/env_utils.dart new file mode 100644 index 0000000..7b19a83 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/env_utils.dart @@ -0,0 +1,23 @@ +// environment utils + +bool? _isRelease; + +// http://stackoverflow.com/questions/29592826/detect-during-runtime-whether-the-application-is-in-release-mode-or-not + +/// Check whether in release mode +bool get isRelease { + if (_isRelease == null) { + _isRelease = true; + assert(() { + _isRelease = false; + return true; + }()); + } + return _isRelease!; +} + +/// Check whether running in debug mode +bool get isDebug => !isRelease; + +/// Special runtime trick to known whether we are in the javascript world +const kSqfliteIsWeb = identical(1, 1.0); diff --git a/sqflite/tripartite/sqflite_common/lib/src/exception.dart b/sqflite/tripartite/sqflite_common/lib/src/exception.dart new file mode 100644 index 0000000..30710eb --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/exception.dart @@ -0,0 +1,193 @@ +import 'package:sqflite_common/src/arg_utils.dart'; +import 'package:sqflite_common/src/constant.dart'; + +/// Wrap sqlite native exception +abstract class DatabaseException implements Exception { + /// Create an exception with a message + DatabaseException(this._message); + + final String? _message; + + @override + String toString() => 'DatabaseException($_message)'; + + /// True if the exception is a no such table exception + bool isNoSuchTableError([String? table]) { + if (_message != null) { + var expected = 'no such table: '; + if (table != null) { + expected += table; + } + return _message!.contains(expected); + } + return false; + } + + /// True if the exception is a duplicate column error + bool isDuplicateColumnError([String? column]) { + if (_message != null) { + var expected = 'duplicate column name: '; + if (column != null) { + expected += column; + } + return _message!.contains(expected); + } + return false; + } + + /// True if the exception is a syntax error + bool isSyntaxError() { + if (_message != null) { + return _message!.contains('syntax error'); + } + return false; + } + + /// True if the exception is an open failed error + bool isOpenFailedError() { + if (_message != null) { + return _message!.contains('open_failed'); + } + return false; + } + + /// True if the exception is a database closed error + bool isDatabaseClosedError() { + if (_message != null) { + return _message!.contains('database_closed') || + _message!.contains('This database has already been closed'); + } + return false; + } + + /// True if the exception is a read-only error + bool isReadOnlyError() { + if (_message != null) { + return _message!.contains('readonly'); + } + return false; + } + + /// True if the exception is a unique constraint error + bool isUniqueConstraintError([String? field]) { + if (_message != null) { + var expected = 'UNIQUE constraint failed: '; + if (field != null) { + expected += field; + } + return _message!.toLowerCase().contains(expected.toLowerCase()); + } + return false; + } + + /// True if the exception is a not null constraint error + bool isNotNullConstraintError([String? field]) { + if (_message != null) { + var expected = 'NOT NULL constraint failed: '; + if (field != null) { + expected += field; + } + return _message!.toLowerCase().contains(expected.toLowerCase()); + } + return false; + } + + /// Extended result code on Android/ffi, normal result code on iOS. + /// + /// This might involve parsing the sqlite native message to extract the code + /// See https://www.sqlite.org/rescode.html for the list of result code + int? getResultCode(); + + /// Platform specific error result. + /// + /// Its content is platform dependent and used internally and could change + /// in the future but could help in analyzing the error. + Object? get result; +} + +/// Exception implementation +class SqfliteDatabaseException extends DatabaseException { + /// ctor with a message and some data + SqfliteDatabaseException(String? message, this.result, {int? resultCode}) + : super(message) { + _resultCode = resultCode; + } + + /// Our exception message + String? get message => _message; + + /// Extended result code. + int? _resultCode; + + /// Typically the result of a native call + @override + Object? result; + + /// The result as a map + Map get resultMap => result as Map; + + @override + String toString() { + if (result is Map) { + if (resultMap[paramSql] != null) { + final dynamic args = resultMap[paramSqlArguments]; + if (args is List) { + return "DatabaseException($_message) sql '${resultMap[paramSql]}' args ${argumentsToString(args)}"; + } else { + return "DatabaseException($_message) sql '${resultMap[paramSql]}'"; + } + } + } + return super.toString(); + } + + /// Get the (extended if available) result code. + /// + /// This might involve parsing the sqlite native message to extract the code + /// See https://www.sqlite.org/rescode.html for the list of result code. + /// + /// iOS returns normal code while Android/ffi returns extended code for now + /// The application should handle both. + @override + int? getResultCode() => _resultCode ??= () { + final message = _message!.toLowerCase(); + int? findCode(String patternPrefix) { + final index = message.indexOf(patternPrefix); + if (index != -1) { + try { + // Split at first space + var code = message + .substring(index + patternPrefix.length) + .trim() + .split(' ')[0]; + // Find ending parenthesis if any + final endIndex = code.indexOf(')'); + if (endIndex != -1) { + code = code.substring(0, endIndex); + } + + final resultCode = int.tryParse(code); + if (resultCode != null) { + return resultCode; + } + } catch (_) {} + } + return null; + } + + var code = findCode('(sqlite code '); + if (code != null) { + return code; + } + code = findCode('(code '); + if (code != null) { + return code; + } + // ios + code = findCode('code='); + if (code != null) { + return code; + } + return null; + }(); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/factory.dart b/sqflite/tripartite/sqflite_common/lib/src/factory.dart new file mode 100644 index 0000000..60d3247 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/factory.dart @@ -0,0 +1,35 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/mixin/factory.dart'; + +/// Internal database factory interface. +abstract class SqfliteDatabaseFactory + implements DatabaseFactory, SqfliteInvokeHandler { + /// Wrap any exception to a [DatabaseException]. + Future wrapDatabaseException(Future Function() action); + + // To override + // This also should wrap exception + //Future safeInvokeMethod(String method, [Object? arguments]); + + /// Create a new database object. + SqfliteDatabase newDatabase( + SqfliteDatabaseOpenHelper openHelper, String path); + + /// Remove our internal open helper. + void removeDatabaseOpenHelper(String path); + + @override + Future openDatabase(String path, {OpenDatabaseOptions? options}); + + /// Close the database. + /// + /// db.close() calls this right await. + Future closeDatabase(SqfliteDatabase database); + + @override + Future deleteDatabase(String path); + + @override + Future databaseExists(String path); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/factory_mixin.dart b/sqflite/tripartite/sqflite_common/lib/src/factory_mixin.dart new file mode 100644 index 0000000..4bf7582 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/factory_mixin.dart @@ -0,0 +1,273 @@ +import 'package:path/path.dart'; +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/database_mixin.dart'; +import 'package:sqflite_common/src/exception.dart'; +import 'package:sqflite_common/src/factory.dart'; +import 'package:sqflite_common/src/mixin/factory.dart'; +import 'package:sqflite_common/src/open_options.dart'; +import 'package:synchronized/synchronized.dart'; +import 'path_utils.dart' as pu; + +/// Base factory implementation +abstract class SqfliteDatabaseFactoryBase with SqfliteDatabaseFactoryMixin {} + +/// Named lock, unique by name and its private class +class _NamedLock { + factory _NamedLock(String name) { + // Add to cache, create if needed + return cacheLocks[name] ??= _NamedLock._(name, Lock(reentrant: true)); + } + + _NamedLock._(this.name, this.lock); + + // Global cache per db name + // Remain allocated forever but that is fine. + static final cacheLocks = {}; + + final String name; + final Lock lock; +} + +/// Common factory mixin +mixin SqfliteDatabaseFactoryMixin implements SqfliteDatabaseFactory, SqfliteInvokeHandler { + /// To override to wrap wanted exception + @override + Future wrapDatabaseException(Future Function() action) => action(); + + /// Invoke native method and wrap exception. + Future safeInvokeMethod(String method, [Object? arguments]) => + wrapDatabaseException(() => invokeMethod(method, arguments)); + + /// Open helpers for single instances only. + Map databaseOpenHelpers = {}; + + /// Avoid concurrent open operation on the same database + Lock _getDatabaseOpenLock(String path) => _NamedLock(path).lock; + + /// Optional tag (read-only) + String? tag; + + @override + SqfliteDatabase newDatabase(SqfliteDatabaseOpenHelper openHelper, String path) { + return SqfliteDatabaseBase(openHelper, path); + } + + @override + void removeDatabaseOpenHelper(String path) { + databaseOpenHelpers.remove(path); + } + + // Close an instance of the database + @override + Future closeDatabase(SqfliteDatabase database) { + // Lock per database name + final lock = _getDatabaseOpenLock(database.path); + return lock.synchronized(() async { + await (database as SqfliteDatabaseMixin).openHelper!.closeDatabase(database); + if (database.options?.singleInstance != false) { + removeDatabaseOpenHelper(database.path); + } + }); + } + + @override + Future openDatabase(String path, {OpenDatabaseOptions? options}) async { + print("步骤2:${StackTrace.current.toString()}"); + path = await fixPath(path); + // Lock per database name + final lock = _getDatabaseOpenLock(path); + return lock.synchronized(() async { + options ??= SqfliteOpenDatabaseOptions(); + + if (options?.singleInstance != false) { + SqfliteDatabaseOpenHelper? getExistingDatabaseOpenHelper(String path) { + return databaseOpenHelpers[path]; + } + + void setDatabaseOpenHelper(SqfliteDatabaseOpenHelper? helper) { + if (helper == null) { + databaseOpenHelpers.remove(path); + } else { + databaseOpenHelpers[path] = helper; + } + } + + var databaseOpenHelper = getExistingDatabaseOpenHelper(path); + + final firstOpen = databaseOpenHelper == null; + if (firstOpen) { + databaseOpenHelper = SqfliteDatabaseOpenHelper(this, path, options); + setDatabaseOpenHelper(databaseOpenHelper); + } + try { + return await databaseOpenHelper.openDatabase(); + } catch (e) { + // If first open fail remove the reference + if (firstOpen) { + removeDatabaseOpenHelper(path); + } + rethrow; + } + } else { + final databaseOpenHelper = SqfliteDatabaseOpenHelper(this, path, options); + return await databaseOpenHelper.openDatabase(); + } + }); + } + + @override + Future deleteDatabase(String path) async { + path = await fixPath(path); + // Lock per database name + final lock = _getDatabaseOpenLock(path); + return lock.synchronized(() async { + // Handle already single instance open database + removeDatabaseOpenHelper(path); + return safeInvokeMethod(methodDeleteDatabase, {paramPath: path}); + }); + } + + @override + Future databaseExists(String path) async { + path = await fixPath(path); + return safeInvokeMethod(methodDatabaseExists, {paramPath: path}); + } + + String? _databasesPath; + + @override + Future getDatabasesPath() async { + if (_databasesPath == null) { + final path = await safeInvokeMethod(methodGetDatabasesPath); + + if (path == null) { + throw SqfliteDatabaseException('getDatabasesPath is null', null); + } + _databasesPath = path; + } + return _databasesPath!; + } + + /// Set the databases path. + @override + @Deprecated('Use setDatabasesPathOrNull') + Future setDatabasesPath(String? path) async { + setDatabasesPathOrNull(path); + } + + /// Set the databases path. + void setDatabasesPathOrNull(String? path) { + _databasesPath = path; + } + + /// True if a database path is in memory + // @Deprecated('use path_utils.isInMemoryDatabasePath') + static bool isInMemoryDatabasePath(String path) => pu.isInMemoryDatabasePath(path); + + final bool _kIsWeb = identical(0, 0.0); + + /// path must be non null + Future fixPath(String path) async { + /// Transform file::memory: to :memory as current implementation + /// relies on this feature. + if (pu.isInMemoryDatabasePath(path)) { + return inMemoryDatabasePath; + } else if (_kIsWeb || pu.isFileUriDatabasePath(path)) { + // nothing + } else { + if (isRelative(path)) { + path = join(await getDatabasesPath(), path); + } + path = absolute(normalize(path)); + } + return path; + } + + /// Debug information. + Future getDebugInfo() async { + final info = SqfliteDebugInfo(); + final map = await safeInvokeMethod(methodDebug, {'cmd': 'get'}); + final databasesMap = map[paramDatabases]; + if (databasesMap is Map) { + info.databases = databasesMap.map((dynamic id, dynamic info) { + final dbInfo = SqfliteDatabaseDebugInfo(); + final databaseId = id.toString(); + + if (info is Map) { + dbInfo.fromMap(info); + } + return MapEntry(databaseId, dbInfo); + }); + } + info.logLevel = map[paramLogLevel] as int?; + return info; + } + + @override + String toString() => 'SqfliteDatabaseFactory(${tag ?? 'sqflite'})'; +} + +// When opening the database (bool) +/// Native parameter (int) +const String paramLogLevel = 'logLevel'; + +/// Native parameter +const String paramDatabases = 'databases'; + +/// Debug information +class SqfliteDatabaseDebugInfo { + /// Database path + String? path; + + /// Whether the database was open as a single instance + bool? singleInstance; + + /// Log level + int? logLevel; + + /// Deserializer + void fromMap(Map map) { + path = map[paramPath]?.toString(); + singleInstance = map[paramSingleInstance] as bool?; + logLevel = map[paramLogLevel] as int?; + } + + /// Debug formatting helper + Map toDebugMap() { + final map = {paramPath: path, paramSingleInstance: singleInstance}; + if ((logLevel ?? sqfliteLogLevelNone) > sqfliteLogLevelNone) { + map[paramLogLevel] = logLevel; + } + return map; + } + + @override + String toString() => toDebugMap().toString(); +} + +/// Internal debug info +class SqfliteDebugInfo { + /// List of databases + Map? databases; + + /// global log level (set for new opened databases) + int? logLevel; + + /// Debug formatting helper + Map toDebugMap() { + final map = {}; + if (databases != null) { + map[paramDatabases] = databases! + .map((String key, SqfliteDatabaseDebugInfo dbInfo) => MapEntry>(key, dbInfo.toDebugMap())); + } + if ((logLevel ?? sqfliteLogLevelNone) > sqfliteLogLevelNone) { + map[paramLogLevel] = logLevel; + } + return map; + } + + @override + String toString() => toDebugMap().toString(); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/internals.dart b/sqflite/tripartite/sqflite_common/lib/src/internals.dart new file mode 100644 index 0000000..90ef2b3 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/internals.dart @@ -0,0 +1,26 @@ +import 'package:meta/meta.dart'; +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/database_mixin.dart'; +import 'package:sqflite_common/src/factory.dart'; + +/// Internal access to invoke method +extension DatabaseFactoryInternalsExt on DatabaseFactory { + /// Call invoke method manually. + @visibleForTesting + Future internalsInvokeMethod(String method, Object? arguments) async { + return (this as SqfliteDatabaseFactory).invokeMethod(method, arguments); + } +} + +/// Internal access to database configuration +extension DatabaseInternalsExt on Database { + /// Do not use synchronized to allow concurrent access + @visibleForTesting + set internalsDoNotUseSynchronized(bool doNotUseSynchronized) => + (this as SqfliteDatabaseMixin).doNotUseSynchronized = + doNotUseSynchronized; + + /// Internal database id. + @visibleForTesting + int? get databaseId => (this as SqfliteDatabaseMixin).id; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/log_level.dart b/sqflite/tripartite/sqflite_common/lib/src/log_level.dart new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/log_level.dart @@ -0,0 +1 @@ + diff --git a/sqflite/tripartite/sqflite_common/lib/src/logger/sqflite_logger.dart b/sqflite/tripartite/sqflite_common/lib/src/logger/sqflite_logger.dart new file mode 100644 index 0000000..dbacfa6 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/logger/sqflite_logger.dart @@ -0,0 +1,880 @@ +import 'dart:async'; +import 'dart:core'; +import 'dart:core' as core; +import 'package:meta/meta.dart'; +import 'package:sqflite_common/sqflite_logger.dart'; +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/batch.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/database_mixin.dart'; +import 'package:sqflite_common/src/env_utils.dart'; +import 'package:sqflite_common/src/factory.dart'; +import 'package:sqflite_common/src/factory_mixin.dart'; +import 'package:sqflite_common/src/sql_command.dart'; +import 'package:sqflite_common/src/transaction.dart'; + +/// Log helper to avoid overflow +String logTruncateAny(Object? value) { + return logTruncate(value?.toString() ?? ''); +} + +/// Log helper to avoid overflow +String logTruncate(String text, {int len = 256}) { + if (text.length > len) { + text = text.substring(0, len); + } + return text; +} + +/// Type of logging. For now, only all logs (no filtering) are supported. +enum SqfliteDatabaseFactoryLoggerType { + /// All logs are returned. default. For the 3rd party debugging. + all, + + /// Internal implementation invocation. For internal debugging. + /// + /// all events are SqfliteLoggerInvokeEvent + invoke, +} + +/// Logger event function. +typedef SqfliteLoggerEventFunction = void Function(SqfliteLoggerEvent event); + +/// Every operation/event is a command +abstract class SqfliteLoggerCommand { + /// Name of the command (insert/delete/update...) for display only. + String get name; + + /// Set on failure + Object? get error; +} + +/// Logger event. +abstract class SqfliteLoggerEvent implements SqfliteLoggerCommand { + /// Stopwatch. for performance testing. + Stopwatch? get sw; +} + +/// View helper +@visibleForTesting +abstract class SqfliteLoggerEventView implements SqfliteLoggerEvent { + /// Map view. + Map toMap(); +} + +abstract class _SqfliteLoggerEvent + implements SqfliteLoggerEvent, SqfliteLoggerEventView { + @override + late final Object? error; + + @override + late final Stopwatch? sw; + + _SqfliteLoggerEvent(this.sw, this.error); + + /// Allow late init. + _SqfliteLoggerEvent._(); + + @override + Map toMap() => { + if (sw != null) 'sw': '${sw!.elapsed}', + if (error != null) 'error': error + }; + + @override + String toString() => toLogString(toMap()); +} + +/// Generic method event. +abstract class SqfliteLoggerInvokeEvent extends SqfliteLoggerEvent { + /// Invoke method. + String get method; + + /// Invoke arguments. + Object? get arguments; + + /// The result (result can be null if error is null but cannot be non null if error is null). + Object? get result; +} + +/// Open db event +abstract class SqfliteLoggerDatabaseDeleteEvent extends SqfliteLoggerEvent { + /// Database path. + String? get path; +} + +/// Open db event +abstract class SqfliteLoggerDatabaseOpenEvent extends SqfliteLoggerEvent { + /// The options used. + OpenDatabaseOptions? get options; + + /// Invoke arguments. + String? get path; + + /// The resulting database on success + Database? get db; +} + +/// Open db event +abstract class SqfliteLoggerDatabaseCloseEvent extends SqfliteLoggerEvent { + /// The closed database. + Database? get db; +} + +/// In database event. +abstract class SqfliteLoggerDatabaseEvent implements SqfliteLoggerEvent { + /// The database client (transaction or database) + DatabaseExecutor get client; +} + +/// Open db event +abstract class SqfliteLoggerSqlEvent extends SqfliteLoggerDatabaseEvent + implements SqfliteLoggerSqlCommand {} + +/// Typed sql command +abstract class SqfliteLoggerSqlCommand implements SqfliteLoggerCommand { + /// The command type. + SqliteSqlCommandType get type; + + /// Invoke arguments. + String get sql; + + /// Sql arguments. + Object? get arguments; + + /// Optional result. + T? get result; +} + +/// batch event +abstract class SqfliteLoggerBatchEvent extends SqfliteLoggerDatabaseEvent { + /// batch operations. + List get operations; +} + +/// Sql batch operation. +abstract class SqfliteLoggerBatchOperation + implements SqfliteLoggerSqlCommand {} + +mixin _SqfliteLoggerSqlCommandMixin implements SqfliteLoggerSqlCommand { + @override + late final SqliteSqlCommandType type; + + /// Invoke arguments. + @override + late final String sql; + + /// Sql arguments. + @override + late final Object? arguments; + + /// Optional result. + @override + late final T? result; + + String get _typeAsText => type.toString().split('.').last; +} + +abstract class _SqfliteLoggerDatabaseEvent extends _SqfliteLoggerEvent + implements SqfliteLoggerDatabaseEvent { + late final DatabaseExecutor _client; + + @override + DatabaseExecutor get client => _client; + + set client(DatabaseExecutor client) { + _client = client; + // save txn id right away to handle when not set yet. + txnId = (client as SqfliteDatabaseExecutorMixin).txn?.transactionId; + } + + Map get _databasePrefixMap => { + if (client.database is SqfliteDatabase) + 'db': (client.database as SqfliteDatabase).id, + if (txnId != null) 'txn': txnId + }; + + late int? txnId; + + @override + Map toMap() => {..._databasePrefixMap, ...super.toMap()}; + + _SqfliteLoggerDatabaseEvent(super.sw, DatabaseExecutor client, super.error) { + this.client = client; + } + + /// Allow late init. + _SqfliteLoggerDatabaseEvent._() : super._(); +} + +/// Event or batch operation execute command return a count. +abstract class SqfliteLoggerSqlCommandExecute + extends SqfliteLoggerSqlCommand {} + +/// Event or batch operation insert command return a record id. +abstract class SqfliteLoggerSqlCommandInsert + extends SqfliteLoggerSqlCommand {} + +/// Event or batch operation update command return a count. +abstract class SqfliteLoggerSqlCommandUpdate + extends SqfliteLoggerSqlCommand {} + +/// Event or batch operation delete command return a count. +abstract class SqfliteLoggerSqlCommandDelete + extends SqfliteLoggerSqlCommand {} + +/// Event or batch operation query command. +abstract class SqfliteLoggerSqlCommandQuery + extends SqfliteLoggerSqlCommand>> {} + +mixin _SqfliteLoggerSqlCommandInsertMixin { + String get name => 'insert'; +} +mixin _SqfliteLoggerSqlCommandExecuteMixin { + String get name => 'execute'; +} +mixin _SqfliteLoggerSqlCommandUpdateMixin { + String get name => 'update'; +} + +mixin _SqfliteLoggerSqlCommandDeleteMixin { + String get name => 'delete'; +} + +mixin _SqfliteLoggerSqlCommandQueryMixin { + String get name => 'query'; +} + +class _SqfliteLoggerSqlEventInsert extends _SqfliteLoggerSqlEvent + with _SqfliteLoggerSqlCommandInsertMixin + implements SqfliteLoggerSqlCommandInsert {} + +class _SqfliteLoggerSqlEventExecute extends _SqfliteLoggerSqlEvent + with _SqfliteLoggerSqlCommandExecuteMixin + implements SqfliteLoggerSqlCommandExecute {} + +class _SqfliteLoggerSqlEventUpdate extends _SqfliteLoggerSqlEvent + with _SqfliteLoggerSqlCommandUpdateMixin + implements SqfliteLoggerSqlCommandUpdate {} + +class _SqfliteLoggerSqlEventDelete extends _SqfliteLoggerSqlEvent + with _SqfliteLoggerSqlCommandDeleteMixin + implements SqfliteLoggerSqlCommandDelete {} + +class _SqfliteLoggerSqlEventQuery + extends _SqfliteLoggerSqlEvent>> + with _SqfliteLoggerSqlCommandQueryMixin + implements SqfliteLoggerSqlCommandQuery {} + +abstract class _SqfliteLoggerSqlEvent extends _SqfliteLoggerDatabaseEvent + with _SqfliteLoggerSqlCommandMixin + implements SqfliteLoggerSqlEvent { + _SqfliteLoggerSqlEvent() : super._(); + + static _SqfliteLoggerSqlEvent fromDynamic( + Stopwatch sw, + DatabaseExecutor client, + SqliteSqlCommandType type, + String sql, + List? arguments, + Object? result, + Object? error) { + _SqfliteLoggerSqlEvent event; + switch (type) { + case SqliteSqlCommandType.execute: + event = _SqfliteLoggerSqlEventExecute(); + break; + case SqliteSqlCommandType.insert: + event = _SqfliteLoggerSqlEventInsert(); + break; + case SqliteSqlCommandType.update: + event = _SqfliteLoggerSqlEventUpdate(); + break; + case SqliteSqlCommandType.delete: + event = _SqfliteLoggerSqlEventDelete(); + break; + case SqliteSqlCommandType.query: + event = _SqfliteLoggerSqlEventQuery(); + break; + } + + event.type = type; + event.sql = sql; + event.arguments = arguments; + event.result = result; + event.error = error; + event.sw = sw; + event.client = client; + return event; + } + + @override + Map toMap() => { + ..._databasePrefixMap, + 'sql': sql, + if (arguments != null) 'arguments': arguments, + if (result != null) 'result': result, + ...super.toMap() + }; + + @override + String toString() => '$_typeAsText(${super.toString()})'; +} + +/// Open db event +class _SqfliteLoggerBatchEvent extends _SqfliteLoggerDatabaseEvent + implements SqfliteLoggerBatchEvent { + @override + String get name => 'batch'; + @override + final List operations; + + _SqfliteLoggerBatchEvent( + super.sw, super.client, this.operations, super.error); + + @override + Map toMap() => { + ..._databasePrefixMap, + 'operations': operations + .map((e) => (e as _SqfliteLoggerBatchOperation).toMap()) + .toList(), + ...super.toMap() + }; +} + +class _SqfliteLoggerBatchInsertOperation + extends _SqfliteLoggerBatchOperation + with _SqfliteLoggerSqlCommandInsertMixin + implements SqfliteLoggerSqlCommandInsert {} + +class _SqfliteLoggerBatchUpdateOperation + extends _SqfliteLoggerBatchOperation + with _SqfliteLoggerSqlCommandUpdateMixin + implements SqfliteLoggerSqlCommandUpdate {} + +class _SqfliteLoggerBatchDeleteOperation + extends _SqfliteLoggerBatchOperation + with _SqfliteLoggerSqlCommandDeleteMixin + implements SqfliteLoggerSqlCommandDelete {} + +class _SqfliteLoggerBatchExecuteOperation + extends _SqfliteLoggerBatchOperation + with _SqfliteLoggerSqlCommandExecuteMixin + implements SqfliteLoggerSqlCommandExecute {} + +class _SqfliteLoggerBatchQueryOperation + extends _SqfliteLoggerBatchOperation>> + with _SqfliteLoggerSqlCommandQueryMixin + implements SqfliteLoggerSqlCommandQuery {} + +/// Batch sql operation +abstract class _SqfliteLoggerBatchOperation + with _SqfliteLoggerSqlCommandMixin + implements SqfliteLoggerBatchOperation { + @override + late final Object? error; + + static _SqfliteLoggerBatchOperation fromDynamic(SqliteSqlCommandType type, + String sql, List? arguments, Object? result, Object? error) { + _SqfliteLoggerBatchOperation operation; + switch (type) { + case SqliteSqlCommandType.execute: + operation = _SqfliteLoggerBatchExecuteOperation(); + break; + case SqliteSqlCommandType.insert: + operation = _SqfliteLoggerBatchInsertOperation(); + break; + + case SqliteSqlCommandType.update: + operation = _SqfliteLoggerBatchUpdateOperation(); + break; + case SqliteSqlCommandType.delete: + operation = _SqfliteLoggerBatchDeleteOperation(); + break; + case SqliteSqlCommandType.query: + operation = _SqfliteLoggerBatchQueryOperation(); + break; + } + operation.type = type; + operation.sql = sql; + operation.arguments = arguments; + operation.result = result; + operation.error = error; + return operation; + } + + Map toMap() { + var map = { + 'sql': sql, + if (arguments != null) 'arguments': arguments, + if (result != null) 'result': result, + if (error != null) 'error': error + }; + return map; + } + + @override + String toString() => '$_typeAsText(${logTruncate(toMap().toString())})'; +} + +class _SqfliteLoggerDatabaseDeleteEvent extends _SqfliteLoggerEvent + implements SqfliteLoggerDatabaseDeleteEvent { + @override + final String path; + + @override + Map toMap() => { + 'path': path, + }; + + _SqfliteLoggerDatabaseDeleteEvent(super.sw, this.path, super.error); + + @override + String get name => 'deleteDatabase'; +} + +class _SqfliteLoggerDatabaseOpenEvent extends _SqfliteLoggerEvent + implements SqfliteLoggerDatabaseOpenEvent { + @override + final SqfliteDatabase? db; + + @override + final OpenDatabaseOptions? options; + + @override + final String path; + + @override + Map toMap() => { + 'path': path, + if (options != null) 'options': options!.toMap(), + if (db?.id != null) 'id': db!.id, + ...super.toMap() + }; + + _SqfliteLoggerDatabaseOpenEvent( + super.sw, this.path, this.options, this.db, super.error); + + @override + String get name => 'openDatabase'; +} + +class _SqfliteLoggerDatabaseCloseEvent extends _SqfliteLoggerDatabaseEvent + implements SqfliteLoggerDatabaseCloseEvent { + @override + Map toMap() => {..._databasePrefixMap, ...super.toMap()}; + + _SqfliteLoggerDatabaseCloseEvent(super.sw, super.db, super.error); + @override + String get name => 'closeDatabase'; + + @override + Database get db => client.database; +} + +class _SqfliteLoggerInvokeEvent extends _SqfliteLoggerEvent + implements SqfliteLoggerInvokeEvent { + @override + final Object? result; + + @override + final Object? arguments; + + @override + final String method; + + @override + Map toMap() => { + 'method': method, + if (arguments != null) 'arguments': arguments, + if (result != null) 'result': result, + ...super.toMap() + }; + + _SqfliteLoggerInvokeEvent( + super.sw, this.method, this.arguments, this.result, super.error); + + @override + String get name => 'invoke'; +} + +class _EventInfo { + Object? error; + StackTrace? stackTrace; + T? result; + final sw = Stopwatch()..start(); + + T throwOrResult() { + if (error != null) { + if (isDebug && (stackTrace != null)) { + print(stackTrace); + } + throw error!; + } + return result as T; + } +} + +/// Default logger. print! +void _logDefault(SqfliteLoggerEvent event) { + event.dump(); +} + +/// Default type, all! +var _typeDefault = SqfliteDatabaseFactoryLoggerType.all; + +/// Sqflite logger option. +/// +/// [type] default to [SqfliteDatabaseFactoryLoggerType.all] +/// [log] default to print. +class SqfliteLoggerOptions { + /// True if write should be logged + late final void Function(SqfliteLoggerEvent event) log; + + /// The logger type (filtering) + late final SqfliteDatabaseFactoryLoggerType type; + + /// Sqflite logger option. + SqfliteLoggerOptions( + {SqfliteLoggerEventFunction? log, + SqfliteDatabaseFactoryLoggerType? type}) { + this.log = log ?? _logDefault; + this.type = type ?? _typeDefault; + } +} + +/// Special wrapper that allows easily wrapping each API calls. +abstract class SqfliteDatabaseFactoryLogger implements SqfliteDatabaseFactory { + /// Wrap each call in a logger. + @experimental + factory SqfliteDatabaseFactoryLogger(DatabaseFactory factory, + {SqfliteLoggerOptions? options}) { + var delegate = factory; + if (factory is SqfliteDatabaseFactoryLogger) { + delegate = (factory as _SqfliteDatabaseFactoryLogger)._delegate; + } + return _SqfliteDatabaseFactoryLogger( + delegate as SqfliteDatabaseFactory, options ?? SqfliteLoggerOptions()); + } +} + +mixin _SqfliteDatabaseExecutorLoggerMixin implements SqfliteDatabaseExecutor { + SqfliteDatabaseExecutor _executor(SqfliteTransaction? txn) => + txn ?? this.txn ?? this; +} + +class _SqfliteDatabaseLogger extends SqfliteDatabaseBase + with _SqfliteDatabaseExecutorLoggerMixin + implements SqfliteDatabase { + late final _SqfliteDatabaseFactoryLogger _factory; + + SqfliteLoggerOptions get _options => _factory._options; + + @override + _SqfliteDatabaseFactoryLogger get factory => _factory; + + _SqfliteDatabaseLogger(SqfliteDatabaseOpenHelper openHelper, String path, + {OpenDatabaseOptions? options}) + : super(openHelper, path, options: options) { + _factory = openHelper.factory as _SqfliteDatabaseFactoryLogger; + } + + void _log(SqfliteLoggerEvent event) => _options.log(event); + + bool get _needLogAll => _options.type == SqfliteDatabaseFactoryLoggerType.all; + + @override + Future openDatabase() async { + Future doOpenDatabase() async { + return (await super.openDatabase()); + } + + if (!_needLogAll) { + return await doOpenDatabase(); + } else { + var info = await _wrap(doOpenDatabase); + _options.log(_SqfliteLoggerDatabaseOpenEvent( + info.sw, path, options, this, info.error)); + return info.throwOrResult(); + } + } + + @override + Future close() async { + Future doClose() { + return super.close(); + } + + if (_needLogAll) { + var info = await _wrap(doClose); + _log(_SqfliteLoggerDatabaseCloseEvent(info.sw, this, info.error)); + info.throwOrResult(); + } else { + await doClose(); + } + } + + /// Commit a batch. + @override + Future> txnApplyBatch( + SqfliteTransaction? txn, SqfliteBatch batch, + {bool? noResult, bool? continueOnError}) async { + Future> doApplyBatch() { + return super.txnApplyBatch(txn, batch, + noResult: noResult, continueOnError: continueOnError); + } + + if (_needLogAll) { + var info = await _wrap(doApplyBatch); + + var logOperations = <_SqfliteLoggerBatchOperation>[]; + if (info.error == null) { + var operations = batch.operations; + + for (var i = 0; i < operations.length; i++) { + var operation = operations[i]; + Object? result; + Object? error; + if (noResult != true) { + var resultOrError = info.result![i]; + if (resultOrError is DatabaseException) { + error = resultOrError; + } else { + result = resultOrError; + } + } + logOperations.add(_SqfliteLoggerBatchOperation.fromDynamic( + operation.type, + operation.sql, + operation.arguments, + result, + error)); + } + } + _options.log(_SqfliteLoggerBatchEvent( + info.sw, _executor(txn), logOperations, info.error)); + return info.throwOrResult(); + } else { + return await doApplyBatch(); + } + } + + /// Execute a raw SQL SELECT query + /// + /// Returns a list of rows that were found + @override + Future>> txnRawQuery( + SqfliteTransaction? txn, String sql, List? arguments) { + return _txnWrapSql(txn, SqliteSqlCommandType.query, sql, arguments, + () async { + return super.txnRawQuery(txn, sql, arguments); + }); + } + + @override + Future txnRawDelete( + SqfliteTransaction? txn, String sql, List? arguments) { + return _txnWrapSql(txn, SqliteSqlCommandType.delete, sql, arguments, + () async { + return super.txnRawDelete(txn, sql, arguments); + }); + } + + @override + Future txnRawUpdate( + SqfliteTransaction? txn, String sql, List? arguments) { + return _txnWrapSql(txn, SqliteSqlCommandType.update, sql, arguments, + () async { + return super.txnRawUpdate(txn, sql, arguments); + }); + } + + /// for INSERT sql query + /// returns the last inserted record id + /// + /// 0 returned instead of null + @override + Future txnRawInsert( + SqfliteTransaction? txn, String sql, List? arguments) { + return _txnWrapSql(txn, SqliteSqlCommandType.insert, sql, arguments, + () async { + return super.txnRawInsert(txn, sql, arguments); + }); + } + + /// Execute a command. + @override + Future txnExecute( + SqfliteTransaction? txn, String sql, List? arguments, + {bool? beginTransaction}) { + return _txnWrapSql( + txn, + SqliteSqlCommandType.execute, + sql, + arguments, + () => super.txnExecute(txn, sql, arguments, + beginTransaction: beginTransaction)); + } + + Future _txnWrapSql(SqfliteTransaction? txn, SqliteSqlCommandType type, + String sql, List? arguments, Future Function() action) async { + if (!_needLogAll) { + return await action(); + } else { + var info = await _wrap(action); + _options.log(_SqfliteLoggerSqlEvent.fromDynamic(info.sw, _executor(txn), + type, sql, arguments, info.result, info.error)); + return info.throwOrResult(); + } + } + + Future<_EventInfo> _wrap(FutureOr Function() action) => + _factory._wrap(action); +} + +class _SqfliteDatabaseFactoryLogger + with SqfliteDatabaseFactoryMixin + implements SqfliteDatabaseFactoryLogger { + final SqfliteDatabaseFactory _delegate; + final SqfliteLoggerOptions _options; + + _SqfliteDatabaseFactoryLogger(this._delegate, this._options); + + // Needed for proper exception conversion. + @override + Future wrapDatabaseException(Future Function() action) => + _delegate.wrapDatabaseException(action); + + /// The only method to override to create a custom object. + @override + SqfliteDatabaseMixin newDatabase( + SqfliteDatabaseOpenHelper openHelper, String path) { + return _SqfliteDatabaseLogger(openHelper, path); + } + + Future<_EventInfo> _wrap(FutureOr Function() action) async { + var info = _EventInfo(); + try { + var result = await action(); + info.result = result; + } catch (error, stackTrace) { + info.error = error; + if (isDebug) { + info.stackTrace = stackTrace; + } + } finally { + info.sw.stop(); + } + return info; + } + + /// The only method to override to use the delegate + @override + Future invokeMethod(String method, [Object? arguments]) async { + Future doInvokeMethod() { + return _delegate.invokeMethod(method, arguments); + } + + if (_options.type == SqfliteDatabaseFactoryLoggerType.invoke) { + var info = await _wrap(doInvokeMethod); + _options.log(_SqfliteLoggerInvokeEvent( + info.sw, method, arguments, info.result, info.error)); + return info.throwOrResult(); + } else { + return await doInvokeMethod(); + } + } + + @override + Future deleteDatabase(String path) async { + Future doDeleteDatabase() { + return super.deleteDatabase(path); + } + + if (_options.type == SqfliteDatabaseFactoryLoggerType.all) { + var info = await _wrap(doDeleteDatabase); + _options + .log(_SqfliteLoggerDatabaseDeleteEvent(info.sw, path, info.error)); + return info.throwOrResult(); + } else { + return await doDeleteDatabase(); + } + } +} + +/// internal extension. +@visibleForTesting +extension OpenDatabaseOptionsLogger on OpenDatabaseOptions { + /// To map view + Map toMap() => { + 'readOnly': readOnly, + 'singleInstance': singleInstance, + if (version != null) 'version': version + }; +} + +/// Basic dump +extension SqfliteLoggerEventExt on SqfliteLoggerEvent { + /// dump event by lines + void dump({void Function(Object? object)? print, bool? noStopwatch}) { + print ??= core.print; + + if (this is SqfliteLoggerBatchEvent) { + if (noStopwatch ?? false) { + print(toLogString(toMapNoOperationsNoStopwatch())); + } else { + print(toLogString(toMapNoOperations())); + } + for (var operation in (this as SqfliteLoggerBatchEvent).operations) { + print(' $operation'); + } + } else { + // default to improve + if (noStopwatch ?? false) { + print(toStringNoStopwatch()); + } else { + print(toString()); + } + } + } +} + +/// Not exported. +extension SqfliteLoggerEventInternalExt on SqfliteLoggerEvent { + /// Internal only. + Map toMapNoStopwatch() { + return (Map.from((this as SqfliteLoggerEventView).toMap())) + ..remove('sw'); + } + + /// Internal only. + Map toMapNoOperations() { + return (Map.from((this as SqfliteLoggerEventView).toMap())) + ..remove('operations'); + } + + /// Internal only. + Map toMapNoOperationsNoStopwatch() { + return (toMapNoStopwatch())..remove('operations'); + } + + /// Internal only, prefix with the event name. + String toLogString(Object? data) => logTruncate('$name:($data)'); + + /// Internal only. + String toStringNoStopwatch() => toLogString(toMapNoStopwatch()); +} + +/// Debug extension for Logger. +extension DatabaseFactoryLoggerDebugExt on DatabaseFactory { + /// Quick logger wrapper, useful in unit test. + /// + /// databaseFactory = databaseFactory.debugQuickLoggerWrapper() + @Deprecated('Debug/dev mode') + DatabaseFactory debugQuickLoggerWrapper() { + var factoryWithLogs = SqfliteDatabaseFactoryLogger(this, + options: + SqfliteLoggerOptions(type: SqfliteDatabaseFactoryLoggerType.all)); + return factoryWithLogs; + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/method_call.dart b/sqflite/tripartite/sqflite_common/lib/src/method_call.dart new file mode 100644 index 0000000..63e1ad8 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/method_call.dart @@ -0,0 +1,33 @@ +import 'package:meta/meta.dart'; + +/// An command object representing the invocation of a named method. +@immutable +class SqfliteMethodCall { + /// Creates a [MethodCall] representing the invocation of [method] with the + /// specified [arguments]. + const SqfliteMethodCall(this.method, [this.arguments]); + + /// Build from a map. + factory SqfliteMethodCall.fromMap(Map map) { + return SqfliteMethodCall(map['method'] as String, map['arguments']); + } + + /// The name of the method to be called. + final String method; + + /// The arguments for the method. + /// + /// Must be a valid value for the [MethodCodec] used. + final Object? arguments; + + /// To map + Map toMap() { + return { + 'method': method, + if (arguments != null) 'arguments': arguments + }; + } + + @override + String toString() => '$runtimeType($method, $arguments)'; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/mixin.dart b/sqflite/tripartite/sqflite_common/lib/src/mixin.dart new file mode 100644 index 0000000..4eb3798 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/mixin.dart @@ -0,0 +1,5 @@ +/// Sqflite mixins +/// +/// Warning the API here are exposed to external implementation +export 'database_mixin.dart'; +export 'factory_mixin.dart'; diff --git a/sqflite/tripartite/sqflite_common/lib/src/mixin/constant.dart b/sqflite/tripartite/sqflite_common/lib/src/mixin/constant.dart new file mode 100644 index 0000000..5d9fb8c --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/mixin/constant.dart @@ -0,0 +1 @@ +export 'package:sqflite_common/src/constant.dart' hide methodSetDebugModeOn; diff --git a/sqflite/tripartite/sqflite_common/lib/src/mixin/dev_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/mixin/dev_utils.dart new file mode 100644 index 0000000..0c71a18 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/mixin/dev_utils.dart @@ -0,0 +1,2 @@ +// ignore: deprecated_member_use, deprecated_member_use_from_same_package +export 'package:sqflite_common/src/dev_utils.dart' show devPrint, devWarning; diff --git a/sqflite/tripartite/sqflite_common/lib/src/mixin/factory.dart b/sqflite/tripartite/sqflite_common/lib/src/mixin/factory.dart new file mode 100644 index 0000000..bedde06 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/mixin/factory.dart @@ -0,0 +1,38 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/factory_mixin.dart'; + +/// Mixin handler +abstract class SqfliteInvokeHandler { + /// Invoke method + Future invokeMethod(String method, [Object? arguments]); +} + +class _SqfliteDatabaseFactoryImpl + with SqfliteDatabaseFactoryMixin + implements SqfliteInvokeHandler { + _SqfliteDatabaseFactoryImpl(this._invokeMethod, {String? tag}) { + this.tag = tag; + } + + final Future Function(String method, [Object? arguments]) + _invokeMethod; + + @override + Future invokeMethod(String method, [Object? arguments]) async => + (await _invokeMethod(method, arguments)) as T; +} + +/// Build a database factory invoking the invoke method instead of going through +/// flutter services. +/// +/// To use to enable running without flutter plugins (unit test) +/// +/// [tag] is an optional debug +DatabaseFactory buildDatabaseFactory( + {String? tag, + required Future Function(String method, [Object? arguments]) + invokeMethod}) { + final DatabaseFactory impl = + _SqfliteDatabaseFactoryImpl(invokeMethod, tag: tag); + return impl; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/mixin/import_mixin.dart b/sqflite/tripartite/sqflite_common/lib/src/mixin/import_mixin.dart new file mode 100644 index 0000000..c76b8f9 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/mixin/import_mixin.dart @@ -0,0 +1,45 @@ +/// +/// Export for implementation: sqflite, sqflite_common_ffi +/// +export 'package:sqflite_common/src/compat.dart' + show + SqfliteOptions; // ignore: deprecated_member_use, deprecated_member_use_from_same_package +/// Explicit list of needed private import +export 'package:sqflite_common/src/database.dart' // ignore: implementation_imports + show + SqfliteDatabaseOpenHelper, + SqfliteDatabase; +export 'package:sqflite_common/src/database_mixin.dart' // ignore: implementation_imports + show + SqfliteDatabaseMixin, + SqfliteDatabaseBase; + +// +// Exception +// +export 'package:sqflite_common/src/exception.dart' + show SqfliteDatabaseException; +export 'package:sqflite_common/src/factory.dart' show SqfliteDatabaseFactory; + +// +// Factory mixin +// +export 'package:sqflite_common/src/factory_mixin.dart' + show SqfliteDatabaseFactoryBase, SqfliteDatabaseFactoryMixin; + +// +// Constant +// +export 'package:sqflite_common/src/mixin/constant.dart' + show + methodOpenDatabase, + methodCloseDatabase, + methodOptions, + methodInsert, + methodQuery, + methodUpdate, + methodExecute, + methodBatch, + sqliteErrorCode; +export 'package:sqflite_common/src/mixin/factory.dart' + show buildDatabaseFactory, SqfliteInvokeHandler; diff --git a/sqflite/tripartite/sqflite_common/lib/src/open_options.dart b/sqflite/tripartite/sqflite_common/lib/src/open_options.dart new file mode 100644 index 0000000..b5c0ca4 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/open_options.dart @@ -0,0 +1,48 @@ +import 'package:sqflite_common/sqlite_api.dart'; + +/// +/// Options to open a database +/// See [openDatabase] for details +/// +class SqfliteOpenDatabaseOptions implements OpenDatabaseOptions { + /// See [openDatabase] for details + SqfliteOpenDatabaseOptions({ + this.version, + this.onConfigure, + this.onCreate, + this.onUpgrade, + this.onDowngrade, + this.onOpen, + bool? readOnly = false, + bool? singleInstance = true, + }) : readOnly = readOnly ?? false, + singleInstance = singleInstance ?? true; + + @override + int? version; + @override + OnDatabaseConfigureFn? onConfigure; + @override + OnDatabaseCreateFn? onCreate; + @override + OnDatabaseVersionChangeFn? onUpgrade; + @override + OnDatabaseVersionChangeFn? onDowngrade; + @override + OnDatabaseOpenFn? onOpen; + @override + bool readOnly; + @override + bool singleInstance; + + @override + String toString() { + final map = {}; + if (version != null) { + map['version'] = version; + } + map['readOnly'] = readOnly; + map['singleInstance'] = singleInstance; + return map.toString(); + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/path_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/path_utils.dart new file mode 100644 index 0000000..ee4e6dc --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/path_utils.dart @@ -0,0 +1,21 @@ +import 'package:sqflite_common/sqlite_api.dart'; + +const _fileUriPrefix = 'file:'; + +/// True if a database path is in memory +bool isInMemoryDatabasePath(String path) { + if (path == inMemoryDatabasePath) { + return true; + } + if (isFileUriDatabasePath(path)) { + if (path.substring(_fileUriPrefix.length) == inMemoryDatabasePath) { + return true; + } + } + return false; +} + +/// True if a database path is a file uri +bool isFileUriDatabasePath(String path) { + return path.startsWith(_fileUriPrefix); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/platform/platform.dart b/sqflite/tripartite/sqflite_common/lib/src/platform/platform.dart new file mode 100644 index 0000000..42c7d42 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/platform/platform.dart @@ -0,0 +1,22 @@ +export 'platform_io.dart' if (dart.library.js) 'platform_web.dart'; + +/// IO/web support +abstract class Platform { + /// True if web + bool get isWeb => false; + + /// True if IO windows + bool get isWindows => false; + + /// True if IO ios + bool get isIOS => false; + + /// True if IO Android + bool get isAndroid => false; + + /// True if IO Linux + bool get isLinux => false; + + /// True if IO MacOS + bool get isMacOS => false; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/platform/platform_io.dart b/sqflite/tripartite/sqflite_common/lib/src/platform/platform_io.dart new file mode 100644 index 0000000..fc68d2d --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/platform/platform_io.dart @@ -0,0 +1,23 @@ +import 'dart:io' as io; + +import 'package:sqflite_common/src/platform/platform.dart'; + +class _PlatformIo extends Platform { + @override + bool get isWindows => io.Platform.isWindows; + + @override + bool get isIOS => io.Platform.isIOS; + + @override + bool get isAndroid => io.Platform.isAndroid; + + @override + bool get isLinux => io.Platform.isLinux; + + @override + bool get isMacOS => io.Platform.isMacOS; +} + +/// Platform (IO) +final platform = _PlatformIo(); diff --git a/sqflite/tripartite/sqflite_common/lib/src/platform/platform_web.dart b/sqflite/tripartite/sqflite_common/lib/src/platform/platform_web.dart new file mode 100644 index 0000000..80e287d --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/platform/platform_web.dart @@ -0,0 +1,9 @@ +import 'package:sqflite_common/src/platform/platform.dart'; + +class _PlatformWeb extends Platform { + @override + bool get isWeb => false; +} + +/// Platform (Web) +final platform = _PlatformWeb(); diff --git a/sqflite/tripartite/sqflite_common/lib/src/sqflite_database_factory.dart b/sqflite/tripartite/sqflite_common/lib/src/sqflite_database_factory.dart new file mode 100644 index 0000000..f8de035 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/sqflite_database_factory.dart @@ -0,0 +1,57 @@ +import 'package:meta/meta.dart'; +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/factory.dart'; + +SqfliteDatabaseFactory? _databaseFactory; + +/// Default database factory. +@visibleForTesting +DatabaseFactory? get databaseFactoryOrNull => _databaseFactory; + +/// Change the default factory. +set databaseFactoryOrNull(DatabaseFactory? databaseFactory) { + if (databaseFactory != null) { + if (databaseFactory is! SqfliteDatabaseFactory) { + throw ArgumentError.value( + databaseFactory, 'databaseFactory', 'Unsupported sqflite factory'); + } + _databaseFactory = databaseFactory; + } else { + /// Unset + _databaseFactory = null; + } +} + +/// sqflite Default factory. +DatabaseFactory get databaseFactory => + _databaseFactory ?? + () { + throw StateError('''databaseFactory not initialized +databaseFactory is only initialized when using sqflite. When using `sqflite_common_ffi` +You must call `databaseFactory = databaseFactoryFfi;` before using global openDatabase API +'''); + }(); + +/// Change the default factory. +/// +/// Be aware of the potential side effect. Any library using sqflite +/// will have this factory as the default for all operations. +/// +/// This setter must be call only once, before any other calls to sqflite. +set databaseFactory(DatabaseFactory? databaseFactory) { + // Warn when changing. might throw in the future + if (databaseFactory != null) { + if (_databaseFactory != null) { + print(''' +*** sqflite warning *** + +You are changing sqflite default factory. +Be aware of the potential side effects. Any library using sqflite +will have this factory as the default for all operations. + +*** sqflite warning *** +'''); + } + } + databaseFactoryOrNull = databaseFactory; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/sqflite_debug.dart b/sqflite/tripartite/sqflite_common/lib/src/sqflite_debug.dart new file mode 100644 index 0000000..56a79fd --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/sqflite_debug.dart @@ -0,0 +1,27 @@ +import 'package:sqflite_common/sqlite_api.dart'; + +import 'mixin/import_mixin.dart'; +export 'logger/sqflite_logger.dart' show DatabaseFactoryLoggerDebugExt; + +/// Debug extension +/// +/// Access to dev options, deprecated for temp usage only +extension SqfliteDatabaseFactoryDebug on DatabaseFactory { + /// Change the log level if you want to see the SQL query + /// executed natively. + /// + /// Deprecated for temp usage only + @Deprecated('Dev only') + Future debugSetLogLevel(int logLevel) async { + await debugSetOptions(SqfliteOptions(logLevel: logLevel)); + } + + /// Testing only. + /// + /// deprecated on purpose to remove from code. + @Deprecated('Dev only') + Future debugSetOptions(SqfliteOptions options) async { + await (this as SqfliteInvokeHandler) + .invokeMethod(methodOptions, options.toMap()); + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/sqflite_import.dart b/sqflite/tripartite/sqflite_common/lib/src/sqflite_import.dart new file mode 100644 index 0000000..ec97042 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/sqflite_import.dart @@ -0,0 +1,32 @@ +/// +/// Export for implementation: sqflite, sqflite_common_ffi +/// +export 'package:sqflite_common/src/compat.dart' + show SqfliteOptions; // ignore: deprecated_member_use_from_same_package +/// Explicit list of needed private import +export 'package:sqflite_common/src/database.dart' // ignore: implementation_imports + show + SqfliteDatabaseOpenHelper, + SqfliteDatabase; +export 'package:sqflite_common/src/database_mixin.dart' // ignore: implementation_imports + show + SqfliteDatabaseMixin, + SqfliteDatabaseBase; +export 'package:sqflite_common/src/exception.dart' + show SqfliteDatabaseException; +export 'package:sqflite_common/src/factory.dart' show SqfliteDatabaseFactory; +export 'package:sqflite_common/src/factory_mixin.dart' + show SqfliteDatabaseFactoryBase, SqfliteDatabaseFactoryMixin; +export 'package:sqflite_common/src/mixin/constant.dart' + show + methodOpenDatabase, + methodCloseDatabase, + methodOptions, + sqliteErrorCode, + methodInsert, + methodQuery, + methodUpdate, + methodExecute, + methodBatch; +export 'package:sqflite_common/src/mixin/factory.dart' + show buildDatabaseFactory, SqfliteInvokeHandler; diff --git a/sqflite/tripartite/sqflite_common/lib/src/sql_builder.dart b/sqflite/tripartite/sqflite_common/lib/src/sql_builder.dart new file mode 100644 index 0000000..e655e34 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/sql_builder.dart @@ -0,0 +1,597 @@ +import 'package:sqflite_common/src/value_utils.dart'; + +/// Insert/Update conflict resolver +enum ConflictAlgorithm { + /// When a constraint violation occurs, an immediate ROLLBACK occurs, + /// thus ending the current transaction, and the command aborts with a + /// return code of SQLITE_CONSTRAINT. If no transaction is active + /// (other than the implied transaction that is created on every command) + /// then this algorithm works the same as ABORT. + rollback, + + /// When a constraint violation occurs,no ROLLBACK is executed + /// so changes from prior commands within the same transaction + /// are preserved. This is the default behavior. + abort, + + /// When a constraint violation occurs, the command aborts with a return + /// code SQLITE_CONSTRAINT. But any changes to the database that + /// the command made prior to encountering the constraint violation + /// are preserved and are not backed out. + fail, + + /// When a constraint violation occurs, the one row that contains + /// the constraint violation is not inserted or changed. + /// But the command continues executing normally. Other rows before and + /// after the row that contained the constraint violation continue to be + /// inserted or updated normally. No error is returned. + ignore, + + /// When a UNIQUE constraint violation occurs, the pre-existing rows that + /// are causing the constraint violation are removed prior to inserting + /// or updating the current row. Thus the insert or update always occurs. + /// The command continues executing normally. No error is returned. + /// If a NOT NULL constraint violation occurs, the NULL value is replaced + /// by the default value for that column. If the column has no default + /// value, then the ABORT algorithm is used. If a CHECK constraint + /// violation occurs then the IGNORE algorithm is used. When this conflict + /// resolution strategy deletes rows in order to satisfy a constraint, + /// it does not invoke delete triggers on those rows. + /// This behavior might change in a future release. + replace, +} + +final List _conflictValues = [ + 'OR ROLLBACK', + 'OR ABORT', + 'OR FAIL', + 'OR IGNORE', + 'OR REPLACE' +]; + +//final RegExp _sLimitPattern = new RegExp('\s*\d+\s*(,\s*\d+\s*)?'); + +/// SQL command builder. +class SqlBuilder { + /// Convenience method for deleting rows in the database. + /// + /// @param table the table to delete from + /// @param where the optional WHERE clause to apply when deleting. + /// Passing null will delete all rows. + /// @param whereArgs You may include ?s in the where clause, which + /// will be replaced by the values from whereArgs. The values + /// will be bound as Strings. + SqlBuilder.delete(String table, {String? where, List? whereArgs}) { + checkWhereArgs(whereArgs); + final delete = StringBuffer(); + delete.write('DELETE FROM '); + delete.write(_escapeName(table)); + _writeClause(delete, ' WHERE ', where); + sql = delete.toString(); + arguments = whereArgs != null ? List.from(whereArgs) : null; + } + + /// Build an SQL query string from the given clauses. + /// + /// @param distinct true if you want each row to be unique, false otherwise. + /// @param table The table names to compile the query against. + /// @param columns A list of which columns to return. Passing null will + /// return all columns, which is discouraged to prevent reading + /// data from storage that isn't going to be used. + /// @param where A filter declaring which rows to return, formatted as an SQL + /// WHERE clause (excluding the WHERE itself). Passing null will + /// return all rows for the given URL. + /// @param groupBy A filter declaring how to group rows, formatted as an SQL + /// GROUP BY clause (excluding the GROUP BY itself). Passing null + /// will cause the rows to not be grouped. + /// @param having A filter declare which row groups to include in the cursor, + /// if row grouping is being used, formatted as an SQL HAVING + /// clause (excluding the HAVING itself). Passing null will cause + /// all row groups to be included, and is required when row + /// grouping is not being used. + /// @param orderBy How to order the rows, formatted as an SQL ORDER BY clause + /// (excluding the ORDER BY itself). Passing null will use the + /// default sort order, which may be unordered. + /// @param limit Limits the number of rows returned by the query, + /// formatted as LIMIT clause. Passing null denotes no LIMIT clause. + SqlBuilder.query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + if (groupBy == null && having != null) { + throw ArgumentError( + 'HAVING clauses are only permitted when using a groupBy clause'); + } + checkWhereArgs(whereArgs); + + final query = StringBuffer(); + + query.write('SELECT '); + if (distinct == true) { + query.write('DISTINCT '); + } + if (columns != null && columns.isNotEmpty) { + _writeColumns(query, columns); + } else { + query.write('* '); + } + query.write('FROM '); + query.write(_escapeName(table)); + _writeClause(query, ' WHERE ', where); + _writeClause(query, ' GROUP BY ', groupBy); + _writeClause(query, ' HAVING ', having); + _writeClause(query, ' ORDER BY ', orderBy); + if (limit != null) { + _writeClause(query, ' LIMIT ', limit.toString()); + } + if (offset != null) { + _writeClause(query, ' OFFSET ', offset.toString()); + } + + sql = query.toString(); + arguments = whereArgs != null ? List.from(whereArgs) : null; + } + + /// Convenience method for inserting a row into the database. + /// Parameters: + /// @table the table to insert the row into + /// @nullColumnHack optional; may be null. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided values is empty, no column names are known and an empty row can't be inserted. If not set to null, the nullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where your values is empty. + /// @values this map contains the initial column values for the row. The keys should be the column names and the values the column values + + SqlBuilder.insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { + final insert = StringBuffer(); + insert.write('INSERT'); + if (conflictAlgorithm != null) { + insert.write(' ${_conflictValues[conflictAlgorithm.index]}'); + } + insert.write(' INTO '); + insert.write(_escapeName(table)); + insert.write(' ('); + + List? bindArgs; + final size = values.length; + + if (size > 0) { + final sbValues = StringBuffer(') VALUES ('); + + bindArgs = []; + var i = 0; + values.forEach((String colName, Object? value) { + if (i++ > 0) { + insert.write(', '); + sbValues.write(', '); + } + + /// This should be just a column name + insert.write(_escapeName(colName)); + if (value == null) { + sbValues.write('NULL'); + } else { + checkNonNullValue(value); + bindArgs!.add(value); + sbValues.write('?'); + } + }); + insert.write(sbValues); + } else { + if (nullColumnHack == null) { + throw ArgumentError('nullColumnHack required when inserting no data'); + } + insert.write('$nullColumnHack) VALUES (NULL'); + } + insert.write(')'); + + sql = insert.toString(); + arguments = bindArgs; + } + + /// Convenience method for updating rows in the database. + /// + /// @param table the table to update in + /// @param values a map from column names to new column values. null is a + /// valid value that will be translated to NULL. + /// @param whereClause the optional WHERE clause to apply when updating. + /// Passing null will update all rows. + /// @param whereArgs You may include ?s in the where clause, which + /// will be replaced by the values from whereArgs. The values + /// will be bound as Strings. + /// @param conflictAlgorithm for update conflict resolver + + SqlBuilder.update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) { + if (values.isEmpty) { + throw ArgumentError('Empty values'); + } + checkWhereArgs(whereArgs); + + final update = StringBuffer(); + update.write('UPDATE'); + if (conflictAlgorithm != null) { + update.write(' ${_conflictValues[conflictAlgorithm.index]}'); + } + update.write(' ${_escapeName(table)}'); + update.write(' SET '); + + final bindArgs = []; + var i = 0; + + for (var colName in values.keys) { + update.write((i++ > 0) ? ', ' : ''); + update.write(_escapeName(colName)); + final value = values[colName]; + if (value != null) { + checkNonNullValue(value); + bindArgs.add(value); + update.write(' = ?'); + } else { + update.write(' = NULL'); + } + } + + if (whereArgs != null) { + bindArgs.addAll(whereArgs); + } + + _writeClause(update, ' WHERE ', where); + + sql = update.toString(); + arguments = bindArgs; + } + + /// The resulting SQL command. + late String sql; + + /// The arguments list; + List? arguments; + + /// Used during build if there was a name with an escaped keyword. + bool hasEscape = false; + + String _escapeName(String name) => escapeName(name); + + void _writeClause(StringBuffer s, String name, String? clause) { + if (clause != null) { + s.write(name); + s.write(clause); + } + } + + /// Add the names that are non-null in columns to s, separating + /// them with commas. + void _writeColumns(StringBuffer s, List columns) { + final n = columns.length; + + for (var i = 0; i < n; i++) { + final column = columns[i]; + + if (i > 0) { + s.write(', '); + } + s.write(_escapeName(column)); + } + s.write(' '); + } +} + +/// True if a name had been escaped already. +bool isEscapedName(String name) { + if (name.length >= 2) { + final codeUnits = name.codeUnits; + if (_areCodeUnitsEscaped(codeUnits)) { + return escapeNames + .contains(name.substring(1, name.length - 1).toLowerCase()); + } + } + return false; +} + +// The actual escape implementation +// We use double quote, although backtick could be used too +String _doEscape(String name) => '"$name"'; + +/// Escape a table or column name if necessary. +/// +/// i.e. if it is an identified it will be surrounded by " (double-quote) +/// Only some name belonging to keywords can be escaped +String escapeName(String name) { + if (escapeNames.contains(name.toLowerCase())) { + return _doEscape(name); + } + return name; +} + +/// Unescape a table or column name. +String unescapeName(String name) { + if (isEscapedName(name)) { + return name.substring(1, name.length - 1); + } + return name; +} + +/// Escape a column name if necessary. +/// +/// Only for insert and update keys +String escapeEntityName(String name) { + if (_entityNameNeedEscape(name)) { + return _doEscape(name); + } + return name; +} + +const _lowercaseA = 0x61; +const _lowercaseZ = 0x7A; + +const _underscore = 0x5F; +const _digit0 = 0x30; +const _digit9 = 0x39; + +const _backtick = 0x60; +const _doubleQuote = 0x22; +const _singleQuote = 0x27; + +const _uppercaseA = 0x41; +const _uppercaseZ = 0x5A; + +/// Returns `true` if [codeUnit] represents a digit. +/// +/// The definition of digit matches the Unicode `0x3?` range of Western +/// European digits. +bool _isDigit(int codeUnit) => codeUnit >= _digit0 && codeUnit <= _digit9; + +/// Returns `true` if [codeUnit] represents matchs azAZ_. +bool _isAlphaOrUnderscore(int codeUnit) => + (codeUnit >= _lowercaseA && codeUnit <= _lowercaseZ) || + (codeUnit >= _uppercaseA && codeUnit <= _uppercaseZ) || + codeUnit == _underscore; + +/// True if already escaped +bool _areCodeUnitsEscaped(List codeUnits) { + if (codeUnits.isNotEmpty) { + final first = codeUnits.first; + switch (first) { + case _doubleQuote: + case _backtick: + final last = codeUnits.last; + return last == first; + case _singleQuote: + // not yet + } + } + return false; +} + +bool _entityNameNeedEscape(String name) { + /// We need to escape if not escaped yet and if not a valid keyword + if (escapeNames.contains(name.toLowerCase())) { + return true; + } + + final codeUnits = name.codeUnits; + + // Must start with a alpha or underscode + if (!_isAlphaOrUnderscore(codeUnits.first)) { + return true; + } + for (var i = 1; i < codeUnits.length; i++) { + final codeUnit = codeUnits[i]; + if (!_isAlphaOrUnderscore(codeUnit) && !_isDigit(codeUnit)) { + return true; + } + } + + return false; +} + +/// Unescape a table or column name. +String unescapeValueKeyName(String name) { + final codeUnits = name.codeUnits; + if (_areCodeUnitsEscaped(codeUnits)) { + return name.substring(1, name.length - 1); + } + return name; +} + +/// SQLite keywords to escape. +/// +/// This list was built from the whole set of keywords +/// ([allKeywords] kept here for reference +/// ignore: prefer_collection_literals +final Set escapeNames = { + 'add', + 'all', + 'alter', + 'and', + 'as', + 'autoincrement', + 'between', + 'case', + 'check', + 'collate', + 'commit', + 'constraint', + 'create', + 'default', + 'deferrable', + 'delete', + 'distinct', + 'drop', + 'else', + 'escape', + 'except', + 'exists', + 'foreign', + 'from', + 'group', + 'having', + 'if', + 'in', + 'index', + 'insert', + 'intersect', + 'into', + 'is', + 'isnull', + 'join', + 'limit', + 'not', + 'notnull', + 'null', + 'on', + 'or', + 'order', + 'primary', + 'references', + 'select', + 'set', + 'table', + 'then', + 'to', + 'transaction', + 'union', + 'unique', + 'update', + 'using', + 'values', + 'when', + 'where' +}; + +/* +All keywords kept here for reference + +Set _allKeywords = new Set.from([ + 'abort', + 'action', + 'add', + 'after', + 'all', + 'alter', + 'analyze', + 'and', + 'as', + 'asc', + 'attach', + 'autoincrement', + 'before', + 'begin', + 'between', + 'by', + 'cascade', + 'case', + 'cast', + 'check', + 'collate', + 'column', + 'commit', + 'conflict', + 'constraint', + 'create', + 'cross', + 'current_date', + 'current_time', + 'current_timestamp', + 'database', + 'default', + 'deferrable', + 'deferred', + 'delete', + 'desc', + 'detach', + 'distinct', + 'drop', + 'each', + 'else', + 'end', + 'escape', + 'except', + 'exclusive', + 'exists', + 'explain', + 'fail', + 'for', + 'foreign', + 'from', + 'full', + 'glob', + 'group', + 'having', + 'if', + 'ignore', + 'immediate', + 'in', + 'index', + 'indexed', + 'initially', + 'inner', + 'insert', + 'instead', + 'intersect', + 'into', + 'is', + 'isnull', + 'join', + 'key', + 'left', + 'like', + 'limit', + 'match', + 'natural', + 'no', + 'not', + 'notnull', + 'null', + 'of', + 'offset', + 'on', + 'or', + 'order', + 'outer', + 'plan', + 'pragma', + 'primary', + 'query', + 'raise', + 'recursive', + 'references', + 'regexp', + 'reindex', + 'release', + 'rename', + 'replace', + 'restrict', + 'right', + 'rollback', + 'row', + 'savepoint', + 'select', + 'set', + 'table', + 'temp', + 'temporary', + 'then', + 'to', + 'transaction', + 'trigger', + 'union', + 'unique', + 'update', + 'using', + 'vacuum', + 'values', + 'view', + 'virtual', + 'when', + 'where', + 'with', + 'without' +]); +*/ diff --git a/sqflite/tripartite/sqflite_common/lib/src/sql_command.dart b/sqflite/tripartite/sqflite_common/lib/src/sql_command.dart new file mode 100644 index 0000000..9336771 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/sql_command.dart @@ -0,0 +1,32 @@ +/// Sql command type. +enum SqliteSqlCommandType { + /// such CREATE TABLE, DROP_INDEX, pragma + execute, + + /// Insert statement, + insert, + + /// Update statement. + update, + + /// Delete statement. + delete, + + /// Query statement (SELECTà + query, +} + +/// Sql command. internal only. +class SqfliteSqlCommand { + /// The command type. + final SqliteSqlCommandType type; + + /// The sql statement. + final String sql; + + /// The sql arguments. + final List? arguments; + + /// Sql command. + SqfliteSqlCommand(this.type, this.sql, this.arguments); +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/transaction.dart b/sqflite/tripartite/sqflite_common/lib/src/transaction.dart new file mode 100644 index 0000000..c61459b --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/transaction.dart @@ -0,0 +1,49 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/batch.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/database_mixin.dart'; + +/// Transaction param, new in transaction v2 +class SqfliteTransactionParam { + /// null for no transaction + /// + final int? transactionId; + + /// Transaction param, new in transaction v2. + SqfliteTransactionParam(this.transactionId); +} + +/// Transaction mixin. +mixin SqfliteTransactionMixin implements Transaction { + /// Optional transaction id, depending on the implementation + int? transactionId; +} + +/// Transaction implementation +class SqfliteTransaction + with SqfliteDatabaseExecutorMixin, SqfliteTransactionMixin + implements Transaction { + /// Create a transaction on a given [database] + SqfliteTransaction(this.database); + + /// The transaction database + @override + final SqfliteDatabaseMixin database; + + @override + SqfliteDatabase get db => database; + + /// True if a transaction is successfull + bool? successful; + + @override + SqfliteTransaction get txn => this; + + @override + Batch batch() => SqfliteTransactionBatch(this); +} + +/// Special transaction that is run even if a pending transaction is in progress. +SqfliteTransaction getForcedSqfliteTransaction(SqfliteDatabaseMixin database) => + SqfliteTransaction(database)..transactionId = paramTransactionIdValueForce; diff --git a/sqflite/tripartite/sqflite_common/lib/src/utils.dart b/sqflite/tripartite/sqflite_common/lib/src/utils.dart new file mode 100644 index 0000000..73b6a2c --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/utils.dart @@ -0,0 +1,64 @@ +import 'constant.dart' as constant; + +/// Try to convert anything (int, String) to an int. +int? parseInt(Object? object) { + if (object is int) { + return object; + } else if (object is String) { + try { + return int.parse(object); + } catch (_) {} + } + return null; +} + +/// Debug mode activated +/// +/// To deprecated since 1.1.7 +bool debugModeOn = false; + +/// True if entering, false if leaving, null otherwise. +bool? getSqlInTransactionArgument(String sql) { + final lowerSql = sql.trim().toLowerCase(); + if (lowerSql.startsWith('begin')) { + return true; + } else if (lowerSql.startsWith('commit') || lowerSql.startsWith('rollback')) { + return false; + } + return null; +} + +/// Default duration before printing a lock warning if a database call hangs. +/// +/// Non final for changing it during testing. +/// +/// If a database called is delayed by this duration, a print will happen. +Duration? lockWarningDuration = constant.lockWarningDurationDefault; + +/// Default lock warning callback. +/// +/// Use [setLockWarningInfo] instead. +void Function()? lockWarningCallback = _lockWarningCallbackDefault; + +void _lockWarningCallbackDefault() { + print('Warning database has been locked for $lockWarningDuration. ' + 'Make sure you always use the transaction object for database operations during a transaction'); +} + +/// Split a list in sub list with a maximum size. +/// +/// Never returns list. if list is null, returns an empty list. +/// If [chunkSize] is null or 0, returns all in one list; +List> listChunk(List list, int? chunkSize) { + var chunks = >[]; + final len = list.length; + if ((chunkSize ?? 0) == 0) { + chunkSize = len; + } + for (var i = 0; i < len; i += chunkSize) { + final size = i + chunkSize!; + chunks.add(list.sublist(i, size > len ? len : size)); + } + + return chunks; +} diff --git a/sqflite/tripartite/sqflite_common/lib/src/value_utils.dart b/sqflite/tripartite/sqflite_common/lib/src/value_utils.dart new file mode 100644 index 0000000..ed0bb4a --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/src/value_utils.dart @@ -0,0 +1,66 @@ +import 'dart:typed_data'; + +import 'package:sqflite_common/src/env_utils.dart'; + +/// Don't throw exception yet. will be done in the future. +var checkThrowException = false; + +var _debugCheckPrinted = {}; + +void _checkArg(dynamic arg) { + if ((arg is! String) && (arg is! num) && (arg is! Uint8List)) { + // Big int ok on the web only + if (kSqfliteIsWeb) { + if (arg is BigInt) { + return; + } + } + final type = arg.runtimeType.toString(); + + final text = ''' +*** WARNING *** + +Invalid argument $arg with type $type. +Only num, String and Uint8List are supported. See https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md for details + +This will throw an exception in the future. For now it is displayed once per type. + + '''; + if (checkThrowException) { + throw ArgumentError(text); + } else { + final printed = _debugCheckPrinted[type] ?? false; + if (!printed) { + _debugCheckPrinted[type] = true; + print(text); + } + } + } +} + +/// Check the value is valid. test for non null only; +void checkNonNullValue(dynamic value) { + if (isDebug) { + _checkArg(value); + } +} + +/// Check whether the args are valid in raw statement. null is supported here +void checkRawArgs(List? args) { + if (isDebug && args != null) { + for (var arg in args) { + if (arg != null) { + _checkArg(arg); + } + } + } +} + +/// Check whether the where args are valid. null is not supported here. +void checkWhereArgs(List? args) { + if (isDebug && args != null) { + for (var arg in args) { + _checkArg(arg); + } + } +} diff --git a/sqflite/tripartite/sqflite_common/lib/utils/utils.dart b/sqflite/tripartite/sqflite_common/lib/utils/utils.dart new file mode 100644 index 0000000..2191a3a --- /dev/null +++ b/sqflite/tripartite/sqflite_common/lib/utils/utils.dart @@ -0,0 +1,60 @@ +import 'package:sqflite_common/src/utils.dart'; +import 'package:sqflite_common/src/utils.dart' as impl; + +/// helper to get the first int value in a query +/// Useful for COUNT(*) queries +int? firstIntValue(List> list) { + if (list.isNotEmpty) { + final firstRow = list.first; + if (firstRow.isNotEmpty) { + return parseInt(firstRow.values.first); + } + } + return null; +} + +/// Utility to encode a blob to allow blob query using +/// 'hex(blob_field) = ?', Sqlite.hex([1,2,3]) +String hex(List bytes) { + final buffer = StringBuffer(); + for (var part in bytes) { + if (part & 0xff != part) { + throw FormatException('$part is not a byte integer'); + } + buffer.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}'); + } + return buffer.toString().toUpperCase(); +} + +/// Deprecated since 1.1.7+. +/// +/// Used internally. +@Deprecated('Used internally') +void Function()? get lockWarningCallback => impl.lockWarningCallback; + +/// Deprecated since 1.1.7+. +@Deprecated('Used internally') +set lockWarningCallback(void Function()? callback) => + impl.lockWarningCallback = callback; + +/// Deprecated since 1.1.7+. +@Deprecated('Used internally') +Duration? get lockWarningDuration => impl.lockWarningDuration; + +/// Deprecated since 1.1.7+. +@Deprecated('Used internally') +set lockWarningDuration(Duration? duration) => + impl.lockWarningDuration = duration; + +/// Change database lock behavior mechanism. +/// +/// Default behavior is to print a message if a command hangs for more than +/// 10 seconds. Set en empty callback (not null) to prevent it from being +/// displayed. +void setLockWarningInfo({Duration? duration, void Function()? callback}) { + impl.lockWarningDuration = duration ?? impl.lockWarningDuration; + impl.lockWarningCallback = callback ?? impl.lockWarningCallback; +} + +/// count column. +const sqlCountColumn = 'COUNT(*)'; diff --git a/sqflite/tripartite/sqflite_common/pubspec.yaml b/sqflite/tripartite/sqflite_common/pubspec.yaml new file mode 100644 index 0000000..4822e0e --- /dev/null +++ b/sqflite/tripartite/sqflite_common/pubspec.yaml @@ -0,0 +1,22 @@ +name: sqflite_common +homepage: https://github.com/tekartik/sqflite/tree/master/sqflite_common +description: Dart wrapper on SQLite, a self-contained, high-reliability, embedded, SQL database engine. +version: 2.4.5 +funding: + - https://github.com/sponsors/alextekartik + +environment: + sdk: '>=2.18.0 <4.0.0' + +dependencies: + synchronized: '>=3.0.0 <5.0.0' + path: '>=1.8.0 <3.0.0' + meta: '>=1.3.0 <3.0.0' + +dev_dependencies: + lints: '>=1.0.0' + process_run: '>=0.12.0' + http: '>=0.13.0' + test: '>=1.16.2' + test_api: '>=0.2.19' + pub_semver: '>=2.0.0' \ No newline at end of file diff --git a/sqflite/tripartite/sqflite_common/test/import_mixin_test.dart b/sqflite/tripartite/sqflite_common/test/import_mixin_test.dart new file mode 100644 index 0000000..3a733ab --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/import_mixin_test.dart @@ -0,0 +1,37 @@ +import 'package:sqflite_common/src/mixin/dev_utils.dart'; +import 'package:sqflite_common/src/mixin/import_mixin.dart'; +import 'package:test/test.dart'; + +void main() { + group('handler_mixin', () { + // Check that public api are exported + test('exported', () { + for (var value in [ + // ignore: deprecated_member_use_from_same_package + SqfliteOptions, + methodOpenDatabase, + methodOpenDatabase, + methodCloseDatabase, + methodOptions, + sqliteErrorCode, + methodInsert, + methodQuery, + methodUpdate, + methodExecute, + methodBatch, + // Factory + buildDatabaseFactory, SqfliteInvokeHandler, SqfliteDatabaseFactoryBase, + SqfliteDatabaseFactoryMixin, SqfliteDatabaseFactory, + // Database + SqfliteDatabaseOpenHelper, SqfliteDatabase, SqfliteDatabaseMixin, + SqfliteDatabaseBase, + // Exception + SqfliteDatabaseException, + // ignore: deprecated_member_use_from_same_package + devPrint, devWarning, + ]) { + expect(value, isNotNull); + } + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/list_mixin_test.dart b/sqflite/tripartite/sqflite_common/test/list_mixin_test.dart new file mode 100644 index 0000000..003f7b2 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/list_mixin_test.dart @@ -0,0 +1,74 @@ +import 'dart:collection'; + +import 'package:test/test.dart'; + +class MyList1 extends Object with ListMixin> { + MyList1.from(this._list); + + final List _list; + + @override + Map operator [](int index) { + final value = _list[index] as Map; + return value.cast(); + } + + @override + void operator []=(int index, Map value) { + throw 'read-only'; + } + + @override + set length(int newLength) { + throw 'read-only'; + } + + @override + int get length => _list.length; +} + +class MyList2 extends ListBase> { + MyList2.from(this._list); + + final List _list; + + @override + Map operator [](int index) { + final value = _list[index] as Map; + return value.cast(); + } + + @override + void operator []=(int index, Map value) { + throw 'read-only'; + } + + @override + set length(int newLength) { + throw 'read-only'; + } + + @override + int get length => _list.length; +} + +void main() { + group('mixin', () { + // This fails on beta 1, should work now + test('ListMixin', () { + final raw = [ + {'col': 1} + ]; + final rows = MyList1.from(raw); + expect(rows, raw); + }); + + test('ListBase', () { + final raw = [ + {'col': 1} + ]; + final rows = MyList2.from(raw); + expect(rows, raw); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/path_utils_test.dart b/sqflite/tripartite/sqflite_common/test/path_utils_test.dart new file mode 100644 index 0000000..45e2ce6 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/path_utils_test.dart @@ -0,0 +1,22 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/path_utils.dart'; +import 'package:test/test.dart'; + +void main() { + group('path_utils', () { + test('inMemory', () { + // Sounds obvious... + expect(inMemoryDatabasePath, ':memory:'); + expect(isInMemoryDatabasePath('test.db'), isFalse); + expect(isInMemoryDatabasePath(':memory:'), isTrue); + expect(isInMemoryDatabasePath('file::memory:'), isTrue); + }); + + test('fileUri', () { + expect(isFileUriDatabasePath('file::memory:'), isTrue); + expect(isFileUriDatabasePath('filememory'), isFalse); + expect(isFileUriDatabasePath('file:relative'), isTrue); + expect(isFileUriDatabasePath('file:///abs'), isTrue); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_batch_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_batch_test.dart new file mode 100644 index 0000000..a5d4314 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_batch_test.dart @@ -0,0 +1,74 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:test/test.dart'; + +import 'test_scenario.dart'; + +void main() { + group('sqflite', () { + var startCommands = [protocolOpenStep]; + var endCommands = [protocolCloseStep]; + test('batch commit', () async { + final scenario = startScenario([ + ...startCommands, + [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + null + ], + [ + 'batch', + { + 'operations': [ + {'method': 'execute', 'sql': 'PRAGMA dummy'} + ], + 'id': 1 + }, + null + ], + [ + 'execute', + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + null + ], + ...endCommands, + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + var batch = db.batch(); + expect(batch.length, 0); + batch.execute('PRAGMA dummy'); + expect(batch.length, 1); + expect(await batch.commit(), isEmpty); // Mock return values + await db.close(); + scenario.end(); + }); + test('batch apply', () async { + final scenario = startScenario([ + ...startCommands, + [ + 'batch', + { + 'operations': [ + {'method': 'execute', 'sql': 'PRAGMA dummy'} + ], + 'id': 1 + }, + null + ], + ...endCommands, + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + var batch = db.batch(); + batch.execute('PRAGMA dummy'); + await batch.apply(); + await db.close(); + scenario.end(); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_debug_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_debug_test.dart new file mode 100644 index 0000000..e669fa6 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_debug_test.dart @@ -0,0 +1,39 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/method_call.dart'; +import 'package:sqflite_common/src/mixin/factory.dart'; +import 'package:test/test.dart'; + +var logs = []; +var databaseFactoryMock = buildDatabaseFactory( + tag: 'mock', + invokeMethod: (method, [arguments]) async { + logs.add(SqfliteMethodCall(method, arguments)); + if (method == methodGetDatabasesPath) { + return 'mock_path'; + } + }); + +void main() { + test('simple sqflite example', () async { + logs.clear(); + // ignore: deprecated_member_use_from_same_package + await databaseFactoryMock.debugSetLogLevel(sqfliteLogLevelVerbose); + expect(logs.map((log) => log.toMap()), [ + { + 'method': 'options', + 'arguments': {'logLevel': 2} + } + ]); + }); + test('databasesPath', () async { + final oldDatabasePath = await databaseFactoryMock.getDatabasesPath(); + try { + await databaseFactoryMock.setDatabasesPath('.'); + final path = await databaseFactoryMock.getDatabasesPath(); + expect(path, '.'); + } finally { + await databaseFactoryMock.setDatabasesPath(oldDatabasePath); + } + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_dev_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_dev_test.dart new file mode 100644 index 0000000..7b92113 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_dev_test.dart @@ -0,0 +1,39 @@ +import 'package:sqflite_common/sqflite_dev.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/method_call.dart'; +import 'package:sqflite_common/src/mixin/factory.dart'; +import 'package:test/test.dart'; + +var logs = []; +var databaseFactoryMock = buildDatabaseFactory( + tag: 'mock', + invokeMethod: (method, [arguments]) async { + logs.add(SqfliteMethodCall(method, arguments)); + if (method == methodGetDatabasesPath) { + return 'mock_path'; + } + }); + +void main() { + test('simple sqflite example', () async { + logs.clear(); + // ignore: deprecated_member_use_from_same_package + await databaseFactoryMock.setLogLevel(sqfliteLogLevelVerbose); + expect(logs.map((log) => log.toMap()), [ + { + 'method': 'options', + 'arguments': {'logLevel': 2} + } + ]); + }); + test('databasesPath', () async { + final oldDatabasePath = await databaseFactoryMock.getDatabasesPath(); + try { + await databaseFactoryMock.setDatabasesPath('.'); + final path = await databaseFactoryMock.getDatabasesPath(); + expect(path, '.'); + } finally { + await databaseFactoryMock.setDatabasesPath(oldDatabasePath); + } + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_exception_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_exception_test.dart new file mode 100644 index 0000000..2d51463 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_exception_test.dart @@ -0,0 +1,162 @@ +import 'dart:typed_data'; + +import 'package:sqflite_common/src/exception.dart'; +import 'package:test/test.dart'; + +void main() { + group('sqflite_exception', () { + test('isUniqueConstraint', () async { + // Android + var msg = 'UNIQUE constraint failed: Test.name (code 2067))'; + var exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isNoSuchTableError(), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isNotNullConstraintError(), isFalse); + expect(exception.isUniqueConstraintError(), isTrue); + expect(exception.isUniqueConstraintError('Test.name'), isTrue); + + msg = 'UNIQUE constraint failed: Test.name (code 1555))'; + exception = SqfliteDatabaseException(msg, null); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isUniqueConstraintError(), isTrue); + expect(exception.isUniqueConstraintError('Test.name'), isTrue); + }); + + test('isNotNullConstraint', () async { + // FFI mac + var msg = + 'DatabaseException(SqliteException(1299): NOT NULL constraint failed: Test.name, constraint failed (code 1299))'; + var exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isNoSuchTableError(), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.isUniqueConstraintError('Test.name'), isFalse); + expect(exception.getResultCode(), 1299); + + // ios + msg = + 'DatabaseException(Error Domain=FMDatabase Code=1299 "NOT NULL constraint failed: Test.name"'; + exception = SqfliteDatabaseException(msg, null); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isNotNullConstraintError(), isTrue); + expect(exception.isNotNullConstraintError('Test.name'), isTrue); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.isUniqueConstraintError('Test.name'), isFalse); + expect(exception.getResultCode(), 1299); + }); + + test('isSyntaxError', () async { + // Android + final msg = 'near "DUMMY": syntax error (code 1)'; + final exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isNoSuchTableError(), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isTrue); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.getResultCode(), 1); + }); + + test('isSyntaxError with symbolic names', () { + // Android + final msg = 'near "DUMMY": syntax error (code 1 SQLITE_ERROR)'; + final exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isNoSuchTableError(), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isTrue); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.getResultCode(), 1); + }); + + test('isNoSuchTable', () async { + // Android + final msg = 'no such table: Test (code 1)'; + final exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isNoSuchTableError(), isTrue); + expect(exception.isNoSuchTableError('Test'), isTrue); + expect(exception.isNoSuchTableError('Other'), isFalse); + expect(exception.isDuplicateColumnError('tableName'), isFalse); + expect(exception.isDuplicateColumnError(), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.getResultCode(), 1); + }); + + test('isDuplicateColumn', () { + // Android + final msg = 'duplicate column name: tableName (code 1 SQLITE_ERROR)'; + final exception = SqfliteDatabaseException(msg, null); + expect(exception.isDatabaseClosedError(), isFalse); + expect(exception.isReadOnlyError(), isFalse); + expect(exception.isDuplicateColumnError('tableName'), isTrue); + expect(exception.isDuplicateColumnError(), isTrue); + expect(exception.isDuplicateColumnError('tableName2'), isFalse); + expect(exception.isNoSuchTableError(), isFalse); + expect(exception.isNoSuchTableError('Test'), isFalse); + expect(exception.isNoSuchTableError('Other'), isFalse); + expect(exception.isOpenFailedError(), isFalse); + expect(exception.isSyntaxError(), isFalse); + expect(exception.isUniqueConstraintError(), isFalse); + expect(exception.getResultCode(), 1); + }); + test('getResultCode', () async { + // Android + final msg = 'UNIQUE constraint failed: Test.name (code 2067))'; + var exception = SqfliteDatabaseException(msg, null); + expect(exception.getResultCode(), 2067); + exception = SqfliteDatabaseException( + 'UNIQUE constraint failed: Test.name (code 1555))', null); + expect(exception.getResultCode(), 1555); + exception = + SqfliteDatabaseException('near "DUMMY": syntax error (code 1)', null); + expect(exception.getResultCode(), 1); + + exception = SqfliteDatabaseException( + 'attempt to write a readonly database (code 8)) running Open read-only', + null); + expect(exception.getResultCode(), 8); + + // iOS: Error Domain=FMDatabase Code=19 'UNIQUE constraint failed: Test.name' UserInfo={NSLocalizedDescription=UNIQUE constraint failed: Test.name}) s + exception = SqfliteDatabaseException( + "Error Domain=FMDatabase Code=19 'UNIQUE constraint failed: Test.name' UserInfo={NSLocalizedDescription=UNIQUE constraint failed: Test.name})", + null); + expect(exception.getResultCode(), 19); + exception = + SqfliteDatabaseException('Error Domain=FMDatabase Code=19', null); + expect(exception.getResultCode(), 19); + }); + + test('Exception args', () async { + var exception = SqfliteDatabaseException('test', { + 'sql': 'statement', + 'arguments': [ + null, + 1, + 'short', + '123456789012345678901234567890123456789012345678901', + Uint8List.fromList([1, 2, 3]) + ] + }); + expect(exception.toString(), + 'DatabaseException(test) sql \'statement\' args [null, 1, short, 12345678901234567890123456789012345678901234567890..., Blob(3)]'); + }); + test('Exception result', () async { + DatabaseException exception = SqfliteDatabaseException('test', 1); + expect(exception.result, 1); + exception = SqfliteDatabaseException('test', null); + expect(exception.result, isNull); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_impl_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_impl_test.dart new file mode 100644 index 0000000..82a5402 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_impl_test.dart @@ -0,0 +1,121 @@ +import 'package:sqflite_common/src/collection_utils.dart'; +import 'package:sqflite_common/src/exception.dart'; +import 'package:test/test.dart'; + +void main() { + group('sqflite', () { + test('Rows', () { + final raw = [ + {'col': 1} + ]; + final rows = Rows.from(raw); + final row = rows.first; + expect(rows, raw); + expect(row, {'col': 1}); + }); + + test('fromRawOperationResult', () async { + expect(fromRawOperationResult({'result': 1}), 1); + expect( + fromRawOperationResult({ + 'result': { + 'columns': ['column'], + 'rows': [ + [1] + ] + } + }), + >[ + {'column': 1} + ]); + var exception = fromRawOperationResult({ + 'error': { + 'code': 1234, + 'message': 'hello', + 'data': {'some': 'data'} + } + }) as SqfliteDatabaseException; + expect(exception.message, 'hello'); + expect(exception.result, {'some': 'data'}); + expect(exception.getResultCode(), null); + + exception = fromRawOperationResult({ + 'error': { + 'code': 1234, + 'message': 'hello', + 'data': {'some': 'data'}, + 'resultCode': 1, + } + }) as SqfliteDatabaseException; + expect(exception.message, 'hello'); + expect(exception.result, {'some': 'data'}); + expect(exception.getResultCode(), 1); + }); + test('ResultSet', () { + final raw = { + 'columns': ['column'], + 'rows': [ + [1] + ] + }; + final queryResultSet = QueryResultSet([ + 'column' + ], [ + [1] + ]); + expect(queryResultSet.columnIndex('dummy'), isNull); + expect(queryResultSet.columnIndex('column'), 0); + final row = queryResultSet.first; + //expect(rows, raw); + expect(row, {'column': 1}); + + // read only + try { + row['column'] = 2; + fail('should have failed'); + } on UnsupportedError catch (_) {} + final map = Map.from(row); + // now can modify + map['column'] = 2; + + final queryResultSetMap = { + 'columns': ['id', 'name'], + 'rows': >[ + [1, 'item 1'], + [2, 'item 2'] + ] + }; + final expected = >[ + {'id': 1, 'name': 'item 1'}, + {'id': 2, 'name': 'item 2'} + ]; + expect(queryResultToList(queryResultSetMap), expected); + expect(queryResultToList(expected), expected); + expect(queryResultToList(raw), >[ + {'column': 1} + ]); + + expect(queryResultToList({}), []); + }); + + test('duplicated key', () { + final queryResultSet = QueryResultSet([ + 'col', + 'col' + ], [ + [1, 2] + ]); + // last one wins... + expect(queryResultSet.columnIndex('col'), 1); + final row = queryResultSet.first; + expect(row['col'], 2); + + expect(row.length, 1); + expect(row.keys, ['col']); + expect(row.values, [2]); + expect(row, {'col': 2}); + }); + + test('lockWarning', () {}); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_logger_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_logger_test.dart new file mode 100644 index 0000000..9104505 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_logger_test.dart @@ -0,0 +1,74 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/internals.dart'; +import 'package:sqflite_common/src/logger/sqflite_logger.dart'; +import 'package:test/test.dart'; + +import 'src_mixin_test.dart'; + +void main() { + group('sqflite_logger', () { + test('invoke', () async { + var events = []; + var lines = []; + final factory = SqfliteDatabaseFactoryLogger(MockDatabaseFactoryEmpty(), + options: SqfliteLoggerOptions( + type: SqfliteDatabaseFactoryLoggerType.invoke, + log: (event) { + event.dump( + print: (msg) { + lines.add(msg?.toString() ?? ''); + print(msg); + }, + noStopwatch: true); + events.add(event); + })); + try { + await factory.internalsInvokeMethod('test', {'some': 'param'}); + } catch (_) { + // unimplemented + } + var event = events.first as SqfliteLoggerInvokeEvent; + expect(event.method, 'test'); + expect(event.arguments, {'some': 'param'}); + expect(event.sw!.isRunning, isFalse); + // is currently an error + // 'invoke:({method: test, arguments: {some: param}, error: UnimplementedError: test {some: param}})' + expect(lines.first, + startsWith('invoke:({method: test, arguments: {some: param}')); + }); + test('all', () async { + var events = []; + var lines = []; + final factory = SqfliteDatabaseFactoryLogger(MockDatabaseFactoryEmpty(), + options: SqfliteLoggerOptions( + type: SqfliteDatabaseFactoryLoggerType.all, + log: (event) { + event.dump( + print: (msg) { + lines.add(msg?.toString() ?? ''); + print(msg); + }, + noStopwatch: true); + events.add(event); + })); + var db = await factory.openDatabase(inMemoryDatabasePath); + var batch = db.batch(); + batch.rawQuery('PRAGMA user_version'); + await batch.commit(); + var event = events.first as SqfliteLoggerDatabaseOpenEvent; + expect(event.path, inMemoryDatabasePath); + expect(event.options?.readOnly, false); + expect(event.sw!.isRunning, isFalse); + await db.close(); + expect(lines, [ + 'openDatabase:({path: :memory:, options: {readOnly: false, singleInstance: true}})', + 'execute:({db: 1, sql: BEGIN IMMEDIATE})', + 'batch:({db: 1})', + ' query({sql: PRAGMA user_version})', + 'execute:({db: 1, sql: COMMIT})', + 'closeDatabase:({db: 1})' + ]); + }); + test('batch', () async {}); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_not_initialized_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_not_initialized_test.dart new file mode 100644 index 0000000..d9c6ff5 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_not_initialized_test.dart @@ -0,0 +1,9 @@ +import 'package:sqflite_common/sqflite.dart'; +import 'package:test/test.dart'; + +void main() { + test('basic', () async { + await expectLater( + () => openDatabase(inMemoryDatabasePath), throwsA(isA())); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_open_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_open_test.dart new file mode 100644 index 0000000..2933d8e --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_open_test.dart @@ -0,0 +1,87 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:test/test.dart'; + +import 'test_scenario.dart'; + +void main() { + group('sqflite', () { + test('open id result compat', () async { + final scenario = startScenario([ + [ + 'openDatabase', + {'path': ':memory:', 'singleInstance': false}, + 1 + ], + [ + 'closeDatabase', + {'id': 1}, + null + ], + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + await db.close(); + scenario.end(); + }); + test('open map result', () async { + final scenario = startScenario([ + [ + 'openDatabase', + {'path': ':memory:', 'singleInstance': false}, + {'id': 1}, + ], + [ + 'closeDatabase', + {'id': 1}, + null + ], + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + await db.close(); + scenario.end(); + }); + test('open with version', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'query', + {'sql': 'PRAGMA user_version', 'id': 1}, + // ignore: inference_failure_on_collection_literal + {} + ], + [ + 'execute', + { + 'sql': 'BEGIN EXCLUSIVE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + null + ], + [ + 'query', + {'sql': 'PRAGMA user_version', 'id': 1}, + // ignore: inference_failure_on_collection_literal + {} + ], + [ + 'execute', + {'sql': 'PRAGMA user_version = 1', 'id': 1}, + null + ], + [ + 'execute', + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + null + ], + protocolCloseStep, + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath, + options: OpenDatabaseOptions(version: 1, onCreate: (db, version) {})); + await db.close(); + scenario.end(); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_sql_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_sql_test.dart new file mode 100644 index 0000000..18ab2aa --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_sql_test.dart @@ -0,0 +1,298 @@ +import 'dart:typed_data'; + +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:test/test.dart'; + +import 'test_scenario.dart'; + +void main() { + group('sqflite', () { + test('open execute', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + {'sql': 'PRAGMA user_version = 1', 'id': 1}, + null, + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + await db.setVersion(1); + + await db.close(); + scenario.end(); + }); + test('transaction v2', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + {'transactionId': 1}, + ], + [ + 'execute', + { + 'sql': 'COMMIT', + 'id': 1, + 'inTransaction': false, + 'transactionId': 1 + }, + null, + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + await db.transaction((txn) async {}); + + await db.close(); + scenario.end(); + }); + + test('transaction v1', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + null, + ], + [ + 'execute', + { + 'sql': 'COMMIT', + 'id': 1, + 'inTransaction': false, + }, + null, + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + await db.transaction((txn) async {}); + + await db.close(); + scenario.end(); + }); + + test('manual begin transaction', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + {'sql': 'BEGIN TRANSACTION', 'id': 1, 'inTransaction': true}, + null, + ], + [ + 'execute', + { + 'sql': 'ROLLBACK', + 'id': 1, + 'inTransaction': false, + 'transactionId': -1 + }, + null, + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + await db.execute('BEGIN TRANSACTION'); + + await db.close(); + scenario.end(); + }); + + test('manual begin end transaction', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + {'sql': 'BEGIN TRANSACTION', 'id': 1, 'inTransaction': true}, + null, + ], + [ + 'execute', + {'sql': 'ROLLBACK TRANSACTION', 'id': 1, 'inTransaction': false}, + null, + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + await db.execute('BEGIN TRANSACTION'); + await db.execute('ROLLBACK TRANSACTION'); + + await db.close(); + scenario.end(); + }); + test('open insert', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'insert', + { + 'sql': 'INSERT INTO test (blob) VALUES (?)', + 'arguments': [ + [1, 2, 3] + ], + 'id': 1 + }, + 1 + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + expect( + await db.insert('test', { + 'blob': Uint8List.fromList([1, 2, 3]) + }), + 1); + await db.close(); + scenario.end(); + }); + + test('open insert conflict', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'insert', + { + 'sql': 'INSERT OR IGNORE INTO test (value) VALUES (?)', + 'arguments': [1], + 'id': 1 + }, + 1 + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + expect( + await db.insert('test', {'value': 1}, + conflictAlgorithm: ConflictAlgorithm.ignore), + 1); + await db.close(); + scenario.end(); + }); + + test('open batch insert', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null, + }, + {'transactionId': 1} + ], + [ + 'batch', + { + 'operations': [ + { + 'method': 'insert', + 'sql': 'INSERT INTO test (blob) VALUES (?)', + 'arguments': [ + [1, 2, 3] + ] + } + ], + 'id': 1, + 'transactionId': 1 + }, + null + ], + [ + 'execute', + { + 'sql': 'COMMIT', + 'id': 1, + 'inTransaction': false, + 'transactionId': 1 + }, + null + ], + protocolCloseStep + ]); + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + final batch = db.batch(); + batch.insert('test', { + 'blob': Uint8List.fromList([1, 2, 3]) + }); + await batch.commit(); + await db.close(); + scenario.end(); + }); + + test('queryCursor', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'query', + { + 'sql': '_', + 'id': 1, + 'cursorPageSize': 2, + }, + { + 'cursorId': 1, + 'rows': [ + // ignore: inference_failure_on_collection_literal + [{}] + ], + // ignore: inference_failure_on_collection_literal + 'columns': [] + } + ], + [ + 'queryCursorNext', + {'cursorId': 1, 'id': 1}, + { + 'cursorId': 1, + 'rows': [ + // ignore: inference_failure_on_collection_literal + [{}] + ], + // ignore: inference_failure_on_collection_literal + 'columns': [] + }, + ], + [ + 'queryCursorNext', + {'cursorId': 1, 'cancel': true, 'id': 1}, + null + ], + protocolCloseStep + ]); + var resultList = >[]; + final db = await scenario.factory.openDatabase(inMemoryDatabasePath); + var cursor = await db.rawQueryCursor( + '_', + null, + bufferSize: 2, + ); + expect(await cursor.moveNext(), isTrue); + resultList.add(cursor.current); + expect(await cursor.moveNext(), isTrue); + resultList.add(cursor.current); + await cursor.close(); + + // ignore: inference_failure_on_collection_literal + expect(resultList, [{}, {}]); + await db.close(); + scenario.end(); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqflite_transaction_test.dart b/sqflite/tripartite/sqflite_common/test/sqflite_transaction_test.dart new file mode 100644 index 0000000..f592dad --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqflite_transaction_test.dart @@ -0,0 +1,110 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/exception.dart'; +import 'package:test/test.dart'; + +import 'test_scenario.dart'; + +void main() { + group('transaction', () { + final transactionBeginStep = [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + null, + ]; + final transactionBeginFailureStep = [ + 'execute', + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + SqfliteDatabaseException('failure', null), + ]; + final transactionEndStep = [ + 'execute', + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + 1 + ]; + test('basic', () async { + final scenario = startScenario([ + protocolOpenStep, + transactionBeginStep, + transactionEndStep, + transactionBeginStep, + transactionEndStep, + protocolCloseStep, + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + + await db.transaction((txn) async {}); + await db.transaction((txn) async {}); + await db.close(); + scenario.end(); + }); + test('error in begin after open', () async { + final scenario = startScenario([ + protocolOpenStep, + transactionBeginFailureStep, + transactionBeginStep, + transactionEndStep, + protocolCloseStep, + ]); + final factory = scenario.factory; + final db = await factory.openDatabase(inMemoryDatabasePath); + + try { + await db.transaction((txn) async {}); + fail('should fail'); + } on DatabaseException catch (_) {} + await db.transaction((txn) async {}); + await db.close(); + scenario.end(); + }); + test('error in begin during open', () async { + final scenario = startScenario([ + protocolOpenStep, + [ + 'query', + {'sql': 'PRAGMA user_version', 'id': 1}, + // ignore: inference_failure_on_collection_literal + {}, + ], + [ + 'execute', + { + 'sql': 'BEGIN EXCLUSIVE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + SqfliteDatabaseException('failure', null), + ], + [ + 'execute', + { + 'sql': 'ROLLBACK', + 'id': 1, + 'transactionId': -1, + 'inTransaction': false + }, + null, + ], + protocolCloseStep, + ]); + final factory = scenario.factory; + try { + await factory.openDatabase(inMemoryDatabasePath, + options: + OpenDatabaseOptions(version: 1, onCreate: (db, version) {})); + } on DatabaseException catch (_) {} + scenario.end(); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sql_builder_test.dart b/sqflite/tripartite/sqflite_common/test/sql_builder_test.dart new file mode 100644 index 0000000..03bf093 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sql_builder_test.dart @@ -0,0 +1,188 @@ +//import 'package:test/test.dart'; +import 'package:sqflite_common/src/sql_builder.dart'; +import 'package:test/test.dart'; + +void main() { + group('sql_builder', () { + test('delete', () { + var builder = + SqlBuilder.delete('test', where: 'value = ?', whereArgs: [1]); + expect(builder.sql, 'DELETE FROM test WHERE value = ?'); + expect(builder.arguments, [1]); + + builder = SqlBuilder.delete('test'); + expect(builder.sql, 'DELETE FROM test'); + expect(builder.arguments, isNull); + + // escape + builder = SqlBuilder.delete('table'); + expect(builder.sql, 'DELETE FROM "table"'); + expect(builder.arguments, isNull); + }); + + test('query', () { + var builder = SqlBuilder.query('test'); + expect(builder.sql, 'SELECT * FROM test'); + expect(builder.arguments, isNull); + + builder = SqlBuilder.query('test', columns: ['COUNT(*)']); + expect(builder.sql, 'SELECT COUNT(*) FROM test'); + expect(builder.arguments, isNull); + + builder = SqlBuilder.query('test', + distinct: true, + columns: ['value'], + where: 'value = ?', + whereArgs: [1], + groupBy: 'group_value', + having: 'value > 0', + orderBy: 'other_value', + limit: 2, + offset: 3); + expect(builder.sql, + 'SELECT DISTINCT value FROM test WHERE value = ? GROUP BY group_value HAVING value > 0 ORDER BY other_value LIMIT 2 OFFSET 3'); + expect(builder.arguments, [1]); + }); + + test('insert', () { + try { + SqlBuilder.insert('test', {}); + fail('should fail, no nullColumnHack'); + } on ArgumentError catch (_) {} + + var builder = SqlBuilder.insert('test', {}, + nullColumnHack: 'value'); + expect(builder.sql, 'INSERT INTO test (value) VALUES (NULL)'); + expect(builder.arguments, isNull); + + builder = SqlBuilder.insert('test', {'value': 1}); + expect(builder.sql, 'INSERT INTO test (value) VALUES (?)'); + expect(builder.arguments, [1]); + + builder = SqlBuilder.insert( + 'test', {'value': 1, 'other_value': null}); + expect(builder.sql, + 'INSERT INTO test (value, other_value) VALUES (?, NULL)'); + expect(builder.arguments, [1]); + + builder = SqlBuilder.insert('test', {'value': 1}, + conflictAlgorithm: ConflictAlgorithm.ignore); + expect(builder.sql, 'INSERT OR IGNORE INTO test (value) VALUES (?)'); + expect(builder.arguments, [1]); + + // no escape yet + builder = SqlBuilder.insert('test', {'value:': 1}); + expect(builder.sql, 'INSERT INTO test (value:) VALUES (?)'); + expect(builder.arguments, [1]); + + // escape + builder = SqlBuilder.insert('table', {'table': 1}); + expect(builder.sql, 'INSERT INTO "table" ("table") VALUES (?)'); + expect(builder.arguments, [1]); + }); + + test('update', () { + try { + SqlBuilder.update('test', {}); + fail('should fail, no values'); + } on ArgumentError catch (_) {} + + var builder = SqlBuilder.update('test', {'value': 1}); + expect(builder.sql, 'UPDATE test SET value = ?'); + expect(builder.arguments, [1]); + + builder = SqlBuilder.update( + 'test', {'value': 1, 'other_value': null}); + expect(builder.sql, 'UPDATE test SET value = ?, other_value = NULL'); + expect(builder.arguments, [1]); + + // testing where + builder = SqlBuilder.update('test', {'value': 1}, + where: 'a = ? AND b = ?', whereArgs: ['some_test', 1]); + expect(builder.arguments, [1, 'some_test', 1]); + + // no escape yet + builder = SqlBuilder.update('test:', {'value:': 1}); + expect(builder.sql, 'UPDATE test: SET value: = ?'); + expect(builder.arguments, [1]); + + // escape + builder = SqlBuilder.update('test:', {'table': 1}); + expect(builder.sql, 'UPDATE test: SET "table" = ?'); + expect(builder.arguments, [1]); + }); + + test('query', () { + var builder = SqlBuilder.query('table', orderBy: 'value'); + expect(builder.sql, 'SELECT * FROM "table" ORDER BY value'); + expect(builder.arguments, isNull); + + builder = + SqlBuilder.query('table', orderBy: 'column_1 ASC, column_2 DESC'); + expect(builder.sql, + 'SELECT * FROM "table" ORDER BY column_1 ASC, column_2 DESC'); + expect(builder.arguments, isNull); + + // testing where + builder = SqlBuilder.query('test', + where: 'a = ? AND b = ?', whereArgs: ['some_test', 1]); + expect(builder.arguments, ['some_test', 1]); + }); + + test('isEscapedName', () { + //expect(isEscapedName(null), false); + expect(isEscapedName('group'), false); + expect(isEscapedName("'group'"), false); + expect(isEscapedName('"group"'), true); + expect(isEscapedName('`group`'), true); + expect(isEscapedName("`group'"), false); + expect(isEscapedName('"group"'), true); + }); + + test('escapeName', () { + // expect(escapeName(null!), null); + expect(escapeName('group'), '"group"'); + expect(escapeName('dummy'), 'dummy'); + expect(escapeName('"dummy"'), '"dummy"'); + expect(escapeName('semicolumn:'), 'semicolumn:'); // for now no escape + expect( + escapeName( + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'), + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'); + + for (var name in escapeNames) { + expect(escapeName(name), '"$name"'); + } + }); + + test('escapeEntityName', () { + // expect(escapeEntityName(null!), null); + expect(escapeEntityName('group'), '"group"'); + expect(escapeEntityName('dummy'), 'dummy'); + expect(escapeEntityName('"dummy"'), '""dummy""'); + expect(escapeEntityName('semicolumn:'), '"semicolumn:"'); + expect( + escapeEntityName( + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'), + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'); + + for (var name in escapeNames) { + expect(escapeEntityName(name), '"$name"'); + } + }); + + test('unescapeName', () { + // expect(unescapeName(null!), null); + + expect(unescapeName('dummy'), 'dummy'); + expect(unescapeName("'dummy'"), "'dummy'"); + expect(unescapeName("'group'"), "'group'"); + expect(unescapeName('"group"'), 'group'); + expect(unescapeName('`group`'), 'group'); + + for (var name in escapeNames) { + expect(unescapeName('"$name"'), name); + } + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sql_test.dart b/sqflite/tripartite/sqflite_common/test/sql_test.dart new file mode 100644 index 0000000..82f4453 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sql_test.dart @@ -0,0 +1,18 @@ +import 'package:sqflite_common/sql.dart'; +import 'package:test/test.dart'; + +void main() { + group('sqflite', () { + test('exported', () { + expect(ConflictAlgorithm.abort, isNotNull); + }); + + test('escapeName_export', () { + expect(escapeName('group'), '"group"'); + }); + + test('unescapeName_export', () { + expect(unescapeName('"group"'), 'group'); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/sqlite_api_test.dart b/sqflite/tripartite/sqflite_common/test/sqlite_api_test.dart new file mode 100644 index 0000000..86688fe --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/sqlite_api_test.dart @@ -0,0 +1,29 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:test/test.dart'; + +void main() { + group('sqlite_api', () { + // Check that public api are exported + test('exported', () { + for (var value in [ + OpenDatabaseOptions, + DatabaseFactory, + Database, + Transaction, + Batch, + ConflictAlgorithm, + inMemoryDatabasePath, + OnDatabaseConfigureFn, + OnDatabaseCreateFn, + OnDatabaseOpenFn, + OnDatabaseVersionChangeFn, + onDatabaseDowngradeDelete, + sqfliteLogLevelNone, + sqfliteLogLevelSql, + sqfliteLogLevelVerbose, + ]) { + expect(value, isNotNull); + } + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/src_mixin_factory_test.dart b/sqflite/tripartite/sqflite_common/test/src_mixin_factory_test.dart new file mode 100644 index 0000000..39c5b64 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/src_mixin_factory_test.dart @@ -0,0 +1,33 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/factory_mixin.dart'; +import 'package:sqflite_common/src/mixin/factory.dart'; +import 'package:test/test.dart'; + +import 'src_mixin_test.dart'; + +void main() { + group('mixin_factory', () { + test('public', () { + // ignore: unnecessary_statements + buildDatabaseFactory; + // ignore: unnecessary_statements + SqfliteInvokeHandler; + }); + test('buildDatabaseFactory', () async { + final methods = []; + final factory = buildDatabaseFactory( + tag: 'mock', + invokeMethod: (String method, [Object? arguments]) async { + final dynamic result = mockResult(method, arguments); + methods.add(method); + return result; + }); + expect((factory as SqfliteDatabaseFactoryMixin).tag, 'mock'); + // ignore: unnecessary_type_check + expect(factory is SqfliteInvokeHandler, isTrue); + await factory.openDatabase(inMemoryDatabasePath); + expect(methods, ['openDatabase']); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/src_mixin_test.dart b/sqflite/tripartite/sqflite_common/test/src_mixin_test.dart new file mode 100644 index 0000000..9deb030 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/src_mixin_test.dart @@ -0,0 +1,805 @@ +import 'dart:async'; + +import 'package:path/path.dart'; +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/constant.dart'; +import 'package:sqflite_common/src/database.dart'; +import 'package:sqflite_common/src/mixin.dart'; +import 'package:sqflite_common/src/mixin/dev_utils.dart'; // ignore: unused_import +import 'package:sqflite_common/src/open_options.dart'; +import 'package:sqflite_common/utils/utils.dart'; +import 'package:test/test.dart'; + +void main() { + group('src_mixin', () { + run(); + }); +} + +var _mockDatabasesPath = '.'; + +/// Mock the result based on the method used +Object? mockResult(String method, Object? arguments) { + Object? handleSqlMethod(String sqlMethod) { + switch (sqlMethod) { + case methodOpenDatabase: + return 1; + case methodInsert: + return 0; + case methodUpdate: + return 0; + case methodExecute: + return null; + case methodQuery: + return {}; + } + throw UnimplementedError('$method $sqlMethod $arguments'); + } + + // devPrint('$method'); + switch (method) { + case methodGetDatabasesPath: + return _mockDatabasesPath; + case methodOpenDatabase: + return 1; + case methodCloseDatabase: + return null; + case methodDeleteDatabase: + return null; + case methodDatabaseExists: + return true; + case methodInsert: + case methodUpdate: + case methodExecute: + case methodQuery: + return handleSqlMethod(method); + case methodBatch: + var operations = (arguments as Map)[paramOperations] as List; + var results = []; + for (var operation in operations) { + var sqlMethod = (operation as Map)[paramMethod] as String; + results.add(handleSqlMethod(sqlMethod)); + } + return results; + } + throw UnimplementedError('$method $arguments'); +} + +class MockDatabase extends SqfliteDatabaseBase { + MockDatabase(SqfliteDatabaseOpenHelper openHelper, [String name = 'mock']) + : super(openHelper, name); + + int? version; + List methods = []; + List sqls = []; + List?> argumentsLists = ?>[]; + + @override + Future invokeMethod(String method, [Object? arguments]) async { + // return super.invokeMethod(method, arguments); + + methods.add(method); + if (arguments is Map) { + argumentsLists.add(arguments.cast()); + if (arguments[paramOperations] != null) { + final operations = + arguments[paramOperations] as List>; + for (var operation in operations) { + final sql = operation[paramSql] as String?; + sqls.add(sql); + } + } else { + final sql = arguments[paramSql] as String?; + sqls.add(sql); + + // Basic version handling + if (sql?.startsWith('PRAGMA user_version = ') == true) { + version = int.tryParse(sql!.split(' ').last); + } else if (sql == 'PRAGMA user_version') { + return >[ + {'user_version': version} + ] as T; + } + } + } else { + argumentsLists.add(null); + sqls.add(null); + } + return mockResult(method, arguments) as T; + } +} + +class MockDatabaseFactory extends SqfliteDatabaseFactoryBase { + final List methods = []; + final List argumentsList = []; + final Map databases = {}; + + @override + Future invokeMethod(String method, [Object? arguments]) async { + methods.add(method); + argumentsList.add(arguments); + return mockResult(method, arguments) as T; + } + + SqfliteDatabase newEmptyDatabase() { + final path = 'empty'; + final helper = SqfliteDatabaseOpenHelper(this, path, OpenDatabaseOptions()); + final db = helper.newDatabase(path)..id = 1; + return db; + } + + @override + SqfliteDatabaseMixin newDatabase( + SqfliteDatabaseOpenHelper openHelper, String path) { + final existing = databases[path]; + final db = MockDatabase(openHelper, path); + // Copy version + db.version = existing?.version; + // Last replaces + databases[path] = db; + + return db; + } + + @override + Future getDatabasesPath() async { + return join('.dart_tool', 'sqlite', 'test', 'mock'); + } +} + +class MockDatabaseFactoryEmpty extends SqfliteDatabaseFactoryBase { + final List methods = []; + + @override + Future invokeMethod(String method, [Object? arguments]) async { + methods.add(method); + return mockResult(method, arguments) as T; + } +} + +final MockDatabaseFactory mockDatabaseFactory = MockDatabaseFactory(); + +void run() { + group('database_factory', () { + test('getDatabasesPath', () async { + final factory = MockDatabaseFactoryEmpty(); + await factory.getDatabasesPath(); + expect(factory.methods, ['getDatabasesPath']); + }); + test('setDatabasesPath', () async { + final factory = MockDatabaseFactoryEmpty(); + + factory.setDatabasesPathOrNull('.'); + expect(await factory.getDatabasesPath(), '.'); + + // reset + factory.setDatabasesPathOrNull(null); + expect(factory.methods, []); + + await factory.getDatabasesPath(); + expect(factory.methods, ['getDatabasesPath']); + //expect(directory, ) + }); + }); + group('database', () { + test('transaction', () async { + final Database db = mockDatabaseFactory.newEmptyDatabase(); + await db.execute('test'); + await db.insert('test', {'test': 1}); + await db.update('test', {'test': 1}); + await db.delete('test'); + await db.query('test'); + + await db.transaction((Transaction txn) async { + await txn.execute('test'); + await txn.insert('test', {'test': 1}); + await txn.update('test', {'test': 1}); + await txn.delete('test'); + await txn.query('test'); + }); + + final batch = db.batch(); + batch.execute('test'); + batch.insert('test', {'test': 1}); + batch.update('test', {'test': 1}); + batch.delete('test'); + batch.query('test'); + await batch.commit(); + }); + + group('open', () { + test('read-only', () async { + // var db = mockDatabaseFactory.newEmptyDatabase(); + final db = await mockDatabaseFactory.openDatabase('test', + options: SqfliteOpenDatabaseOptions(readOnly: true)) + as MockDatabase; + await db.close(); + expect(db.methods, ['openDatabase', 'closeDatabase']); + expect(db.argumentsLists.first, { + 'path': absolute( + join(await mockDatabaseFactory.getDatabasesPath(), 'test')), + 'readOnly': true, + 'singleInstance': true + }); + }); + test('not single_instance', () async { + // var db = mockDatabaseFactory.newEmptyDatabase(); + final db = await mockDatabaseFactory.openDatabase('single_instance.db', + options: SqfliteOpenDatabaseOptions(singleInstance: false)) + as MockDatabase; + await db.close(); + expect(db.methods, ['openDatabase', 'closeDatabase']); + expect(db.argumentsLists.first, { + 'path': absolute(join(await mockDatabaseFactory.getDatabasesPath(), + 'single_instance.db')), + 'singleInstance': false + }); + }); + + test('rollback transaction', () async { + // var db = mockDatabaseFactory.newEmptyDatabase(); + final db = await mockDatabaseFactory.openDatabase( + 'rollback_transaction.db', + options: SqfliteOpenDatabaseOptions(singleInstance: false)) + as MockDatabase; + await db.execute('BEGIN TRANSACTION'); + await db.close(); + expect(db.methods, + ['openDatabase', 'execute', 'execute', 'closeDatabase']); + expect(db.argumentsLists.first, { + 'path': absolute(join(await mockDatabaseFactory.getDatabasesPath(), + 'rollback_transaction.db')), + 'singleInstance': false + }); + expect(db.argumentsLists[2], { + 'sql': 'ROLLBACK', + 'id': 1, + 'transactionId': -1, + 'inTransaction': false + }); + }); + test('isOpen', () async { + // var db = mockDatabaseFactory.newEmptyDatabase(); + final db = await mockDatabaseFactory.openDatabase('is_open.db', + options: SqfliteOpenDatabaseOptions(readOnly: true)) + as MockDatabase; + expect(db.isOpen, true); + final closeFuture = db.close(); + // it is not closed right away + expect(db.isOpen, true); + await closeFuture; + expect(db.isOpen, false); + }); + + test('reOpenSameVersion', () async { + var db = await mockDatabaseFactory.openDatabase('on_reopen.db', + options: OpenDatabaseOptions( + version: 1, + )) as MockDatabase; + await db.close(); + + expect(db.sqls, [ + null, + 'PRAGMA user_version', + 'BEGIN EXCLUSIVE', + 'PRAGMA user_version', + 'PRAGMA user_version = 1', + 'COMMIT', + null + ]); + + db = await mockDatabaseFactory.openDatabase('on_reopen.db', + options: OpenDatabaseOptions( + version: 1, + )) as MockDatabase; + await db.close(); + + // Re-opening, no transaction is created + expect(db.sqls, [null, 'PRAGMA user_version', null]); + }); + }); + group('openTransaction', () { + test('onCreate', () async { + final db = await mockDatabaseFactory.openDatabase('on_create.db', + options: SqfliteOpenDatabaseOptions( + version: 1, + onCreate: (Database db, int version) async { + await db.execute('test1'); + await db.transaction((Transaction txn) async { + await txn.execute('test2'); + }); + })) as MockDatabase; + + await db.close(); + expect(db.methods, [ + 'openDatabase', + 'query', + 'execute', + 'query', + 'execute', + 'execute', + 'execute', + 'execute', + 'closeDatabase' + ]); + expect(db.sqls, [ + null, + 'PRAGMA user_version', + 'BEGIN EXCLUSIVE', + 'PRAGMA user_version', + 'test1', + 'test2', + 'PRAGMA user_version = 1', + 'COMMIT', + null + ]); + }); + + test('onConfigure', () async { + final db = await mockDatabaseFactory.openDatabase('on_configure.db', + options: OpenDatabaseOptions( + version: 1, + onConfigure: (Database db) async { + await db.execute('test1'); + await db.transaction((Transaction txn) async { + await txn.execute('test2'); + }); + })) as MockDatabase; + + await db.close(); + expect(db.sqls, [ + null, + 'test1', + 'BEGIN IMMEDIATE', + 'test2', + 'COMMIT', + 'PRAGMA user_version', + 'BEGIN EXCLUSIVE', + 'PRAGMA user_version', + 'PRAGMA user_version = 1', + 'COMMIT', + null + ]); + }); + + test('onOpen', () async { + final db = await mockDatabaseFactory.openDatabase('on_open', + options: OpenDatabaseOptions( + version: 1, + onOpen: (Database db) async { + await db.execute('test1'); + await db.transaction((Transaction txn) async { + await txn.execute('test2'); + }); + })) as MockDatabase; + + await db.close(); + expect(db.sqls, [ + null, + 'PRAGMA user_version', + 'BEGIN EXCLUSIVE', + 'PRAGMA user_version', + 'PRAGMA user_version = 1', + 'COMMIT', + 'test1', + 'BEGIN IMMEDIATE', + 'test2', + 'COMMIT', + null + ]); + }); + + test('batch', () async { + final db = await mockDatabaseFactory.openDatabase('test', + options: OpenDatabaseOptions( + version: 1, + onConfigure: (Database db) async { + final batch = db.batch(); + batch.execute('test1'); + await batch.commit(); + }, + onCreate: (db, _) async { + final batch = db.batch(); + batch.execute('test2'); + await batch.commit(noResult: true); + }, + onOpen: (Database db) async { + final batch = db.batch(); + batch.execute('test3'); + await batch.commit(continueOnError: true); + })) as MockDatabase; + + await db.close(); + expect(db.sqls, [ + null, + 'BEGIN IMMEDIATE', + 'test1', + 'COMMIT', + 'PRAGMA user_version', + 'BEGIN EXCLUSIVE', + 'PRAGMA user_version', + 'test2', + 'PRAGMA user_version = 1', + 'COMMIT', + 'BEGIN IMMEDIATE', + 'test3', + 'COMMIT', + null + ]); + expect(db.argumentsLists, [ + { + 'path': absolute( + join(await mockDatabaseFactory.getDatabasesPath(), 'test')), + 'singleInstance': true + }, + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null + }, + { + 'operations': [ + { + 'method': 'execute', + 'sql': 'test1', + } + ], + 'id': 1 + }, + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + {'sql': 'PRAGMA user_version', 'id': 1}, + { + 'sql': 'BEGIN EXCLUSIVE', + 'inTransaction': true, + 'id': 1, + 'transactionId': null + }, + {'sql': 'PRAGMA user_version', 'id': 1}, + { + 'operations': >[ + { + 'method': 'execute', + 'sql': 'test2', + } + ], + 'id': 1, + 'noResult': true + }, + {'sql': 'PRAGMA user_version = 1', 'id': 1}, + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + { + 'sql': 'BEGIN IMMEDIATE', + 'id': 1, + 'inTransaction': true, + 'transactionId': null, + }, + { + 'operations': >[ + { + 'method': 'execute', + 'sql': 'test3', + } + ], + 'id': 1, + 'continueOnError': true + }, + {'sql': 'COMMIT', 'id': 1, 'inTransaction': false}, + {'id': 1} + ]); + }); + }); + + group('concurrency', () { + test('concurrent 1', () async { + final db = mockDatabaseFactory.newEmptyDatabase() as MockDatabase; + final step1 = Completer(); + final step2 = Completer(); + final step3 = Completer(); + + Future action1() async { + await db.execute('test'); + step1.complete(); + + await step2.future; + try { + await db.execute('test').timeout(const Duration(milliseconds: 100)); + throw 'should fail'; + } catch (e) { + expect(e is TimeoutException, true); + } + + step3.complete(); + } + + Future action2() async { + // This is the change with concurrency 2 + await step1.future; + await db.transaction((Transaction txn) async { + // Wait for table being created; + await txn.execute('test'); + step2.complete(); + + await step3.future; + + await txn.execute('test'); + }); + } + + final Future future1 = action1(); + final Future future2 = action2(); + + await Future.wait(>[future1, future2]); + // check ready + await db.transaction(((_) async {})); + }); + + test('concurrent 2', () async { + final db = mockDatabaseFactory.newEmptyDatabase() as MockDatabase; + final step1 = Completer(); + final step2 = Completer(); + final step3 = Completer(); + + Future action1() async { + await db.execute('test'); + step1.complete(); + + await step2.future; + try { + await db.execute('test').timeout(const Duration(milliseconds: 100)); + throw 'should fail'; + } catch (e) { + expect(e is TimeoutException, true); + } + + step3.complete(); + } + + Future action2() async { + await db.transaction((Transaction txn) async { + await step1.future; + // Wait for table being created; + await txn.execute('test'); + step2.complete(); + + await step3.future; + + await txn.execute('test'); + }); + } + + final Future future1 = action1(); + final Future future2 = action2(); + + await Future.wait(>[future1, future2]); + }); + }); + + group('compatibility 1', () { + test('concurrent 1', () async { + final db = mockDatabaseFactory.newEmptyDatabase() as MockDatabase; + final step1 = Completer(); + final step2 = Completer(); + final step3 = Completer(); + + Future action1() async { + await db.execute('test'); + step1.complete(); + + await step2.future; + try { + await db.execute('test').timeout(const Duration(milliseconds: 100)); + throw 'should fail'; + } catch (e) { + expect(e is TimeoutException, true); + } + + step3.complete(); + } + + Future action2() async { + // This is the change with concurrency 2 + await step1.future; + await db.transaction((Transaction txn) async { + // Wait for table being created; + await txn.execute('test'); + step2.complete(); + + await step3.future; + + await txn.execute('test'); + }); + } + + final Future future1 = action1(); + final Future future2 = action2(); + + await Future.wait(>[future1, future2]); + // check ready + await db.transaction(((_) async {})); + }); + + test('concurrent 2', () async { + final db = mockDatabaseFactory.newEmptyDatabase() as MockDatabase; + final step1 = Completer(); + final step2 = Completer(); + final step3 = Completer(); + + Future action1() async { + await step1.future; + try { + await db.execute('test').timeout(const Duration(milliseconds: 100)); + throw 'should fail'; + } catch (e) { + expect(e is TimeoutException, true); + } + + await step2.future; + try { + await db.execute('test').timeout(const Duration(milliseconds: 100)); + throw 'should fail'; + } catch (e) { + expect(e is TimeoutException, true); + } + + step3.complete(); + } + + Future action2() async { + await db.transaction((Transaction txn) async { + step1.complete(); + + // Wait for table being created; + await txn.execute('test'); + step2.complete(); + + await step3.future; + + await txn.execute('test'); + }); + } + + final Future future2 = action2(); + final Future future1 = action1(); + + await Future.wait(>[future1, future2]); + // check ready + await db.transaction(((_) async {})); + }); + }); + + group('batch', () { + test('simple', () async { + final db = await mockDatabaseFactory.openDatabase('batch_simple.db') + as MockDatabase; + + final batch = db.batch(); + batch.execute('test'); + await batch.commit(); + await batch.commit(); + await db.close(); + expect(db.methods, [ + 'openDatabase', + 'execute', + 'batch', + 'execute', + 'execute', + 'batch', + 'execute', + 'closeDatabase' + ]); + expect(db.sqls, [ + null, + 'BEGIN IMMEDIATE', + 'test', + 'COMMIT', + 'BEGIN IMMEDIATE', + 'test', + 'COMMIT', + null + ]); + }); + + test('in_transaction', () async { + final db = await mockDatabaseFactory + .openDatabase('batch_in_transaction.db') as MockDatabase; + + await db.transaction((Transaction txn) async { + final batch = txn.batch(); + batch.execute('test'); + + await batch.commit(); + await batch.commit(); + }); + await db.close(); + expect(db.methods, [ + 'openDatabase', + 'execute', + 'batch', + 'batch', + 'execute', + 'closeDatabase' + ]); + expect(db.sqls, + [null, 'BEGIN IMMEDIATE', 'test', 'test', 'COMMIT', null]); + }); + }); + + group('instances', () { + test('singleInstance same', () async { + final futureDb1 = mockDatabaseFactory.openDatabase('test', + options: OpenDatabaseOptions(singleInstance: true)); + final db2 = await mockDatabaseFactory.openDatabase('test', + options: OpenDatabaseOptions(singleInstance: true)) as MockDatabase; + final db1 = await futureDb1 as MockDatabase; + expect(db1, db2); + }); + test('singleInstance', () async { + final futureDb1 = mockDatabaseFactory.openDatabase('test', + options: OpenDatabaseOptions(singleInstance: true)); + final db2 = await mockDatabaseFactory.openDatabase('test', + options: OpenDatabaseOptions(singleInstance: true)) as MockDatabase; + final db1 = await futureDb1 as MockDatabase; + final db3 = await mockDatabaseFactory.openDatabase('other', + options: OpenDatabaseOptions(singleInstance: true)) as MockDatabase; + final db4 = await mockDatabaseFactory.openDatabase(join('.', 'other'), + options: OpenDatabaseOptions(singleInstance: true)) as MockDatabase; + //expect(db1, db2); + expect(db1, isNot(db3)); + expect(db3, db4); + await db1.close(); + await db2.close(); + await db3.close(); + }); + + test('multiInstances', () async { + final futureDb1 = mockDatabaseFactory.openDatabase('multi_instances.db', + options: OpenDatabaseOptions(singleInstance: false)); + final db2 = await mockDatabaseFactory.openDatabase('multi_instances.db', + options: OpenDatabaseOptions(singleInstance: false)) + as MockDatabase; + final db1 = await futureDb1 as MockDatabase; + expect(db1, isNot(db2)); + await db1.close(); + await db2.close(); + }); + }); + + test('dead lock', () async { + final db = mockDatabaseFactory.newEmptyDatabase() as MockDatabase; + var hasTimedOut = false; + var callbackCount = 0; + setLockWarningInfo( + duration: const Duration(milliseconds: 200), + callback: () { + callbackCount++; + }); + try { + await db.transaction((Transaction txn) async { + await db.execute('test'); + fail('should fail'); + }).timeout(const Duration(milliseconds: 500)); + } on TimeoutException catch (_) { + hasTimedOut = true; + } + expect(hasTimedOut, isTrue); + expect(callbackCount, 1); + await db.close(); + }); + + test('deleted/exists', () async { + final path = 'test_exists.db'; + await mockDatabaseFactory.deleteDatabase(path); + final exists = await mockDatabaseFactory.databaseExists(path); + expect(exists, isTrue); + final expectedPath = + absolute(join(await mockDatabaseFactory.getDatabasesPath(), path)); + expect(mockDatabaseFactory.methods, + ['deleteDatabase', 'databaseExists']); + expect(mockDatabaseFactory.argumentsList, >[ + {'path': expectedPath}, + {'path': expectedPath} + ]); + }); + }); +} diff --git a/sqflite/tripartite/sqflite_common/test/test_scenario.dart b/sqflite/tripartite/sqflite_common/test/test_scenario.dart new file mode 100644 index 0000000..8820ff4 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/test_scenario.dart @@ -0,0 +1,73 @@ +import 'package:sqflite_common/sqlite_api.dart'; +import 'package:sqflite_common/src/mixin/import_mixin.dart'; +import 'package:test/test.dart'; + +/// Common open step +var protocolOpenStep = [ + 'openDatabase', + {'path': ':memory:', 'singleInstance': false}, + {'id': 1} +]; + +/// Common close step +var protocolCloseStep = [ + 'closeDatabase', + {'id': 1}, + null +]; + +class MockMethodCall { + String? expectedMethod; + dynamic expectedArguments; + + /// Response can be an exception + dynamic response; + + @override + String toString() => '$expectedMethod $expectedArguments $response'; +} + +class MockScenario { + MockScenario(this.factory, List data) { + methodsCalls = data + .map((list) => MockMethodCall() + ..expectedMethod = list[0]?.toString() + ..expectedArguments = list[1] + ..response = list[2]) + .toList(growable: false); + } + + final DatabaseFactory factory; + late List methodsCalls; + var index = 0; + dynamic exception; + + void end() { + expect(exception, isNull, reason: '$exception'); + expect(index, methodsCalls.length); + } +} + +MockScenario startScenario(List data) { + late MockScenario scenario; + final databaseFactoryMock = buildDatabaseFactory( + tag: 'mock', + invokeMethod: (String method, [Object? arguments]) async { + final index = scenario.index++; + // devPrint('$index ${scenario.methodsCalls[index]}'); + final item = scenario.methodsCalls[index]; + try { + expect(method, item.expectedMethod); + expect(arguments, item.expectedArguments); + } catch (e) { + // devPrint(e); + scenario.exception ??= '$e $index'; + } + if (item.response is DatabaseException) { + throw item.response as DatabaseException; + } + return item.response; + }); + scenario = MockScenario(databaseFactoryMock, data); + return scenario; +} diff --git a/sqflite/tripartite/sqflite_common/test/utils_test.dart b/sqflite/tripartite/sqflite_common/test/utils_test.dart new file mode 100644 index 0000000..dc98c82 --- /dev/null +++ b/sqflite/tripartite/sqflite_common/test/utils_test.dart @@ -0,0 +1,96 @@ +import 'package:sqflite_common/src/utils.dart'; +import 'package:sqflite_common/utils/utils.dart'; +import 'package:test/test.dart'; + +void main() { + group('sqflite', () { + test('firstIntValue', () { + expect( + firstIntValue(>[ + {'test': 1} + ]), + 1); + expect( + firstIntValue(>[ + {'test': 1}, + {'test': 1} + ]), + 1); + expect( + firstIntValue(>[ + {'test': null} + ]), + null); + expect( + firstIntValue(>[{}]), isNull); + expect(firstIntValue(>[]), isNull); + expect( + firstIntValue(>[{}]), isNull); + }); + + test('hex', () { + expect( + hex([ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 255 + ]), + '000102030405060708090A0B0C0D0E0F1011FF'); + expect(hex([]), ''); + expect(hex([32]), '20'); + + try { + hex([-1]); + fail('should fail'); + } on FormatException catch (_) {} + + try { + hex([256]); + fail('should fail'); + } on FormatException catch (_) {} + }); + + test('chunk', () { + expect(listChunk([], null), isEmpty); + expect(listChunk([1], null), [ + [1] + ]); + expect(listChunk([1], 0), [ + [1] + ]); + expect(listChunk([1, 2], 0), [ + [1, 2] + ]); + expect(listChunk([1, 2], 2), [ + [1, 2] + ]); + expect(listChunk([1, 2], 3), [ + [1, 2] + ]); + expect(listChunk([1, 2], 1), [ + [1], + [2] + ]); + expect(listChunk([1, 2, 3], 2), [ + [1, 2], + [3] + ]); + }); + }); +} -- Gitee From bc22806cb04a04d13c0c5c85e0ec01f86e1f04bb Mon Sep 17 00:00:00 2001 From: SimpleLove520 <1960997571@qq.com> Date: Wed, 24 Jan 2024 20:40:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SimpleLove520 <1960997571@qq.com> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6b6e886..df9874f 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,5 @@ Supports iOS, Android and MacOS. * [Documentation](https://github.com/tekartik/sqflite/blob/master/sqflite/README.md) * [API reference](https://pub.dartlang.org/documentation/sqflite/latest/sqflite/sqflite-library.html) * [How to](https://github.com/tekartik/sqflite/blob/master/sqflite/doc/how_to.md) guide + + -- Gitee