react-native-nitro-version-check 1.0.1 â 1.1.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/README.md +22 -82
- package/android/src/main/java/com/margelo/nitro/nitroversioncheck/HybridVersionCheck.kt +4 -2
- package/ios/HybridVersionCheck.swift +10 -6
- package/lib/index.d.ts +58 -59
- package/lib/index.js +60 -61
- package/lib/specs/Version.nitro.d.ts +2 -2
- package/nitrogen/generated/android/c++/JHybridVersionCheckSpec.cpp +6 -6
- package/nitrogen/generated/android/c++/JHybridVersionCheckSpec.hpp +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroversioncheck/HybridVersionCheckSpec.kt +2 -2
- package/nitrogen/generated/ios/c++/HybridVersionCheckSpecSwift.hpp +4 -4
- package/nitrogen/generated/ios/swift/HybridVersionCheckSpec.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridVersionCheckSpec_cxx.swift +18 -4
- package/nitrogen/generated/shared/c++/HybridVersionCheckSpec.hpp +2 -2
- package/package.json +12 -6
- package/src/index.ts +0 -185
- package/src/semver.ts +0 -54
- package/src/specs/Version.nitro.ts +0 -16
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
</h1>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<b>A
|
|
6
|
+
<b>A lightweight, fast version-checking library for React Native, powered by <a href="https://github.com/mrousavy/nitro">Nitro Modules</a>.</b>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
@@ -12,105 +12,45 @@
|
|
|
12
12
|
|
|
13
13
|
<br />
|
|
14
14
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
- ⥠**Synchronous access** to version, build number, package name, and country
|
|
18
|
-
- ðŠ **Store version lookup** from the App Store or Play Store
|
|
19
|
-
- ð **Granular update checks** â major, minor, or patch
|
|
20
|
-
- ðĶ **Install source detection** â TestFlight, App Store, Play Store, or sideloaded
|
|
21
|
-
- ðŠķ **Tiny footprint** â pure Swift on iOS, Kotlin on Android
|
|
22
|
-
|
|
23
|
-
## Performance
|
|
24
|
-
|
|
25
|
-
Benchmarked against [`react-native-version-check`](https://github.com/kimxogus/react-native-version-check). 100,000 iterations averaged over 5 runs on an iPhone 12:
|
|
26
|
-
|
|
27
|
-
| Method | Speedup |
|
|
28
|
-
|--------|---------|
|
|
29
|
-
| `getAllInfo` | **~3.1x faster** |
|
|
30
|
-
| `packageName` | **~1.6x faster** |
|
|
31
|
-
| `version` | **~1.6x faster** |
|
|
32
|
-
| `buildNumber` | **~1.6x faster** |
|
|
33
|
-
| `getCountry` | **~3.1x faster** |
|
|
34
|
-
|
|
35
|
-
## Installation
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
bun add react-native-nitro-version-check react-native-nitro-modules
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
For Expo projects, run prebuild:
|
|
42
|
-
```sh
|
|
43
|
-
npx expo prebuild
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
For bare React Native projects:
|
|
47
|
-
```sh
|
|
48
|
-
cd ios && pod install
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Usage
|
|
15
|
+
## Example
|
|
52
16
|
|
|
53
17
|
```ts
|
|
54
|
-
import { VersionCheck
|
|
18
|
+
import { VersionCheck } from 'react-native-nitro-version-check'
|
|
55
19
|
|
|
56
|
-
// Sync
|
|
20
|
+
// Sync â no bridge, no async
|
|
57
21
|
VersionCheck.version // "1.2.0"
|
|
58
22
|
VersionCheck.buildNumber // "42"
|
|
59
23
|
VersionCheck.packageName // "com.example.app"
|
|
60
24
|
VersionCheck.installSource // "appstore" | "testflight" | "playstore" | undefined
|
|
61
|
-
getCountry() // "US"
|
|
62
|
-
|
|
63
|
-
// Async
|
|
64
|
-
const url = await getStoreUrl() // App Store / Play Store URL
|
|
65
|
-
const latest = await getLatestVersion() // "1.3.0"
|
|
66
25
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
26
|
+
// Or destructure properties
|
|
27
|
+
const { version, buildNumber, packageName, installSource } = VersionCheck
|
|
70
28
|
|
|
71
|
-
//
|
|
72
|
-
if (await needsUpdate(
|
|
73
|
-
|
|
29
|
+
// Check for updates
|
|
30
|
+
if (await VersionCheck.needsUpdate()) {
|
|
31
|
+
Linking.openURL(await VersionCheck.getStoreUrl())
|
|
74
32
|
}
|
|
75
33
|
```
|
|
76
34
|
|
|
77
|
-
##
|
|
78
|
-
|
|
79
|
-
### `VersionCheck`
|
|
80
|
-
|
|
81
|
-
| Property | Type | Description |
|
|
82
|
-
|----------|------|-------------|
|
|
83
|
-
| `version` | `string` | App version |
|
|
84
|
-
| `buildNumber` | `string` | Build number |
|
|
85
|
-
| `packageName` | `string` | Bundle ID / Application ID |
|
|
86
|
-
| `installSource` | `string \| undefined` | `"appstore"` `"testflight"` `"playstore"` or `undefined` |
|
|
87
|
-
| `getCountry()` | `string` | Device's 2-letter ISO country code |
|
|
88
|
-
| `getStoreUrl()` | `Promise<string>` | App Store / Play Store URL |
|
|
89
|
-
| `getLatestVersion()` | `Promise<string>` | Latest version in the store |
|
|
90
|
-
| `needsUpdate()` | `Promise<boolean>` | Whether an update is available |
|
|
91
|
-
|
|
92
|
-
### Standalone exports
|
|
35
|
+
## Installation
|
|
93
36
|
|
|
94
|
-
|
|
37
|
+
```sh
|
|
38
|
+
bun add react-native-nitro-version-check
|
|
39
|
+
```
|
|
95
40
|
|
|
96
|
-
|
|
97
|
-
|--------|---------|-------------|
|
|
98
|
-
| `getCountry()` | `string` | Device's 2-letter ISO country code |
|
|
99
|
-
| `getStoreUrl()` | `Promise<string>` | App Store / Play Store URL |
|
|
100
|
-
| `getLatestVersion()` | `Promise<string>` | Latest version in the store |
|
|
101
|
-
| `needsUpdate(options?)` | `Promise<boolean>` | Whether an update is available |
|
|
41
|
+
> Check the [full installation guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/installation) for platform setup and additional dependencies.
|
|
102
42
|
|
|
103
|
-
|
|
43
|
+
## Documentation
|
|
104
44
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
45
|
+
- [**Nitro Version Check** docs ð](https://alshehriali0.github.io/react-native-nitro-version-check/)
|
|
46
|
+
- [**Getting Started** guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/getting-started)
|
|
47
|
+
- [**Installation** guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/installation)
|
|
48
|
+
- [**API Reference**](https://alshehriali0.github.io/react-native-nitro-version-check/docs/api-reference)
|
|
49
|
+
- [**Migration Guide** from react-native-version-check](https://alshehriali0.github.io/react-native-nitro-version-check/docs/migration-guide)
|
|
108
50
|
|
|
109
|
-
|
|
51
|
+
## Contributing
|
|
110
52
|
|
|
111
|
-
|
|
112
|
-
|----------|---------|-------------|
|
|
113
|
-
| `compareVersions(v1, v2)` | `-1 \| 0 \| 1` | Compare two semver strings |
|
|
53
|
+
See the [contributing guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/contributing) to learn how to contribute to the repository and the development workflow.
|
|
114
54
|
|
|
115
55
|
## License
|
|
116
56
|
|
|
@@ -36,15 +36,17 @@ class HybridVersionCheck : HybridVersionCheckSpec() {
|
|
|
36
36
|
return java.util.Locale.getDefault().country ?: "unknown"
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
override fun getStoreUrl(): Promise<String> {
|
|
39
|
+
override fun getStoreUrl(countryCode: String?): Promise<String> {
|
|
40
40
|
return Promise.async {
|
|
41
|
+
// Country code is not used on Android Play Store, but parameter is kept for API consistency
|
|
41
42
|
"https://play.google.com/store/apps/details?id=$packageName"
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
override fun getLatestVersion(): Promise<String> {
|
|
46
|
+
override fun getLatestVersion(countryCode: String?): Promise<String> {
|
|
46
47
|
return Promise.async {
|
|
47
48
|
try {
|
|
49
|
+
// Country code is not used on Android Play Store, but parameter is kept for API consistency
|
|
48
50
|
val url = URL("https://play.google.com/store/apps/details?id=$packageName&hl=en")
|
|
49
51
|
val connection = url.openConnection() as HttpURLConnection
|
|
50
52
|
connection.connectTimeout = TIMEOUT_MS
|
|
@@ -30,10 +30,12 @@ class HybridVersionCheck: HybridVersionCheckSpec {
|
|
|
30
30
|
return Locale.current.regionCode ?? "unknown"
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
func getStoreUrl() throws -> Promise<String> {
|
|
34
|
-
return Promise.async {
|
|
33
|
+
func getStoreUrl(countryCode: String? = nil) throws -> Promise<String> {
|
|
34
|
+
return Promise.async { [self] in
|
|
35
35
|
let bundleId = Bundle.main.bundleIdentifier ?? ""
|
|
36
|
-
let
|
|
36
|
+
let country = countryCode ?? (try? self.getCountry()) ?? "US"
|
|
37
|
+
let urlString = "https://itunes.apple.com/\(country.lowercased())/lookup?bundleId=\(bundleId)"
|
|
38
|
+
let url = URL(string: urlString)!
|
|
37
39
|
let (data, _) = try await HybridVersionCheck.session.data(from: url)
|
|
38
40
|
guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
39
41
|
let results = json["results"] as? [[String: Any]],
|
|
@@ -44,10 +46,12 @@ class HybridVersionCheck: HybridVersionCheckSpec {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
func getLatestVersion() throws -> Promise<String> {
|
|
48
|
-
return Promise.async {
|
|
49
|
+
func getLatestVersion(countryCode: String? = nil) throws -> Promise<String> {
|
|
50
|
+
return Promise.async { [self] in
|
|
49
51
|
let bundleId = Bundle.main.bundleIdentifier ?? ""
|
|
50
|
-
let
|
|
52
|
+
let country = countryCode ?? (try? self.getCountry()) ?? "US"
|
|
53
|
+
let urlString = "https://itunes.apple.com/\(country.lowercased())/lookup?bundleId=\(bundleId)"
|
|
54
|
+
let url = URL(string: urlString)!
|
|
51
55
|
let (data, _) = try await HybridVersionCheck.session.data(from: url)
|
|
52
56
|
guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
53
57
|
let results = json["results"] as? [[String: Any]],
|
package/lib/index.d.ts
CHANGED
|
@@ -1,62 +1,11 @@
|
|
|
1
1
|
import type { UpdateLevel } from "./semver";
|
|
2
2
|
import { compareVersions } from "./semver";
|
|
3
|
-
/**
|
|
4
|
-
* Returns the device's current 2-letter ISO country code.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```ts
|
|
8
|
-
* getCountry() // "US"
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
export declare const getCountry: () => string;
|
|
12
|
-
/**
|
|
13
|
-
* Returns the store URL for this app.
|
|
14
|
-
*
|
|
15
|
-
* Automatically resolves to the App Store on iOS and Play Store on Android.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* const url = await getStoreUrl();
|
|
20
|
-
* Linking.openURL(url);
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export declare const getStoreUrl: () => Promise<string>;
|
|
24
|
-
/**
|
|
25
|
-
* Fetches the latest version of this app available in the store.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```ts
|
|
29
|
-
* const latest = await getLatestVersion(); // "1.3.0"
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export declare const getLatestVersion: () => Promise<string>;
|
|
33
|
-
/**
|
|
34
|
-
* Checks whether an app update is available.
|
|
35
|
-
*
|
|
36
|
-
* Uses semantic version comparison. By default checks for any version
|
|
37
|
-
* increase, but you can filter by granularity:
|
|
38
|
-
*
|
|
39
|
-
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
40
|
-
* - `"minor"` â returns `true` for major or minor bumps
|
|
41
|
-
* - `"patch"` â returns `true` for any version increase (default)
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* if (await needsUpdate()) {
|
|
46
|
-
* const url = await getStoreUrl();
|
|
47
|
-
* Linking.openURL(url);
|
|
48
|
-
* }
|
|
49
|
-
*
|
|
50
|
-
* // Only prompt for major updates
|
|
51
|
-
* const majorUpdate = await needsUpdate({ level: "major" });
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
export declare const needsUpdate: (options?: {
|
|
55
|
-
level?: UpdateLevel;
|
|
56
|
-
}) => Promise<boolean>;
|
|
57
3
|
/**
|
|
58
4
|
* All version-check APIs in one object.
|
|
59
5
|
*
|
|
6
|
+
* Provides access to app version information, store URLs, and update checking.
|
|
7
|
+
* Sync properties are cached at module init for zero native overhead.
|
|
8
|
+
*
|
|
60
9
|
* @example
|
|
61
10
|
* ```ts
|
|
62
11
|
* VersionCheck.version // "1.2.0"
|
|
@@ -65,6 +14,9 @@ export declare const needsUpdate: (options?: {
|
|
|
65
14
|
* VersionCheck.getCountry() // "US"
|
|
66
15
|
*
|
|
67
16
|
* const url = await VersionCheck.getStoreUrl();
|
|
17
|
+
* if (await VersionCheck.needsUpdate()) {
|
|
18
|
+
* Linking.openURL(url);
|
|
19
|
+
* }
|
|
68
20
|
* ```
|
|
69
21
|
*/
|
|
70
22
|
export declare const VersionCheck: {
|
|
@@ -132,37 +84,84 @@ export declare const VersionCheck: {
|
|
|
132
84
|
/**
|
|
133
85
|
* Returns the App Store (iOS) or Play Store (Android) URL for this app.
|
|
134
86
|
*
|
|
87
|
+
* @param options - Optional configuration
|
|
88
|
+
* @param options.countryCode - 2-letter ISO country code (e.g., "US", "GB")
|
|
89
|
+
* Defaults to the device's current country from `getCountry()`.
|
|
90
|
+
* Only used on iOS; ignored on Android.
|
|
91
|
+
*
|
|
135
92
|
* @example
|
|
136
93
|
* ```ts
|
|
137
94
|
* const url = await VersionCheck.getStoreUrl();
|
|
95
|
+
* const urlUS = await VersionCheck.getStoreUrl({ countryCode: "US" });
|
|
138
96
|
* Linking.openURL(url);
|
|
139
97
|
* ```
|
|
140
98
|
*/
|
|
141
|
-
readonly getStoreUrl: (
|
|
99
|
+
readonly getStoreUrl: (options?: {
|
|
100
|
+
countryCode?: string;
|
|
101
|
+
}) => Promise<string>;
|
|
142
102
|
/**
|
|
143
103
|
* Fetches the latest version of this app available in the store.
|
|
144
104
|
*
|
|
145
105
|
* Queries the iTunes API on iOS and the Play Store on Android.
|
|
106
|
+
* On iOS, uses the device's current country code by default but can be overridden.
|
|
107
|
+
*
|
|
108
|
+
* @param options - Optional configuration
|
|
109
|
+
* @param options.countryCode - 2-letter ISO country code (e.g., "US", "GB")
|
|
110
|
+
* Defaults to the device's current country from `getCountry()`.
|
|
111
|
+
* If the device region changes, the next call will use the new country.
|
|
112
|
+
* Only used on iOS; ignored on Android.
|
|
146
113
|
*
|
|
147
114
|
* @example
|
|
148
115
|
* ```ts
|
|
149
|
-
* const latest = await VersionCheck.getLatestVersion(); //
|
|
116
|
+
* const latest = await VersionCheck.getLatestVersion(); // Uses current device country
|
|
117
|
+
* const latestUS = await VersionCheck.getLatestVersion({ countryCode: "US" });
|
|
118
|
+
* const latestGB = await VersionCheck.getLatestVersion({ countryCode: "GB" });
|
|
150
119
|
* ```
|
|
151
120
|
*/
|
|
152
|
-
readonly getLatestVersion: (
|
|
121
|
+
readonly getLatestVersion: (options?: {
|
|
122
|
+
countryCode?: string;
|
|
123
|
+
}) => Promise<string>;
|
|
153
124
|
/**
|
|
154
125
|
* Checks whether an app update is available by comparing the current
|
|
155
126
|
* version against the latest store version.
|
|
156
127
|
*
|
|
128
|
+
* Uses semantic version comparison. By default checks for any version
|
|
129
|
+
* increase, but you can filter by granularity:
|
|
130
|
+
*
|
|
131
|
+
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
132
|
+
* - `"minor"` â returns `true` for major or minor bumps
|
|
133
|
+
* - `"patch"` â returns `true` for any version increase (default)
|
|
134
|
+
*
|
|
157
135
|
* @example
|
|
158
136
|
* ```ts
|
|
159
137
|
* if (await VersionCheck.needsUpdate()) {
|
|
160
138
|
* const url = await VersionCheck.getStoreUrl();
|
|
161
139
|
* Linking.openURL(url);
|
|
162
140
|
* }
|
|
141
|
+
*
|
|
142
|
+
* // Only prompt for major updates
|
|
143
|
+
* const majorUpdate = await VersionCheck.needsUpdate({ level: "major" });
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
readonly needsUpdate: (options?: {
|
|
147
|
+
level?: UpdateLevel;
|
|
148
|
+
}) => Promise<boolean>;
|
|
149
|
+
/**
|
|
150
|
+
* Compares two semantic version strings.
|
|
151
|
+
*
|
|
152
|
+
* @returns -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* VersionCheck.compareVersions('1.0.0', '1.0.1') // -1
|
|
157
|
+
* VersionCheck.compareVersions('2.0.0', '2.0.0') // 0
|
|
158
|
+
* VersionCheck.compareVersions('3.0.0', '2.9.9') // 1
|
|
159
|
+
*
|
|
160
|
+
* if (VersionCheck.compareVersions(currentVersion, minimumVersion) < 0) {
|
|
161
|
+
* // Current version is below minimum â force update
|
|
162
|
+
* }
|
|
163
163
|
* ```
|
|
164
164
|
*/
|
|
165
|
-
readonly
|
|
165
|
+
readonly compareVersions: typeof compareVersions;
|
|
166
166
|
};
|
|
167
|
-
export { compareVersions };
|
|
168
167
|
export type { UpdateLevel };
|
package/lib/index.js
CHANGED
|
@@ -6,64 +6,12 @@ const version = HybridVersionCheck.version;
|
|
|
6
6
|
const buildNumber = HybridVersionCheck.buildNumber;
|
|
7
7
|
const packageName = HybridVersionCheck.packageName;
|
|
8
8
|
const installSource = HybridVersionCheck.installSource;
|
|
9
|
-
/**
|
|
10
|
-
* Returns the device's current 2-letter ISO country code.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* getCountry() // "US"
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
export const getCountry = () => HybridVersionCheck.getCountry();
|
|
18
|
-
/**
|
|
19
|
-
* Returns the store URL for this app.
|
|
20
|
-
*
|
|
21
|
-
* Automatically resolves to the App Store on iOS and Play Store on Android.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```ts
|
|
25
|
-
* const url = await getStoreUrl();
|
|
26
|
-
* Linking.openURL(url);
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export const getStoreUrl = () => HybridVersionCheck.getStoreUrl();
|
|
30
|
-
/**
|
|
31
|
-
* Fetches the latest version of this app available in the store.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```ts
|
|
35
|
-
* const latest = await getLatestVersion(); // "1.3.0"
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
export const getLatestVersion = () => HybridVersionCheck.getLatestVersion();
|
|
39
|
-
/**
|
|
40
|
-
* Checks whether an app update is available.
|
|
41
|
-
*
|
|
42
|
-
* Uses semantic version comparison. By default checks for any version
|
|
43
|
-
* increase, but you can filter by granularity:
|
|
44
|
-
*
|
|
45
|
-
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
46
|
-
* - `"minor"` â returns `true` for major or minor bumps
|
|
47
|
-
* - `"patch"` â returns `true` for any version increase (default)
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* ```ts
|
|
51
|
-
* if (await needsUpdate()) {
|
|
52
|
-
* const url = await getStoreUrl();
|
|
53
|
-
* Linking.openURL(url);
|
|
54
|
-
* }
|
|
55
|
-
*
|
|
56
|
-
* // Only prompt for major updates
|
|
57
|
-
* const majorUpdate = await needsUpdate({ level: "major" });
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
export const needsUpdate = async (options) => {
|
|
61
|
-
const latest = await HybridVersionCheck.getLatestVersion();
|
|
62
|
-
return isNewerVersion(version, latest, options?.level ?? "patch");
|
|
63
|
-
};
|
|
64
9
|
/**
|
|
65
10
|
* All version-check APIs in one object.
|
|
66
11
|
*
|
|
12
|
+
* Provides access to app version information, store URLs, and update checking.
|
|
13
|
+
* Sync properties are cached at module init for zero native overhead.
|
|
14
|
+
*
|
|
67
15
|
* @example
|
|
68
16
|
* ```ts
|
|
69
17
|
* VersionCheck.version // "1.2.0"
|
|
@@ -72,6 +20,9 @@ export const needsUpdate = async (options) => {
|
|
|
72
20
|
* VersionCheck.getCountry() // "US"
|
|
73
21
|
*
|
|
74
22
|
* const url = await VersionCheck.getStoreUrl();
|
|
23
|
+
* if (await VersionCheck.needsUpdate()) {
|
|
24
|
+
* Linking.openURL(url);
|
|
25
|
+
* }
|
|
75
26
|
* ```
|
|
76
27
|
*/
|
|
77
28
|
export const VersionCheck = {
|
|
@@ -135,40 +86,88 @@ export const VersionCheck = {
|
|
|
135
86
|
* VersionCheck.getCountry() // "US"
|
|
136
87
|
* ```
|
|
137
88
|
*/
|
|
138
|
-
getCountry,
|
|
89
|
+
getCountry: () => HybridVersionCheck.getCountry(),
|
|
139
90
|
/**
|
|
140
91
|
* Returns the App Store (iOS) or Play Store (Android) URL for this app.
|
|
141
92
|
*
|
|
93
|
+
* @param options - Optional configuration
|
|
94
|
+
* @param options.countryCode - 2-letter ISO country code (e.g., "US", "GB")
|
|
95
|
+
* Defaults to the device's current country from `getCountry()`.
|
|
96
|
+
* Only used on iOS; ignored on Android.
|
|
97
|
+
*
|
|
142
98
|
* @example
|
|
143
99
|
* ```ts
|
|
144
100
|
* const url = await VersionCheck.getStoreUrl();
|
|
101
|
+
* const urlUS = await VersionCheck.getStoreUrl({ countryCode: "US" });
|
|
145
102
|
* Linking.openURL(url);
|
|
146
103
|
* ```
|
|
147
104
|
*/
|
|
148
|
-
getStoreUrl
|
|
105
|
+
getStoreUrl: async (options) => {
|
|
106
|
+
return HybridVersionCheck.getStoreUrl(options?.countryCode);
|
|
107
|
+
},
|
|
149
108
|
/**
|
|
150
109
|
* Fetches the latest version of this app available in the store.
|
|
151
110
|
*
|
|
152
111
|
* Queries the iTunes API on iOS and the Play Store on Android.
|
|
112
|
+
* On iOS, uses the device's current country code by default but can be overridden.
|
|
113
|
+
*
|
|
114
|
+
* @param options - Optional configuration
|
|
115
|
+
* @param options.countryCode - 2-letter ISO country code (e.g., "US", "GB")
|
|
116
|
+
* Defaults to the device's current country from `getCountry()`.
|
|
117
|
+
* If the device region changes, the next call will use the new country.
|
|
118
|
+
* Only used on iOS; ignored on Android.
|
|
153
119
|
*
|
|
154
120
|
* @example
|
|
155
121
|
* ```ts
|
|
156
|
-
* const latest = await VersionCheck.getLatestVersion(); //
|
|
122
|
+
* const latest = await VersionCheck.getLatestVersion(); // Uses current device country
|
|
123
|
+
* const latestUS = await VersionCheck.getLatestVersion({ countryCode: "US" });
|
|
124
|
+
* const latestGB = await VersionCheck.getLatestVersion({ countryCode: "GB" });
|
|
157
125
|
* ```
|
|
158
126
|
*/
|
|
159
|
-
getLatestVersion
|
|
127
|
+
getLatestVersion: async (options) => {
|
|
128
|
+
return HybridVersionCheck.getLatestVersion(options?.countryCode);
|
|
129
|
+
},
|
|
160
130
|
/**
|
|
161
131
|
* Checks whether an app update is available by comparing the current
|
|
162
132
|
* version against the latest store version.
|
|
163
133
|
*
|
|
134
|
+
* Uses semantic version comparison. By default checks for any version
|
|
135
|
+
* increase, but you can filter by granularity:
|
|
136
|
+
*
|
|
137
|
+
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
138
|
+
* - `"minor"` â returns `true` for major or minor bumps
|
|
139
|
+
* - `"patch"` â returns `true` for any version increase (default)
|
|
140
|
+
*
|
|
164
141
|
* @example
|
|
165
142
|
* ```ts
|
|
166
143
|
* if (await VersionCheck.needsUpdate()) {
|
|
167
144
|
* const url = await VersionCheck.getStoreUrl();
|
|
168
145
|
* Linking.openURL(url);
|
|
169
146
|
* }
|
|
147
|
+
*
|
|
148
|
+
* // Only prompt for major updates
|
|
149
|
+
* const majorUpdate = await VersionCheck.needsUpdate({ level: "major" });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
needsUpdate: async (options) => {
|
|
153
|
+
const latest = await HybridVersionCheck.getLatestVersion();
|
|
154
|
+
return isNewerVersion(version, latest, options?.level ?? "patch");
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* Compares two semantic version strings.
|
|
158
|
+
*
|
|
159
|
+
* @returns -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* VersionCheck.compareVersions('1.0.0', '1.0.1') // -1
|
|
164
|
+
* VersionCheck.compareVersions('2.0.0', '2.0.0') // 0
|
|
165
|
+
* VersionCheck.compareVersions('3.0.0', '2.9.9') // 1
|
|
166
|
+
*
|
|
167
|
+
* if (VersionCheck.compareVersions(currentVersion, minimumVersion) < 0) {
|
|
168
|
+
* // Current version is below minimum â force update
|
|
169
|
+
* }
|
|
170
170
|
* ```
|
|
171
171
|
*/
|
|
172
|
-
|
|
172
|
+
compareVersions,
|
|
173
173
|
};
|
|
174
|
-
export { compareVersions };
|
|
@@ -8,7 +8,7 @@ export interface VersionCheck extends HybridObject<{
|
|
|
8
8
|
readonly packageName: string;
|
|
9
9
|
readonly installSource: string | undefined;
|
|
10
10
|
getCountry(): string;
|
|
11
|
-
getStoreUrl(): Promise<string>;
|
|
12
|
-
getLatestVersion(): Promise<string>;
|
|
11
|
+
getStoreUrl(countryCode?: string): Promise<string>;
|
|
12
|
+
getLatestVersion(countryCode?: string): Promise<string>;
|
|
13
13
|
needsUpdate(): Promise<boolean>;
|
|
14
14
|
}
|
|
@@ -77,9 +77,9 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
77
77
|
auto __result = method(_javaPart);
|
|
78
78
|
return __result->toStdString();
|
|
79
79
|
}
|
|
80
|
-
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getStoreUrl() {
|
|
81
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("getStoreUrl");
|
|
82
|
-
auto __result = method(_javaPart);
|
|
80
|
+
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getStoreUrl(const std::optional<std::string>& countryCode) {
|
|
81
|
+
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JString> /* countryCode */)>("getStoreUrl");
|
|
82
|
+
auto __result = method(_javaPart, countryCode.has_value() ? jni::make_jstring(countryCode.value()) : nullptr);
|
|
83
83
|
return [&]() {
|
|
84
84
|
auto __promise = Promise<std::string>::create();
|
|
85
85
|
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
@@ -93,9 +93,9 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
93
93
|
return __promise;
|
|
94
94
|
}();
|
|
95
95
|
}
|
|
96
|
-
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getLatestVersion() {
|
|
97
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("getLatestVersion");
|
|
98
|
-
auto __result = method(_javaPart);
|
|
96
|
+
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getLatestVersion(const std::optional<std::string>& countryCode) {
|
|
97
|
+
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JString> /* countryCode */)>("getLatestVersion");
|
|
98
|
+
auto __result = method(_javaPart, countryCode.has_value() ? jni::make_jstring(countryCode.value()) : nullptr);
|
|
99
99
|
return [&]() {
|
|
100
100
|
auto __promise = Promise<std::string>::create();
|
|
101
101
|
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
@@ -59,8 +59,8 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
59
59
|
public:
|
|
60
60
|
// Methods
|
|
61
61
|
std::string getCountry() override;
|
|
62
|
-
std::shared_ptr<Promise<std::string>> getStoreUrl() override;
|
|
63
|
-
std::shared_ptr<Promise<std::string>> getLatestVersion() override;
|
|
62
|
+
std::shared_ptr<Promise<std::string>> getStoreUrl(const std::optional<std::string>& countryCode) override;
|
|
63
|
+
std::shared_ptr<Promise<std::string>> getLatestVersion(const std::optional<std::string>& countryCode) override;
|
|
64
64
|
std::shared_ptr<Promise<bool>> needsUpdate() override;
|
|
65
65
|
|
|
66
66
|
private:
|
|
@@ -66,11 +66,11 @@ abstract class HybridVersionCheckSpec: HybridObject() {
|
|
|
66
66
|
|
|
67
67
|
@DoNotStrip
|
|
68
68
|
@Keep
|
|
69
|
-
abstract fun getStoreUrl(): Promise<String>
|
|
69
|
+
abstract fun getStoreUrl(countryCode: String?): Promise<String>
|
|
70
70
|
|
|
71
71
|
@DoNotStrip
|
|
72
72
|
@Keep
|
|
73
|
-
abstract fun getLatestVersion(): Promise<String>
|
|
73
|
+
abstract fun getLatestVersion(countryCode: String?): Promise<String>
|
|
74
74
|
|
|
75
75
|
@DoNotStrip
|
|
76
76
|
@Keep
|
|
@@ -91,16 +91,16 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
91
91
|
auto __value = std::move(__result.value());
|
|
92
92
|
return __value;
|
|
93
93
|
}
|
|
94
|
-
inline std::shared_ptr<Promise<std::string>> getStoreUrl() override {
|
|
95
|
-
auto __result = _swiftPart.getStoreUrl();
|
|
94
|
+
inline std::shared_ptr<Promise<std::string>> getStoreUrl(const std::optional<std::string>& countryCode) override {
|
|
95
|
+
auto __result = _swiftPart.getStoreUrl(countryCode);
|
|
96
96
|
if (__result.hasError()) [[unlikely]] {
|
|
97
97
|
std::rethrow_exception(__result.error());
|
|
98
98
|
}
|
|
99
99
|
auto __value = std::move(__result.value());
|
|
100
100
|
return __value;
|
|
101
101
|
}
|
|
102
|
-
inline std::shared_ptr<Promise<std::string>> getLatestVersion() override {
|
|
103
|
-
auto __result = _swiftPart.getLatestVersion();
|
|
102
|
+
inline std::shared_ptr<Promise<std::string>> getLatestVersion(const std::optional<std::string>& countryCode) override {
|
|
103
|
+
auto __result = _swiftPart.getLatestVersion(countryCode);
|
|
104
104
|
if (__result.hasError()) [[unlikely]] {
|
|
105
105
|
std::rethrow_exception(__result.error());
|
|
106
106
|
}
|
|
@@ -17,8 +17,8 @@ public protocol HybridVersionCheckSpec_protocol: HybridObject {
|
|
|
17
17
|
|
|
18
18
|
// Methods
|
|
19
19
|
func getCountry() throws -> String
|
|
20
|
-
func getStoreUrl() throws -> Promise<String>
|
|
21
|
-
func getLatestVersion() throws -> Promise<String>
|
|
20
|
+
func getStoreUrl(countryCode: String?) throws -> Promise<String>
|
|
21
|
+
func getLatestVersion(countryCode: String?) throws -> Promise<String>
|
|
22
22
|
func needsUpdate() throws -> Promise<Bool>
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -169,9 +169,16 @@ open class HybridVersionCheckSpec_cxx {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
@inline(__always)
|
|
172
|
-
public final func getStoreUrl() -> bridge.Result_std__shared_ptr_Promise_std__string___ {
|
|
172
|
+
public final func getStoreUrl(countryCode: bridge.std__optional_std__string_) -> bridge.Result_std__shared_ptr_Promise_std__string___ {
|
|
173
173
|
do {
|
|
174
|
-
let __result = try self.__implementation.getStoreUrl()
|
|
174
|
+
let __result = try self.__implementation.getStoreUrl(countryCode: { () -> String? in
|
|
175
|
+
if bridge.has_value_std__optional_std__string_(countryCode) {
|
|
176
|
+
let __unwrapped = bridge.get_std__optional_std__string_(countryCode)
|
|
177
|
+
return String(__unwrapped)
|
|
178
|
+
} else {
|
|
179
|
+
return nil
|
|
180
|
+
}
|
|
181
|
+
}())
|
|
175
182
|
let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__string__ in
|
|
176
183
|
let __promise = bridge.create_std__shared_ptr_Promise_std__string__()
|
|
177
184
|
let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(__promise)
|
|
@@ -188,9 +195,16 @@ open class HybridVersionCheckSpec_cxx {
|
|
|
188
195
|
}
|
|
189
196
|
|
|
190
197
|
@inline(__always)
|
|
191
|
-
public final func getLatestVersion() -> bridge.Result_std__shared_ptr_Promise_std__string___ {
|
|
198
|
+
public final func getLatestVersion(countryCode: bridge.std__optional_std__string_) -> bridge.Result_std__shared_ptr_Promise_std__string___ {
|
|
192
199
|
do {
|
|
193
|
-
let __result = try self.__implementation.getLatestVersion()
|
|
200
|
+
let __result = try self.__implementation.getLatestVersion(countryCode: { () -> String? in
|
|
201
|
+
if bridge.has_value_std__optional_std__string_(countryCode) {
|
|
202
|
+
let __unwrapped = bridge.get_std__optional_std__string_(countryCode)
|
|
203
|
+
return String(__unwrapped)
|
|
204
|
+
} else {
|
|
205
|
+
return nil
|
|
206
|
+
}
|
|
207
|
+
}())
|
|
194
208
|
let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__string__ in
|
|
195
209
|
let __promise = bridge.create_std__shared_ptr_Promise_std__string__()
|
|
196
210
|
let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(__promise)
|
|
@@ -54,8 +54,8 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
54
54
|
public:
|
|
55
55
|
// Methods
|
|
56
56
|
virtual std::string getCountry() = 0;
|
|
57
|
-
virtual std::shared_ptr<Promise<std::string>> getStoreUrl() = 0;
|
|
58
|
-
virtual std::shared_ptr<Promise<std::string>> getLatestVersion() = 0;
|
|
57
|
+
virtual std::shared_ptr<Promise<std::string>> getStoreUrl(const std::optional<std::string>& countryCode) = 0;
|
|
58
|
+
virtual std::shared_ptr<Promise<std::string>> getLatestVersion(const std::optional<std::string>& countryCode) = 0;
|
|
59
59
|
virtual std::shared_ptr<Promise<bool>> needsUpdate() = 0;
|
|
60
60
|
|
|
61
61
|
protected:
|
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-version-check",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "A lightweight, fast version-checking library for React Native, powered by Nitro Modules",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"module": "lib/index",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"react-native": "src/index",
|
|
9
9
|
"source": "src/index",
|
|
10
10
|
"files": [
|
|
11
|
-
"src",
|
|
12
|
-
"react-native.config.js",
|
|
13
11
|
"lib",
|
|
12
|
+
"react-native.config.js",
|
|
14
13
|
"nitrogen",
|
|
15
14
|
"android/build.gradle",
|
|
16
15
|
"android/gradle.properties",
|
|
@@ -34,6 +33,9 @@
|
|
|
34
33
|
"release": "release-it",
|
|
35
34
|
"build": "tsc",
|
|
36
35
|
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "jest",
|
|
37
|
+
"test:watch": "jest --watch",
|
|
38
|
+
"test:coverage": "jest --coverage",
|
|
37
39
|
"lint": "biome check .",
|
|
38
40
|
"lint:fix": "biome check --write .",
|
|
39
41
|
"format": "biome format --write .",
|
|
@@ -62,7 +64,8 @@
|
|
|
62
64
|
"nitro-modules-version",
|
|
63
65
|
"app store version",
|
|
64
66
|
"play store version",
|
|
65
|
-
"market version"
|
|
67
|
+
"market version",
|
|
68
|
+
"lightweight"
|
|
66
69
|
],
|
|
67
70
|
"repository": {
|
|
68
71
|
"type": "git",
|
|
@@ -73,7 +76,7 @@
|
|
|
73
76
|
"bugs": {
|
|
74
77
|
"url": "https://github.com/AlshehriAli0/react-native-nitro-version-check/issues"
|
|
75
78
|
},
|
|
76
|
-
"homepage": "https://github.
|
|
79
|
+
"homepage": "https://alshehriali0.github.io/react-native-nitro-version-check/",
|
|
77
80
|
"publishConfig": {
|
|
78
81
|
"registry": "https://registry.npmjs.org/"
|
|
79
82
|
},
|
|
@@ -148,12 +151,15 @@
|
|
|
148
151
|
},
|
|
149
152
|
"devDependencies": {
|
|
150
153
|
"@release-it/conventional-changelog": "^10.0.5",
|
|
154
|
+
"@types/jest": "^29.5.12",
|
|
151
155
|
"@types/react": "^19.1.03",
|
|
156
|
+
"jest": "^29.7.0",
|
|
152
157
|
"nitrogen": "*",
|
|
153
158
|
"react": "19.2.0",
|
|
154
159
|
"react-native": "0.83.0",
|
|
155
160
|
"react-native-nitro-modules": "*",
|
|
156
161
|
"release-it": "^19.2.4",
|
|
162
|
+
"ts-jest": "^29.1.2",
|
|
157
163
|
"typescript": "^5.8.3"
|
|
158
164
|
},
|
|
159
165
|
"peerDependencies": {
|
package/src/index.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { NitroModules } from "react-native-nitro-modules";
|
|
2
|
-
import type { UpdateLevel } from "./semver";
|
|
3
|
-
import { compareVersions, isNewerVersion } from "./semver";
|
|
4
|
-
import type { VersionCheck as VersionCheckType } from "./specs/Version.nitro";
|
|
5
|
-
|
|
6
|
-
const HybridVersionCheck = NitroModules.createHybridObject<VersionCheckType>("VersionCheck");
|
|
7
|
-
|
|
8
|
-
// Cached at module init â plain JS values, no JSI overhead on repeated access.
|
|
9
|
-
const version = HybridVersionCheck.version;
|
|
10
|
-
const buildNumber = HybridVersionCheck.buildNumber;
|
|
11
|
-
const packageName = HybridVersionCheck.packageName;
|
|
12
|
-
const installSource = HybridVersionCheck.installSource;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Returns the device's current 2-letter ISO country code.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* getCountry() // "US"
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export const getCountry = () => HybridVersionCheck.getCountry();
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Returns the store URL for this app.
|
|
26
|
-
*
|
|
27
|
-
* Automatically resolves to the App Store on iOS and Play Store on Android.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```ts
|
|
31
|
-
* const url = await getStoreUrl();
|
|
32
|
-
* Linking.openURL(url);
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export const getStoreUrl = () => HybridVersionCheck.getStoreUrl();
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Fetches the latest version of this app available in the store.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* ```ts
|
|
42
|
-
* const latest = await getLatestVersion(); // "1.3.0"
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export const getLatestVersion = () => HybridVersionCheck.getLatestVersion();
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Checks whether an app update is available.
|
|
49
|
-
*
|
|
50
|
-
* Uses semantic version comparison. By default checks for any version
|
|
51
|
-
* increase, but you can filter by granularity:
|
|
52
|
-
*
|
|
53
|
-
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
54
|
-
* - `"minor"` â returns `true` for major or minor bumps
|
|
55
|
-
* - `"patch"` â returns `true` for any version increase (default)
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```ts
|
|
59
|
-
* if (await needsUpdate()) {
|
|
60
|
-
* const url = await getStoreUrl();
|
|
61
|
-
* Linking.openURL(url);
|
|
62
|
-
* }
|
|
63
|
-
*
|
|
64
|
-
* // Only prompt for major updates
|
|
65
|
-
* const majorUpdate = await needsUpdate({ level: "major" });
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
export const needsUpdate = async (options?: { level?: UpdateLevel }): Promise<boolean> => {
|
|
69
|
-
const latest = await HybridVersionCheck.getLatestVersion();
|
|
70
|
-
return isNewerVersion(version, latest, options?.level ?? "patch");
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* All version-check APIs in one object.
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* ```ts
|
|
78
|
-
* VersionCheck.version // "1.2.0"
|
|
79
|
-
* VersionCheck.buildNumber // "42"
|
|
80
|
-
* VersionCheck.packageName // "com.example.app"
|
|
81
|
-
* VersionCheck.getCountry() // "US"
|
|
82
|
-
*
|
|
83
|
-
* const url = await VersionCheck.getStoreUrl();
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
export const VersionCheck = {
|
|
87
|
-
/**
|
|
88
|
-
* The current app version string.
|
|
89
|
-
*
|
|
90
|
-
* Read from `CFBundleShortVersionString` on iOS and `versionName` on Android.
|
|
91
|
-
* Cached at module init, so repeated reads have zero native overhead.
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```ts
|
|
95
|
-
* VersionCheck.version // "1.2.0"
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
version,
|
|
99
|
-
/**
|
|
100
|
-
* The current build number.
|
|
101
|
-
*
|
|
102
|
-
* Read from `CFBundleVersion` on iOS and `versionCode` on Android.
|
|
103
|
-
* Cached at module init.
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```ts
|
|
107
|
-
* VersionCheck.buildNumber // "42"
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
buildNumber,
|
|
111
|
-
/**
|
|
112
|
-
* The app's unique identifier.
|
|
113
|
-
*
|
|
114
|
-
* This is the Bundle ID on iOS and the Application ID on Android.
|
|
115
|
-
* Cached at module init.
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* ```ts
|
|
119
|
-
* VersionCheck.packageName // "com.example.app"
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
packageName,
|
|
123
|
-
/**
|
|
124
|
-
* Where the app was installed from, or `undefined` for dev/sideloaded builds.
|
|
125
|
-
*
|
|
126
|
-
* - iOS: `"appstore"` | `"testflight"` | `undefined`
|
|
127
|
-
* - Android: `"playstore"` | `undefined`
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```ts
|
|
131
|
-
* if (VersionCheck.installSource === "testflight") {
|
|
132
|
-
* // running a TestFlight build
|
|
133
|
-
* }
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
installSource,
|
|
137
|
-
/**
|
|
138
|
-
* Returns the device's current 2-letter ISO country code.
|
|
139
|
-
*
|
|
140
|
-
* This is a synchronous Nitro call, no `await` needed.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* VersionCheck.getCountry() // "US"
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
|
-
getCountry,
|
|
148
|
-
/**
|
|
149
|
-
* Returns the App Store (iOS) or Play Store (Android) URL for this app.
|
|
150
|
-
*
|
|
151
|
-
* @example
|
|
152
|
-
* ```ts
|
|
153
|
-
* const url = await VersionCheck.getStoreUrl();
|
|
154
|
-
* Linking.openURL(url);
|
|
155
|
-
* ```
|
|
156
|
-
*/
|
|
157
|
-
getStoreUrl,
|
|
158
|
-
/**
|
|
159
|
-
* Fetches the latest version of this app available in the store.
|
|
160
|
-
*
|
|
161
|
-
* Queries the iTunes API on iOS and the Play Store on Android.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```ts
|
|
165
|
-
* const latest = await VersionCheck.getLatestVersion(); // "1.3.0"
|
|
166
|
-
* ```
|
|
167
|
-
*/
|
|
168
|
-
getLatestVersion,
|
|
169
|
-
/**
|
|
170
|
-
* Checks whether an app update is available by comparing the current
|
|
171
|
-
* version against the latest store version.
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* ```ts
|
|
175
|
-
* if (await VersionCheck.needsUpdate()) {
|
|
176
|
-
* const url = await VersionCheck.getStoreUrl();
|
|
177
|
-
* Linking.openURL(url);
|
|
178
|
-
* }
|
|
179
|
-
* ```
|
|
180
|
-
*/
|
|
181
|
-
needsUpdate: () => HybridVersionCheck.needsUpdate(),
|
|
182
|
-
} as const;
|
|
183
|
-
|
|
184
|
-
export { compareVersions };
|
|
185
|
-
export type { UpdateLevel };
|
package/src/semver.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export type UpdateLevel = "major" | "minor" | "patch";
|
|
2
|
-
|
|
3
|
-
type SemVer = [major: number, minor: number, patch: number];
|
|
4
|
-
|
|
5
|
-
function parseVersion(version: string): SemVer {
|
|
6
|
-
const parts = version.split(".");
|
|
7
|
-
return [Number(parts[0]) || 0, Number(parts[1]) || 0, Number(parts[2]) || 0];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Compares two version strings.
|
|
12
|
-
*
|
|
13
|
-
* @returns `-1` if `v1 < v2`, `0` if equal, `1` if `v1 > v2`
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```ts
|
|
17
|
-
* compareVersions("1.2.0", "1.3.0") // -1
|
|
18
|
-
* compareVersions("2.0.0", "1.9.9") // 1
|
|
19
|
-
* compareVersions("1.0.0", "1.0.0") // 0
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export function compareVersions(v1: string, v2: string): -1 | 0 | 1 {
|
|
23
|
-
const a = parseVersion(v1);
|
|
24
|
-
const b = parseVersion(v2);
|
|
25
|
-
|
|
26
|
-
for (let i = 0; i < 3; i++) {
|
|
27
|
-
if (a[i]! > b[i]!) return 1;
|
|
28
|
-
if (a[i]! < b[i]!) return -1;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Checks whether `latest` is newer than `current` at the given granularity.
|
|
36
|
-
*
|
|
37
|
-
* - `"major"` â only returns `true` for major bumps (1.x â 2.x)
|
|
38
|
-
* - `"minor"` â returns `true` for major or minor bumps
|
|
39
|
-
* - `"patch"` â returns `true` for any version increase (default)
|
|
40
|
-
*/
|
|
41
|
-
export function isNewerVersion(current: string, latest: string, level: UpdateLevel = "patch"): boolean {
|
|
42
|
-
const [curMajor, curMinor, curPatch] = parseVersion(current);
|
|
43
|
-
const [latMajor, latMinor, latPatch] = parseVersion(latest);
|
|
44
|
-
|
|
45
|
-
if (latMajor > curMajor) return true;
|
|
46
|
-
if (latMajor < curMajor) return false;
|
|
47
|
-
if (level === "major") return false;
|
|
48
|
-
|
|
49
|
-
if (latMinor > curMinor) return true;
|
|
50
|
-
if (latMinor < curMinor) return false;
|
|
51
|
-
if (level === "minor") return false;
|
|
52
|
-
|
|
53
|
-
return latPatch > curPatch;
|
|
54
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from "react-native-nitro-modules";
|
|
2
|
-
|
|
3
|
-
export interface VersionCheck
|
|
4
|
-
extends HybridObject<{
|
|
5
|
-
ios: "swift";
|
|
6
|
-
android: "kotlin";
|
|
7
|
-
}> {
|
|
8
|
-
readonly version: string;
|
|
9
|
-
readonly buildNumber: string;
|
|
10
|
-
readonly packageName: string;
|
|
11
|
-
readonly installSource: string | undefined;
|
|
12
|
-
getCountry(): string;
|
|
13
|
-
getStoreUrl(): Promise<string>;
|
|
14
|
-
getLatestVersion(): Promise<string>;
|
|
15
|
-
needsUpdate(): Promise<boolean>;
|
|
16
|
-
}
|