react-native-nitro-version-check 1.0.2 → 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.
- package/README.md +11 -3
- 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/NitroVersionCheckOnLoad.cpp +11 -4
- package/nitrogen/generated/android/c++/JHybridVersionCheckSpec.cpp +30 -36
- package/nitrogen/generated/android/c++/JHybridVersionCheckSpec.hpp +21 -24
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroversioncheck/HybridVersionCheckSpec.kt +17 -20
- 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 +10 -5
- package/src/index.ts +0 -185
- package/src/semver.ts +0 -54
- package/src/specs/Version.nitro.ts +0 -16
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
## Example
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
-
import { VersionCheck
|
|
18
|
+
import { VersionCheck } from 'react-native-nitro-version-check'
|
|
19
19
|
|
|
20
20
|
// Sync — no bridge, no async
|
|
21
21
|
VersionCheck.version // "1.2.0"
|
|
@@ -23,9 +23,12 @@ VersionCheck.buildNumber // "42"
|
|
|
23
23
|
VersionCheck.packageName // "com.example.app"
|
|
24
24
|
VersionCheck.installSource // "appstore" | "testflight" | "playstore" | undefined
|
|
25
25
|
|
|
26
|
+
// Or destructure properties
|
|
27
|
+
const { version, buildNumber, packageName, installSource } = VersionCheck
|
|
28
|
+
|
|
26
29
|
// Check for updates
|
|
27
|
-
if (await needsUpdate()) {
|
|
28
|
-
Linking.openURL(await getStoreUrl())
|
|
30
|
+
if (await VersionCheck.needsUpdate()) {
|
|
31
|
+
Linking.openURL(await VersionCheck.getStoreUrl())
|
|
29
32
|
}
|
|
30
33
|
```
|
|
31
34
|
|
|
@@ -35,11 +38,16 @@ if (await needsUpdate()) {
|
|
|
35
38
|
bun add react-native-nitro-version-check
|
|
36
39
|
```
|
|
37
40
|
|
|
41
|
+
> **Version 2.x and newer requires Nitro 0.35+** — for earlier versions, use version 1.x
|
|
42
|
+
>
|
|
43
|
+
> Check the [full installation guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/installation) for platform setup and additional dependencies.
|
|
44
|
+
|
|
38
45
|
## Documentation
|
|
39
46
|
|
|
40
47
|
- [**Nitro Version Check** docs 📚](https://alshehriali0.github.io/react-native-nitro-version-check/)
|
|
41
48
|
- [**Getting Started** guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/getting-started)
|
|
42
49
|
- [**Installation** guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/installation)
|
|
50
|
+
- [**Compatibility** guide](https://alshehriali0.github.io/react-native-nitro-version-check/docs/compatibility)
|
|
43
51
|
- [**API Reference**](https://alshehriali0.github.io/react-native-nitro-version-check/docs/api-reference)
|
|
44
52
|
- [**Migration Guide** from react-native-version-check](https://alshehriali0.github.io/react-native-nitro-version-check/docs/migration-guide)
|
|
45
53
|
|
|
@@ -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
|
}
|
|
@@ -26,20 +26,27 @@ int initialize(JavaVM* vm) {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
struct JHybridVersionCheckSpecImpl: public jni::JavaClass<JHybridVersionCheckSpecImpl, JHybridVersionCheckSpec::JavaPart> {
|
|
30
|
+
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroversioncheck/HybridVersionCheck;";
|
|
31
|
+
static std::shared_ptr<JHybridVersionCheckSpec> create() {
|
|
32
|
+
static auto constructorFn = javaClassStatic()->getConstructor<JHybridVersionCheckSpecImpl::javaobject()>();
|
|
33
|
+
jni::local_ref<JHybridVersionCheckSpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);
|
|
34
|
+
return javaPart->getJHybridVersionCheckSpec();
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
29
38
|
void registerAllNatives() {
|
|
30
39
|
using namespace margelo::nitro;
|
|
31
40
|
using namespace margelo::nitro::nitroversioncheck;
|
|
32
41
|
|
|
33
42
|
// Register native JNI methods
|
|
34
|
-
margelo::nitro::nitroversioncheck::JHybridVersionCheckSpec::registerNatives();
|
|
43
|
+
margelo::nitro::nitroversioncheck::JHybridVersionCheckSpec::CxxPart::registerNatives();
|
|
35
44
|
|
|
36
45
|
// Register Nitro Hybrid Objects
|
|
37
46
|
HybridObjectRegistry::registerHybridObjectConstructor(
|
|
38
47
|
"VersionCheck",
|
|
39
48
|
[]() -> std::shared_ptr<HybridObject> {
|
|
40
|
-
|
|
41
|
-
auto instance = object.create();
|
|
42
|
-
return instance->cthis()->shared();
|
|
49
|
+
return JHybridVersionCheckSpecImpl::create();
|
|
43
50
|
}
|
|
44
51
|
);
|
|
45
52
|
}
|
|
@@ -16,70 +16,64 @@
|
|
|
16
16
|
|
|
17
17
|
namespace margelo::nitro::nitroversioncheck {
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
19
|
+
std::shared_ptr<JHybridVersionCheckSpec> JHybridVersionCheckSpec::JavaPart::getJHybridVersionCheckSpec() {
|
|
20
|
+
auto hybridObject = JHybridObject::JavaPart::getJHybridObject();
|
|
21
|
+
auto castHybridObject = std::dynamic_pointer_cast<JHybridVersionCheckSpec>(hybridObject);
|
|
22
|
+
if (castHybridObject == nullptr) [[unlikely]] {
|
|
23
|
+
throw std::runtime_error("Failed to downcast JHybridObject to JHybridVersionCheckSpec!");
|
|
24
|
+
}
|
|
25
|
+
return castHybridObject;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return method(_javaPart);
|
|
28
|
+
jni::local_ref<JHybridVersionCheckSpec::CxxPart::jhybriddata> JHybridVersionCheckSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {
|
|
29
|
+
return makeCxxInstance(jThis);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
std::shared_ptr<JHybridObject> JHybridVersionCheckSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {
|
|
33
|
+
auto castJavaPart = jni::dynamic_ref_cast<JHybridVersionCheckSpec::JavaPart>(javaPart);
|
|
34
|
+
if (castJavaPart == nullptr) [[unlikely]] {
|
|
35
|
+
throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridVersionCheckSpec::JavaPart!");
|
|
37
36
|
}
|
|
38
|
-
return
|
|
37
|
+
return std::make_shared<JHybridVersionCheckSpec>(castJavaPart);
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
void JHybridVersionCheckSpec::
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
std::string JHybridVersionCheckSpec::toString() {
|
|
47
|
-
static const auto method = javaClassStatic()->getMethod<jni::JString()>("toString");
|
|
48
|
-
auto javaString = method(_javaPart);
|
|
49
|
-
return javaString->toStdString();
|
|
40
|
+
void JHybridVersionCheckSpec::CxxPart::registerNatives() {
|
|
41
|
+
registerHybrid({
|
|
42
|
+
makeNativeMethod("initHybrid", JHybridVersionCheckSpec::CxxPart::initHybrid),
|
|
43
|
+
});
|
|
50
44
|
}
|
|
51
45
|
|
|
52
46
|
// Properties
|
|
53
47
|
std::string JHybridVersionCheckSpec::getVersion() {
|
|
54
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getVersion");
|
|
48
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getVersion");
|
|
55
49
|
auto __result = method(_javaPart);
|
|
56
50
|
return __result->toStdString();
|
|
57
51
|
}
|
|
58
52
|
std::string JHybridVersionCheckSpec::getBuildNumber() {
|
|
59
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getBuildNumber");
|
|
53
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getBuildNumber");
|
|
60
54
|
auto __result = method(_javaPart);
|
|
61
55
|
return __result->toStdString();
|
|
62
56
|
}
|
|
63
57
|
std::string JHybridVersionCheckSpec::getPackageName() {
|
|
64
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getPackageName");
|
|
58
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getPackageName");
|
|
65
59
|
auto __result = method(_javaPart);
|
|
66
60
|
return __result->toStdString();
|
|
67
61
|
}
|
|
68
62
|
std::optional<std::string> JHybridVersionCheckSpec::getInstallSource() {
|
|
69
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getInstallSource");
|
|
63
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getInstallSource");
|
|
70
64
|
auto __result = method(_javaPart);
|
|
71
65
|
return __result != nullptr ? std::make_optional(__result->toStdString()) : std::nullopt;
|
|
72
66
|
}
|
|
73
67
|
|
|
74
68
|
// Methods
|
|
75
69
|
std::string JHybridVersionCheckSpec::getCountry() {
|
|
76
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getCountry");
|
|
70
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getCountry");
|
|
77
71
|
auto __result = method(_javaPart);
|
|
78
72
|
return __result->toStdString();
|
|
79
73
|
}
|
|
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);
|
|
74
|
+
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getStoreUrl(const std::optional<std::string>& countryCode) {
|
|
75
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JString> /* countryCode */)>("getStoreUrl");
|
|
76
|
+
auto __result = method(_javaPart, countryCode.has_value() ? jni::make_jstring(countryCode.value()) : nullptr);
|
|
83
77
|
return [&]() {
|
|
84
78
|
auto __promise = Promise<std::string>::create();
|
|
85
79
|
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
@@ -93,9 +87,9 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
93
87
|
return __promise;
|
|
94
88
|
}();
|
|
95
89
|
}
|
|
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);
|
|
90
|
+
std::shared_ptr<Promise<std::string>> JHybridVersionCheckSpec::getLatestVersion(const std::optional<std::string>& countryCode) {
|
|
91
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JString> /* countryCode */)>("getLatestVersion");
|
|
92
|
+
auto __result = method(_javaPart, countryCode.has_value() ? jni::make_jstring(countryCode.value()) : nullptr);
|
|
99
93
|
return [&]() {
|
|
100
94
|
auto __promise = Promise<std::string>::create();
|
|
101
95
|
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
@@ -110,7 +104,7 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
110
104
|
}();
|
|
111
105
|
}
|
|
112
106
|
std::shared_ptr<Promise<bool>> JHybridVersionCheckSpec::needsUpdate() {
|
|
113
|
-
static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("needsUpdate");
|
|
107
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("needsUpdate");
|
|
114
108
|
auto __result = method(_javaPart);
|
|
115
109
|
return [&]() {
|
|
116
110
|
auto __promise = Promise<bool>::create();
|
|
@@ -18,34 +18,33 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
18
18
|
|
|
19
19
|
using namespace facebook;
|
|
20
20
|
|
|
21
|
-
class JHybridVersionCheckSpec: public
|
|
22
|
-
public virtual HybridVersionCheckSpec {
|
|
21
|
+
class JHybridVersionCheckSpec: public virtual HybridVersionCheckSpec, public virtual JHybridObject {
|
|
23
22
|
public:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
HybridBase
|
|
33
|
-
|
|
23
|
+
struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {
|
|
24
|
+
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroversioncheck/HybridVersionCheckSpec;";
|
|
25
|
+
std::shared_ptr<JHybridVersionCheckSpec> getJHybridVersionCheckSpec();
|
|
26
|
+
};
|
|
27
|
+
struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {
|
|
28
|
+
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroversioncheck/HybridVersionCheckSpec$CxxPart;";
|
|
29
|
+
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
|
|
30
|
+
static void registerNatives();
|
|
31
|
+
using HybridBase::HybridBase;
|
|
32
|
+
protected:
|
|
33
|
+
std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;
|
|
34
|
+
};
|
|
34
35
|
|
|
35
36
|
public:
|
|
37
|
+
explicit JHybridVersionCheckSpec(const jni::local_ref<JHybridVersionCheckSpec::JavaPart>& javaPart):
|
|
38
|
+
HybridObject(HybridVersionCheckSpec::TAG),
|
|
39
|
+
JHybridObject(javaPart),
|
|
40
|
+
_javaPart(jni::make_global(javaPart)) {}
|
|
36
41
|
~JHybridVersionCheckSpec() override {
|
|
37
42
|
// Hermes GC can destroy JS objects on a non-JNI Thread.
|
|
38
43
|
jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
public:
|
|
42
|
-
|
|
43
|
-
bool equals(const std::shared_ptr<HybridObject>& other) override;
|
|
44
|
-
void dispose() noexcept override;
|
|
45
|
-
std::string toString() override;
|
|
46
|
-
|
|
47
|
-
public:
|
|
48
|
-
inline const jni::global_ref<JHybridVersionCheckSpec::javaobject>& getJavaPart() const noexcept {
|
|
47
|
+
inline const jni::global_ref<JHybridVersionCheckSpec::JavaPart>& getJavaPart() const noexcept {
|
|
49
48
|
return _javaPart;
|
|
50
49
|
}
|
|
51
50
|
|
|
@@ -59,14 +58,12 @@ namespace margelo::nitro::nitroversioncheck {
|
|
|
59
58
|
public:
|
|
60
59
|
// Methods
|
|
61
60
|
std::string getCountry() override;
|
|
62
|
-
std::shared_ptr<Promise<std::string>> getStoreUrl() override;
|
|
63
|
-
std::shared_ptr<Promise<std::string>> getLatestVersion() override;
|
|
61
|
+
std::shared_ptr<Promise<std::string>> getStoreUrl(const std::optional<std::string>& countryCode) override;
|
|
62
|
+
std::shared_ptr<Promise<std::string>> getLatestVersion(const std::optional<std::string>& countryCode) override;
|
|
64
63
|
std::shared_ptr<Promise<bool>> needsUpdate() override;
|
|
65
64
|
|
|
66
65
|
private:
|
|
67
|
-
|
|
68
|
-
using HybridBase::HybridBase;
|
|
69
|
-
jni::global_ref<JHybridVersionCheckSpec::javaobject> _javaPart;
|
|
66
|
+
jni::global_ref<JHybridVersionCheckSpec::JavaPart> _javaPart;
|
|
70
67
|
};
|
|
71
68
|
|
|
72
69
|
} // namespace margelo::nitro::nitroversioncheck
|
|
@@ -25,23 +25,6 @@ import com.margelo.nitro.core.HybridObject
|
|
|
25
25
|
"LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName"
|
|
26
26
|
)
|
|
27
27
|
abstract class HybridVersionCheckSpec: HybridObject() {
|
|
28
|
-
@DoNotStrip
|
|
29
|
-
private var mHybridData: HybridData = initHybrid()
|
|
30
|
-
|
|
31
|
-
init {
|
|
32
|
-
super.updateNative(mHybridData)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
override fun updateNative(hybridData: HybridData) {
|
|
36
|
-
mHybridData = hybridData
|
|
37
|
-
super.updateNative(hybridData)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Default implementation of `HybridObject.toString()`
|
|
41
|
-
override fun toString(): String {
|
|
42
|
-
return "[HybridObject VersionCheck]"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
28
|
// Properties
|
|
46
29
|
@get:DoNotStrip
|
|
47
30
|
@get:Keep
|
|
@@ -66,17 +49,31 @@ abstract class HybridVersionCheckSpec: HybridObject() {
|
|
|
66
49
|
|
|
67
50
|
@DoNotStrip
|
|
68
51
|
@Keep
|
|
69
|
-
abstract fun getStoreUrl(): Promise<String>
|
|
52
|
+
abstract fun getStoreUrl(countryCode: String?): Promise<String>
|
|
70
53
|
|
|
71
54
|
@DoNotStrip
|
|
72
55
|
@Keep
|
|
73
|
-
abstract fun getLatestVersion(): Promise<String>
|
|
56
|
+
abstract fun getLatestVersion(countryCode: String?): Promise<String>
|
|
74
57
|
|
|
75
58
|
@DoNotStrip
|
|
76
59
|
@Keep
|
|
77
60
|
abstract fun needsUpdate(): Promise<Boolean>
|
|
78
61
|
|
|
79
|
-
|
|
62
|
+
// Default implementation of `HybridObject.toString()`
|
|
63
|
+
override fun toString(): String {
|
|
64
|
+
return "[HybridObject VersionCheck]"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// C++ backing class
|
|
68
|
+
@DoNotStrip
|
|
69
|
+
@Keep
|
|
70
|
+
protected open class CxxPart(javaPart: HybridVersionCheckSpec): HybridObject.CxxPart(javaPart) {
|
|
71
|
+
// C++ JHybridVersionCheckSpec::CxxPart::initHybrid(...)
|
|
72
|
+
external override fun initHybrid(): HybridData
|
|
73
|
+
}
|
|
74
|
+
override fun createCxxPart(): CxxPart {
|
|
75
|
+
return CxxPart(this)
|
|
76
|
+
}
|
|
80
77
|
|
|
81
78
|
companion object {
|
|
82
79
|
protected const val TAG = "HybridVersionCheckSpec"
|
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-version-check",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
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",
|
|
@@ -8,9 +8,8 @@
|
|
|
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 .",
|
|
@@ -149,17 +151,20 @@
|
|
|
149
151
|
},
|
|
150
152
|
"devDependencies": {
|
|
151
153
|
"@release-it/conventional-changelog": "^10.0.5",
|
|
154
|
+
"@types/jest": "^29.5.12",
|
|
152
155
|
"@types/react": "^19.1.03",
|
|
153
|
-
"
|
|
156
|
+
"jest": "^29.7.0",
|
|
157
|
+
"nitrogen": "^0.35.0",
|
|
154
158
|
"react": "19.2.0",
|
|
155
159
|
"react-native": "0.83.0",
|
|
156
160
|
"react-native-nitro-modules": "*",
|
|
157
161
|
"release-it": "^19.2.4",
|
|
162
|
+
"ts-jest": "^29.1.2",
|
|
158
163
|
"typescript": "^5.8.3"
|
|
159
164
|
},
|
|
160
165
|
"peerDependencies": {
|
|
161
166
|
"react": "*",
|
|
162
167
|
"react-native": "*",
|
|
163
|
-
"react-native-nitro-modules": ">=
|
|
168
|
+
"react-native-nitro-modules": ">=35.0"
|
|
164
169
|
}
|
|
165
170
|
}
|
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
|
-
}
|