@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,244 @@
1
+ import type { ReleaseInfo, SwiftPatchEvent } from '../types';
2
+
3
+ interface CheckUpdateParams {
4
+ serverUrl: string;
5
+ deploymentKey: string;
6
+ appVersion: string;
7
+ currentBundleHash: string | null;
8
+ platform: 'ios' | 'android';
9
+ deviceId: string;
10
+ customHeaders?: Record<string, string>;
11
+ unverifiedHashes?: string[];
12
+ }
13
+
14
+ interface CheckUpdateResponse {
15
+ updateAvailable: boolean;
16
+ release?: ReleaseInfo;
17
+ appliedRelease?: {
18
+ isRolledBack: boolean;
19
+ targetAppVersion: string;
20
+ };
21
+ }
22
+
23
+ /**
24
+ * Check for available updates from the SwiftPatch server
25
+ */
26
+ export async function checkForUpdateAPI(
27
+ params: CheckUpdateParams
28
+ ): Promise<CheckUpdateResponse> {
29
+ const {
30
+ serverUrl,
31
+ deploymentKey,
32
+ appVersion,
33
+ currentBundleHash,
34
+ platform,
35
+ deviceId,
36
+ customHeaders = {},
37
+ unverifiedHashes,
38
+ } = params;
39
+
40
+ const response = await fetch(`${serverUrl}/sdk/check-update`, {
41
+ method: 'POST',
42
+ headers: {
43
+ 'Content-Type': 'application/json',
44
+ ...customHeaders,
45
+ },
46
+ body: JSON.stringify({
47
+ deploymentKey,
48
+ appVersion,
49
+ currentBundleHash,
50
+ platform,
51
+ deviceId,
52
+ unverifiedHashes,
53
+ }),
54
+ });
55
+
56
+ if (!response.ok) {
57
+ throw new Error(
58
+ `Update check failed: ${response.status} ${response.statusText}`
59
+ );
60
+ }
61
+
62
+ return response.json();
63
+ }
64
+
65
+ interface ReportStatusParams {
66
+ serverUrl: string;
67
+ deploymentKey: string;
68
+ releaseId: string;
69
+ status: 'downloaded' | 'installed' | 'crashed' | 'rolledBack';
70
+ error?: string;
71
+ }
72
+
73
+ /**
74
+ * Report install status to the SwiftPatch server
75
+ */
76
+ export async function reportInstallStatus(
77
+ params: ReportStatusParams
78
+ ): Promise<void> {
79
+ const { serverUrl, deploymentKey, releaseId, status, error } = params;
80
+
81
+ try {
82
+ await fetch(`${serverUrl}/sdk/report-status`, {
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/json',
86
+ },
87
+ body: JSON.stringify({
88
+ deploymentKey,
89
+ releaseId,
90
+ status,
91
+ error,
92
+ timestamp: new Date().toISOString(),
93
+ }),
94
+ });
95
+ } catch (_e) {
96
+ console.warn('[SwiftPatch] Failed to report install status');
97
+ }
98
+ }
99
+
100
+ interface LogBulkEventsParams {
101
+ serverUrl: string;
102
+ deploymentKey: string;
103
+ deviceId: string;
104
+ events: SwiftPatchEvent[];
105
+ customHeaders?: Record<string, string>;
106
+ }
107
+
108
+ /**
109
+ * Send bulk analytics events to the server
110
+ */
111
+ export async function logBulkEvents(
112
+ params: LogBulkEventsParams
113
+ ): Promise<{ acknowledged: string[] }> {
114
+ const { serverUrl, deploymentKey, deviceId, events, customHeaders = {} } = params;
115
+
116
+ try {
117
+ const response = await fetch(`${serverUrl}/sdk/log-bulk-events`, {
118
+ method: 'POST',
119
+ headers: {
120
+ 'Content-Type': 'application/json',
121
+ ...customHeaders,
122
+ },
123
+ body: JSON.stringify({
124
+ deploymentKey,
125
+ deviceId,
126
+ events,
127
+ }),
128
+ });
129
+
130
+ if (!response.ok) {
131
+ throw new Error(`Failed to log events: ${response.status}`);
132
+ }
133
+
134
+ return response.json();
135
+ } catch (_e) {
136
+ console.warn('[SwiftPatch] Failed to log bulk events');
137
+ return { acknowledged: [] };
138
+ }
139
+ }
140
+
141
+ interface VerifyPinParams {
142
+ serverUrl: string;
143
+ deploymentKey: string;
144
+ pin: string;
145
+ customHeaders?: Record<string, string>;
146
+ }
147
+
148
+ /**
149
+ * Verify SDK PIN for dashboard access
150
+ */
151
+ export async function verifySDKPin(
152
+ params: VerifyPinParams
153
+ ): Promise<{ sdkToken: string } | null> {
154
+ const { serverUrl, deploymentKey, pin, customHeaders = {} } = params;
155
+
156
+ try {
157
+ const response = await fetch(`${serverUrl}/sdk/auth/verify-pin`, {
158
+ method: 'POST',
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ 'x-deployment-key': deploymentKey,
162
+ ...customHeaders,
163
+ },
164
+ body: JSON.stringify({ pin }),
165
+ });
166
+
167
+ if (!response.ok) return null;
168
+ return response.json();
169
+ } catch (_e) {
170
+ return null;
171
+ }
172
+ }
173
+
174
+ interface ListBucketsParams {
175
+ serverUrl: string;
176
+ sdkToken: string;
177
+ deploymentKey: string;
178
+ customHeaders?: Record<string, string>;
179
+ }
180
+
181
+ /**
182
+ * List available channels/buckets
183
+ */
184
+ export async function listBuckets(
185
+ params: ListBucketsParams
186
+ ): Promise<any[]> {
187
+ const { serverUrl, sdkToken, deploymentKey, customHeaders = {} } = params;
188
+
189
+ try {
190
+ const response = await fetch(`${serverUrl}/sdk/list-buckets`, {
191
+ method: 'POST',
192
+ headers: {
193
+ 'Content-Type': 'application/json',
194
+ 'x-sdk-token': sdkToken,
195
+ 'x-deployment-key': deploymentKey,
196
+ ...customHeaders,
197
+ },
198
+ body: JSON.stringify({}),
199
+ });
200
+
201
+ if (!response.ok) return [];
202
+ const data = await response.json();
203
+ return data.buckets || [];
204
+ } catch (_e) {
205
+ return [];
206
+ }
207
+ }
208
+
209
+ interface ListBundlesParams {
210
+ serverUrl: string;
211
+ sdkToken: string;
212
+ deploymentKey: string;
213
+ channelId?: string;
214
+ platform?: string;
215
+ pageOffset?: number;
216
+ customHeaders?: Record<string, string>;
217
+ }
218
+
219
+ /**
220
+ * List bundles with pagination
221
+ */
222
+ export async function listBundles(
223
+ params: ListBundlesParams
224
+ ): Promise<{ bundles: any[]; hasMore: boolean }> {
225
+ const { serverUrl, sdkToken, deploymentKey, channelId, platform, pageOffset = 0, customHeaders = {} } = params;
226
+
227
+ try {
228
+ const response = await fetch(`${serverUrl}/sdk/list-bundles`, {
229
+ method: 'POST',
230
+ headers: {
231
+ 'Content-Type': 'application/json',
232
+ 'x-sdk-token': sdkToken,
233
+ 'x-deployment-key': deploymentKey,
234
+ ...customHeaders,
235
+ },
236
+ body: JSON.stringify({ channelId, platform, pageOffset }),
237
+ });
238
+
239
+ if (!response.ok) return { bundles: [], hasMore: false };
240
+ return response.json();
241
+ } catch (_e) {
242
+ return { bundles: [], hasMore: false };
243
+ }
244
+ }
@@ -0,0 +1,15 @@
1
+ import NativeSwiftPatch from '../native/NativeSwiftPatch';
2
+
3
+ /**
4
+ * Get a unique device identifier for rollout bucketing
5
+ */
6
+ export async function getDeviceId(): Promise<string> {
7
+ return NativeSwiftPatch.getDeviceId();
8
+ }
9
+
10
+ /**
11
+ * Get the current binary app version
12
+ */
13
+ export async function getAppVersion(): Promise<string> {
14
+ return NativeSwiftPatch.getAppVersion();
15
+ }
@@ -0,0 +1,29 @@
1
+ const TAG = '[SwiftPatch]';
2
+
3
+ let debugEnabled = false;
4
+
5
+ export const logger = {
6
+ setDebug(enabled: boolean): void {
7
+ debugEnabled = enabled;
8
+ },
9
+
10
+ debug(...args: unknown[]): void {
11
+ if (debugEnabled) {
12
+ console.debug(TAG, ...args);
13
+ }
14
+ },
15
+
16
+ info(...args: unknown[]): void {
17
+ if (debugEnabled) {
18
+ console.info(TAG, ...args);
19
+ }
20
+ },
21
+
22
+ warn(...args: unknown[]): void {
23
+ console.warn(TAG, ...args);
24
+ },
25
+
26
+ error(...args: unknown[]): void {
27
+ console.error(TAG, ...args);
28
+ },
29
+ };
@@ -0,0 +1,23 @@
1
+ import NativeSwiftPatch from '../native/NativeSwiftPatch';
2
+ import type { BundleInfo } from '../types';
3
+
4
+ /**
5
+ * Get current bundle info from native storage
6
+ */
7
+ export async function getCurrentBundleInfo(): Promise<BundleInfo | null> {
8
+ return NativeSwiftPatch.getCurrentBundle();
9
+ }
10
+
11
+ /**
12
+ * Check if an install is pending confirmation
13
+ */
14
+ export async function hasPendingInstall(): Promise<boolean> {
15
+ return NativeSwiftPatch.hasPendingInstall();
16
+ }
17
+
18
+ /**
19
+ * Confirm the current install is stable
20
+ */
21
+ export async function confirmInstall(): Promise<void> {
22
+ return NativeSwiftPatch.confirmInstall();
23
+ }
@@ -0,0 +1,41 @@
1
+ import React, { useState, type ComponentType } from 'react';
2
+ import { SwiftPatchProvider } from './SwiftPatchProvider';
3
+ import { SwiftPatchModal } from './modal/SwiftPatchModal';
4
+ import type { SwiftPatchConfig } from './types';
5
+ import { DEFAULT_CONFIG } from './constants';
6
+
7
+ /**
8
+ * Higher-order component to wrap your root component with SwiftPatchProvider.
9
+ * Also includes the built-in dashboard modal (accessible via useSwiftPatchModal).
10
+ */
11
+ export function withSwiftPatch<P extends object>(
12
+ WrappedComponent: ComponentType<P>,
13
+ config: SwiftPatchConfig
14
+ ) {
15
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
16
+
17
+ function WithSwiftPatch(props: P) {
18
+ const [modalVisible, setModalVisible] = useState(false);
19
+
20
+ return (
21
+ <SwiftPatchProvider config={config}>
22
+ <WrappedComponent {...props} />
23
+ <SwiftPatchModal
24
+ visible={modalVisible}
25
+ onClose={() => setModalVisible(false)}
26
+ serverUrl={mergedConfig.serverUrl!}
27
+ deploymentKey={config.deploymentKey}
28
+ customHeaders={mergedConfig.customHeaders}
29
+ />
30
+ </SwiftPatchProvider>
31
+ );
32
+ }
33
+
34
+ WithSwiftPatch.displayName = `withSwiftPatch(${
35
+ WrappedComponent.displayName || WrappedComponent.name || 'Component'
36
+ })`;
37
+
38
+ return WithSwiftPatch;
39
+ }
40
+
41
+ export default withSwiftPatch;