@codeimplants/version-control 1.0.5 → 1.0.7
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 +1 -2
- package/dist/client.js +4 -4
- package/dist/detector.d.ts +3 -3
- package/dist/detector.d.ts.map +1 -1
- package/dist/detector.js +116 -22
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +12 -3
- package/package.json +1 -1
- package/src/client.ts +4 -4
- package/src/detector.ts +107 -22
- package/src/sdk.ts +16 -4
package/README.md
CHANGED
|
@@ -105,8 +105,7 @@ Checks in order:
|
|
|
105
105
|
Checks in order:
|
|
106
106
|
|
|
107
107
|
1. Capacitor App plugin bundle ID
|
|
108
|
-
2.
|
|
109
|
-
3. Fallback: `"unknown.app"`
|
|
108
|
+
2. Fallback: `"unknown.app"`
|
|
110
109
|
|
|
111
110
|
## Configuration
|
|
112
111
|
|
package/dist/client.js
CHANGED
|
@@ -2,10 +2,10 @@ export async function fetchRules(config) {
|
|
|
2
2
|
const controller = new AbortController();
|
|
3
3
|
const id = setTimeout(() => controller.abort(), config.timeout || 8000);
|
|
4
4
|
const body = {
|
|
5
|
-
appId: config.appId
|
|
6
|
-
platform: config.platform
|
|
7
|
-
currentVersion: config.version
|
|
8
|
-
environment: "prod"
|
|
5
|
+
appId: config.appId, // Send undefined if missing
|
|
6
|
+
platform: config.platform, // Send undefined if missing
|
|
7
|
+
currentVersion: config.version, // Send undefined if missing
|
|
8
|
+
environment: "prod"
|
|
9
9
|
};
|
|
10
10
|
if (config.debug) {
|
|
11
11
|
console.log("[VC-SDK] Request Body:", body);
|
package/dist/detector.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Platform } from "./types";
|
|
2
|
-
export declare function detectPlatform(): Promise<Platform>;
|
|
3
|
-
export declare function detectVersion(): Promise<string>;
|
|
4
|
-
export declare function detectAppId(): Promise<string>;
|
|
2
|
+
export declare function detectPlatform(): Promise<Platform | undefined>;
|
|
3
|
+
export declare function detectVersion(): Promise<string | undefined>;
|
|
4
|
+
export declare function detectAppId(): Promise<string | undefined>;
|
|
5
5
|
//# sourceMappingURL=detector.d.ts.map
|
package/dist/detector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAoDpE;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA+CjE;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA8C/D"}
|
package/dist/detector.js
CHANGED
|
@@ -1,29 +1,63 @@
|
|
|
1
1
|
export async function detectPlatform() {
|
|
2
|
-
var _a, _b;
|
|
3
|
-
if (typeof window === "undefined")
|
|
4
|
-
|
|
2
|
+
var _a, _b, _c;
|
|
3
|
+
if (typeof window === "undefined") {
|
|
4
|
+
// Node environment or similar
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
5
7
|
const win = window;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
try {
|
|
9
|
+
// 1. Try React Native detection
|
|
10
|
+
if (((_a = win.navigator) === null || _a === void 0 ? void 0 : _a.product) === "ReactNative") {
|
|
11
|
+
// Attempt to dynamically require Platform from react-native
|
|
12
|
+
// This works in Metro bundler environments
|
|
13
|
+
try {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const RN = require("react-native");
|
|
16
|
+
if (RN && RN.Platform && (RN.Platform.OS === "android" || RN.Platform.OS === "ios")) {
|
|
17
|
+
return RN.Platform.OS;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
// ignore
|
|
22
|
+
}
|
|
23
|
+
// Fallback for RN if require fails but we know it's RN
|
|
24
|
+
// We might return "android" or "ios" if we can infer from userAgent, otherwise return undefined to let backend decide or user override
|
|
25
|
+
const ua = ((_c = (_b = win.navigator) === null || _b === void 0 ? void 0 : _b.userAgent) === null || _c === void 0 ? void 0 : _c.toLowerCase()) || "";
|
|
26
|
+
if (ua.includes("android"))
|
|
27
|
+
return "android";
|
|
28
|
+
if (ua.includes("iphone") || ua.includes("ipad"))
|
|
29
|
+
return "ios";
|
|
30
|
+
return undefined; // Let SDK user provide it explicitly if we can't be sure
|
|
31
|
+
}
|
|
32
|
+
// 2. Try Capacitor detection
|
|
33
|
+
if (win.Capacitor) {
|
|
34
|
+
if (win.Capacitor.isNativePlatform()) {
|
|
35
|
+
const platform = win.Capacitor.getPlatform();
|
|
36
|
+
if (platform === "android" || platform === "ios")
|
|
37
|
+
return platform;
|
|
38
|
+
}
|
|
39
|
+
// Even if not native, Capacitor.getPlatform() might return 'web'
|
|
40
|
+
// We can check if we are truly in a Capacitor shell
|
|
41
|
+
}
|
|
42
|
+
// 3. Browser / Web detection
|
|
43
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
44
|
+
if (ua.includes("android"))
|
|
45
|
+
return "android";
|
|
46
|
+
if (ua.includes("iphone") || ua.includes("ipad") || ua.includes("ipod"))
|
|
47
|
+
return "ios";
|
|
48
|
+
return "web";
|
|
11
49
|
}
|
|
12
|
-
|
|
13
|
-
|
|
50
|
+
catch (e) {
|
|
51
|
+
console.warn("[VC-SDK] Error detecting platform:", e);
|
|
52
|
+
return undefined;
|
|
14
53
|
}
|
|
15
|
-
const ua = navigator.userAgent.toLowerCase();
|
|
16
|
-
if (ua.includes("android"))
|
|
17
|
-
return "android";
|
|
18
|
-
if (ua.includes("iphone") || ua.includes("ipad") || ua.includes("ipod"))
|
|
19
|
-
return "ios";
|
|
20
|
-
return "web";
|
|
21
54
|
}
|
|
22
55
|
export async function detectVersion() {
|
|
23
|
-
var _a, _b;
|
|
56
|
+
var _a, _b, _c;
|
|
24
57
|
const win = window;
|
|
25
58
|
if (typeof window === "undefined")
|
|
26
|
-
return
|
|
59
|
+
return undefined;
|
|
60
|
+
// 1. Capacitor
|
|
27
61
|
if ((_b = (_a = win.Capacitor) === null || _a === void 0 ? void 0 : _a.Plugins) === null || _b === void 0 ? void 0 : _b.App) {
|
|
28
62
|
try {
|
|
29
63
|
const info = await win.Capacitor.Plugins.App.getInfo();
|
|
@@ -34,18 +68,47 @@ export async function detectVersion() {
|
|
|
34
68
|
// ignore
|
|
35
69
|
}
|
|
36
70
|
}
|
|
71
|
+
// 2. React Native (Expo / DeviceInfo)
|
|
72
|
+
try {
|
|
73
|
+
if (((_c = win.navigator) === null || _c === void 0 ? void 0 : _c.product) === "ReactNative") {
|
|
74
|
+
// Try Expo Constants
|
|
75
|
+
try {
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
const Constants = require("expo-constants").default;
|
|
78
|
+
if (Constants && Constants.manifest && Constants.manifest.version) {
|
|
79
|
+
return Constants.manifest.version;
|
|
80
|
+
}
|
|
81
|
+
if (Constants && Constants.expoConfig && Constants.expoConfig.version) {
|
|
82
|
+
return Constants.expoConfig.version;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e) { }
|
|
86
|
+
// Try replace-native-device-info
|
|
87
|
+
try {
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
const DeviceInfo = require("react-native-device-info");
|
|
90
|
+
if (DeviceInfo && DeviceInfo.getVersion) {
|
|
91
|
+
return DeviceInfo.getVersion();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (e) { }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) { }
|
|
98
|
+
// 3. Globals
|
|
37
99
|
const versionKeys = ["APP_VERSION", "__VERSION__", "VERSION", "packageVersion"];
|
|
38
100
|
for (const key of versionKeys) {
|
|
39
101
|
if (win[key])
|
|
40
102
|
return win[key];
|
|
41
103
|
}
|
|
42
|
-
return
|
|
104
|
+
return undefined;
|
|
43
105
|
}
|
|
44
106
|
export async function detectAppId() {
|
|
45
|
-
var _a, _b;
|
|
107
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
46
108
|
const win = window;
|
|
47
109
|
if (typeof window === "undefined")
|
|
48
|
-
return
|
|
110
|
+
return undefined;
|
|
111
|
+
// 1. Capacitor
|
|
49
112
|
if ((_b = (_a = win.Capacitor) === null || _a === void 0 ? void 0 : _a.Plugins) === null || _b === void 0 ? void 0 : _b.App) {
|
|
50
113
|
try {
|
|
51
114
|
const info = await win.Capacitor.Plugins.App.getInfo();
|
|
@@ -56,10 +119,41 @@ export async function detectAppId() {
|
|
|
56
119
|
// ignore
|
|
57
120
|
}
|
|
58
121
|
}
|
|
122
|
+
// 2. React Native (Expo / DeviceInfo)
|
|
123
|
+
try {
|
|
124
|
+
if (((_c = win.navigator) === null || _c === void 0 ? void 0 : _c.product) === "ReactNative") {
|
|
125
|
+
// Try Expo Constants
|
|
126
|
+
try {
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
const Constants = require("expo-constants").default;
|
|
129
|
+
// Expo Go app ID or standalone bundle ID
|
|
130
|
+
if ((_e = (_d = Constants === null || Constants === void 0 ? void 0 : Constants.manifest) === null || _d === void 0 ? void 0 : _d.android) === null || _e === void 0 ? void 0 : _e.package)
|
|
131
|
+
return Constants.manifest.android.package;
|
|
132
|
+
if ((_g = (_f = Constants === null || Constants === void 0 ? void 0 : Constants.manifest) === null || _f === void 0 ? void 0 : _f.ios) === null || _g === void 0 ? void 0 : _g.bundleIdentifier)
|
|
133
|
+
return Constants.manifest.ios.bundleIdentifier;
|
|
134
|
+
if ((_j = (_h = Constants === null || Constants === void 0 ? void 0 : Constants.expoConfig) === null || _h === void 0 ? void 0 : _h.android) === null || _j === void 0 ? void 0 : _j.package)
|
|
135
|
+
return Constants.expoConfig.android.package;
|
|
136
|
+
if ((_l = (_k = Constants === null || Constants === void 0 ? void 0 : Constants.expoConfig) === null || _k === void 0 ? void 0 : _k.ios) === null || _l === void 0 ? void 0 : _l.bundleIdentifier)
|
|
137
|
+
return Constants.expoConfig.ios.bundleIdentifier;
|
|
138
|
+
}
|
|
139
|
+
catch (e) { }
|
|
140
|
+
// Try react-native-device-info
|
|
141
|
+
try {
|
|
142
|
+
// @ts-ignore
|
|
143
|
+
const DeviceInfo = require("react-native-device-info");
|
|
144
|
+
if (DeviceInfo && DeviceInfo.getBundleId) {
|
|
145
|
+
return DeviceInfo.getBundleId();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (e) { }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (e) { }
|
|
152
|
+
// 3. Globals
|
|
59
153
|
const idKeys = ["APP_ID", "__APP_ID__", "BUNDLE_ID", "PACKAGE_NAME"];
|
|
60
154
|
for (const key of idKeys) {
|
|
61
155
|
if (win[key])
|
|
62
156
|
return win[key];
|
|
63
157
|
}
|
|
64
|
-
return
|
|
158
|
+
return undefined;
|
|
65
159
|
}
|
package/dist/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK/C,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAY;IAE1B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;WAc1D,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI9F,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK/C,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAY;IAE1B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;WAc1D,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI9F,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC;CAkE5C"}
|
package/dist/sdk.js
CHANGED
|
@@ -20,12 +20,17 @@ export class VersionSDK {
|
|
|
20
20
|
}
|
|
21
21
|
async checkVersion() {
|
|
22
22
|
try {
|
|
23
|
-
if
|
|
23
|
+
// Auto-detect only if NOT provided, but allow them to remain undefined if detection fails or is not desired.
|
|
24
|
+
// The backend should handle cases where appId or version are missing (e.g. web or simple API key check).
|
|
25
|
+
if (!this.config.platform) {
|
|
24
26
|
this.config.platform = await detectPlatform();
|
|
25
|
-
|
|
27
|
+
}
|
|
28
|
+
if (!this.config.version) {
|
|
26
29
|
this.config.version = await detectVersion();
|
|
27
|
-
|
|
30
|
+
}
|
|
31
|
+
if (!this.config.appId) {
|
|
28
32
|
this.config.appId = await detectAppId();
|
|
33
|
+
}
|
|
29
34
|
if (this.config.debug) {
|
|
30
35
|
console.log("[VC-SDK] Checking version for:", {
|
|
31
36
|
appId: this.config.appId,
|
|
@@ -33,6 +38,10 @@ export class VersionSDK {
|
|
|
33
38
|
version: this.config.version,
|
|
34
39
|
url: `${this.config.backendUrl}/sdk/version/check`
|
|
35
40
|
});
|
|
41
|
+
if (!this.config.platform || !this.config.version) {
|
|
42
|
+
console.warn("[VC-SDK] ⚠️ WARNING: Platform or Version not detected. Rules might not apply correctly.");
|
|
43
|
+
console.warn("[VC-SDK] Please ensure these are either auto-detectable or provided explicitly.");
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
const response = await fetchRules(this.config);
|
|
38
47
|
if (this.config.debug) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeimplants/version-control",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "A lightweight cross-platform SDK to remotely control app version behavior such as soft update, force update, and maintenance mode using backend-driven rules, without enforcing UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"version-control",
|
package/src/client.ts
CHANGED
|
@@ -5,10 +5,10 @@ export async function fetchRules(config: VCConfig) {
|
|
|
5
5
|
const id = setTimeout(() => controller.abort(), config.timeout || 8000);
|
|
6
6
|
|
|
7
7
|
const body = {
|
|
8
|
-
appId: config.appId
|
|
9
|
-
platform: config.platform
|
|
10
|
-
currentVersion: config.version
|
|
11
|
-
environment: "prod"
|
|
8
|
+
appId: config.appId, // Send undefined if missing
|
|
9
|
+
platform: config.platform, // Send undefined if missing
|
|
10
|
+
currentVersion: config.version, // Send undefined if missing
|
|
11
|
+
environment: "prod"
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
if (config.debug) {
|
package/src/detector.ts
CHANGED
|
@@ -1,32 +1,64 @@
|
|
|
1
1
|
import { Platform } from "./types";
|
|
2
2
|
|
|
3
|
-
export async function detectPlatform(): Promise<Platform> {
|
|
4
|
-
if (typeof window === "undefined")
|
|
3
|
+
export async function detectPlatform(): Promise<Platform | undefined> {
|
|
4
|
+
if (typeof window === "undefined") {
|
|
5
|
+
// Node environment or similar
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
5
8
|
|
|
6
9
|
const win = window as any;
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
try {
|
|
12
|
+
// 1. Try React Native detection
|
|
13
|
+
if (win.navigator?.product === "ReactNative") {
|
|
14
|
+
// Attempt to dynamically require Platform from react-native
|
|
15
|
+
// This works in Metro bundler environments
|
|
16
|
+
try {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
const RN = require("react-native");
|
|
19
|
+
if (RN && RN.Platform && (RN.Platform.OS === "android" || RN.Platform.OS === "ios")) {
|
|
20
|
+
return RN.Platform.OS as Platform;
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// ignore
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Fallback for RN if require fails but we know it's RN
|
|
27
|
+
// We might return "android" or "ios" if we can infer from userAgent, otherwise return undefined to let backend decide or user override
|
|
28
|
+
const ua = win.navigator?.userAgent?.toLowerCase() || "";
|
|
29
|
+
if (ua.includes("android")) return "android";
|
|
30
|
+
if (ua.includes("iphone") || ua.includes("ipad")) return "ios";
|
|
31
|
+
|
|
32
|
+
return undefined; // Let SDK user provide it explicitly if we can't be sure
|
|
33
|
+
}
|
|
13
34
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
// 2. Try Capacitor detection
|
|
36
|
+
if (win.Capacitor) {
|
|
37
|
+
if (win.Capacitor.isNativePlatform()) {
|
|
38
|
+
const platform = win.Capacitor.getPlatform();
|
|
39
|
+
if (platform === "android" || platform === "ios") return platform as Platform;
|
|
40
|
+
}
|
|
41
|
+
// Even if not native, Capacitor.getPlatform() might return 'web'
|
|
42
|
+
// We can check if we are truly in a Capacitor shell
|
|
43
|
+
}
|
|
17
44
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
45
|
+
// 3. Browser / Web detection
|
|
46
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
47
|
+
if (ua.includes("android")) return "android";
|
|
48
|
+
if (ua.includes("iphone") || ua.includes("ipad") || ua.includes("ipod")) return "ios";
|
|
21
49
|
|
|
22
|
-
|
|
50
|
+
return "web";
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.warn("[VC-SDK] Error detecting platform:", e);
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
23
55
|
}
|
|
24
56
|
|
|
25
|
-
export async function detectVersion(): Promise<string> {
|
|
57
|
+
export async function detectVersion(): Promise<string | undefined> {
|
|
26
58
|
const win = window as any;
|
|
59
|
+
if (typeof window === "undefined") return undefined;
|
|
27
60
|
|
|
28
|
-
|
|
29
|
-
|
|
61
|
+
// 1. Capacitor
|
|
30
62
|
if (win.Capacitor?.Plugins?.App) {
|
|
31
63
|
try {
|
|
32
64
|
const info = await win.Capacitor.Plugins.App.getInfo();
|
|
@@ -36,19 +68,46 @@ export async function detectVersion(): Promise<string> {
|
|
|
36
68
|
}
|
|
37
69
|
}
|
|
38
70
|
|
|
71
|
+
// 2. React Native (Expo / DeviceInfo)
|
|
72
|
+
try {
|
|
73
|
+
if (win.navigator?.product === "ReactNative") {
|
|
74
|
+
// Try Expo Constants
|
|
75
|
+
try {
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
const Constants = require("expo-constants").default;
|
|
78
|
+
if (Constants && Constants.manifest && Constants.manifest.version) {
|
|
79
|
+
return Constants.manifest.version;
|
|
80
|
+
}
|
|
81
|
+
if (Constants && Constants.expoConfig && Constants.expoConfig.version) {
|
|
82
|
+
return Constants.expoConfig.version;
|
|
83
|
+
}
|
|
84
|
+
} catch (e) { }
|
|
85
|
+
|
|
86
|
+
// Try replace-native-device-info
|
|
87
|
+
try {
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
const DeviceInfo = require("react-native-device-info");
|
|
90
|
+
if (DeviceInfo && DeviceInfo.getVersion) {
|
|
91
|
+
return DeviceInfo.getVersion();
|
|
92
|
+
}
|
|
93
|
+
} catch (e) { }
|
|
94
|
+
}
|
|
95
|
+
} catch (e) { }
|
|
96
|
+
|
|
97
|
+
// 3. Globals
|
|
39
98
|
const versionKeys = ["APP_VERSION", "__VERSION__", "VERSION", "packageVersion"];
|
|
40
99
|
for (const key of versionKeys) {
|
|
41
100
|
if (win[key]) return win[key];
|
|
42
101
|
}
|
|
43
102
|
|
|
44
|
-
return
|
|
103
|
+
return undefined;
|
|
45
104
|
}
|
|
46
105
|
|
|
47
|
-
export async function detectAppId(): Promise<string> {
|
|
106
|
+
export async function detectAppId(): Promise<string | undefined> {
|
|
48
107
|
const win = window as any;
|
|
108
|
+
if (typeof window === "undefined") return undefined;
|
|
49
109
|
|
|
50
|
-
|
|
51
|
-
|
|
110
|
+
// 1. Capacitor
|
|
52
111
|
if (win.Capacitor?.Plugins?.App) {
|
|
53
112
|
try {
|
|
54
113
|
const info = await win.Capacitor.Plugins.App.getInfo();
|
|
@@ -58,10 +117,36 @@ export async function detectAppId(): Promise<string> {
|
|
|
58
117
|
}
|
|
59
118
|
}
|
|
60
119
|
|
|
120
|
+
// 2. React Native (Expo / DeviceInfo)
|
|
121
|
+
try {
|
|
122
|
+
if (win.navigator?.product === "ReactNative") {
|
|
123
|
+
// Try Expo Constants
|
|
124
|
+
try {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
const Constants = require("expo-constants").default;
|
|
127
|
+
// Expo Go app ID or standalone bundle ID
|
|
128
|
+
if (Constants?.manifest?.android?.package) return Constants.manifest.android.package;
|
|
129
|
+
if (Constants?.manifest?.ios?.bundleIdentifier) return Constants.manifest.ios.bundleIdentifier;
|
|
130
|
+
if (Constants?.expoConfig?.android?.package) return Constants.expoConfig.android.package;
|
|
131
|
+
if (Constants?.expoConfig?.ios?.bundleIdentifier) return Constants.expoConfig.ios.bundleIdentifier;
|
|
132
|
+
} catch (e) { }
|
|
133
|
+
|
|
134
|
+
// Try react-native-device-info
|
|
135
|
+
try {
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
const DeviceInfo = require("react-native-device-info");
|
|
138
|
+
if (DeviceInfo && DeviceInfo.getBundleId) {
|
|
139
|
+
return DeviceInfo.getBundleId();
|
|
140
|
+
}
|
|
141
|
+
} catch (e) { }
|
|
142
|
+
}
|
|
143
|
+
} catch (e) { }
|
|
144
|
+
|
|
145
|
+
// 3. Globals
|
|
61
146
|
const idKeys = ["APP_ID", "__APP_ID__", "BUNDLE_ID", "PACKAGE_NAME"];
|
|
62
147
|
for (const key of idKeys) {
|
|
63
148
|
if (win[key]) return win[key];
|
|
64
149
|
}
|
|
65
150
|
|
|
66
|
-
return
|
|
151
|
+
return undefined;
|
|
67
152
|
}
|
package/src/sdk.ts
CHANGED
|
@@ -26,10 +26,17 @@ export class VersionSDK {
|
|
|
26
26
|
|
|
27
27
|
async checkVersion(): Promise<VCDecision> {
|
|
28
28
|
try {
|
|
29
|
-
if
|
|
30
|
-
|
|
31
|
-
if (!this.config.
|
|
32
|
-
|
|
29
|
+
// Auto-detect only if NOT provided, but allow them to remain undefined if detection fails or is not desired.
|
|
30
|
+
// The backend should handle cases where appId or version are missing (e.g. web or simple API key check).
|
|
31
|
+
if (!this.config.platform) {
|
|
32
|
+
this.config.platform = await detectPlatform();
|
|
33
|
+
}
|
|
34
|
+
if (!this.config.version) {
|
|
35
|
+
this.config.version = await detectVersion();
|
|
36
|
+
}
|
|
37
|
+
if (!this.config.appId) {
|
|
38
|
+
this.config.appId = await detectAppId();
|
|
39
|
+
}
|
|
33
40
|
if (this.config.debug) {
|
|
34
41
|
console.log("[VC-SDK] Checking version for:", {
|
|
35
42
|
appId: this.config.appId,
|
|
@@ -37,6 +44,11 @@ export class VersionSDK {
|
|
|
37
44
|
version: this.config.version,
|
|
38
45
|
url: `${this.config.backendUrl}/sdk/version/check`
|
|
39
46
|
});
|
|
47
|
+
|
|
48
|
+
if (!this.config.platform || !this.config.version) {
|
|
49
|
+
console.warn("[VC-SDK] ⚠️ WARNING: Platform or Version not detected. Rules might not apply correctly.");
|
|
50
|
+
console.warn("[VC-SDK] Please ensure these are either auto-detectable or provided explicitly.");
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
const response = await fetchRules(this.config);
|