react-native-bspatch 1.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.
- package/LICENSE +21 -0
- package/README.md +471 -0
- package/android/build.gradle +100 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/vn/reactnativebspatch/BsPatchModule.kt +139 -0
- package/android/src/main/java/vn/reactnativebspatch/BsPatchPackage.kt +16 -0
- package/android/src/main/java/vn/reactnativebspatch/OtaBundleResolver.kt +227 -0
- package/cpp/CMakeLists.txt +43 -0
- package/cpp/bsdiff/bspatch.c +194 -0
- package/cpp/bsdiff/bspatch.h +41 -0
- package/cpp/bsdiff/bspatch_wrapper.c +150 -0
- package/cpp/bsdiff/bspatch_wrapper.h +6 -0
- package/cpp/bspatch_jni.cpp +41 -0
- package/cpp/bzip2/LICENSE +42 -0
- package/cpp/bzip2/blocksort.c +1094 -0
- package/cpp/bzip2/bzlib.c +1572 -0
- package/cpp/bzip2/bzlib.h +282 -0
- package/cpp/bzip2/bzlib_private.h +509 -0
- package/cpp/bzip2/compress.c +672 -0
- package/cpp/bzip2/crctable.c +104 -0
- package/cpp/bzip2/decompress.c +652 -0
- package/cpp/bzip2/huffman.c +205 -0
- package/cpp/bzip2/randtable.c +84 -0
- package/ios/OtaBundleResolver.swift +241 -0
- package/ios/RNBsPatch.h +8 -0
- package/ios/RNBsPatch.mm +198 -0
- package/lib/commonjs/NativeBsPatch.js +9 -0
- package/lib/commonjs/NativeBsPatch.js.map +1 -0
- package/lib/commonjs/crypto-js.d.js +2 -0
- package/lib/commonjs/crypto-js.d.js.map +1 -0
- package/lib/commonjs/index.js +90 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/ota/OtaProvider.js +306 -0
- package/lib/commonjs/ota/OtaProvider.js.map +1 -0
- package/lib/commonjs/ota/otaAssetResolver.js +145 -0
- package/lib/commonjs/ota/otaAssetResolver.js.map +1 -0
- package/lib/commonjs/ota/otaCore.js +736 -0
- package/lib/commonjs/ota/otaCore.js.map +1 -0
- package/lib/commonjs/ota/otaLogger.js +64 -0
- package/lib/commonjs/ota/otaLogger.js.map +1 -0
- package/lib/commonjs/ota/otaMetadata.js +138 -0
- package/lib/commonjs/ota/otaMetadata.js.map +1 -0
- package/lib/commonjs/ota/storage/CustomStorage.js +140 -0
- package/lib/commonjs/ota/storage/CustomStorage.js.map +1 -0
- package/lib/commonjs/ota/storage/GitHubReleaseStorage.js +96 -0
- package/lib/commonjs/ota/storage/GitHubReleaseStorage.js.map +1 -0
- package/lib/commonjs/ota/types.js +39 -0
- package/lib/commonjs/ota/types.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/module/NativeBsPatch.js +5 -0
- package/lib/module/NativeBsPatch.js.map +1 -0
- package/lib/module/crypto-js.d.js +2 -0
- package/lib/module/crypto-js.d.js.map +1 -0
- package/lib/module/index.js +23 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/ota/OtaProvider.js +299 -0
- package/lib/module/ota/OtaProvider.js.map +1 -0
- package/lib/module/ota/otaAssetResolver.js +138 -0
- package/lib/module/ota/otaAssetResolver.js.map +1 -0
- package/lib/module/ota/otaCore.js +725 -0
- package/lib/module/ota/otaCore.js.map +1 -0
- package/lib/module/ota/otaLogger.js +59 -0
- package/lib/module/ota/otaLogger.js.map +1 -0
- package/lib/module/ota/otaMetadata.js +127 -0
- package/lib/module/ota/otaMetadata.js.map +1 -0
- package/lib/module/ota/storage/CustomStorage.js +134 -0
- package/lib/module/ota/storage/CustomStorage.js.map +1 -0
- package/lib/module/ota/storage/GitHubReleaseStorage.js +90 -0
- package/lib/module/ota/storage/GitHubReleaseStorage.js.map +1 -0
- package/lib/module/ota/types.js +38 -0
- package/lib/module/ota/types.js.map +1 -0
- package/lib/typescript/NativeBsPatch.d.ts +39 -0
- package/lib/typescript/NativeBsPatch.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +15 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/ota/OtaProvider.d.ts +10 -0
- package/lib/typescript/ota/OtaProvider.d.ts.map +1 -0
- package/lib/typescript/ota/otaAssetResolver.d.ts +15 -0
- package/lib/typescript/ota/otaAssetResolver.d.ts.map +1 -0
- package/lib/typescript/ota/otaCore.d.ts +109 -0
- package/lib/typescript/ota/otaCore.d.ts.map +1 -0
- package/lib/typescript/ota/otaLogger.d.ts +44 -0
- package/lib/typescript/ota/otaLogger.d.ts.map +1 -0
- package/lib/typescript/ota/otaMetadata.d.ts +46 -0
- package/lib/typescript/ota/otaMetadata.d.ts.map +1 -0
- package/lib/typescript/ota/storage/CustomStorage.d.ts +12 -0
- package/lib/typescript/ota/storage/CustomStorage.d.ts.map +1 -0
- package/lib/typescript/ota/storage/GitHubReleaseStorage.d.ts +20 -0
- package/lib/typescript/ota/storage/GitHubReleaseStorage.d.ts.map +1 -0
- package/lib/typescript/ota/types.d.ts +191 -0
- package/lib/typescript/ota/types.d.ts.map +1 -0
- package/package.json +89 -0
- package/react-native-bspatch.podspec +46 -0
- package/src/NativeBsPatch.ts +52 -0
- package/src/crypto-js.d.ts +1 -0
- package/src/index.ts +29 -0
- package/src/ota/OtaProvider.tsx +399 -0
- package/src/ota/otaAssetResolver.ts +182 -0
- package/src/ota/otaCore.ts +963 -0
- package/src/ota/otaLogger.ts +72 -0
- package/src/ota/otaMetadata.ts +149 -0
- package/src/ota/storage/CustomStorage.ts +143 -0
- package/src/ota/storage/GitHubReleaseStorage.ts +98 -0
- package/src/ota/types.ts +211 -0
- package/tools/bsdiff +0 -0
- package/tools/bsdiff.c +445 -0
- package/tools/bsdiff.h +45 -0
- package/tools/build_ota.sh +457 -0
- package/tools/setup_project.js +273 -0
- package/tools/update_registry.js +145 -0
- package/tools/upload_ota_custom.sh +138 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otaAssetResolver.d.ts","sourceRoot":"","sources":["../../../src/ota/otaAssetResolver.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAqCxE,CAAC;AA4FF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAO,IAKxC,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core OTA Logic (Stateless)
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Download patches with retry
|
|
6
|
+
* - Verify integrity (SHA-256 hash)
|
|
7
|
+
* - Verify security (HMAC signature)
|
|
8
|
+
* - Handle gzip decompression
|
|
9
|
+
* - Apply binary patch (bsdiff)
|
|
10
|
+
* - Atomic bundle swap
|
|
11
|
+
* - Full bundle fallback on failure
|
|
12
|
+
* - Structured telemetry logging
|
|
13
|
+
*/
|
|
14
|
+
import { OtaStatus, type OtaConfig, type OtaMetrics, type OtaPatch } from './types';
|
|
15
|
+
/**
|
|
16
|
+
* Compares two semantic version strings.
|
|
17
|
+
*
|
|
18
|
+
* @param a - First version string (e.g., "1.2.3")
|
|
19
|
+
* @param b - Second version string (e.g., "1.2.4")
|
|
20
|
+
* @returns `true` if `a >= b`, `false` otherwise
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* semverGte("1.2.3", "1.2.3") // true
|
|
24
|
+
* semverGte("1.2.4", "1.2.3") // true
|
|
25
|
+
* semverGte("1.2.2", "1.2.3") // false
|
|
26
|
+
*/
|
|
27
|
+
export declare const semverGte: (a: string, b: string) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Verifies the SHA-256 hash of a file.
|
|
30
|
+
*
|
|
31
|
+
* @param path - Absolute path to the file to verify
|
|
32
|
+
* @param expectedHash - Expected SHA-256 hash (hex string). If undefined, verification is skipped.
|
|
33
|
+
* @returns `true` if hash matches or `expectedHash` is undefined, `false` otherwise
|
|
34
|
+
*/
|
|
35
|
+
export declare const verifyHash: (path: string, expectedHash?: string) => Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Verify HMAC-SHA256 signature of a file.
|
|
38
|
+
*
|
|
39
|
+
* Uses CryptoJS to verify that the signature matches the file content
|
|
40
|
+
* using the provided HMAC key.
|
|
41
|
+
*
|
|
42
|
+
* @param filePath - Path to the file to verify
|
|
43
|
+
* @param signature - Base64-encoded HMAC signature to verify against
|
|
44
|
+
* @param publicKey - Base64-encoded HMAC key
|
|
45
|
+
* @returns true if signature is valid, false otherwise
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Server-side (Node.js) - generate signature:
|
|
49
|
+
* const crypto = require('crypto');
|
|
50
|
+
* const key = crypto.randomBytes(32).toString('base64');
|
|
51
|
+
* const fileBuffer = fs.readFileSync('bundle.patch');
|
|
52
|
+
* const signature = crypto.createHmac('sha256', Buffer.from(key, 'base64'))
|
|
53
|
+
* .update(fileBuffer)
|
|
54
|
+
* .digest('base64');
|
|
55
|
+
*/
|
|
56
|
+
export declare const verifySignature: (filePath: string, signature?: string, publicKey?: string) => Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Fetches the list of available OTA patches from the remote manifest.
|
|
59
|
+
*
|
|
60
|
+
* Falls back to bundled patches if the remote fetch fails, ensuring
|
|
61
|
+
* the app can still apply updates that were bundled at build time.
|
|
62
|
+
*
|
|
63
|
+
* @param config - OTA configuration containing storage provider and fallback patches
|
|
64
|
+
* @returns Array of available patches, or bundled patches if remote fetch fails
|
|
65
|
+
*/
|
|
66
|
+
export declare const fetchOtaManifest: (config: OtaConfig) => Promise<OtaPatch[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Gets the local filesystem path for a content-addressed asset.
|
|
69
|
+
*
|
|
70
|
+
* Assets are stored by their hash, so the same asset file is shared
|
|
71
|
+
* across all OTA versions that reference it.
|
|
72
|
+
*
|
|
73
|
+
* @param hash - SHA-256 hash of the asset content
|
|
74
|
+
* @param ext - File extension (e.g., "png", "jpg")
|
|
75
|
+
* @returns Absolute path to the asset in the local store
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* getLocalAssetPath("abc123...", "png")
|
|
79
|
+
* // Returns: "/var/mobile/Containers/Data/Application/.../ota/assets/abc123....png"
|
|
80
|
+
*/
|
|
81
|
+
export declare const getLocalAssetPath: (hash: string, ext: string) => string;
|
|
82
|
+
/**
|
|
83
|
+
* Gets the local filesystem path for a downloaded patch file.
|
|
84
|
+
*
|
|
85
|
+
* @param patch - Patch metadata object
|
|
86
|
+
* @param docDir - Document directory path (use `ReactNativeBlobUtil.fs.dirs.DocumentDir`)
|
|
87
|
+
* @returns Absolute path to the patch file
|
|
88
|
+
*/
|
|
89
|
+
export declare const getLocalPatchPath: (patch: OtaPatch, docDir: string) => string;
|
|
90
|
+
/**
|
|
91
|
+
* Applies a single patch and reloads the bundle.
|
|
92
|
+
*
|
|
93
|
+
* Pipeline:
|
|
94
|
+
* 1. Version compatibility check
|
|
95
|
+
* 2. Download patch (with retry)
|
|
96
|
+
* 3. Decompress (if .gz)
|
|
97
|
+
* 4. Security signature check
|
|
98
|
+
* 5. Resolve source bundle
|
|
99
|
+
* 6. Verify source hash
|
|
100
|
+
* 7. Apply binary patch
|
|
101
|
+
* 8. Verify result hash
|
|
102
|
+
* 9. Atomic commit (mv)
|
|
103
|
+
* 10. Update metadata
|
|
104
|
+
* 11. Reload bundle
|
|
105
|
+
*
|
|
106
|
+
* On failure → fallback to full bundle download if URL available.
|
|
107
|
+
*/
|
|
108
|
+
export declare const applyOtaPatchInternal: (patch: OtaPatch, config: OtaConfig, onStatus: (status: OtaStatus, message: string, metrics?: OtaMetrics) => void, onProgress: (percent: number) => void) => Promise<void>;
|
|
109
|
+
//# sourceMappingURL=otaCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otaCore.d.ts","sourceRoot":"","sources":["../../../src/ota/otaCore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgBH,OAAO,EACH,SAAS,EAGT,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,QAAQ,EAEhB,MAAM,SAAS,CAAC;AAqBjB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAUhD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GACnB,MAAM,MAAM,EACZ,eAAe,MAAM,KACtB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,eAAe,GACxB,UAAU,MAAM,EAChB,YAAY,MAAM,EAClB,YAAY,MAAM,KACnB,OAAO,CAAC,OAAO,CA4BjB,CAAC;AA0FF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GACzB,QAAQ,SAAS,KAClB,OAAO,CAAC,QAAQ,EAAE,CAWpB,CAAC;AAyLF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,KAAG,MACvB,CAAC;AAExC;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,EAAE,QAAQ,MAAM,KAAG,MACzB,CAAC;AAI5C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,qBAAqB,GAC9B,OAAO,QAAQ,EACf,QAAQ,SAAS,EACjB,UAAU,CACN,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,KACnB,IAAI,EACT,YAAY,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,kBAycxC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTA Structured Event Logger
|
|
3
|
+
*
|
|
4
|
+
* Provides a centralized logging system for all OTA operations.
|
|
5
|
+
* Events can be forwarded to external analytics via the `onEvent` callback in OtaConfig.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum OtaEvent {
|
|
8
|
+
CHECK_UPDATE = "check_update",
|
|
9
|
+
DOWNLOAD_START = "download_start",
|
|
10
|
+
DOWNLOAD_SUCCESS = "download_success",
|
|
11
|
+
DOWNLOAD_FAIL = "download_fail",
|
|
12
|
+
PATCH_START = "patch_start",
|
|
13
|
+
PATCH_SUCCESS = "patch_success",
|
|
14
|
+
PATCH_FAIL = "patch_fail",
|
|
15
|
+
HASH_VERIFY_START = "hash_verify_start",
|
|
16
|
+
HASH_VERIFY_SUCCESS = "hash_verify_success",
|
|
17
|
+
HASH_MISMATCH = "hash_mismatch",
|
|
18
|
+
ROLLBACK = "rollback",
|
|
19
|
+
FALLBACK_FULL_BUNDLE = "fallback_full_bundle",
|
|
20
|
+
MARK_HEALTHY = "mark_healthy",
|
|
21
|
+
RESET_FACTORY = "reset_factory",
|
|
22
|
+
VERSION_INCOMPATIBLE = "version_incompatible",
|
|
23
|
+
SIGNATURE_INVALID = "signature_invalid",
|
|
24
|
+
DECOMPRESS_START = "decompress_start",
|
|
25
|
+
DECOMPRESS_SUCCESS = "decompress_success"
|
|
26
|
+
}
|
|
27
|
+
export type OtaLogEntry = {
|
|
28
|
+
event: OtaEvent;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
version?: number;
|
|
31
|
+
message?: string;
|
|
32
|
+
durationMs?: number;
|
|
33
|
+
sizeKB?: number;
|
|
34
|
+
error?: string;
|
|
35
|
+
metadata?: Record<string, unknown>;
|
|
36
|
+
};
|
|
37
|
+
export type OtaEventCallback = (entry: OtaLogEntry) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Creates an OTA logger instance bound to an optional external callback.
|
|
40
|
+
*/
|
|
41
|
+
export declare const createOtaLogger: (onEvent?: OtaEventCallback) => {
|
|
42
|
+
emit: (event: OtaEvent, details?: Omit<OtaLogEntry, "event" | "timestamp">) => void;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=otaLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otaLogger.d.ts","sourceRoot":"","sources":["../../../src/ota/otaLogger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,oBAAY,QAAQ;IAClB,YAAY,iBAAiB;IAC7B,cAAc,mBAAmB;IACjC,gBAAgB,qBAAqB;IACrC,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,UAAU,eAAe;IACzB,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IACrB,oBAAoB,yBAAyB;IAC7C,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,oBAAoB,yBAAyB;IAC7C,iBAAiB,sBAAsB;IACvC,gBAAgB,qBAAqB;IACrC,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,gBAAgB;kBAE/C,QAAQ,YACL,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,CAAC;CAsBrD,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { OtaMetadata } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Ensures the OTA root directory exists.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ensureOtaDir: () => Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Loads the current OTA metadata from the local filesystem.
|
|
8
|
+
*
|
|
9
|
+
* @param defaultVersion - The version to return if no metadata exists (usually baseAppVersion).
|
|
10
|
+
* @returns The persisted metadata or a default if loading fails.
|
|
11
|
+
*/
|
|
12
|
+
export declare const loadMetadata: (defaultVersion: number) => Promise<OtaMetadata>;
|
|
13
|
+
/**
|
|
14
|
+
* Persists OTA metadata to the local filesystem.
|
|
15
|
+
*
|
|
16
|
+
* @param metadata - The metadata object to save.
|
|
17
|
+
*/
|
|
18
|
+
export declare const saveMetadata: (metadata: OtaMetadata) => Promise<void>;
|
|
19
|
+
/** Maximum number of previous versions kept in history for rollback. */
|
|
20
|
+
export declare const MAX_VERSION_HISTORY = 3;
|
|
21
|
+
/**
|
|
22
|
+
* Rotates OTA versions for auditing and rollback capabilities.
|
|
23
|
+
* Pushes the current version to the history and limits history to MAX_VERSION_HISTORY.
|
|
24
|
+
*
|
|
25
|
+
* @param metadata - Current metadata object.
|
|
26
|
+
* @param newVersion - The newly applied OTA version.
|
|
27
|
+
* @returns Updated metadata object.
|
|
28
|
+
*/
|
|
29
|
+
export declare const registerNewVersion: (metadata: OtaMetadata, newVersion: number) => OtaMetadata;
|
|
30
|
+
/**
|
|
31
|
+
* Marks the current session as healthy, indicating a successful boot.
|
|
32
|
+
* This prevents the native bridge from rolling back the version on the next launch.
|
|
33
|
+
*
|
|
34
|
+
* @param defaultVersion - Base version for metadata lookup fallback.
|
|
35
|
+
* @returns The updated metadata.
|
|
36
|
+
*/
|
|
37
|
+
export declare const markHealthy: (defaultVersion: number) => Promise<OtaMetadata>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves the absolute path to the JS bundle for a specific version.
|
|
40
|
+
*
|
|
41
|
+
* @param version - The OTA version number.
|
|
42
|
+
* @param baseVersion - The app's base version (bundled).
|
|
43
|
+
* @returns Absolute path to the bundle or null if it refers to the base bundle.
|
|
44
|
+
*/
|
|
45
|
+
export declare const getBundlePath: (version: number, baseVersion: number) => string | null;
|
|
46
|
+
//# sourceMappingURL=otaMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otaMetadata.d.ts","sourceRoot":"","sources":["../../../src/ota/otaMetadata.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQtC;;GAEG;AACH,eAAO,MAAM,YAAY,QAAa,OAAO,CAAC,IAAI,CAIjD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACrB,gBAAgB,MAAM,KACvB,OAAO,CAAC,WAAW,CAmBrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,UAAU,WAAW,KAAG,OAAO,CAAC,IAAI,CAoBtE,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC3B,UAAU,WAAW,EACrB,YAAY,MAAM,KACnB,WAiBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GACpB,gBAAgB,MAAM,KACvB,OAAO,CAAC,WAAW,CASrB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GACtB,SAAS,MAAM,EACf,aAAa,MAAM,KACpB,MAAM,GAAG,IAUX,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OtaPatch, OtaConfig, OtaStorageProvider } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Implementation for the custom MinIO-based storage server.
|
|
4
|
+
*/
|
|
5
|
+
export declare class CustomStorageProvider implements OtaStorageProvider {
|
|
6
|
+
private getEndpoint;
|
|
7
|
+
private getAccessToken;
|
|
8
|
+
fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
|
|
9
|
+
getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
|
|
10
|
+
getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=CustomStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/CustomStorage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAUxE;;GAEG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,OAAO,CAAC,WAAW;YAIL,cAAc;IAqCtB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAuCrD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBtE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;CAsBjF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Releases Storage Provider
|
|
3
|
+
*
|
|
4
|
+
* Reads the OTA registry from a GitHub Release asset and resolves download URLs
|
|
5
|
+
* directly from the release. Supports both public and token-authenticated repos.
|
|
6
|
+
*
|
|
7
|
+
* Registry format:
|
|
8
|
+
* - Expected at: `https://raw.githubusercontent.com/{owner}/{repo}/{tag}/{registryPath}`
|
|
9
|
+
* - Asset download: `https://github.com/{owner}/{repo}/releases/download/{tag}/{filename}`
|
|
10
|
+
*/
|
|
11
|
+
import type { OtaPatch, OtaConfig, OtaStorageProvider } from '../types';
|
|
12
|
+
export declare class GitHubReleaseStorageProvider implements OtaStorageProvider {
|
|
13
|
+
private getRawRegistryUrl;
|
|
14
|
+
private getAssetDownloadUrl;
|
|
15
|
+
private authHeaders;
|
|
16
|
+
fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
|
|
17
|
+
getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
|
|
18
|
+
getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=GitHubReleaseStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubReleaseStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/GitHubReleaseStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAExE,qBAAa,4BAA6B,YAAW,kBAAkB;IACnE,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,WAAW;IAKb,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgDrD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAKtE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;CAanF"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTA Data Types
|
|
3
|
+
*/
|
|
4
|
+
import type { OtaEventCallback } from './otaLogger';
|
|
5
|
+
export interface OtaStorageProvider {
|
|
6
|
+
/**
|
|
7
|
+
* Fetch the list of available patches for the current configuration.
|
|
8
|
+
*/
|
|
9
|
+
fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Get a signed download URL for a version-specific update file (patch or full bundle).
|
|
12
|
+
*/
|
|
13
|
+
getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Get a signed download URL for a content-addressed asset.
|
|
16
|
+
*/
|
|
17
|
+
getAssetUrl(hash: string, ext: string, config: OtaConfig): Promise<string>;
|
|
18
|
+
}
|
|
19
|
+
export declare enum OtaUpdateMode {
|
|
20
|
+
MANUAL = "MANUAL",
|
|
21
|
+
ON_APP_START = "ON_APP_START",
|
|
22
|
+
ON_APP_FOREGROUND = "ON_APP_FOREGROUND",
|
|
23
|
+
BACKGROUND_DOWNLOAD = "BACKGROUND_DOWNLOAD"
|
|
24
|
+
}
|
|
25
|
+
export declare enum OtaStorageType {
|
|
26
|
+
/** Custom storage server (primary) */
|
|
27
|
+
CUSTOM = "CUSTOM",
|
|
28
|
+
/** GitHub Releases — public or token-authenticated */
|
|
29
|
+
GITHUB = "GITHUB"
|
|
30
|
+
}
|
|
31
|
+
export type OtaPatch = {
|
|
32
|
+
/** Unique ID: `v{from}-to-v{to}` */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Human-readable label shown in UI */
|
|
35
|
+
label: string;
|
|
36
|
+
/** App version this patch belongs to */
|
|
37
|
+
appVersion: string;
|
|
38
|
+
/** Release tag (legacy, keep for type compatibility) */
|
|
39
|
+
releaseTag?: string;
|
|
40
|
+
/** Filename on the server (e.g. "v1-to-v3.patch") */
|
|
41
|
+
filename: string;
|
|
42
|
+
/** Version the app must be at to apply this patch */
|
|
43
|
+
fromVersion: number;
|
|
44
|
+
/** Version this patch upgrades to */
|
|
45
|
+
toVersion: number;
|
|
46
|
+
/** Integrity hashes (optional for legacy support) */
|
|
47
|
+
baseHash?: string;
|
|
48
|
+
/** Hash of the bundle after patching */
|
|
49
|
+
bundleHash?: string;
|
|
50
|
+
/** Minimum native app version required (semver) */
|
|
51
|
+
minAppVersion?: string;
|
|
52
|
+
/** URL for full bundle download (fallback when patch fails) */
|
|
53
|
+
fullBundleUrl?: string;
|
|
54
|
+
/** Whether the patch/bundle is gzip compressed */
|
|
55
|
+
compressed?: boolean;
|
|
56
|
+
/** HMAC-SHA256 signature for security verification */
|
|
57
|
+
signature?: string;
|
|
58
|
+
/** Whether this update is mandatory */
|
|
59
|
+
mandatory?: boolean;
|
|
60
|
+
/** URL to the asset manifest JSON for this version */
|
|
61
|
+
assetManifestUrl?: string;
|
|
62
|
+
/** Target platform for this patch */
|
|
63
|
+
platform?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* A single content-addressed asset from the OTA asset store.
|
|
67
|
+
*/
|
|
68
|
+
export type OtaAsset = {
|
|
69
|
+
/** SHA-256 hash of the file (used as filename: `{hash}.{ext}`) */
|
|
70
|
+
hash: string;
|
|
71
|
+
/** File extension without dot (e.g. "jpg", "png") */
|
|
72
|
+
ext: string;
|
|
73
|
+
/** Original relative path as Metro knows it (e.g. "drawable-mdpi/assets_images_foo.jpg") */
|
|
74
|
+
originalPath: string;
|
|
75
|
+
};
|
|
76
|
+
export type OtaRemotePatch = {
|
|
77
|
+
version: number;
|
|
78
|
+
minAppVersion: string;
|
|
79
|
+
patchUrl: string;
|
|
80
|
+
bundleHash: string;
|
|
81
|
+
baseHash: string;
|
|
82
|
+
mandatory: boolean;
|
|
83
|
+
};
|
|
84
|
+
export type OtaMetadata = {
|
|
85
|
+
currentVersion: number;
|
|
86
|
+
previousVersions: number[];
|
|
87
|
+
rollbackCount: number;
|
|
88
|
+
lastLaunchSuccessful: boolean;
|
|
89
|
+
};
|
|
90
|
+
export type OtaMetrics = {
|
|
91
|
+
patchSizeKB: number;
|
|
92
|
+
downloadMs: number;
|
|
93
|
+
applyMs: number;
|
|
94
|
+
totalMs: number;
|
|
95
|
+
fromCache: boolean;
|
|
96
|
+
};
|
|
97
|
+
export type OtaNetworkStrategy = {
|
|
98
|
+
retry?: number;
|
|
99
|
+
timeoutMs?: number;
|
|
100
|
+
wifiOnly?: boolean;
|
|
101
|
+
};
|
|
102
|
+
export type OtaConfig = {
|
|
103
|
+
/** Current app versionName (e.g. "1.0.0") */
|
|
104
|
+
appVersion: string;
|
|
105
|
+
/** Initial version baked into the APK (usually 1) */
|
|
106
|
+
baseAppVersion: number;
|
|
107
|
+
/** Default patches if manifest fetch fails */
|
|
108
|
+
bundledPatches?: OtaPatch[];
|
|
109
|
+
/** Enterprise configurations */
|
|
110
|
+
updateMode?: OtaUpdateMode;
|
|
111
|
+
maxRollback?: number;
|
|
112
|
+
network?: OtaNetworkStrategy;
|
|
113
|
+
/** Telemetry: structured event callback for analytics */
|
|
114
|
+
onEvent?: OtaEventCallback;
|
|
115
|
+
/** Public key for signature verification (base64) */
|
|
116
|
+
publicKey?: string;
|
|
117
|
+
/** Base URL for the shared hashed asset store (e.g. a GitHub release URL) */
|
|
118
|
+
assetBaseUrl?: string;
|
|
119
|
+
/** Storage strategy */
|
|
120
|
+
storageType?: OtaStorageType;
|
|
121
|
+
/** GitHub Releases configuration (used when storageType === GITHUB) */
|
|
122
|
+
githubRelease?: {
|
|
123
|
+
/** Owner / repo in the format "owner/repo" */
|
|
124
|
+
repo: string;
|
|
125
|
+
/** Tag name of the release to fetch updates from */
|
|
126
|
+
tag: string;
|
|
127
|
+
/**
|
|
128
|
+
* Path inside the release where ota_registry.json lives.
|
|
129
|
+
* If your release contains the file at root, set to "ota_registry.json".
|
|
130
|
+
* If it's inside a folder "ota/", set to "ota/ota_registry.json".
|
|
131
|
+
*/
|
|
132
|
+
registryPath?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Optional GitHub personal access token for private repos or higher rate limits.
|
|
135
|
+
* For public repos this is optional.
|
|
136
|
+
*/
|
|
137
|
+
token?: string;
|
|
138
|
+
/**
|
|
139
|
+
* Asset base URL for content-addressed assets.
|
|
140
|
+
* Supports CDN URLs (jsDelivr, GitHub raw) or a custom base.
|
|
141
|
+
* Example: "https://cdn.jsdelivr.net/gh/owner/repo@tag/assets"
|
|
142
|
+
*/
|
|
143
|
+
assetBaseUrl?: string;
|
|
144
|
+
};
|
|
145
|
+
/** Custom storage server configuration */
|
|
146
|
+
customServer?: {
|
|
147
|
+
baseUrl: string;
|
|
148
|
+
username: string;
|
|
149
|
+
password: string;
|
|
150
|
+
channel: string;
|
|
151
|
+
baseFolder?: string;
|
|
152
|
+
useMinio?: boolean;
|
|
153
|
+
/** Override default API endpoints for non-standard servers */
|
|
154
|
+
endpoints?: {
|
|
155
|
+
/** Auth login endpoint (default: /public/authen/login) */
|
|
156
|
+
login?: string;
|
|
157
|
+
/** Generate download link endpoint (default: /api/minio/gen-download-link) */
|
|
158
|
+
genDownloadLink?: string;
|
|
159
|
+
/** Direct file download endpoint (default: /files/downloadStreamFile) */
|
|
160
|
+
downloadFile?: string;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
/** Storage provider instance (optional, defaults to CustomStorageProvider) */
|
|
164
|
+
storage?: OtaStorageProvider;
|
|
165
|
+
};
|
|
166
|
+
export declare enum OtaStatus {
|
|
167
|
+
IDLE = "IDLE",
|
|
168
|
+
CHECKING = "CHECKING",
|
|
169
|
+
UPDATE_AVAILABLE = "UPDATE_AVAILABLE",
|
|
170
|
+
UP_TO_DATE = "UP_TO_DATE",
|
|
171
|
+
DOWNLOADING = "DOWNLOADING",
|
|
172
|
+
APPLYING = "APPLYING",
|
|
173
|
+
SYNCING_ASSETS = "SYNCING_ASSETS",
|
|
174
|
+
SUCCESS = "SUCCESS",
|
|
175
|
+
ERROR = "ERROR"
|
|
176
|
+
}
|
|
177
|
+
export type OtaState = {
|
|
178
|
+
status: OtaStatus;
|
|
179
|
+
message: string;
|
|
180
|
+
progress: number;
|
|
181
|
+
currentVersion: number;
|
|
182
|
+
latestVersion: number;
|
|
183
|
+
pendingCount: number;
|
|
184
|
+
isChecking: boolean;
|
|
185
|
+
metrics: OtaMetrics | null;
|
|
186
|
+
applyUpdate: () => Promise<void>;
|
|
187
|
+
resetToFactory: () => Promise<void>;
|
|
188
|
+
markAsHealthy: () => Promise<void>;
|
|
189
|
+
checkUpdate: () => Promise<void>;
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/ota/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEtD;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvE;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9E;AAED,oBAAY,aAAa;IACrB,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;CAC9C;AAED,oBAAY,cAAc;IACtB,sCAAsC;IACtC,MAAM,WAAW;IACjB,sDAAsD;IACtD,MAAM,WAAW;CACpB;AAED,MAAM,MAAM,QAAQ,GAAG;IACnB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACnB,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACpB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAE5B,gCAAgC;IAChC,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAE7B,yDAAyD;IACzD,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,uBAAuB;IACvB,WAAW,CAAC,EAAE,cAAc,CAAC;IAE7B,uEAAuE;IACvE,aAAa,CAAC,EAAE;QACZ,8CAA8C;QAC9C,IAAI,EAAE,MAAM,CAAC;QACb,oDAAoD;QACpD,GAAG,EAAE,MAAM,CAAC;QACZ;;;;WAIG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf;;;;WAIG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IAEF,0CAA0C;IAC1C,YAAY,CAAC,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,8DAA8D;QAC9D,SAAS,CAAC,EAAE;YACR,0DAA0D;YAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,8EAA8E;YAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,yEAAyE;YACzE,YAAY,CAAC,EAAE,MAAM,CAAC;SACzB,CAAC;KACL,CAAC;IAEF,8EAA8E;IAC9E,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,oBAAY,SAAS;IACjB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,gBAAgB,qBAAqB;IACrC,UAAU,eAAe;IACzB,WAAW,gBAAgB;IAC3B,QAAQ,aAAa;IACrB,cAAc,mBAAmB;IACjC,OAAO,YAAY;IACnB,KAAK,UAAU;CAClB;AAED,MAAM,MAAM,QAAQ,GAAG;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-bspatch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Premium OTA Update Solution for React Native using TurboModules and bsdiff",
|
|
5
|
+
"main": "lib/commonjs/index.js",
|
|
6
|
+
"module": "lib/module/index.js",
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
|
+
"react-native": "src/index.ts",
|
|
9
|
+
"source": "src/index.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"android",
|
|
12
|
+
"ios",
|
|
13
|
+
"cpp",
|
|
14
|
+
"src",
|
|
15
|
+
"lib",
|
|
16
|
+
"tools",
|
|
17
|
+
"react-native-bspatch.podspec",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"!**/__tests__",
|
|
21
|
+
"!**/__fixtures__",
|
|
22
|
+
"!**/__mocks__"
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"react-native",
|
|
26
|
+
"ota",
|
|
27
|
+
"update",
|
|
28
|
+
"bspatch",
|
|
29
|
+
"bsdiff",
|
|
30
|
+
"turbo-module",
|
|
31
|
+
"android",
|
|
32
|
+
"ios"
|
|
33
|
+
],
|
|
34
|
+
|
|
35
|
+
"codegenConfig": {
|
|
36
|
+
"name": "RNBsPatchSpec",
|
|
37
|
+
"type": "modules",
|
|
38
|
+
"jsSrcsDir": "src"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "*",
|
|
42
|
+
"react-native": "*",
|
|
43
|
+
"react-native-blob-util": "*"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"crypto-js": "^4.2.0"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/BuiHung1612/react-native-bspatch.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "Hung Bui <https://github.com/BuiHung1612>",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/BuiHung1612/react-native-bspatch/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/BuiHung1612/react-native-bspatch#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"bin": {
|
|
62
|
+
"react-native-bspatch": "./tools/build_ota.sh"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"setup": "node ./tools/setup_project.js",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"prepare": "bob build"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/crypto-js": "^4.2.2",
|
|
71
|
+
"@types/react": "^19.2.0",
|
|
72
|
+
"react-native-builder-bob": "^0.43.0",
|
|
73
|
+
"typescript": "^5.0.0"
|
|
74
|
+
},
|
|
75
|
+
"react-native-builder-bob": {
|
|
76
|
+
"source": "src",
|
|
77
|
+
"output": "lib",
|
|
78
|
+
"targets": [
|
|
79
|
+
"commonjs",
|
|
80
|
+
"module",
|
|
81
|
+
[
|
|
82
|
+
"typescript",
|
|
83
|
+
{
|
|
84
|
+
"project": "tsconfig.build.json"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
+
|
|
6
|
+
Pod::Spec.new do |s|
|
|
7
|
+
s.name = "react-native-bspatch"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = package["homepage"]
|
|
11
|
+
s.license = "MIT"
|
|
12
|
+
s.authors = package["author"]
|
|
13
|
+
|
|
14
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
15
|
+
s.source = { :git => "https://github.com/BuiHung1612/react-native-bspatch.git", :tag => "#{s.version}" }
|
|
16
|
+
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}", "cpp/**/*.{h,c,cpp}"
|
|
18
|
+
s.exclude_files = "cpp/bspatch_jni.cpp"
|
|
19
|
+
s.public_header_files = 'ios/**/*.h'
|
|
20
|
+
|
|
21
|
+
s.library = 'bz2'
|
|
22
|
+
|
|
23
|
+
s.dependency "SSZipArchive"
|
|
24
|
+
|
|
25
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
26
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
27
|
+
install_modules_dependencies(s)
|
|
28
|
+
else
|
|
29
|
+
s.dependency "React-Core"
|
|
30
|
+
|
|
31
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
32
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
33
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
34
|
+
s.pod_target_xcconfig = {
|
|
35
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
36
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
37
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
38
|
+
}
|
|
39
|
+
s.dependency "React-Codegen"
|
|
40
|
+
s.dependency "RCT-Folly"
|
|
41
|
+
s.dependency "RCTRequired"
|
|
42
|
+
s.dependency "RCTTypeSafety"
|
|
43
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface Spec extends TurboModule {
|
|
5
|
+
/**
|
|
6
|
+
* Apply a bspatch file to an old bundle to generate a new bundle
|
|
7
|
+
* @param oldPath The absolute path to the existing bundle file
|
|
8
|
+
* @param newPath The absolute path where the new bundle should be saved
|
|
9
|
+
* @param patchPath The absolute path to the patch file
|
|
10
|
+
* @param callback Promise-like callback receiving true if successful, or false on error.
|
|
11
|
+
*/
|
|
12
|
+
applyPatch(
|
|
13
|
+
oldPath: string,
|
|
14
|
+
newPath: string,
|
|
15
|
+
patchPath: string,
|
|
16
|
+
): Promise<boolean>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Unzip a file to a target directory
|
|
20
|
+
* @param source The absolute path to the zip file
|
|
21
|
+
* @param targetDir The absolute path to the destination directory
|
|
22
|
+
*/
|
|
23
|
+
unzip(source: string, targetDir: string): Promise<boolean>;
|
|
24
|
+
extractBundleFromAssets(
|
|
25
|
+
assetName: string,
|
|
26
|
+
destPath: string,
|
|
27
|
+
): Promise<boolean>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Decompress a gzip file to the destination path.
|
|
31
|
+
* @param sourcePath Absolute path to the .gz file
|
|
32
|
+
* @param destPath Absolute path to write the decompressed output
|
|
33
|
+
*/
|
|
34
|
+
decompressGzip(sourcePath: string, destPath: string): Promise<boolean>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Mark the current boot as healthy to prevent rollback
|
|
38
|
+
*/
|
|
39
|
+
markAsHealthy(): void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Reload the React Native JS bundle
|
|
43
|
+
*/
|
|
44
|
+
reloadBundle(): void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Log a message to the native console (NSLog on iOS)
|
|
48
|
+
*/
|
|
49
|
+
logNative(message: string): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('BsPatch');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'crypto-js';
|