@rs-native-kit/version-check 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +256 -0
- package/VersionCheck.podspec +20 -0
- package/android/build.gradle +56 -0
- package/android/src/main/AndroidManifest.xml +9 -0
- package/android/src/main/java/com/rsnativekit/versioncheck/SecureStorageCipher.kt +57 -0
- package/android/src/main/java/com/rsnativekit/versioncheck/VersionCheckHeadlessTaskService.kt +31 -0
- package/android/src/main/java/com/rsnativekit/versioncheck/VersionCheckModule.kt +215 -0
- package/android/src/main/java/com/rsnativekit/versioncheck/VersionCheckPackage.kt +31 -0
- package/android/src/main/java/com/rsnativekit/versioncheck/VersionCheckWorker.kt +29 -0
- package/ios/PlatformBridge/Ed25519Verifier.swift +19 -0
- package/ios/VersionCheck.h +5 -0
- package/ios/VersionCheck.mm +278 -0
- package/lib/module/data/cache/MemoryCacheStore.js +30 -0
- package/lib/module/data/cache/MemoryCacheStore.js.map +1 -0
- package/lib/module/data/cache/PersistentCacheStore.js +56 -0
- package/lib/module/data/cache/PersistentCacheStore.js.map +1 -0
- package/lib/module/data/config/ConfigCache.js +29 -0
- package/lib/module/data/config/ConfigCache.js.map +1 -0
- package/lib/module/data/config/ConfigDocumentValidator.js +185 -0
- package/lib/module/data/config/ConfigDocumentValidator.js.map +1 -0
- package/lib/module/data/config/ConfigLoader.js +82 -0
- package/lib/module/data/config/ConfigLoader.js.map +1 -0
- package/lib/module/data/config/ConfigProvider.js +58 -0
- package/lib/module/data/config/ConfigProvider.js.map +1 -0
- package/lib/module/data/config/ConfigResolutionPipeline.js +268 -0
- package/lib/module/data/config/ConfigResolutionPipeline.js.map +1 -0
- package/lib/module/data/config/ConfigValidator.js +69 -0
- package/lib/module/data/config/ConfigValidator.js.map +1 -0
- package/lib/module/data/config/SignatureVerifier.js +80 -0
- package/lib/module/data/config/SignatureVerifier.js.map +1 -0
- package/lib/module/data/config/canonicalize.js +88 -0
- package/lib/module/data/config/canonicalize.js.map +1 -0
- package/lib/module/data/config/sources/EnvironmentOverrideSource.js +20 -0
- package/lib/module/data/config/sources/EnvironmentOverrideSource.js.map +1 -0
- package/lib/module/data/config/sources/LocalConfigSource.js +22 -0
- package/lib/module/data/config/sources/LocalConfigSource.js.map +1 -0
- package/lib/module/data/config/sources/RemoteConfigSource.js +38 -0
- package/lib/module/data/config/sources/RemoteConfigSource.js.map +1 -0
- package/lib/module/data/providers/amazon/AmazonAppstoreProvider.js +13 -0
- package/lib/module/data/providers/amazon/AmazonAppstoreProvider.js.map +1 -0
- package/lib/module/data/providers/apple/AppleStoreProvider.js +67 -0
- package/lib/module/data/providers/apple/AppleStoreProvider.js.map +1 -0
- package/lib/module/data/providers/custom-api/CustomApiProvider.js +51 -0
- package/lib/module/data/providers/custom-api/CustomApiProvider.js.map +1 -0
- package/lib/module/data/providers/firebase-remote-config/FirebaseRemoteConfigProvider.js +13 -0
- package/lib/module/data/providers/firebase-remote-config/FirebaseRemoteConfigProvider.js.map +1 -0
- package/lib/module/data/providers/google-play/GooglePlayProvider.js +62 -0
- package/lib/module/data/providers/google-play/GooglePlayProvider.js.map +1 -0
- package/lib/module/data/providers/huawei/HuaweiAppGalleryProvider.js +18 -0
- package/lib/module/data/providers/huawei/HuaweiAppGalleryProvider.js.map +1 -0
- package/lib/module/data/repositories/VersionRepositoryImpl.js +69 -0
- package/lib/module/data/repositories/VersionRepositoryImpl.js.map +1 -0
- package/lib/module/di/container.js +80 -0
- package/lib/module/di/container.js.map +1 -0
- package/lib/module/domain/IVersionManagerCore.js +4 -0
- package/lib/module/domain/IVersionManagerCore.js.map +1 -0
- package/lib/module/domain/VersionManagerCore.js +276 -0
- package/lib/module/domain/VersionManagerCore.js.map +1 -0
- package/lib/module/domain/engines/decision/DecisionEngine.js +40 -0
- package/lib/module/domain/engines/decision/DecisionEngine.js.map +1 -0
- package/lib/module/domain/engines/policy/IUpdatePolicyEngine.js +4 -0
- package/lib/module/domain/engines/policy/IUpdatePolicyEngine.js.map +1 -0
- package/lib/module/domain/engines/policy/PolicyEngine.js +42 -0
- package/lib/module/domain/engines/policy/PolicyEngine.js.map +1 -0
- package/lib/module/domain/engines/semver/IVersionComparator.js +4 -0
- package/lib/module/domain/engines/semver/IVersionComparator.js.map +1 -0
- package/lib/module/domain/engines/semver/SemVerEngine.js +176 -0
- package/lib/module/domain/engines/semver/SemVerEngine.js.map +1 -0
- package/lib/module/domain/errors/VersionManagerException.js +104 -0
- package/lib/module/domain/errors/VersionManagerException.js.map +1 -0
- package/lib/module/domain/models/ActionPlan.js +9 -0
- package/lib/module/domain/models/ActionPlan.js.map +1 -0
- package/lib/module/domain/models/ConfigDocument.js +4 -0
- package/lib/module/domain/models/ConfigDocument.js.map +1 -0
- package/lib/module/domain/models/Events.js +4 -0
- package/lib/module/domain/models/Events.js.map +1 -0
- package/lib/module/domain/models/LifecycleState.js +29 -0
- package/lib/module/domain/models/LifecycleState.js.map +1 -0
- package/lib/module/domain/models/ParsedVersion.js +2 -0
- package/lib/module/domain/models/ParsedVersion.js.map +1 -0
- package/lib/module/domain/models/PlatformId.js +2 -0
- package/lib/module/domain/models/PlatformId.js.map +1 -0
- package/lib/module/domain/models/PublicApiOptions.js +2 -0
- package/lib/module/domain/models/PublicApiOptions.js.map +1 -0
- package/lib/module/domain/models/RemoteVersionInfo.js +4 -0
- package/lib/module/domain/models/RemoteVersionInfo.js.map +1 -0
- package/lib/module/domain/models/StoreLookup.js +2 -0
- package/lib/module/domain/models/StoreLookup.js.map +1 -0
- package/lib/module/domain/models/Unsubscribe.js +2 -0
- package/lib/module/domain/models/Unsubscribe.js.map +1 -0
- package/lib/module/domain/models/UpdateInfo.js +4 -0
- package/lib/module/domain/models/UpdateInfo.js.map +1 -0
- package/lib/module/domain/models/VersionManagerOptions.js +4 -0
- package/lib/module/domain/models/VersionManagerOptions.js.map +1 -0
- package/lib/module/domain/ports/ICacheStore.js +2 -0
- package/lib/module/domain/ports/ICacheStore.js.map +1 -0
- package/lib/module/domain/ports/IClock.js +2 -0
- package/lib/module/domain/ports/IClock.js.map +1 -0
- package/lib/module/domain/ports/IConfigProvider.js +4 -0
- package/lib/module/domain/ports/IConfigProvider.js.map +1 -0
- package/lib/module/domain/ports/IConfigSources.js +4 -0
- package/lib/module/domain/ports/IConfigSources.js.map +1 -0
- package/lib/module/domain/ports/IPlatformBridge.js +4 -0
- package/lib/module/domain/ports/IPlatformBridge.js.map +1 -0
- package/lib/module/domain/ports/IStoreProvider.js +4 -0
- package/lib/module/domain/ports/IStoreProvider.js.map +1 -0
- package/lib/module/domain/ports/IVersionRepository.js +4 -0
- package/lib/module/domain/ports/IVersionRepository.js.map +1 -0
- package/lib/module/domain/statemachine/LifecycleStateMachine.js +55 -0
- package/lib/module/domain/statemachine/LifecycleStateMachine.js.map +1 -0
- package/lib/module/domain/usecases/CheckForUpdatesUseCase.js +31 -0
- package/lib/module/domain/usecases/CheckForUpdatesUseCase.js.map +1 -0
- package/lib/module/domain/usecases/ForceTriggerUpdateUseCase.js +20 -0
- package/lib/module/domain/usecases/ForceTriggerUpdateUseCase.js.map +1 -0
- package/lib/module/domain/usecases/ResetIgnoredVersionsUseCase.js +24 -0
- package/lib/module/domain/usecases/ResetIgnoredVersionsUseCase.js.map +1 -0
- package/lib/module/index.js +10 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/platform/contracts/IPlatformBridge.js +2 -0
- package/lib/module/platform/contracts/IPlatformBridge.js.map +1 -0
- package/lib/module/platform/createPlatformBridge.js +17 -0
- package/lib/module/platform/createPlatformBridge.js.map +1 -0
- package/lib/module/platform/createPlatformBridge.native.js +9 -0
- package/lib/module/platform/createPlatformBridge.native.js.map +1 -0
- package/lib/module/platform/native/NativePlatformBridge.js +143 -0
- package/lib/module/platform/native/NativePlatformBridge.js.map +1 -0
- package/lib/module/platform/native/NativeVersionCheck.js +33 -0
- package/lib/module/platform/native/NativeVersionCheck.js.map +1 -0
- package/lib/module/platform/web/WebPlatformBridge.js +228 -0
- package/lib/module/platform/web/WebPlatformBridge.js.map +1 -0
- package/lib/module/presentation/components/ForceUpdateScreen.js +68 -0
- package/lib/module/presentation/components/ForceUpdateScreen.js.map +1 -0
- package/lib/module/presentation/components/OptionalUpdateBanner.js +69 -0
- package/lib/module/presentation/components/OptionalUpdateBanner.js.map +1 -0
- package/lib/module/presentation/components/SoftUpdateDialog.js +101 -0
- package/lib/module/presentation/components/SoftUpdateDialog.js.map +1 -0
- package/lib/module/presentation/hooks/VersionManagerProvider.js +18 -0
- package/lib/module/presentation/hooks/VersionManagerProvider.js.map +1 -0
- package/lib/module/presentation/hooks/context.js +5 -0
- package/lib/module/presentation/hooks/context.js.map +1 -0
- package/lib/module/presentation/hooks/useUpdateState.js +26 -0
- package/lib/module/presentation/hooks/useUpdateState.js.map +1 -0
- package/lib/module/presentation/hooks/useVersionManager.js +33 -0
- package/lib/module/presentation/hooks/useVersionManager.js.map +1 -0
- package/lib/module/presentation/state/VersionManagerStore.js +47 -0
- package/lib/module/presentation/state/VersionManagerStore.js.map +1 -0
- package/lib/module/publicApi.js +114 -0
- package/lib/module/publicApi.js.map +1 -0
- package/lib/module/shared/eventbus/EventBus.js +34 -0
- package/lib/module/shared/eventbus/EventBus.js.map +1 -0
- package/lib/module/shared/logging/Logger.js +56 -0
- package/lib/module/shared/logging/Logger.js.map +1 -0
- package/lib/module/ui.js +13 -0
- package/lib/module/ui.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/data/cache/MemoryCacheStore.d.ts +12 -0
- package/lib/typescript/src/data/cache/MemoryCacheStore.d.ts.map +1 -0
- package/lib/typescript/src/data/cache/PersistentCacheStore.d.ts +14 -0
- package/lib/typescript/src/data/cache/PersistentCacheStore.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigCache.d.ts +15 -0
- package/lib/typescript/src/data/config/ConfigCache.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigDocumentValidator.d.ts +20 -0
- package/lib/typescript/src/data/config/ConfigDocumentValidator.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigLoader.d.ts +28 -0
- package/lib/typescript/src/data/config/ConfigLoader.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigProvider.d.ts +30 -0
- package/lib/typescript/src/data/config/ConfigProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigResolutionPipeline.d.ts +49 -0
- package/lib/typescript/src/data/config/ConfigResolutionPipeline.d.ts.map +1 -0
- package/lib/typescript/src/data/config/ConfigValidator.d.ts +10 -0
- package/lib/typescript/src/data/config/ConfigValidator.d.ts.map +1 -0
- package/lib/typescript/src/data/config/SignatureVerifier.d.ts +16 -0
- package/lib/typescript/src/data/config/SignatureVerifier.d.ts.map +1 -0
- package/lib/typescript/src/data/config/canonicalize.d.ts +13 -0
- package/lib/typescript/src/data/config/canonicalize.d.ts.map +1 -0
- package/lib/typescript/src/data/config/sources/EnvironmentOverrideSource.d.ts +17 -0
- package/lib/typescript/src/data/config/sources/EnvironmentOverrideSource.d.ts.map +1 -0
- package/lib/typescript/src/data/config/sources/LocalConfigSource.d.ts +19 -0
- package/lib/typescript/src/data/config/sources/LocalConfigSource.d.ts.map +1 -0
- package/lib/typescript/src/data/config/sources/RemoteConfigSource.d.ts +10 -0
- package/lib/typescript/src/data/config/sources/RemoteConfigSource.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/amazon/AmazonAppstoreProvider.d.ts +9 -0
- package/lib/typescript/src/data/providers/amazon/AmazonAppstoreProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/apple/AppleStoreProvider.d.ts +19 -0
- package/lib/typescript/src/data/providers/apple/AppleStoreProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/custom-api/CustomApiProvider.d.ts +14 -0
- package/lib/typescript/src/data/providers/custom-api/CustomApiProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/firebase-remote-config/FirebaseRemoteConfigProvider.d.ts +9 -0
- package/lib/typescript/src/data/providers/firebase-remote-config/FirebaseRemoteConfigProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/google-play/GooglePlayProvider.d.ts +22 -0
- package/lib/typescript/src/data/providers/google-play/GooglePlayProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/providers/huawei/HuaweiAppGalleryProvider.d.ts +14 -0
- package/lib/typescript/src/data/providers/huawei/HuaweiAppGalleryProvider.d.ts.map +1 -0
- package/lib/typescript/src/data/repositories/VersionRepositoryImpl.d.ts +23 -0
- package/lib/typescript/src/data/repositories/VersionRepositoryImpl.d.ts.map +1 -0
- package/lib/typescript/src/di/container.d.ts +12 -0
- package/lib/typescript/src/di/container.d.ts.map +1 -0
- package/lib/typescript/src/domain/IVersionManagerCore.d.ts +30 -0
- package/lib/typescript/src/domain/IVersionManagerCore.d.ts.map +1 -0
- package/lib/typescript/src/domain/VersionManagerCore.d.ts +94 -0
- package/lib/typescript/src/domain/VersionManagerCore.d.ts.map +1 -0
- package/lib/typescript/src/domain/engines/decision/DecisionEngine.d.ts +16 -0
- package/lib/typescript/src/domain/engines/decision/DecisionEngine.d.ts.map +1 -0
- package/lib/typescript/src/domain/engines/policy/IUpdatePolicyEngine.d.ts +17 -0
- package/lib/typescript/src/domain/engines/policy/IUpdatePolicyEngine.d.ts.map +1 -0
- package/lib/typescript/src/domain/engines/policy/PolicyEngine.d.ts +16 -0
- package/lib/typescript/src/domain/engines/policy/PolicyEngine.d.ts.map +1 -0
- package/lib/typescript/src/domain/engines/semver/IVersionComparator.d.ts +7 -0
- package/lib/typescript/src/domain/engines/semver/IVersionComparator.d.ts.map +1 -0
- package/lib/typescript/src/domain/engines/semver/SemVerEngine.d.ts +11 -0
- package/lib/typescript/src/domain/engines/semver/SemVerEngine.d.ts.map +1 -0
- package/lib/typescript/src/domain/errors/VersionManagerException.d.ts +97 -0
- package/lib/typescript/src/domain/errors/VersionManagerException.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/ActionPlan.d.ts +15 -0
- package/lib/typescript/src/domain/models/ActionPlan.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/ConfigDocument.d.ts +86 -0
- package/lib/typescript/src/domain/models/ConfigDocument.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/Events.d.ts +39 -0
- package/lib/typescript/src/domain/models/Events.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/LifecycleState.d.ts +18 -0
- package/lib/typescript/src/domain/models/LifecycleState.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/ParsedVersion.d.ts +9 -0
- package/lib/typescript/src/domain/models/ParsedVersion.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/PlatformId.d.ts +3 -0
- package/lib/typescript/src/domain/models/PlatformId.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/PublicApiOptions.d.ts +13 -0
- package/lib/typescript/src/domain/models/PublicApiOptions.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/RemoteVersionInfo.d.ts +21 -0
- package/lib/typescript/src/domain/models/RemoteVersionInfo.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/StoreLookup.d.ts +12 -0
- package/lib/typescript/src/domain/models/StoreLookup.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/Unsubscribe.d.ts +2 -0
- package/lib/typescript/src/domain/models/Unsubscribe.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/UpdateInfo.d.ts +11 -0
- package/lib/typescript/src/domain/models/UpdateInfo.d.ts.map +1 -0
- package/lib/typescript/src/domain/models/VersionManagerOptions.d.ts +149 -0
- package/lib/typescript/src/domain/models/VersionManagerOptions.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/ICacheStore.d.ts +6 -0
- package/lib/typescript/src/domain/ports/ICacheStore.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IClock.d.ts +4 -0
- package/lib/typescript/src/domain/ports/IClock.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IConfigProvider.d.ts +11 -0
- package/lib/typescript/src/domain/ports/IConfigProvider.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IConfigSources.d.ts +25 -0
- package/lib/typescript/src/domain/ports/IConfigSources.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IPlatformBridge.d.ts +77 -0
- package/lib/typescript/src/domain/ports/IPlatformBridge.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IStoreProvider.d.ts +7 -0
- package/lib/typescript/src/domain/ports/IStoreProvider.d.ts.map +1 -0
- package/lib/typescript/src/domain/ports/IVersionRepository.d.ts +8 -0
- package/lib/typescript/src/domain/ports/IVersionRepository.d.ts.map +1 -0
- package/lib/typescript/src/domain/statemachine/LifecycleStateMachine.d.ts +25 -0
- package/lib/typescript/src/domain/statemachine/LifecycleStateMachine.d.ts.map +1 -0
- package/lib/typescript/src/domain/usecases/CheckForUpdatesUseCase.d.ts +30 -0
- package/lib/typescript/src/domain/usecases/CheckForUpdatesUseCase.d.ts.map +1 -0
- package/lib/typescript/src/domain/usecases/ForceTriggerUpdateUseCase.d.ts +17 -0
- package/lib/typescript/src/domain/usecases/ForceTriggerUpdateUseCase.d.ts.map +1 -0
- package/lib/typescript/src/domain/usecases/ResetIgnoredVersionsUseCase.d.ts +7 -0
- package/lib/typescript/src/domain/usecases/ResetIgnoredVersionsUseCase.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +17 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/platform/contracts/IPlatformBridge.d.ts +2 -0
- package/lib/typescript/src/platform/contracts/IPlatformBridge.d.ts.map +1 -0
- package/lib/typescript/src/platform/createPlatformBridge.d.ts +12 -0
- package/lib/typescript/src/platform/createPlatformBridge.d.ts.map +1 -0
- package/lib/typescript/src/platform/createPlatformBridge.native.d.ts +4 -0
- package/lib/typescript/src/platform/createPlatformBridge.native.d.ts.map +1 -0
- package/lib/typescript/src/platform/native/NativePlatformBridge.d.ts +17 -0
- package/lib/typescript/src/platform/native/NativePlatformBridge.d.ts.map +1 -0
- package/lib/typescript/src/platform/native/NativeVersionCheck.d.ts +45 -0
- package/lib/typescript/src/platform/native/NativeVersionCheck.d.ts.map +1 -0
- package/lib/typescript/src/platform/web/WebPlatformBridge.d.ts +17 -0
- package/lib/typescript/src/platform/web/WebPlatformBridge.d.ts.map +1 -0
- package/lib/typescript/src/presentation/components/ForceUpdateScreen.d.ts +12 -0
- package/lib/typescript/src/presentation/components/ForceUpdateScreen.d.ts.map +1 -0
- package/lib/typescript/src/presentation/components/OptionalUpdateBanner.d.ts +12 -0
- package/lib/typescript/src/presentation/components/OptionalUpdateBanner.d.ts.map +1 -0
- package/lib/typescript/src/presentation/components/SoftUpdateDialog.d.ts +14 -0
- package/lib/typescript/src/presentation/components/SoftUpdateDialog.d.ts.map +1 -0
- package/lib/typescript/src/presentation/hooks/VersionManagerProvider.d.ts +9 -0
- package/lib/typescript/src/presentation/hooks/VersionManagerProvider.d.ts.map +1 -0
- package/lib/typescript/src/presentation/hooks/context.d.ts +3 -0
- package/lib/typescript/src/presentation/hooks/context.d.ts.map +1 -0
- package/lib/typescript/src/presentation/hooks/useUpdateState.d.ts +17 -0
- package/lib/typescript/src/presentation/hooks/useUpdateState.d.ts.map +1 -0
- package/lib/typescript/src/presentation/hooks/useVersionManager.d.ts +22 -0
- package/lib/typescript/src/presentation/hooks/useVersionManager.d.ts.map +1 -0
- package/lib/typescript/src/presentation/state/VersionManagerStore.d.ts +28 -0
- package/lib/typescript/src/presentation/state/VersionManagerStore.d.ts.map +1 -0
- package/lib/typescript/src/publicApi.d.ts +24 -0
- package/lib/typescript/src/publicApi.d.ts.map +1 -0
- package/lib/typescript/src/shared/eventbus/EventBus.d.ts +21 -0
- package/lib/typescript/src/shared/eventbus/EventBus.d.ts.map +1 -0
- package/lib/typescript/src/shared/logging/Logger.d.ts +17 -0
- package/lib/typescript/src/shared/logging/Logger.d.ts.map +1 -0
- package/lib/typescript/src/ui.d.ts +15 -0
- package/lib/typescript/src/ui.d.ts.map +1 -0
- package/package.json +192 -0
- package/src/data/cache/MemoryCacheStore.ts +36 -0
- package/src/data/cache/PersistentCacheStore.ts +63 -0
- package/src/data/config/ConfigCache.ts +30 -0
- package/src/data/config/ConfigDocumentValidator.ts +309 -0
- package/src/data/config/ConfigLoader.ts +105 -0
- package/src/data/config/ConfigProvider.ts +84 -0
- package/src/data/config/ConfigResolutionPipeline.ts +424 -0
- package/src/data/config/ConfigValidator.ts +79 -0
- package/src/data/config/SignatureVerifier.ts +90 -0
- package/src/data/config/canonicalize.ts +111 -0
- package/src/data/config/sources/EnvironmentOverrideSource.ts +22 -0
- package/src/data/config/sources/LocalConfigSource.ts +24 -0
- package/src/data/config/sources/RemoteConfigSource.ts +41 -0
- package/src/data/providers/amazon/AmazonAppstoreProvider.ts +16 -0
- package/src/data/providers/apple/AppleStoreProvider.ts +94 -0
- package/src/data/providers/custom-api/CustomApiProvider.ts +75 -0
- package/src/data/providers/firebase-remote-config/FirebaseRemoteConfigProvider.ts +16 -0
- package/src/data/providers/google-play/GooglePlayProvider.ts +75 -0
- package/src/data/providers/huawei/HuaweiAppGalleryProvider.ts +21 -0
- package/src/data/repositories/VersionRepositoryImpl.ts +90 -0
- package/src/di/container.ts +128 -0
- package/src/domain/IVersionManagerCore.ts +54 -0
- package/src/domain/VersionManagerCore.ts +425 -0
- package/src/domain/engines/decision/DecisionEngine.ts +47 -0
- package/src/domain/engines/policy/IUpdatePolicyEngine.ts +18 -0
- package/src/domain/engines/policy/PolicyEngine.ts +60 -0
- package/src/domain/engines/semver/IVersionComparator.ts +7 -0
- package/src/domain/engines/semver/SemVerEngine.ts +200 -0
- package/src/domain/errors/VersionManagerException.ts +166 -0
- package/src/domain/models/ActionPlan.ts +17 -0
- package/src/domain/models/ConfigDocument.ts +97 -0
- package/src/domain/models/Events.ts +48 -0
- package/src/domain/models/LifecycleState.ts +50 -0
- package/src/domain/models/ParsedVersion.ts +8 -0
- package/src/domain/models/PlatformId.ts +9 -0
- package/src/domain/models/PublicApiOptions.ts +14 -0
- package/src/domain/models/RemoteVersionInfo.ts +23 -0
- package/src/domain/models/StoreLookup.ts +12 -0
- package/src/domain/models/Unsubscribe.ts +1 -0
- package/src/domain/models/UpdateInfo.ts +11 -0
- package/src/domain/models/VersionManagerOptions.ts +150 -0
- package/src/domain/ports/ICacheStore.ts +5 -0
- package/src/domain/ports/IClock.ts +3 -0
- package/src/domain/ports/IConfigProvider.ts +18 -0
- package/src/domain/ports/IConfigSources.ts +44 -0
- package/src/domain/ports/IPlatformBridge.ts +97 -0
- package/src/domain/ports/IStoreProvider.ts +12 -0
- package/src/domain/ports/IVersionRepository.ts +14 -0
- package/src/domain/statemachine/LifecycleStateMachine.ts +76 -0
- package/src/domain/usecases/CheckForUpdatesUseCase.ts +63 -0
- package/src/domain/usecases/ForceTriggerUpdateUseCase.ts +35 -0
- package/src/domain/usecases/ResetIgnoredVersionsUseCase.ts +26 -0
- package/src/index.tsx +84 -0
- package/src/platform/contracts/IPlatformBridge.ts +14 -0
- package/src/platform/createPlatformBridge.native.ts +7 -0
- package/src/platform/createPlatformBridge.ts +15 -0
- package/src/platform/native/NativePlatformBridge.ts +179 -0
- package/src/platform/native/NativeVersionCheck.ts +64 -0
- package/src/platform/web/WebPlatformBridge.ts +347 -0
- package/src/presentation/components/ForceUpdateScreen.tsx +64 -0
- package/src/presentation/components/OptionalUpdateBanner.tsx +53 -0
- package/src/presentation/components/SoftUpdateDialog.tsx +84 -0
- package/src/presentation/hooks/VersionManagerProvider.tsx +23 -0
- package/src/presentation/hooks/context.ts +6 -0
- package/src/presentation/hooks/useUpdateState.ts +50 -0
- package/src/presentation/hooks/useVersionManager.ts +68 -0
- package/src/presentation/state/VersionManagerStore.ts +72 -0
- package/src/publicApi.ts +126 -0
- package/src/shared/eventbus/EventBus.ts +56 -0
- package/src/shared/logging/Logger.ts +70 -0
- package/src/ui.tsx +19 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.rsnativekit.versioncheck
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class VersionCheckPackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == VersionCheckModule.NAME) {
|
|
13
|
+
VersionCheckModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
|
|
20
|
+
mapOf(
|
|
21
|
+
VersionCheckModule.NAME to ReactModuleInfo(
|
|
22
|
+
name = VersionCheckModule.NAME,
|
|
23
|
+
className = VersionCheckModule.NAME,
|
|
24
|
+
canOverrideExistingModule = false,
|
|
25
|
+
needsEagerInit = false,
|
|
26
|
+
isCxxModule = false,
|
|
27
|
+
isTurboModule = true
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
package com.rsnativekit.versioncheck
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import androidx.work.Worker
|
|
6
|
+
import androidx.work.WorkerParameters
|
|
7
|
+
import com.facebook.react.HeadlessJsTaskService
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* WorkManager Worker enqueued by VersionCheckModule.scheduleBackgroundCheck(). Runs on
|
|
11
|
+
* WorkManager's background thread pool (never the JS thread — doc 01 §10); its only job
|
|
12
|
+
* is to wake the headless JS task, which does the actual checkForUpdates() call in JS
|
|
13
|
+
* (business logic stays in the domain layer, per doc 01 §1.1 — native code never
|
|
14
|
+
* reimplements it).
|
|
15
|
+
*/
|
|
16
|
+
class VersionCheckWorker(context: Context, params: WorkerParameters) :
|
|
17
|
+
Worker(context, params) {
|
|
18
|
+
|
|
19
|
+
override fun doWork(): Result {
|
|
20
|
+
return try {
|
|
21
|
+
val intent = Intent(applicationContext, VersionCheckHeadlessTaskService::class.java)
|
|
22
|
+
HeadlessJsTaskService.acquireWakeLockNow(applicationContext)
|
|
23
|
+
applicationContext.startService(intent)
|
|
24
|
+
Result.success()
|
|
25
|
+
} catch (error: Exception) {
|
|
26
|
+
Result.retry()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import CryptoKit
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
/// Doc 03 §3.4 — Ed25519 signature verification using CryptoKit exclusively (Prompt 1
|
|
5
|
+
/// §9.3: OS-provided cryptography only, no third-party crypto library). CryptoKit's
|
|
6
|
+
/// `Curve25519.Signing` API is Swift-only, so this small `@objc`-exposed wrapper is what
|
|
7
|
+
/// lets `ios/VersionCheck.mm` (Obj-C++) call into it via CocoaPods' auto-generated
|
|
8
|
+
/// `VersionCheck-Swift.h` header — a standard mixed-language-pod interop pattern that
|
|
9
|
+
/// requires no manual bridging header (bridging headers are only needed for an app
|
|
10
|
+
/// target calling into Swift; for a pod, `DEFINES_MODULE` + the generated `-Swift.h`
|
|
11
|
+
/// header handles it automatically once a Swift file is present in `s.source_files`).
|
|
12
|
+
@objc public class Ed25519Verifier: NSObject {
|
|
13
|
+
@objc public static func verify(publicKey: Data, message: Data, signature: Data) -> Bool {
|
|
14
|
+
guard let key = try? Curve25519.Signing.PublicKey(rawRepresentation: publicKey) else {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
return key.isValidSignature(signature, for: message)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#import "VersionCheck.h"
|
|
2
|
+
#import <CommonCrypto/CommonHMAC.h>
|
|
3
|
+
#import <BackgroundTasks/BackgroundTasks.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
#import <Security/Security.h>
|
|
6
|
+
#import <UIKit/UIKit.h>
|
|
7
|
+
#import <sys/utsname.h>
|
|
8
|
+
|
|
9
|
+
#if __has_include("VersionCheck-Swift.h")
|
|
10
|
+
#import "VersionCheck-Swift.h"
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
static NSString *const kVersionCheckKeychainService = @"com.rsnativekit.versioncheck";
|
|
14
|
+
|
|
15
|
+
@implementation VersionCheck
|
|
16
|
+
|
|
17
|
+
#pragma mark - App info
|
|
18
|
+
|
|
19
|
+
- (void)getCurrentAppVersion:(RCTPromiseResolveBlock)resolve
|
|
20
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
21
|
+
{
|
|
22
|
+
NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
|
23
|
+
resolve(version ?: @"");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (void)getBuildNumber:(RCTPromiseResolveBlock)resolve
|
|
27
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
28
|
+
{
|
|
29
|
+
NSString *build = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
|
|
30
|
+
resolve(build ?: @"");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (void)getBundleId:(RCTPromiseResolveBlock)resolve
|
|
34
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
35
|
+
{
|
|
36
|
+
resolve([[NSBundle mainBundle] bundleIdentifier] ?: @"");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#pragma mark - Device info
|
|
40
|
+
|
|
41
|
+
- (void)getOsVersion:(RCTPromiseResolveBlock)resolve
|
|
42
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
43
|
+
{
|
|
44
|
+
resolve([[UIDevice currentDevice] systemVersion]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
- (void)getDeviceModel:(RCTPromiseResolveBlock)resolve
|
|
48
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
49
|
+
{
|
|
50
|
+
struct utsname systemInfo;
|
|
51
|
+
uname(&systemInfo);
|
|
52
|
+
NSString *identifier = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
|
|
53
|
+
resolve(identifier ?: [[UIDevice currentDevice] model]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
- (void)getLocale:(RCTPromiseResolveBlock)resolve
|
|
57
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
58
|
+
{
|
|
59
|
+
resolve([[NSLocale currentLocale] localeIdentifier]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#pragma mark - Key-value storage (UserDefaults)
|
|
63
|
+
|
|
64
|
+
- (void)storageGet:(NSString *)key
|
|
65
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
66
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
67
|
+
{
|
|
68
|
+
NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:key];
|
|
69
|
+
resolve(value ?: [NSNull null]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (void)storageSet:(NSString *)key
|
|
73
|
+
value:(NSString *)value
|
|
74
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
75
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
76
|
+
{
|
|
77
|
+
[[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
|
|
78
|
+
resolve(nil);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
- (void)storageRemove:(NSString *)key
|
|
82
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
83
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
84
|
+
{
|
|
85
|
+
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
|
|
86
|
+
resolve(nil);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#pragma mark - Secure storage (Keychain)
|
|
90
|
+
|
|
91
|
+
- (NSMutableDictionary *)keychainQueryForKey:(NSString *)key
|
|
92
|
+
{
|
|
93
|
+
return [@{
|
|
94
|
+
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
|
|
95
|
+
(__bridge id)kSecAttrService: kVersionCheckKeychainService,
|
|
96
|
+
(__bridge id)kSecAttrAccount: key,
|
|
97
|
+
} mutableCopy];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
- (void)secureStorageGet:(NSString *)key
|
|
101
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
102
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
103
|
+
{
|
|
104
|
+
NSMutableDictionary *query = [self keychainQueryForKey:key];
|
|
105
|
+
query[(__bridge id)kSecReturnData] = @YES;
|
|
106
|
+
query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
|
|
107
|
+
|
|
108
|
+
CFTypeRef result = NULL;
|
|
109
|
+
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
|
110
|
+
if (status == errSecSuccess) {
|
|
111
|
+
NSData *data = (__bridge_transfer NSData *)result;
|
|
112
|
+
NSString *value = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
113
|
+
resolve(value ?: [NSNull null]);
|
|
114
|
+
} else if (status == errSecItemNotFound) {
|
|
115
|
+
resolve([NSNull null]);
|
|
116
|
+
} else {
|
|
117
|
+
reject(@"secure_storage_get_failed", @"Keychain read failed", nil);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
- (void)secureStorageSet:(NSString *)key
|
|
122
|
+
value:(NSString *)value
|
|
123
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
124
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
125
|
+
{
|
|
126
|
+
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
|
|
127
|
+
NSMutableDictionary *query = [self keychainQueryForKey:key];
|
|
128
|
+
|
|
129
|
+
// Overwrite semantics: delete any existing item before adding, since SecItemUpdate
|
|
130
|
+
// requires a separate attributes dictionary and delete+add is simpler/safer here.
|
|
131
|
+
SecItemDelete((__bridge CFDictionaryRef)query);
|
|
132
|
+
query[(__bridge id)kSecValueData] = data;
|
|
133
|
+
query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlock;
|
|
134
|
+
|
|
135
|
+
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
|
|
136
|
+
if (status == errSecSuccess) {
|
|
137
|
+
resolve(nil);
|
|
138
|
+
} else {
|
|
139
|
+
reject(@"secure_storage_set_failed", @"Keychain write failed", nil);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (void)secureStorageRemove:(NSString *)key
|
|
144
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
145
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
146
|
+
{
|
|
147
|
+
NSMutableDictionary *query = [self keychainQueryForKey:key];
|
|
148
|
+
SecItemDelete((__bridge CFDictionaryRef)query);
|
|
149
|
+
resolve(nil);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#pragma mark - Signature verification (doc 03 §3.4)
|
|
153
|
+
|
|
154
|
+
// Trusted key material is embedded at build time via Info.plist ("VMTrustedSigningKeys",
|
|
155
|
+
// a dictionary mapping keyId -> base64 key material) rather than shipped from JS, per
|
|
156
|
+
// §3.4's "embedded at build time, not hardcoded in the JS bundle" requirement. Host apps
|
|
157
|
+
// add this key to their own Info.plist; if absent, verification fails closed.
|
|
158
|
+
- (NSData *)resolveKeyMaterial:(NSString *)keyId
|
|
159
|
+
{
|
|
160
|
+
NSDictionary *keys = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"VMTrustedSigningKeys"];
|
|
161
|
+
NSString *base64 = keys[keyId];
|
|
162
|
+
if (![base64 isKindOfClass:[NSString class]]) return nil;
|
|
163
|
+
return [[NSData alloc] initWithBase64EncodedString:base64 options:0];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
- (void)verifyEd25519:(NSString *)keyId
|
|
167
|
+
messageBase64:(NSString *)messageBase64
|
|
168
|
+
signatureBase64:(NSString *)signatureBase64
|
|
169
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
170
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
171
|
+
{
|
|
172
|
+
NSData *keyMaterial = [self resolveKeyMaterial:keyId];
|
|
173
|
+
NSData *message = [[NSData alloc] initWithBase64EncodedString:messageBase64 options:0];
|
|
174
|
+
NSData *signature = [[NSData alloc] initWithBase64EncodedString:signatureBase64 options:0];
|
|
175
|
+
if (!keyMaterial || !message || !signature) {
|
|
176
|
+
resolve(@NO);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
#if __has_include("VersionCheck-Swift.h")
|
|
180
|
+
// CryptoKit's Curve25519 API is Swift-only — bridged via Ed25519Verifier.swift,
|
|
181
|
+
// exposed to this Obj-C++ file through CocoaPods' auto-generated -Swift.h header
|
|
182
|
+
// (standard mixed-language-pod interop; no manual bridging header required).
|
|
183
|
+
BOOL valid = [Ed25519Verifier verifyWithPublicKey:keyMaterial message:message signature:signature];
|
|
184
|
+
resolve(@(valid));
|
|
185
|
+
#else
|
|
186
|
+
reject(@"verify_ed25519_unavailable",
|
|
187
|
+
@"Ed25519Verifier.swift was not compiled into this pod — Ed25519 verification is unavailable on this build",
|
|
188
|
+
nil);
|
|
189
|
+
#endif
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
- (void)verifyHmacSha256:(NSString *)keyId
|
|
193
|
+
messageBase64:(NSString *)messageBase64
|
|
194
|
+
macBase64:(NSString *)macBase64
|
|
195
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
196
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
197
|
+
{
|
|
198
|
+
NSData *keyMaterial = [self resolveKeyMaterial:keyId];
|
|
199
|
+
NSData *message = [[NSData alloc] initWithBase64EncodedString:messageBase64 options:0];
|
|
200
|
+
NSData *expectedMac = [[NSData alloc] initWithBase64EncodedString:macBase64 options:0];
|
|
201
|
+
if (!keyMaterial || !message || !expectedMac) {
|
|
202
|
+
resolve(@NO);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
unsigned char computed[CC_SHA256_DIGEST_LENGTH];
|
|
207
|
+
CCHmac(kCCHmacAlgSHA256, keyMaterial.bytes, keyMaterial.length, message.bytes, message.length, computed);
|
|
208
|
+
|
|
209
|
+
if (expectedMac.length != CC_SHA256_DIGEST_LENGTH) {
|
|
210
|
+
resolve(@NO);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Constant-time comparison.
|
|
214
|
+
const unsigned char *expectedBytes = (const unsigned char *)expectedMac.bytes;
|
|
215
|
+
unsigned char diff = 0;
|
|
216
|
+
for (NSUInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
|
|
217
|
+
diff |= computed[i] ^ expectedBytes[i];
|
|
218
|
+
}
|
|
219
|
+
resolve(@(diff == 0));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#pragma mark - Background scheduling (doc 01 §4.1 "scheduler" row)
|
|
223
|
+
|
|
224
|
+
// BGTaskScheduler requires the host app to declare the task identifier in Info.plist
|
|
225
|
+
// (`BGTaskSchedulerPermittedIdentifiers`) and enable the "Background Modes > Background
|
|
226
|
+
// processing" capability — standard BGTaskScheduler integration any RN library using it
|
|
227
|
+
// requires (this library cannot inject those into a consumer's Info.plist itself). The
|
|
228
|
+
// scheduled task, once the OS runs it, starts a background URLSession-driven check;
|
|
229
|
+
// full headless-JS-on-cold-launch parity with Android's WorkManager path is not
|
|
230
|
+
// implemented in this pass — while the app process is alive this still lets iOS wake it
|
|
231
|
+
// periodically to call into the already-running JS runtime via the task handler below.
|
|
232
|
+
|
|
233
|
+
static NSString *const kVersionCheckBGTaskIdentifier = @"com.rsnativekit.versioncheck.refresh";
|
|
234
|
+
|
|
235
|
+
- (void)scheduleBackgroundCheck:(NSString *)taskId
|
|
236
|
+
minIntervalMs:(double)minIntervalMs
|
|
237
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
238
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
239
|
+
{
|
|
240
|
+
if (@available(iOS 13.0, *)) {
|
|
241
|
+
BGAppRefreshTaskRequest *request = [[BGAppRefreshTaskRequest alloc] initWithIdentifier:kVersionCheckBGTaskIdentifier];
|
|
242
|
+
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:(minIntervalMs / 1000.0)];
|
|
243
|
+
NSError *error = nil;
|
|
244
|
+
BOOL submitted = [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error];
|
|
245
|
+
if (!submitted) {
|
|
246
|
+
reject(@"schedule_background_check_failed", error.localizedDescription ?: @"BGTaskScheduler submission failed — verify BGTaskSchedulerPermittedIdentifiers in Info.plist", error);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
resolve(nil);
|
|
250
|
+
} else {
|
|
251
|
+
reject(@"schedule_background_check_unavailable", @"BGTaskScheduler requires iOS 13+", nil);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
- (void)cancelBackgroundCheck:(NSString *)taskId
|
|
256
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
257
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
258
|
+
{
|
|
259
|
+
if (@available(iOS 13.0, *)) {
|
|
260
|
+
[[BGTaskScheduler sharedScheduler] cancelTaskRequestWithIdentifier:kVersionCheckBGTaskIdentifier];
|
|
261
|
+
}
|
|
262
|
+
resolve(nil);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
#pragma mark - TurboModule plumbing
|
|
266
|
+
|
|
267
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
268
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
269
|
+
{
|
|
270
|
+
return std::make_shared<facebook::react::NativeVersionCheckSpecJSI>(params);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
+ (NSString *)moduleName
|
|
274
|
+
{
|
|
275
|
+
return @"VersionCheck";
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export class MemoryCacheStore {
|
|
4
|
+
entries = new Map();
|
|
5
|
+
constructor(clock, defaultTtlMs) {
|
|
6
|
+
this.clock = clock;
|
|
7
|
+
this.defaultTtlMs = defaultTtlMs;
|
|
8
|
+
}
|
|
9
|
+
async get(key) {
|
|
10
|
+
const entry = this.entries.get(key);
|
|
11
|
+
if (!entry) return null;
|
|
12
|
+
if (entry.expiresAt !== null && this.clock.now() > entry.expiresAt) {
|
|
13
|
+
this.entries.delete(key);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return entry.value;
|
|
17
|
+
}
|
|
18
|
+
async set(key, value, ttlMs) {
|
|
19
|
+
const ttl = ttlMs ?? this.defaultTtlMs;
|
|
20
|
+
const expiresAt = ttl > 0 ? this.clock.now() + ttl : null;
|
|
21
|
+
this.entries.set(key, {
|
|
22
|
+
value,
|
|
23
|
+
expiresAt
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async invalidate(key) {
|
|
27
|
+
this.entries.delete(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=MemoryCacheStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["MemoryCacheStore","entries","Map","constructor","clock","defaultTtlMs","get","key","entry","expiresAt","now","delete","value","set","ttlMs","ttl","invalidate"],"sourceRoot":"../../../../src","sources":["data/cache/MemoryCacheStore.ts"],"mappings":";;AAQA,OAAO,MAAMA,gBAAgB,CAA8B;EACxCC,OAAO,GAAG,IAAIC,GAAG,CAAmB,CAAC;EAEtDC,WAAWA,CACQC,KAAa,EACbC,YAAoB,EACrC;IAAA,KAFiBD,KAAa,GAAbA,KAAa;IAAA,KACbC,YAAoB,GAApBA,YAAoB;EACpC;EAEH,MAAMC,GAAGA,CAACC,GAAW,EAAqB;IACxC,MAAMC,KAAK,GAAG,IAAI,CAACP,OAAO,CAACK,GAAG,CAACC,GAAG,CAAC;IACnC,IAAI,CAACC,KAAK,EAAE,OAAO,IAAI;IACvB,IAAIA,KAAK,CAACC,SAAS,KAAK,IAAI,IAAI,IAAI,CAACL,KAAK,CAACM,GAAG,CAAC,CAAC,GAAGF,KAAK,CAACC,SAAS,EAAE;MAClE,IAAI,CAACR,OAAO,CAACU,MAAM,CAACJ,GAAG,CAAC;MACxB,OAAO,IAAI;IACb;IACA,OAAOC,KAAK,CAACI,KAAK;EACpB;EAEA,MAAMC,GAAGA,CAACN,GAAW,EAAEK,KAAQ,EAAEE,KAAc,EAAiB;IAC9D,MAAMC,GAAG,GAAGD,KAAK,IAAI,IAAI,CAACT,YAAY;IACtC,MAAMI,SAAS,GAAGM,GAAG,GAAG,CAAC,GAAG,IAAI,CAACX,KAAK,CAACM,GAAG,CAAC,CAAC,GAAGK,GAAG,GAAG,IAAI;IACzD,IAAI,CAACd,OAAO,CAACY,GAAG,CAACN,GAAG,EAAE;MAAEK,KAAK;MAAEH;IAAU,CAAC,CAAC;EAC7C;EAEA,MAAMO,UAAUA,CAACT,GAAW,EAAiB;IAC3C,IAAI,CAACN,OAAO,CAACU,MAAM,CAACJ,GAAG,CAAC;EAC1B;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { CacheCorruptionException, CacheWriteException } from "../../domain/errors/VersionManagerException.js";
|
|
4
|
+
export class PersistentCacheStore {
|
|
5
|
+
constructor(storage, clock, defaultTtlMs, keyPrefix = 'vm_cache_') {
|
|
6
|
+
this.storage = storage;
|
|
7
|
+
this.clock = clock;
|
|
8
|
+
this.defaultTtlMs = defaultTtlMs;
|
|
9
|
+
this.keyPrefix = keyPrefix;
|
|
10
|
+
}
|
|
11
|
+
async get(key) {
|
|
12
|
+
const raw = await this.storage.get(this.keyPrefix + key);
|
|
13
|
+
if (!raw) return null;
|
|
14
|
+
let entry;
|
|
15
|
+
try {
|
|
16
|
+
entry = JSON.parse(raw);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
throw new CacheCorruptionException({
|
|
19
|
+
message: `Corrupt persistent cache entry for key "${key}"`,
|
|
20
|
+
cause: error,
|
|
21
|
+
metadata: {
|
|
22
|
+
key
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (entry.expiresAt !== null && this.clock.now() > entry.expiresAt) {
|
|
27
|
+
await this.storage.remove(this.keyPrefix + key);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return entry.value;
|
|
31
|
+
}
|
|
32
|
+
async set(key, value, ttlMs) {
|
|
33
|
+
const ttl = ttlMs ?? this.defaultTtlMs;
|
|
34
|
+
const expiresAt = ttl > 0 ? this.clock.now() + ttl : null;
|
|
35
|
+
const entry = {
|
|
36
|
+
value,
|
|
37
|
+
expiresAt
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
await this.storage.set(this.keyPrefix + key, JSON.stringify(entry));
|
|
41
|
+
} catch (error) {
|
|
42
|
+
throw new CacheWriteException({
|
|
43
|
+
message: `Failed to persist cache entry for key "${key}"`,
|
|
44
|
+
cause: error,
|
|
45
|
+
retryable: true,
|
|
46
|
+
metadata: {
|
|
47
|
+
key
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async invalidate(key) {
|
|
53
|
+
await this.storage.remove(this.keyPrefix + key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=PersistentCacheStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["CacheCorruptionException","CacheWriteException","PersistentCacheStore","constructor","storage","clock","defaultTtlMs","keyPrefix","get","key","raw","entry","JSON","parse","error","message","cause","metadata","expiresAt","now","remove","value","set","ttlMs","ttl","stringify","retryable","invalidate"],"sourceRoot":"../../../../src","sources":["data/cache/PersistentCacheStore.ts"],"mappings":";;AAAA,SACEA,wBAAwB,EACxBC,mBAAmB,QACd,gDAA6C;AAUpD,OAAO,MAAMC,oBAAoB,CAA8B;EAC7DC,WAAWA,CACQC,OAAyB,EACzBC,KAAa,EACbC,YAAoB,EACpBC,SAAiB,GAAG,WAAW,EAChD;IAAA,KAJiBH,OAAyB,GAAzBA,OAAyB;IAAA,KACzBC,KAAa,GAAbA,KAAa;IAAA,KACbC,YAAoB,GAApBA,YAAoB;IAAA,KACpBC,SAAiB,GAAjBA,SAAiB;EACjC;EAEH,MAAMC,GAAGA,CAACC,GAAW,EAAqB;IACxC,MAAMC,GAAG,GAAG,MAAM,IAAI,CAACN,OAAO,CAACI,GAAG,CAAC,IAAI,CAACD,SAAS,GAAGE,GAAG,CAAC;IACxD,IAAI,CAACC,GAAG,EAAE,OAAO,IAAI;IAErB,IAAIC,KAAwB;IAC5B,IAAI;MACFA,KAAK,GAAGC,IAAI,CAACC,KAAK,CAACH,GAAG,CAAsB;IAC9C,CAAC,CAAC,OAAOI,KAAK,EAAE;MACd,MAAM,IAAId,wBAAwB,CAAC;QACjCe,OAAO,EAAE,2CAA2CN,GAAG,GAAG;QAC1DO,KAAK,EAAEF,KAAK;QACZG,QAAQ,EAAE;UAAER;QAAI;MAClB,CAAC,CAAC;IACJ;IAEA,IAAIE,KAAK,CAACO,SAAS,KAAK,IAAI,IAAI,IAAI,CAACb,KAAK,CAACc,GAAG,CAAC,CAAC,GAAGR,KAAK,CAACO,SAAS,EAAE;MAClE,MAAM,IAAI,CAACd,OAAO,CAACgB,MAAM,CAAC,IAAI,CAACb,SAAS,GAAGE,GAAG,CAAC;MAC/C,OAAO,IAAI;IACb;IACA,OAAOE,KAAK,CAACU,KAAK;EACpB;EAEA,MAAMC,GAAGA,CAACb,GAAW,EAAEY,KAAQ,EAAEE,KAAc,EAAiB;IAC9D,MAAMC,GAAG,GAAGD,KAAK,IAAI,IAAI,CAACjB,YAAY;IACtC,MAAMY,SAAS,GAAGM,GAAG,GAAG,CAAC,GAAG,IAAI,CAACnB,KAAK,CAACc,GAAG,CAAC,CAAC,GAAGK,GAAG,GAAG,IAAI;IACzD,MAAMb,KAAwB,GAAG;MAAEU,KAAK;MAAEH;IAAU,CAAC;IACrD,IAAI;MACF,MAAM,IAAI,CAACd,OAAO,CAACkB,GAAG,CAAC,IAAI,CAACf,SAAS,GAAGE,GAAG,EAAEG,IAAI,CAACa,SAAS,CAACd,KAAK,CAAC,CAAC;IACrE,CAAC,CAAC,OAAOG,KAAK,EAAE;MACd,MAAM,IAAIb,mBAAmB,CAAC;QAC5Bc,OAAO,EAAE,0CAA0CN,GAAG,GAAG;QACzDO,KAAK,EAAEF,KAAK;QACZY,SAAS,EAAE,IAAI;QACfT,QAAQ,EAAE;UAAER;QAAI;MAClB,CAAC,CAAC;IACJ;EACF;EAEA,MAAMkB,UAAUA,CAAClB,GAAW,EAAiB;IAC3C,MAAM,IAAI,CAACL,OAAO,CAACgB,MAAM,CAAC,IAAI,CAACb,SAAS,GAAGE,GAAG,CAAC;EACjD;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const STORAGE_KEY = 'vm_config_cache_v1';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Doc 03 §4.3 — the persistent tier of the access-path cache (backs the in-process
|
|
7
|
+
* memory cache across app restarts). Stores the last config that successfully passed
|
|
8
|
+
* schema+boundary+signature validation, regardless of which tier produced it.
|
|
9
|
+
*/
|
|
10
|
+
export class ConfigCache {
|
|
11
|
+
constructor(storage) {
|
|
12
|
+
this.storage = storage;
|
|
13
|
+
}
|
|
14
|
+
async getLastValid() {
|
|
15
|
+
const raw = await this.storage.get(STORAGE_KEY);
|
|
16
|
+
if (!raw) return null;
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(raw);
|
|
19
|
+
} catch {
|
|
20
|
+
// Corrupt config cache entry — treated as absent (§7.2 falls through to the next
|
|
21
|
+
// tier), not surfaced as a hard failure of the config pipeline itself.
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async setLastValid(config) {
|
|
26
|
+
await this.storage.set(STORAGE_KEY, JSON.stringify(config));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ConfigCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["STORAGE_KEY","ConfigCache","constructor","storage","getLastValid","raw","get","JSON","parse","setLastValid","config","set","stringify"],"sourceRoot":"../../../../src","sources":["data/config/ConfigCache.ts"],"mappings":";;AAIA,MAAMA,WAAW,GAAG,oBAAoB;;AAExC;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,WAAW,CAAyB;EAC/CC,WAAWA,CAAkBC,OAAyB,EAAE;IAAA,KAA3BA,OAAyB,GAAzBA,OAAyB;EAAG;EAEzD,MAAMC,YAAYA,CAAA,EAAiD;IACjE,MAAMC,GAAG,GAAG,MAAM,IAAI,CAACF,OAAO,CAACG,GAAG,CAACN,WAAW,CAAC;IAC/C,IAAI,CAACK,GAAG,EAAE,OAAO,IAAI;IACrB,IAAI;MACF,OAAOE,IAAI,CAACC,KAAK,CAACH,GAAG,CAAC;IACxB,CAAC,CAAC,MAAM;MACN;MACA;MACA,OAAO,IAAI;IACb;EACF;EAEA,MAAMI,YAAYA,CAACC,MAAoC,EAAiB;IACtE,MAAM,IAAI,CAACP,OAAO,CAACQ,GAAG,CAACX,WAAW,EAAEO,IAAI,CAACK,SAAS,CAACF,MAAM,CAAC,CAAC;EAC7D;AACF","ignoreList":[]}
|