@volley/vwr-loader 1.0.5 → 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 +21 -0
- package/dist/amplitudeFlagFetcher.d.ts +4 -2
- package/dist/amplitudeFlagFetcher.d.ts.map +1 -1
- package/dist/amplitudeFlagFetcher.js +26 -19
- package/dist/amplitudeFlagFetcher.js.map +1 -1
- package/dist/cli.js +213 -0
- package/dist/cli.js.map +1 -0
- package/dist/envDefaults.d.ts +3 -0
- package/dist/envDefaults.d.ts.map +1 -1
- package/dist/envDefaults.js +16 -4
- package/dist/envDefaults.js.map +1 -1
- package/dist/getDeviceId.d.ts +2 -40
- package/dist/getDeviceId.d.ts.map +1 -1
- package/dist/getDeviceId.js +31 -18
- package/dist/getDeviceId.js.map +1 -1
- package/dist/getEnvironment.d.ts +1 -1
- package/dist/getEnvironment.d.ts.map +1 -1
- package/dist/getEnvironment.js +15 -7
- package/dist/getEnvironment.js.map +1 -1
- package/dist/getShellVersion.d.ts +2 -19
- package/dist/getShellVersion.d.ts.map +1 -1
- package/dist/getShellVersion.js +41 -6
- package/dist/getShellVersion.js.map +1 -1
- package/dist/index.html +1 -1
- package/dist/loadVwr.d.ts.map +1 -1
- package/dist/loadVwr.js +8 -6
- package/dist/loadVwr.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/vwrConfig.d.ts +2 -0
- package/dist/vwrConfig.d.ts.map +1 -1
- package/dist/vwrConfig.js +148 -119
- package/dist/vwrConfig.js.map +1 -1
- package/package.json +16 -5
- package/src/amplitudeFlagFetcher.test.ts +36 -59
- package/src/amplitudeFlagFetcher.ts +31 -22
- package/src/envDefaults.ts +23 -4
- package/src/getDeviceId.test.ts +89 -27
- package/src/getDeviceId.ts +35 -58
- package/src/getEnvironment.test.ts +479 -0
- package/src/getEnvironment.ts +16 -8
- package/src/getShellVersion.test.ts +123 -4
- package/src/getShellVersion.ts +46 -21
- package/src/loadVwr.ts +13 -6
- package/src/main.ts +3 -1
- package/src/types.ts +88 -0
- package/src/vite-env.d.ts +3 -0
- package/src/vwrConfig.test.ts +2 -2
- package/src/vwrConfig.ts +202 -199
- package/eslint.config.mjs +0 -23
- package/scripts/build.js +0 -2
- package/scripts/build.ts +0 -207
- package/tsconfig.eslint.json +0 -16
- package/tsconfig.json +0 -17
- package/vite.config.ts +0 -24
- package/vitest.config.ts +0 -8
package/src/envDefaults.ts
CHANGED
|
@@ -3,7 +3,10 @@ export interface EnvConfig {
|
|
|
3
3
|
vwrUrl: string
|
|
4
4
|
configUrl: string
|
|
5
5
|
configFile: string
|
|
6
|
+
platformApiUrl: string
|
|
7
|
+
platformAuthApiUrl: string
|
|
6
8
|
amplitudeKey: string // Used for amplitude flag fetch, not part of VWRConfig
|
|
9
|
+
trustedOrigins?: string[]
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
const CONFIG_URL_DEFAULT = "https://vwr.volley.tv/config/"
|
|
@@ -15,22 +18,36 @@ const prodConfig: EnvConfig = {
|
|
|
15
18
|
vwrUrl: `https://vwr.volley.tv/${VWR_URL_PATH_DEFAULT}`,
|
|
16
19
|
configUrl: CONFIG_URL_DEFAULT,
|
|
17
20
|
configFile: CONFIG_FILE_DEFAULT,
|
|
21
|
+
platformApiUrl: "https://platform.volley-services.net",
|
|
22
|
+
platformAuthApiUrl: "https://auth.volley.tv",
|
|
18
23
|
amplitudeKey: "",
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export const ENV_DEFAULTS: Record<string, EnvConfig> = {
|
|
22
27
|
local: {
|
|
23
|
-
hubUrl: "http://localhost:5173",
|
|
24
|
-
vwrUrl: "http://localhost:5174/vwr.js",
|
|
25
|
-
configUrl:
|
|
26
|
-
|
|
28
|
+
hubUrl: import.meta.env.VITE_HUB_URL || "http://localhost:5173",
|
|
29
|
+
vwrUrl: import.meta.env.VITE_VWR_URL || "http://localhost:5174/vwr.js",
|
|
30
|
+
configUrl:
|
|
31
|
+
import.meta.env.VITE_CONFIG_URL || "http://localhost:5174/config/",
|
|
32
|
+
configFile: import.meta.env.VITE_CONFIG_FILE || CONFIG_FILE_DEFAULT,
|
|
33
|
+
platformApiUrl:
|
|
34
|
+
import.meta.env.VITE_PLATFORM_API_URL ||
|
|
35
|
+
"https://platform-dev.volley-services.net",
|
|
36
|
+
platformAuthApiUrl:
|
|
37
|
+
import.meta.env.VITE_PLATFORM_AUTH_API_URL ||
|
|
38
|
+
"https://auth-dev.volley.tv",
|
|
27
39
|
amplitudeKey: "client-uJJVW3zKPC1G9kqPhUumLnZN6eaY42iQ",
|
|
40
|
+
trustedOrigins: import.meta.env.VITE_TRUSTED_ORIGINS?.split(",").filter(
|
|
41
|
+
Boolean
|
|
42
|
+
),
|
|
28
43
|
},
|
|
29
44
|
dev: {
|
|
30
45
|
hubUrl: "https://game-clients-dev.volley.tv/hub",
|
|
31
46
|
vwrUrl: `https://vwr.volley.tv/dev/${VWR_URL_PATH_DEFAULT}`,
|
|
32
47
|
configUrl: CONFIG_URL_DEFAULT,
|
|
33
48
|
configFile: CONFIG_FILE_DEFAULT,
|
|
49
|
+
platformApiUrl: "https://platform-dev.volley-services.net",
|
|
50
|
+
platformAuthApiUrl: "https://auth-dev.volley.tv",
|
|
34
51
|
amplitudeKey: "client-uJJVW3zKPC1G9kqPhUumLnZN6eaY42iQ",
|
|
35
52
|
},
|
|
36
53
|
staging: {
|
|
@@ -38,6 +55,8 @@ export const ENV_DEFAULTS: Record<string, EnvConfig> = {
|
|
|
38
55
|
vwrUrl: `https://vwr.volley.tv/staging/${VWR_URL_PATH_DEFAULT}`,
|
|
39
56
|
configUrl: CONFIG_URL_DEFAULT,
|
|
40
57
|
configFile: CONFIG_FILE_DEFAULT,
|
|
58
|
+
platformApiUrl: "https://platform-staging.volley-services.net",
|
|
59
|
+
platformAuthApiUrl: "https://auth-staging.volley.tv",
|
|
41
60
|
amplitudeKey: "",
|
|
42
61
|
},
|
|
43
62
|
prod: prodConfig,
|
package/src/getDeviceId.test.ts
CHANGED
|
@@ -6,8 +6,9 @@ describe("getDeviceId", () => {
|
|
|
6
6
|
beforeEach(() => {
|
|
7
7
|
vi.clearAllMocks()
|
|
8
8
|
// Clean up window properties
|
|
9
|
-
delete (window as any).
|
|
10
|
-
delete (window as any).
|
|
9
|
+
delete (window as any).Capacitor
|
|
10
|
+
delete (window as any).iosAppContext
|
|
11
|
+
delete (window as any).androidAppContext
|
|
11
12
|
delete (window as any).webapis
|
|
12
13
|
delete (window as any).webOSDev
|
|
13
14
|
delete (window as any).webOS
|
|
@@ -15,21 +16,26 @@ describe("getDeviceId", () => {
|
|
|
15
16
|
|
|
16
17
|
afterEach(() => {
|
|
17
18
|
vi.restoreAllMocks()
|
|
18
|
-
delete (window as any).
|
|
19
|
-
delete (window as any).
|
|
19
|
+
delete (window as any).Capacitor
|
|
20
|
+
delete (window as any).iosAppContext
|
|
21
|
+
delete (window as any).androidAppContext
|
|
20
22
|
delete (window as any).webapis
|
|
21
23
|
delete (window as any).webOSDev
|
|
22
24
|
delete (window as any).webOS
|
|
23
25
|
})
|
|
24
26
|
|
|
25
27
|
describe("FIRE_TV platform", () => {
|
|
26
|
-
it("returns device ID from DeviceInfo.getAndroidId when available", async () => {
|
|
28
|
+
it("returns device ID from Capacitor DeviceInfo.getAndroidId when available", async () => {
|
|
27
29
|
const mockAndroidId = "firetv-android-id-123"
|
|
28
|
-
Object.defineProperty(window, "
|
|
30
|
+
Object.defineProperty(window, "Capacitor", {
|
|
29
31
|
value: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
Plugins: {
|
|
33
|
+
DeviceInfo: {
|
|
34
|
+
getAndroidId: vi.fn().mockResolvedValue({
|
|
35
|
+
androidId: mockAndroidId,
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
33
39
|
},
|
|
34
40
|
writable: true,
|
|
35
41
|
configurable: true,
|
|
@@ -40,11 +46,17 @@ describe("getDeviceId", () => {
|
|
|
40
46
|
})
|
|
41
47
|
|
|
42
48
|
it("returns null when DeviceInfo throws error", async () => {
|
|
43
|
-
Object.defineProperty(window, "
|
|
49
|
+
Object.defineProperty(window, "Capacitor", {
|
|
44
50
|
value: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
Plugins: {
|
|
52
|
+
DeviceInfo: {
|
|
53
|
+
getAndroidId: vi
|
|
54
|
+
.fn()
|
|
55
|
+
.mockRejectedValue(
|
|
56
|
+
new Error("DeviceInfo error")
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
},
|
|
48
60
|
},
|
|
49
61
|
writable: true,
|
|
50
62
|
configurable: true,
|
|
@@ -55,9 +67,15 @@ describe("getDeviceId", () => {
|
|
|
55
67
|
})
|
|
56
68
|
|
|
57
69
|
it("returns null when DeviceInfo returns empty", async () => {
|
|
58
|
-
Object.defineProperty(window, "
|
|
70
|
+
Object.defineProperty(window, "Capacitor", {
|
|
59
71
|
value: {
|
|
60
|
-
|
|
72
|
+
Plugins: {
|
|
73
|
+
DeviceInfo: {
|
|
74
|
+
getAndroidId: vi
|
|
75
|
+
.fn()
|
|
76
|
+
.mockResolvedValue({ androidId: "" }),
|
|
77
|
+
},
|
|
78
|
+
},
|
|
61
79
|
},
|
|
62
80
|
writable: true,
|
|
63
81
|
configurable: true,
|
|
@@ -147,33 +165,77 @@ describe("getDeviceId", () => {
|
|
|
147
165
|
})
|
|
148
166
|
})
|
|
149
167
|
|
|
150
|
-
describe("
|
|
151
|
-
it("returns device ID from
|
|
152
|
-
const mockDeviceId = "
|
|
153
|
-
Object.defineProperty(window, "
|
|
168
|
+
describe("IOS_MOBILE platform", () => {
|
|
169
|
+
it("returns device ID from iosAppContext when available", async () => {
|
|
170
|
+
const mockDeviceId = "ios-device-123"
|
|
171
|
+
Object.defineProperty(window, "iosAppContext", {
|
|
172
|
+
value: {
|
|
173
|
+
phoneDeviceId: mockDeviceId,
|
|
174
|
+
},
|
|
175
|
+
writable: true,
|
|
176
|
+
configurable: true,
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const result = await getDeviceId("IOS_MOBILE")
|
|
180
|
+
expect(result).toBe(mockDeviceId)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it("returns null when no app context is available", async () => {
|
|
184
|
+
const result = await getDeviceId("IOS_MOBILE")
|
|
185
|
+
expect(result).toBeNull()
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it("returns null when phoneDeviceId is empty", async () => {
|
|
189
|
+
Object.defineProperty(window, "iosAppContext", {
|
|
190
|
+
value: {
|
|
191
|
+
phoneDeviceId: "",
|
|
192
|
+
},
|
|
193
|
+
writable: true,
|
|
194
|
+
configurable: true,
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const result = await getDeviceId("IOS_MOBILE")
|
|
198
|
+
expect(result).toBeNull()
|
|
199
|
+
})
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
describe("ANDROID_MOBILE platform", () => {
|
|
203
|
+
it("returns device ID from androidAppContext when available", async () => {
|
|
204
|
+
const mockDeviceId = "android-device-123"
|
|
205
|
+
Object.defineProperty(window, "androidAppContext", {
|
|
154
206
|
value: {
|
|
155
|
-
|
|
207
|
+
phoneDeviceId: mockDeviceId,
|
|
156
208
|
},
|
|
157
209
|
writable: true,
|
|
158
210
|
configurable: true,
|
|
159
211
|
})
|
|
160
212
|
|
|
161
|
-
const result = await getDeviceId("
|
|
213
|
+
const result = await getDeviceId("ANDROID_MOBILE")
|
|
162
214
|
expect(result).toBe(mockDeviceId)
|
|
163
215
|
})
|
|
164
216
|
|
|
165
|
-
it("
|
|
166
|
-
Object.defineProperty(window, "
|
|
217
|
+
it("prefers iosAppContext over androidAppContext", async () => {
|
|
218
|
+
Object.defineProperty(window, "iosAppContext", {
|
|
219
|
+
value: {
|
|
220
|
+
phoneDeviceId: "ios-id",
|
|
221
|
+
},
|
|
222
|
+
writable: true,
|
|
223
|
+
configurable: true,
|
|
224
|
+
})
|
|
225
|
+
Object.defineProperty(window, "androidAppContext", {
|
|
167
226
|
value: {
|
|
168
|
-
|
|
169
|
-
.fn()
|
|
170
|
-
.mockRejectedValue(new Error("Native error")),
|
|
227
|
+
phoneDeviceId: "android-id",
|
|
171
228
|
},
|
|
172
229
|
writable: true,
|
|
173
230
|
configurable: true,
|
|
174
231
|
})
|
|
175
232
|
|
|
176
|
-
const result = await getDeviceId("
|
|
233
|
+
const result = await getDeviceId("ANDROID_MOBILE")
|
|
234
|
+
expect(result).toBe("ios-id")
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it("returns null when no app context is available", async () => {
|
|
238
|
+
const result = await getDeviceId("ANDROID_MOBILE")
|
|
177
239
|
expect(result).toBeNull()
|
|
178
240
|
})
|
|
179
241
|
})
|
package/src/getDeviceId.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defaultLogger, type Logger } from "./logger"
|
|
2
|
+
import type { LGDeviceIdResponse, MobileExtendedWindow } from "./types"
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Get a unique device identifier for the current platform.
|
|
@@ -7,12 +8,12 @@ import { defaultLogger, type Logger } from "./logger"
|
|
|
7
8
|
*
|
|
8
9
|
* Platform handling:
|
|
9
10
|
* - FireTV: DeviceInfo (Capacitor plugin)
|
|
10
|
-
* - Android/iOS:
|
|
11
|
+
* - Android/iOS: window.iosAppContext / window.androidAppContext (phoneDeviceId)
|
|
11
12
|
* - Samsung TV: webapis
|
|
12
13
|
* - LG TV: webOS Luna service
|
|
13
14
|
* - Web: localStorage (with generated UUID fallback)
|
|
14
15
|
*
|
|
15
|
-
* @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', '
|
|
16
|
+
* @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'ANDROID_MOBILE', 'IOS_MOBILE', 'WEB')
|
|
16
17
|
* @param logger - Optional logger for error reporting. Defaults to defaultLogger.
|
|
17
18
|
* @returns A promise that resolves to a unique device identifier string, or null if retrieval fails
|
|
18
19
|
*
|
|
@@ -36,7 +37,8 @@ export async function getDeviceId(
|
|
|
36
37
|
return await getSamsungDeviceId(logger)
|
|
37
38
|
case "LG_TV":
|
|
38
39
|
return await getLGDeviceId(logger)
|
|
39
|
-
case "
|
|
40
|
+
case "ANDROID_MOBILE":
|
|
41
|
+
case "IOS_MOBILE":
|
|
40
42
|
return await getMobileDeviceId(logger)
|
|
41
43
|
case "WEB":
|
|
42
44
|
return getLocalStorageDeviceId()
|
|
@@ -84,24 +86,40 @@ async function getFireTVDeviceId(logger: Logger): Promise<string | null> {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
/**
|
|
87
|
-
* Attempt to get device ID from
|
|
89
|
+
* Attempt to get device ID from mobile app context (Android/iOS)
|
|
90
|
+
*
|
|
91
|
+
* iOS exposes phoneDeviceId via window.iosAppContext
|
|
92
|
+
* Android exposes phoneDeviceId via window.androidAppContext (also check window.top for iframes)
|
|
88
93
|
*/
|
|
89
|
-
|
|
94
|
+
function getMobileDeviceId(logger: Logger): string | null {
|
|
95
|
+
// Try iOS first
|
|
96
|
+
const iosId = (window as MobileExtendedWindow).iosAppContext?.phoneDeviceId
|
|
97
|
+
if (iosId && iosId.trim()) {
|
|
98
|
+
return iosId
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Try Android (check both window and window.top for iframe scenarios)
|
|
102
|
+
const androidContext = (window as MobileExtendedWindow).androidAppContext
|
|
90
103
|
try {
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
const androidId =
|
|
105
|
+
androidContext?.phoneDeviceId ??
|
|
106
|
+
(window.top as MobileExtendedWindow | null)?.androidAppContext
|
|
107
|
+
?.phoneDeviceId
|
|
108
|
+
if (androidId && androidId.trim()) {
|
|
109
|
+
return androidId
|
|
93
110
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
logger.error("NativeBridge.getDeviceId returned empty")
|
|
111
|
+
} catch {
|
|
112
|
+
// window.top access can throw if cross-origin
|
|
113
|
+
const androidId = androidContext?.phoneDeviceId
|
|
114
|
+
if (androidId && androidId.trim()) {
|
|
115
|
+
return androidId
|
|
100
116
|
}
|
|
101
|
-
} catch (error) {
|
|
102
|
-
const message = "NativeBridge.getDeviceId failed:"
|
|
103
|
-
logger.error(message, { error })
|
|
104
117
|
}
|
|
118
|
+
|
|
119
|
+
logger.error("[VWR:MobileDeviceId] phoneDeviceId not found", {
|
|
120
|
+
iosAppContext: !!(window as MobileExtendedWindow).iosAppContext,
|
|
121
|
+
androidAppContext: !!androidContext,
|
|
122
|
+
})
|
|
105
123
|
return null
|
|
106
124
|
}
|
|
107
125
|
|
|
@@ -202,45 +220,4 @@ async function getLGDeviceId(logger: Logger): Promise<string | null> {
|
|
|
202
220
|
})
|
|
203
221
|
}
|
|
204
222
|
|
|
205
|
-
//
|
|
206
|
-
interface LGDeviceIdResponse {
|
|
207
|
-
idList?: Array<{
|
|
208
|
-
idValue?: string
|
|
209
|
-
}>
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Type augmentation for platform-specific APIs
|
|
213
|
-
// Note: Capacitor types are declared in getShellVersion.ts with index signatures
|
|
214
|
-
// to allow extensibility. Additional methods used here are accessed via
|
|
215
|
-
// the index signatures [key: string]: any
|
|
216
|
-
declare global {
|
|
217
|
-
interface Window {
|
|
218
|
-
DeviceInfo?: {
|
|
219
|
-
getAndroidId: () => Promise<{ androidId: string }>
|
|
220
|
-
}
|
|
221
|
-
NativeBridge?: {
|
|
222
|
-
getDeviceId: () => Promise<string>
|
|
223
|
-
}
|
|
224
|
-
webapis?: {
|
|
225
|
-
productinfo?: {
|
|
226
|
-
getDuid: () => string
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
webOS?: {
|
|
230
|
-
service?: {
|
|
231
|
-
request: (
|
|
232
|
-
uri: string,
|
|
233
|
-
options: {
|
|
234
|
-
method?: string
|
|
235
|
-
parameters?: Record<string, unknown>
|
|
236
|
-
onSuccess?: (response: LGDeviceIdResponse) => void
|
|
237
|
-
onFailure?: (error: { errorText?: string }) => void
|
|
238
|
-
subscribe?: boolean
|
|
239
|
-
}
|
|
240
|
-
) => {
|
|
241
|
-
cancel: () => void
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
223
|
+
// Types imported from ./types.ts
|