@swiftpatch/react-native 2.0.0

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.
Files changed (182) hide show
  1. package/README.md +430 -0
  2. package/android/build.gradle +105 -0
  3. package/android/src/main/AndroidManifest.xml +6 -0
  4. package/android/src/main/java/com/swiftpatch/BundleManager.kt +107 -0
  5. package/android/src/main/java/com/swiftpatch/CrashDetector.kt +79 -0
  6. package/android/src/main/java/com/swiftpatch/CryptoVerifier.kt +69 -0
  7. package/android/src/main/java/com/swiftpatch/DownloadManager.kt +120 -0
  8. package/android/src/main/java/com/swiftpatch/EventQueue.kt +86 -0
  9. package/android/src/main/java/com/swiftpatch/FileUtils.kt +60 -0
  10. package/android/src/main/java/com/swiftpatch/PatchApplier.kt +60 -0
  11. package/android/src/main/java/com/swiftpatch/SignalCrashHandler.kt +84 -0
  12. package/android/src/main/java/com/swiftpatch/SlotManager.kt +299 -0
  13. package/android/src/main/java/com/swiftpatch/SwiftPatchModule.kt +630 -0
  14. package/android/src/main/java/com/swiftpatch/SwiftPatchPackage.kt +21 -0
  15. package/android/src/main/jni/CMakeLists.txt +12 -0
  16. package/android/src/main/jni/bspatch.c +188 -0
  17. package/android/src/main/jni/bspatch.h +57 -0
  18. package/android/src/main/jni/bspatch_jni.c +28 -0
  19. package/ios/Libraries/bspatch/bspatch.c +188 -0
  20. package/ios/Libraries/bspatch/bspatch.h +50 -0
  21. package/ios/Libraries/bspatch/module.modulemap +4 -0
  22. package/ios/SwiftPatch/BundleManager.swift +113 -0
  23. package/ios/SwiftPatch/CrashDetector.swift +71 -0
  24. package/ios/SwiftPatch/CryptoVerifier.swift +70 -0
  25. package/ios/SwiftPatch/DownloadManager.swift +125 -0
  26. package/ios/SwiftPatch/EventQueue.swift +116 -0
  27. package/ios/SwiftPatch/FileUtils.swift +38 -0
  28. package/ios/SwiftPatch/PatchApplier.swift +41 -0
  29. package/ios/SwiftPatch/SignalCrashHandler.swift +129 -0
  30. package/ios/SwiftPatch/SlotManager.swift +360 -0
  31. package/ios/SwiftPatch/SwiftPatchModule.m +56 -0
  32. package/ios/SwiftPatch/SwiftPatchModule.swift +621 -0
  33. package/lib/commonjs/SwiftPatchCore.js +140 -0
  34. package/lib/commonjs/SwiftPatchCore.js.map +1 -0
  35. package/lib/commonjs/SwiftPatchProvider.js +617 -0
  36. package/lib/commonjs/SwiftPatchProvider.js.map +1 -0
  37. package/lib/commonjs/constants.js +50 -0
  38. package/lib/commonjs/constants.js.map +1 -0
  39. package/lib/commonjs/core/Downloader.js +63 -0
  40. package/lib/commonjs/core/Downloader.js.map +1 -0
  41. package/lib/commonjs/core/Installer.js +46 -0
  42. package/lib/commonjs/core/Installer.js.map +1 -0
  43. package/lib/commonjs/core/Rollback.js +36 -0
  44. package/lib/commonjs/core/Rollback.js.map +1 -0
  45. package/lib/commonjs/core/UpdateChecker.js +57 -0
  46. package/lib/commonjs/core/UpdateChecker.js.map +1 -0
  47. package/lib/commonjs/core/Verifier.js +82 -0
  48. package/lib/commonjs/core/Verifier.js.map +1 -0
  49. package/lib/commonjs/core/index.js +41 -0
  50. package/lib/commonjs/core/index.js.map +1 -0
  51. package/lib/commonjs/index.js +154 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/modal/SwiftPatchModal.js +667 -0
  54. package/lib/commonjs/modal/SwiftPatchModal.js.map +1 -0
  55. package/lib/commonjs/modal/useSwiftPatchModal.js +26 -0
  56. package/lib/commonjs/modal/useSwiftPatchModal.js.map +1 -0
  57. package/lib/commonjs/native/NativeSwiftPatch.js +85 -0
  58. package/lib/commonjs/native/NativeSwiftPatch.js.map +1 -0
  59. package/lib/commonjs/native/NativeSwiftPatchSpec.js +15 -0
  60. package/lib/commonjs/native/NativeSwiftPatchSpec.js.map +1 -0
  61. package/lib/commonjs/package.json +1 -0
  62. package/lib/commonjs/types.js +126 -0
  63. package/lib/commonjs/types.js.map +1 -0
  64. package/lib/commonjs/useSwiftPatch.js +31 -0
  65. package/lib/commonjs/useSwiftPatch.js.map +1 -0
  66. package/lib/commonjs/utils/api.js +206 -0
  67. package/lib/commonjs/utils/api.js.map +1 -0
  68. package/lib/commonjs/utils/device.js +23 -0
  69. package/lib/commonjs/utils/device.js.map +1 -0
  70. package/lib/commonjs/utils/logger.js +30 -0
  71. package/lib/commonjs/utils/logger.js.map +1 -0
  72. package/lib/commonjs/utils/storage.js +31 -0
  73. package/lib/commonjs/utils/storage.js.map +1 -0
  74. package/lib/commonjs/withSwiftPatch.js +42 -0
  75. package/lib/commonjs/withSwiftPatch.js.map +1 -0
  76. package/lib/module/SwiftPatchCore.js +135 -0
  77. package/lib/module/SwiftPatchCore.js.map +1 -0
  78. package/lib/module/SwiftPatchProvider.js +611 -0
  79. package/lib/module/SwiftPatchProvider.js.map +1 -0
  80. package/lib/module/constants.js +46 -0
  81. package/lib/module/constants.js.map +1 -0
  82. package/lib/module/core/Downloader.js +57 -0
  83. package/lib/module/core/Downloader.js.map +1 -0
  84. package/lib/module/core/Installer.js +41 -0
  85. package/lib/module/core/Installer.js.map +1 -0
  86. package/lib/module/core/Rollback.js +31 -0
  87. package/lib/module/core/Rollback.js.map +1 -0
  88. package/lib/module/core/UpdateChecker.js +51 -0
  89. package/lib/module/core/UpdateChecker.js.map +1 -0
  90. package/lib/module/core/Verifier.js +76 -0
  91. package/lib/module/core/Verifier.js.map +1 -0
  92. package/lib/module/core/index.js +8 -0
  93. package/lib/module/core/index.js.map +1 -0
  94. package/lib/module/index.js +34 -0
  95. package/lib/module/index.js.map +1 -0
  96. package/lib/module/modal/SwiftPatchModal.js +661 -0
  97. package/lib/module/modal/SwiftPatchModal.js.map +1 -0
  98. package/lib/module/modal/useSwiftPatchModal.js +22 -0
  99. package/lib/module/modal/useSwiftPatchModal.js.map +1 -0
  100. package/lib/module/native/NativeSwiftPatch.js +78 -0
  101. package/lib/module/native/NativeSwiftPatch.js.map +1 -0
  102. package/lib/module/native/NativeSwiftPatchSpec.js +12 -0
  103. package/lib/module/native/NativeSwiftPatchSpec.js.map +1 -0
  104. package/lib/module/types.js +139 -0
  105. package/lib/module/types.js.map +1 -0
  106. package/lib/module/useSwiftPatch.js +26 -0
  107. package/lib/module/useSwiftPatch.js.map +1 -0
  108. package/lib/module/utils/api.js +197 -0
  109. package/lib/module/utils/api.js.map +1 -0
  110. package/lib/module/utils/device.js +18 -0
  111. package/lib/module/utils/device.js.map +1 -0
  112. package/lib/module/utils/logger.js +26 -0
  113. package/lib/module/utils/logger.js.map +1 -0
  114. package/lib/module/utils/storage.js +24 -0
  115. package/lib/module/utils/storage.js.map +1 -0
  116. package/lib/module/withSwiftPatch.js +37 -0
  117. package/lib/module/withSwiftPatch.js.map +1 -0
  118. package/lib/typescript/SwiftPatchCore.d.ts +64 -0
  119. package/lib/typescript/SwiftPatchCore.d.ts.map +1 -0
  120. package/lib/typescript/SwiftPatchProvider.d.ts +22 -0
  121. package/lib/typescript/SwiftPatchProvider.d.ts.map +1 -0
  122. package/lib/typescript/constants.d.ts +33 -0
  123. package/lib/typescript/constants.d.ts.map +1 -0
  124. package/lib/typescript/core/Downloader.d.ts +34 -0
  125. package/lib/typescript/core/Downloader.d.ts.map +1 -0
  126. package/lib/typescript/core/Installer.d.ts +25 -0
  127. package/lib/typescript/core/Installer.d.ts.map +1 -0
  128. package/lib/typescript/core/Rollback.d.ts +18 -0
  129. package/lib/typescript/core/Rollback.d.ts.map +1 -0
  130. package/lib/typescript/core/UpdateChecker.d.ts +27 -0
  131. package/lib/typescript/core/UpdateChecker.d.ts.map +1 -0
  132. package/lib/typescript/core/Verifier.d.ts +31 -0
  133. package/lib/typescript/core/Verifier.d.ts.map +1 -0
  134. package/lib/typescript/core/index.d.ts +8 -0
  135. package/lib/typescript/core/index.d.ts.map +1 -0
  136. package/lib/typescript/index.d.ts +13 -0
  137. package/lib/typescript/index.d.ts.map +1 -0
  138. package/lib/typescript/modal/SwiftPatchModal.d.ts +11 -0
  139. package/lib/typescript/modal/SwiftPatchModal.d.ts.map +1 -0
  140. package/lib/typescript/modal/useSwiftPatchModal.d.ts +7 -0
  141. package/lib/typescript/modal/useSwiftPatchModal.d.ts.map +1 -0
  142. package/lib/typescript/native/NativeSwiftPatch.d.ts +61 -0
  143. package/lib/typescript/native/NativeSwiftPatch.d.ts.map +1 -0
  144. package/lib/typescript/native/NativeSwiftPatchSpec.d.ts +67 -0
  145. package/lib/typescript/native/NativeSwiftPatchSpec.d.ts.map +1 -0
  146. package/lib/typescript/types.d.ts +266 -0
  147. package/lib/typescript/types.d.ts.map +1 -0
  148. package/lib/typescript/useSwiftPatch.d.ts +12 -0
  149. package/lib/typescript/useSwiftPatch.d.ts.map +1 -0
  150. package/lib/typescript/utils/api.d.ts +87 -0
  151. package/lib/typescript/utils/api.d.ts.map +1 -0
  152. package/lib/typescript/utils/device.d.ts +9 -0
  153. package/lib/typescript/utils/device.d.ts.map +1 -0
  154. package/lib/typescript/utils/logger.d.ts +8 -0
  155. package/lib/typescript/utils/logger.d.ts.map +1 -0
  156. package/lib/typescript/utils/storage.d.ts +14 -0
  157. package/lib/typescript/utils/storage.d.ts.map +1 -0
  158. package/lib/typescript/withSwiftPatch.d.ts +12 -0
  159. package/lib/typescript/withSwiftPatch.d.ts.map +1 -0
  160. package/package.json +99 -0
  161. package/react-native-swiftpatch.podspec +50 -0
  162. package/src/SwiftPatchCore.ts +148 -0
  163. package/src/SwiftPatchProvider.tsx +514 -0
  164. package/src/constants.ts +49 -0
  165. package/src/core/Downloader.ts +74 -0
  166. package/src/core/Installer.ts +38 -0
  167. package/src/core/Rollback.ts +28 -0
  168. package/src/core/UpdateChecker.ts +70 -0
  169. package/src/core/Verifier.ts +92 -0
  170. package/src/core/index.ts +11 -0
  171. package/src/index.ts +64 -0
  172. package/src/modal/SwiftPatchModal.tsx +657 -0
  173. package/src/modal/useSwiftPatchModal.ts +24 -0
  174. package/src/native/NativeSwiftPatch.ts +205 -0
  175. package/src/native/NativeSwiftPatchSpec.ts +139 -0
  176. package/src/types.ts +336 -0
  177. package/src/useSwiftPatch.ts +29 -0
  178. package/src/utils/api.ts +244 -0
  179. package/src/utils/device.ts +15 -0
  180. package/src/utils/logger.ts +29 -0
  181. package/src/utils/storage.ts +23 -0
  182. package/src/withSwiftPatch.tsx +41 -0
@@ -0,0 +1,205 @@
1
+ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
2
+ import type { BundleInfo, DownloadProgress, SlotMetadata } from '../types';
3
+ import { NativeEvents } from '../constants';
4
+
5
+ const LINKING_ERROR =
6
+ `The package '@swiftpatch/react-native' doesn't seem to be linked. Make sure: \n\n` +
7
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
8
+ '- You rebuilt the app after installing the package\n' +
9
+ '- You are not using Expo Go\n';
10
+
11
+ // Try to get TurboModule first (New Architecture), fallback to legacy
12
+ let SwiftPatchNative: any;
13
+ let isTurboModuleEnabled = false;
14
+
15
+ try {
16
+ // @ts-ignore - TurboModuleRegistry is not typed
17
+ const TurboModuleRegistry = require('react-native').TurboModuleRegistry;
18
+ if (TurboModuleRegistry) {
19
+ SwiftPatchNative = TurboModuleRegistry.get('SwiftPatch');
20
+ if (SwiftPatchNative) {
21
+ isTurboModuleEnabled = true;
22
+ }
23
+ }
24
+ } catch (e) {
25
+ // TurboModuleRegistry not available, will use legacy
26
+ }
27
+
28
+ // Fallback to legacy NativeModules if TurboModule not available
29
+ if (!SwiftPatchNative) {
30
+ SwiftPatchNative = NativeModules.SwiftPatch
31
+ ? NativeModules.SwiftPatch
32
+ : new Proxy(
33
+ {},
34
+ {
35
+ get() {
36
+ throw new Error(LINKING_ERROR);
37
+ },
38
+ }
39
+ );
40
+ }
41
+
42
+ // Event emitter for native events
43
+ export const swiftPatchEmitter = new NativeEventEmitter(SwiftPatchNative);
44
+
45
+ // Export whether TurboModule is enabled for debugging
46
+ export const IS_TURBO_MODULE_ENABLED = isTurboModuleEnabled;
47
+
48
+ /**
49
+ * Native module interface
50
+ */
51
+ export interface NativeSwiftPatchModule {
52
+ // ─── Initialization ────────────────────────────────────────
53
+
54
+ initialize(config: {
55
+ deploymentKey: string;
56
+ serverUrl: string;
57
+ publicKey: string | null;
58
+ }): Promise<void>;
59
+
60
+ getJSBundleFile(): string | null;
61
+
62
+ setDebugMode(enabled: boolean): void;
63
+
64
+ // ─── Mount State (crash detection) ─────────────────────────
65
+
66
+ markMounted(): Promise<void>;
67
+
68
+ markUnmounted(): Promise<void>;
69
+
70
+ // ─── Bundle Information ────────────────────────────────────
71
+
72
+ getCurrentBundle(): Promise<BundleInfo | null>;
73
+
74
+ getSlotMetadata(): Promise<SlotMetadata>;
75
+
76
+ getDeviceId(): Promise<string>;
77
+
78
+ getAppVersion(): Promise<string>;
79
+
80
+ // ─── Environment ───────────────────────────────────────────
81
+
82
+ switchEnvironment(environment: string): Promise<SlotMetadata>;
83
+
84
+ // ─── Download & Install ────────────────────────────────────
85
+
86
+ downloadUpdate(
87
+ url: string,
88
+ expectedHash: string,
89
+ isPatch: boolean,
90
+ signature: string | null
91
+ ): Promise<void>;
92
+
93
+ downloadStageBundle(url: string, expectedHash: string): Promise<void>;
94
+
95
+ installUpdate(bundleHash: string): Promise<void>;
96
+
97
+ hasPendingInstall(): Promise<boolean>;
98
+
99
+ confirmInstall(): Promise<void>;
100
+
101
+ // ─── Stabilization ─────────────────────────────────────────
102
+
103
+ stabilize(): Promise<SlotMetadata>;
104
+
105
+ // ─── Restart & Rollback ────────────────────────────────────
106
+
107
+ restart(): void;
108
+
109
+ rollback(): Promise<string>;
110
+
111
+ clearPendingUpdate(): Promise<void>;
112
+
113
+ // ─── Event Queue ───────────────────────────────────────────
114
+
115
+ popEvents(): Promise<Array<Record<string, unknown>>>;
116
+
117
+ acknowledgeEvents(eventIdsJson: string): Promise<void>;
118
+
119
+ // ─── Launch Tracking ───────────────────────────────────────
120
+
121
+ recordSuccessfulLaunch(bundleHash: string): Promise<number>;
122
+
123
+ getLaunchCount(bundleHash: string): Promise<number>;
124
+
125
+ // ─── Status Reporting ──────────────────────────────────────
126
+
127
+ reportStatus(
128
+ releaseId: string,
129
+ status: 'downloaded' | 'installed' | 'crashed' | 'rolledBack'
130
+ ): Promise<void>;
131
+
132
+ // ─── Legacy / Advanced ─────────────────────────────────────
133
+
134
+ computeHash(filePath: string): Promise<string>;
135
+
136
+ applyPatch(
137
+ currentBundlePath: string,
138
+ patchPath: string,
139
+ outputPath: string
140
+ ): Promise<string>;
141
+
142
+ verifySignature(
143
+ data: string,
144
+ signature: string,
145
+ publicKey: string
146
+ ): Promise<boolean>;
147
+
148
+ cancelDownload(): Promise<void>;
149
+
150
+ getDownloadedBundlePath(bundleHash: string): Promise<string>;
151
+ }
152
+
153
+ export default SwiftPatchNative as NativeSwiftPatchModule;
154
+
155
+ /**
156
+ * Subscribe to download progress events
157
+ */
158
+ export function onDownloadProgress(
159
+ callback: (progress: DownloadProgress) => void
160
+ ): () => void {
161
+ const subscription = swiftPatchEmitter.addListener(
162
+ NativeEvents.DOWNLOAD_PROGRESS,
163
+ callback
164
+ );
165
+ return () => subscription.remove();
166
+ }
167
+
168
+ /**
169
+ * Subscribe to rollback events
170
+ */
171
+ export function onRollback(
172
+ callback: (reason: string) => void
173
+ ): () => void {
174
+ const subscription = swiftPatchEmitter.addListener(
175
+ NativeEvents.ROLLBACK_OCCURRED,
176
+ (event: { reason: string }) => callback(event.reason)
177
+ );
178
+ return () => subscription.remove();
179
+ }
180
+
181
+ /**
182
+ * Subscribe to version change events
183
+ */
184
+ export function onVersionChanged(
185
+ callback: (reason: string) => void
186
+ ): () => void {
187
+ const subscription = swiftPatchEmitter.addListener(
188
+ NativeEvents.VERSION_CHANGED,
189
+ (event: { reason: string }) => callback(event.reason)
190
+ );
191
+ return () => subscription.remove();
192
+ }
193
+
194
+ /**
195
+ * Subscribe to native SDK events
196
+ */
197
+ export function onNativeEvent(
198
+ callback: (event: Record<string, unknown>) => void
199
+ ): () => void {
200
+ const subscription = swiftPatchEmitter.addListener(
201
+ NativeEvents.NATIVE_EVENT,
202
+ callback
203
+ );
204
+ return () => subscription.remove();
205
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * TurboModule Spec for SwiftPatch
3
+ *
4
+ * This file defines the interface for the New Architecture TurboModule.
5
+ * Codegen will use this to generate native code for iOS and Android.
6
+ */
7
+
8
+ import type { TurboModule } from 'react-native';
9
+ import { TurboModuleRegistry } from 'react-native';
10
+
11
+ export interface BundleInfo {
12
+ hash: string;
13
+ version: string;
14
+ installedAt: string;
15
+ isOriginal: boolean;
16
+ slot: string;
17
+ environment: string;
18
+ }
19
+
20
+ export interface SlotMetadata {
21
+ environment: string;
22
+ prod: {
23
+ currentSlot: string;
24
+ newHash: string | null;
25
+ stableHash: string | null;
26
+ tempHash: string | null;
27
+ };
28
+ stage: {
29
+ newHash: string | null;
30
+ };
31
+ }
32
+
33
+ export interface Spec extends TurboModule {
34
+ // ─── Initialization ────────────────────────────────────────
35
+
36
+ initialize(config: {
37
+ deploymentKey: string;
38
+ serverUrl: string;
39
+ publicKey: string | null;
40
+ }): Promise<void>;
41
+
42
+ getJSBundleFile(): string | null;
43
+
44
+ setDebugMode(enabled: boolean): void;
45
+
46
+ // ─── Mount State (crash detection) ─────────────────────────
47
+
48
+ markMounted(): Promise<void>;
49
+
50
+ markUnmounted(): Promise<void>;
51
+
52
+ // ─── Bundle Information ────────────────────────────────────
53
+
54
+ getCurrentBundle(): Promise<BundleInfo | null>;
55
+
56
+ getSlotMetadata(): Promise<SlotMetadata>;
57
+
58
+ getDeviceId(): Promise<string>;
59
+
60
+ getAppVersion(): Promise<string>;
61
+
62
+ // ─── Environment ───────────────────────────────────────────
63
+
64
+ switchEnvironment(environment: string): Promise<SlotMetadata>;
65
+
66
+ // ─── Download & Install ────────────────────────────────────
67
+
68
+ downloadUpdate(
69
+ url: string,
70
+ expectedHash: string,
71
+ isPatch: boolean,
72
+ signature: string | null
73
+ ): Promise<void>;
74
+
75
+ downloadStageBundle(url: string, expectedHash: string): Promise<void>;
76
+
77
+ installUpdate(bundleHash: string): Promise<void>;
78
+
79
+ hasPendingInstall(): Promise<boolean>;
80
+
81
+ confirmInstall(): Promise<void>;
82
+
83
+ // ─── Stabilization ─────────────────────────────────────────
84
+
85
+ stabilize(): Promise<SlotMetadata>;
86
+
87
+ // ─── Restart & Rollback ────────────────────────────────────
88
+
89
+ restart(): void;
90
+
91
+ rollback(): Promise<string>;
92
+
93
+ clearPendingUpdate(): Promise<void>;
94
+
95
+ // ─── Event Queue ───────────────────────────────────────────
96
+
97
+ popEvents(): Promise<Array<Record<string, unknown>>>;
98
+
99
+ acknowledgeEvents(eventIdsJson: string): Promise<void>;
100
+
101
+ // ─── Launch Tracking ───────────────────────────────────────
102
+
103
+ recordSuccessfulLaunch(bundleHash: string): Promise<number>;
104
+
105
+ getLaunchCount(bundleHash: string): Promise<number>;
106
+
107
+ // ─── Status Reporting ──────────────────────────────────────
108
+
109
+ reportStatus(
110
+ releaseId: string,
111
+ status: 'downloaded' | 'installed' | 'crashed' | 'rolledBack'
112
+ ): Promise<void>;
113
+
114
+ // ─── Legacy / Advanced ─────────────────────────────────────
115
+
116
+ computeHash(filePath: string): Promise<string>;
117
+
118
+ applyPatch(
119
+ currentBundlePath: string,
120
+ patchPath: string,
121
+ outputPath: string
122
+ ): Promise<string>;
123
+
124
+ verifySignature(
125
+ data: string,
126
+ signature: string,
127
+ publicKey: string
128
+ ): Promise<boolean>;
129
+
130
+ cancelDownload(): Promise<void>;
131
+
132
+ getDownloadedBundlePath(bundleHash: string): Promise<string>;
133
+
134
+ // Event emitter support
135
+ addListener(eventName: string): void;
136
+ removeListeners(count: number): void;
137
+ }
138
+
139
+ export default TurboModuleRegistry.getEnforcing<Spec>('SwiftPatch');
package/src/types.ts ADDED
@@ -0,0 +1,336 @@
1
+ /**
2
+ * SwiftPatch SDK Configuration
3
+ */
4
+ export interface SwiftPatchConfig {
5
+ /** Deployment key from SwiftPatch dashboard */
6
+ deploymentKey: string;
7
+
8
+ /** Server URL (defaults to cloud) */
9
+ serverUrl?: string;
10
+
11
+ /** Check for updates when app comes to foreground */
12
+ checkOnResume?: boolean;
13
+
14
+ /** Minimum interval between update checks (ms) */
15
+ checkInterval?: number;
16
+
17
+ /** Install mode for non-mandatory updates */
18
+ installMode?: InstallMode;
19
+
20
+ /** Install mode for mandatory updates */
21
+ mandatoryInstallMode?: InstallMode;
22
+
23
+ /** Enable debug logging */
24
+ debug?: boolean;
25
+
26
+ /** Custom headers for API requests */
27
+ customHeaders?: Record<string, string>;
28
+
29
+ /** Public key for bundle verification (optional) */
30
+ publicKey?: string;
31
+
32
+ /** Auto-stabilize after N successful launches (0 = manual only) */
33
+ autoStabilizeAfterLaunches?: number;
34
+
35
+ /** SDK PIN for in-app dashboard access (optional) */
36
+ sdkPin?: string;
37
+ }
38
+
39
+ /**
40
+ * When to install downloaded updates
41
+ */
42
+ export enum InstallMode {
43
+ /** Install immediately and restart */
44
+ IMMEDIATE = 'immediate',
45
+
46
+ /** Install on next app restart */
47
+ ON_NEXT_RESTART = 'onNextRestart',
48
+
49
+ /** Install on next resume from background */
50
+ ON_NEXT_RESUME = 'onNextResume',
51
+ }
52
+
53
+ /**
54
+ * Current update status
55
+ */
56
+ export enum UpdateStatus {
57
+ /** Checking for updates */
58
+ CHECKING = 'checking',
59
+
60
+ /** No update available */
61
+ UP_TO_DATE = 'upToDate',
62
+
63
+ /** Update available, not downloaded */
64
+ UPDATE_AVAILABLE = 'updateAvailable',
65
+
66
+ /** Downloading update */
67
+ DOWNLOADING = 'downloading',
68
+
69
+ /** Download complete, ready to install */
70
+ READY_TO_INSTALL = 'readyToInstall',
71
+
72
+ /** Installing update */
73
+ INSTALLING = 'installing',
74
+
75
+ /** Update installed, restart required */
76
+ RESTART_REQUIRED = 'restartRequired',
77
+
78
+ /** Error occurred */
79
+ ERROR = 'error',
80
+ }
81
+
82
+ /**
83
+ * Slot states for the dual-slot architecture
84
+ */
85
+ export enum SlotState {
86
+ DEFAULT_SLOT = 'DEFAULT_SLOT',
87
+ STABLE_SLOT = 'STABLE_SLOT',
88
+ NEW_SLOT = 'NEW_SLOT',
89
+ }
90
+
91
+ /**
92
+ * Environment mode
93
+ */
94
+ export enum EnvironmentMode {
95
+ PRODUCTION = 'PROD',
96
+ STAGING = 'STAGE',
97
+ }
98
+
99
+ /**
100
+ * Information about an available release
101
+ */
102
+ export interface ReleaseInfo {
103
+ /** Unique release ID */
104
+ id: string;
105
+
106
+ /** Semantic version (e.g., "1.2.3") */
107
+ version: string;
108
+
109
+ /** Release notes */
110
+ releaseNote: string | null;
111
+
112
+ /** Whether update is mandatory */
113
+ isMandatory: boolean;
114
+
115
+ /** SHA-256 hash of the bundle */
116
+ bundleHash: string;
117
+
118
+ /** Download URL (patch or full bundle) */
119
+ downloadUrl: string;
120
+
121
+ /** Size in bytes */
122
+ downloadSize: number;
123
+
124
+ /** Whether this is a patch (true) or full bundle (false) */
125
+ isPatch: boolean;
126
+
127
+ /** Cryptographic signature (if signing enabled) */
128
+ signature?: string;
129
+
130
+ /** Release timestamp */
131
+ releasedAt: string;
132
+ }
133
+
134
+ /**
135
+ * Current bundle information
136
+ */
137
+ export interface BundleInfo {
138
+ /** SHA-256 hash of current bundle */
139
+ hash: string;
140
+
141
+ /** Version string */
142
+ version: string;
143
+
144
+ /** When bundle was installed */
145
+ installedAt: string;
146
+
147
+ /** Whether this is the original bundled bundle */
148
+ isOriginal: boolean;
149
+
150
+ /** Current slot state */
151
+ slot: SlotState;
152
+
153
+ /** Current environment */
154
+ environment: EnvironmentMode;
155
+ }
156
+
157
+ /**
158
+ * Slot metadata for the dual-slot system
159
+ */
160
+ export interface SlotMetadata {
161
+ environment: EnvironmentMode;
162
+ prod: {
163
+ currentSlot: SlotState;
164
+ newHash: string | null;
165
+ stableHash: string | null;
166
+ tempHash: string | null;
167
+ };
168
+ stage: {
169
+ newHash: string | null;
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Download progress information
175
+ */
176
+ export interface DownloadProgress {
177
+ /** Bytes downloaded so far */
178
+ downloadedBytes: number;
179
+
180
+ /** Total bytes to download */
181
+ totalBytes: number;
182
+
183
+ /** Progress percentage (0-100) */
184
+ percentage: number;
185
+ }
186
+
187
+ /**
188
+ * SDK event types for analytics
189
+ */
190
+ export enum SwiftPatchEventType {
191
+ DOWNLOAD_PROD_STARTED = 'DOWNLOAD_PROD_STARTED',
192
+ DOWNLOAD_PROD_COMPLETED = 'DOWNLOAD_PROD_COMPLETED',
193
+ DOWNLOAD_PROD_FAILED = 'DOWNLOAD_PROD_FAILED',
194
+ INSTALLED_PROD = 'INSTALLED_PROD',
195
+ ROLLBACK_PROD = 'ROLLBACK_PROD',
196
+ STABILIZE_PROD = 'STABILIZE_PROD',
197
+ CORRUPTION_PROD = 'CORRUPTION_PROD',
198
+ DOWNLOAD_STAGE_STARTED = 'DOWNLOAD_STAGE_STARTED',
199
+ DOWNLOAD_STAGE_COMPLETED = 'DOWNLOAD_STAGE_COMPLETED',
200
+ DOWNLOAD_STAGE_FAILED = 'DOWNLOAD_STAGE_FAILED',
201
+ INSTALLED_STAGE = 'INSTALLED_STAGE',
202
+ SYNC_ERROR = 'SYNC_ERROR',
203
+ VERSION_CHANGED = 'VERSION_CHANGED',
204
+ CRASH_DETECTED = 'CRASH_DETECTED',
205
+ }
206
+
207
+ /**
208
+ * A queued SDK event
209
+ */
210
+ export interface SwiftPatchEvent {
211
+ id: string;
212
+ eventType: SwiftPatchEventType;
213
+ timestamp: number;
214
+ releaseHash?: string;
215
+ errorMessage?: string;
216
+ metadata?: Record<string, unknown>;
217
+ }
218
+
219
+ /**
220
+ * SwiftPatch state exposed via hook
221
+ */
222
+ export interface SwiftPatchState {
223
+ /** Current update status */
224
+ status: UpdateStatus;
225
+
226
+ /** Download progress (if downloading) */
227
+ downloadProgress: DownloadProgress | null;
228
+
229
+ /** Currently installed bundle info */
230
+ currentBundle: BundleInfo | null;
231
+
232
+ /** Available update info */
233
+ availableUpdate: ReleaseInfo | null;
234
+
235
+ /** Whether restart is required to apply update */
236
+ isRestartRequired: boolean;
237
+
238
+ /** Last error (if status is ERROR) */
239
+ error: SwiftPatchError | null;
240
+
241
+ /** Last check timestamp */
242
+ lastCheckedAt: Date | null;
243
+
244
+ /** Current slot metadata */
245
+ slotMetadata: SlotMetadata | null;
246
+
247
+ /** Current environment */
248
+ environment: EnvironmentMode;
249
+ }
250
+
251
+ /**
252
+ * SwiftPatch actions exposed via hook
253
+ */
254
+ export interface SwiftPatchActions {
255
+ /** Check for available updates */
256
+ checkForUpdate: () => Promise<ReleaseInfo | null>;
257
+
258
+ /** Download available update */
259
+ downloadUpdate: () => Promise<void>;
260
+
261
+ /** Install downloaded update */
262
+ installUpdate: () => Promise<void>;
263
+
264
+ /** Restart app to apply update */
265
+ restart: () => void;
266
+
267
+ /** Manually rollback to previous version */
268
+ rollback: () => Promise<void>;
269
+
270
+ /** Clear pending update */
271
+ clearPendingUpdate: () => Promise<void>;
272
+
273
+ /** Get current bundle info */
274
+ getCurrentBundle: () => Promise<BundleInfo | null>;
275
+
276
+ /** Stabilize current bundle (promote NEW → STABLE) */
277
+ stabilize: () => Promise<SlotMetadata>;
278
+
279
+ /** Switch environment (PROD / STAGE) */
280
+ switchEnvironment: (env: EnvironmentMode) => Promise<SlotMetadata>;
281
+
282
+ /** Get slot metadata */
283
+ getSlotMetadata: () => Promise<SlotMetadata>;
284
+
285
+ /** Mark app as mounted (for crash detection) */
286
+ markMounted: () => void;
287
+
288
+ /** Download a stage bundle for testing */
289
+ downloadStageBundle: (url: string, hash: string) => Promise<void>;
290
+ }
291
+
292
+ /**
293
+ * Combined hook return type
294
+ */
295
+ export type UseSwiftPatchReturn = SwiftPatchState & SwiftPatchActions;
296
+
297
+ /**
298
+ * Simplified update hook return type
299
+ */
300
+ export interface UseSwiftPatchUpdateReturn {
301
+ isRestartRequired: boolean;
302
+ newReleaseBundle: ReleaseInfo | null;
303
+ currentBundle: BundleInfo | null;
304
+ status: UpdateStatus;
305
+ restart: () => void;
306
+ }
307
+
308
+ /**
309
+ * SwiftPatch error
310
+ */
311
+ export interface SwiftPatchError {
312
+ code: SwiftPatchErrorCode;
313
+ message: string;
314
+ details?: unknown;
315
+ }
316
+
317
+ export enum SwiftPatchErrorCode {
318
+ NETWORK_ERROR = 'NETWORK_ERROR',
319
+ DOWNLOAD_ERROR = 'DOWNLOAD_ERROR',
320
+ VERIFICATION_ERROR = 'VERIFICATION_ERROR',
321
+ PATCH_ERROR = 'PATCH_ERROR',
322
+ INSTALL_ERROR = 'INSTALL_ERROR',
323
+ CONFIG_ERROR = 'CONFIG_ERROR',
324
+ STABILIZE_ERROR = 'STABILIZE_ERROR',
325
+ ENVIRONMENT_ERROR = 'ENVIRONMENT_ERROR',
326
+ UNKNOWN_ERROR = 'UNKNOWN_ERROR',
327
+ }
328
+
329
+ /**
330
+ * Modal hook return type
331
+ */
332
+ export interface UseSwiftPatchModalReturn {
333
+ showModal: () => void;
334
+ hideModal: () => void;
335
+ isModalVisible: boolean;
336
+ }
@@ -0,0 +1,29 @@
1
+ import { useSwiftPatchContext } from './SwiftPatchProvider';
2
+ import type {
3
+ UseSwiftPatchReturn,
4
+ UseSwiftPatchUpdateReturn,
5
+ } from './types';
6
+
7
+ /**
8
+ * Main hook for accessing all SwiftPatch state and actions.
9
+ * Must be used within SwiftPatchProvider.
10
+ */
11
+ export function useSwiftPatch(): UseSwiftPatchReturn {
12
+ return useSwiftPatchContext();
13
+ }
14
+
15
+ /**
16
+ * Simplified hook that only exposes update-related state.
17
+ * Useful for showing update banners or restart prompts.
18
+ */
19
+ export function useSwiftPatchUpdate(): UseSwiftPatchUpdateReturn {
20
+ const ctx = useSwiftPatchContext();
21
+
22
+ return {
23
+ isRestartRequired: ctx.isRestartRequired,
24
+ newReleaseBundle: ctx.availableUpdate,
25
+ currentBundle: ctx.currentBundle,
26
+ status: ctx.status,
27
+ restart: ctx.restart,
28
+ };
29
+ }