@volley/vwr-loader 1.0.0-alpha.1
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 +205 -0
- package/dist/amplitudeFlagFetcher.d.ts +23 -0
- package/dist/amplitudeFlagFetcher.d.ts.map +1 -0
- package/dist/amplitudeFlagFetcher.js +60 -0
- package/dist/amplitudeFlagFetcher.js.map +1 -0
- package/dist/cli.js +177 -0
- package/dist/cli.js.map +1 -0
- package/dist/envDefaults.d.ts +9 -0
- package/dist/envDefaults.d.ts.map +1 -0
- package/dist/envDefaults.js +36 -0
- package/dist/envDefaults.js.map +1 -0
- package/dist/getDeviceId.d.ts +65 -0
- package/dist/getDeviceId.d.ts.map +1 -0
- package/dist/getDeviceId.js +196 -0
- package/dist/getDeviceId.js.map +1 -0
- package/dist/getShellVersion.d.ts +34 -0
- package/dist/getShellVersion.d.ts.map +1 -0
- package/dist/getShellVersion.js +84 -0
- package/dist/getShellVersion.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.html +25 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/loadVwr.d.ts +19 -0
- package/dist/loadVwr.d.ts.map +1 -0
- package/dist/loadVwr.js +104 -0
- package/dist/loadVwr.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +6 -0
- package/dist/logger.js.map +1 -0
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -0
- package/dist/vwrConfig.d.ts +19 -0
- package/dist/vwrConfig.d.ts.map +1 -0
- package/dist/vwrConfig.js +172 -0
- package/dist/vwrConfig.js.map +1 -0
- package/package.json +54 -0
- package/src/amplitudeFlagFetcher.test.ts +209 -0
- package/src/amplitudeFlagFetcher.ts +88 -0
- package/src/envDefaults.ts +45 -0
- package/src/getDeviceId.test.ts +237 -0
- package/src/getDeviceId.ts +243 -0
- package/src/getShellVersion.test.ts +278 -0
- package/src/getShellVersion.ts +114 -0
- package/src/index.html +25 -0
- package/src/index.ts +8 -0
- package/src/loadVwr.ts +126 -0
- package/src/logger.ts +14 -0
- package/src/main.ts +26 -0
- package/src/vite-env.d.ts +15 -0
- package/src/vwrConfig.test.ts +316 -0
- package/src/vwrConfig.ts +293 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
|
2
|
+
|
|
3
|
+
import { getDeviceId } from "./getDeviceId"
|
|
4
|
+
|
|
5
|
+
describe("getDeviceId", () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.clearAllMocks()
|
|
8
|
+
// Clean up window properties
|
|
9
|
+
delete (window as any).DeviceInfo
|
|
10
|
+
delete (window as any).NativeBridge
|
|
11
|
+
delete (window as any).webapis
|
|
12
|
+
delete (window as any).webOSDev
|
|
13
|
+
delete (window as any).webOS
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
vi.restoreAllMocks()
|
|
18
|
+
delete (window as any).DeviceInfo
|
|
19
|
+
delete (window as any).NativeBridge
|
|
20
|
+
delete (window as any).webapis
|
|
21
|
+
delete (window as any).webOSDev
|
|
22
|
+
delete (window as any).webOS
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe("FIRE_TV platform", () => {
|
|
26
|
+
it("returns device ID from DeviceInfo.getAndroidId when available", async () => {
|
|
27
|
+
const mockAndroidId = "firetv-android-id-123"
|
|
28
|
+
Object.defineProperty(window, "DeviceInfo", {
|
|
29
|
+
value: {
|
|
30
|
+
getAndroidId: vi
|
|
31
|
+
.fn()
|
|
32
|
+
.mockResolvedValue({ androidId: mockAndroidId }),
|
|
33
|
+
},
|
|
34
|
+
writable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const result = await getDeviceId("FIRE_TV")
|
|
39
|
+
expect(result).toBe(mockAndroidId)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it("returns null when DeviceInfo throws error", async () => {
|
|
43
|
+
Object.defineProperty(window, "DeviceInfo", {
|
|
44
|
+
value: {
|
|
45
|
+
getAndroidId: vi
|
|
46
|
+
.fn()
|
|
47
|
+
.mockRejectedValue(new Error("DeviceInfo error")),
|
|
48
|
+
},
|
|
49
|
+
writable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const result = await getDeviceId("FIRE_TV")
|
|
54
|
+
expect(result).toBeNull()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it("returns null when DeviceInfo returns empty", async () => {
|
|
58
|
+
Object.defineProperty(window, "DeviceInfo", {
|
|
59
|
+
value: {
|
|
60
|
+
getAndroidId: vi.fn().mockResolvedValue({ androidId: "" }),
|
|
61
|
+
},
|
|
62
|
+
writable: true,
|
|
63
|
+
configurable: true,
|
|
64
|
+
})
|
|
65
|
+
const result = await getDeviceId("FIRE_TV")
|
|
66
|
+
expect(result).toBeNull()
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe("SAMSUNG_TV platform", () => {
|
|
71
|
+
it("returns device ID from Samsung webapis when available", async () => {
|
|
72
|
+
const mockDeviceId = "samsung-duid-123"
|
|
73
|
+
Object.defineProperty(window, "webapis", {
|
|
74
|
+
value: {
|
|
75
|
+
productinfo: {
|
|
76
|
+
getDuid: vi.fn().mockReturnValue(mockDeviceId),
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
writable: true,
|
|
80
|
+
configurable: true,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
const result = await getDeviceId("SAMSUNG_TV")
|
|
84
|
+
expect(result).toBe(mockDeviceId)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it("returns null when webapis throws error", async () => {
|
|
88
|
+
Object.defineProperty(window, "webapis", {
|
|
89
|
+
value: {
|
|
90
|
+
productinfo: {
|
|
91
|
+
getDuid: vi.fn().mockImplementation(() => {
|
|
92
|
+
throw new Error("Samsung API error")
|
|
93
|
+
}),
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
writable: true,
|
|
97
|
+
configurable: true,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const result = await getDeviceId("SAMSUNG_TV")
|
|
101
|
+
expect(result).toBeNull()
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
describe("LG_TV platform", () => {
|
|
106
|
+
it("returns device ID from LG webOS.service.request when available", async () => {
|
|
107
|
+
const mockDeviceId = "lg-udid-123"
|
|
108
|
+
const mockRequest = vi.fn().mockImplementation((_uri, options) => {
|
|
109
|
+
options.onSuccess?.({
|
|
110
|
+
idList: [{ idValue: mockDeviceId }],
|
|
111
|
+
})
|
|
112
|
+
return { cancel: vi.fn() }
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
Object.defineProperty(window, "webOS", {
|
|
116
|
+
value: {
|
|
117
|
+
service: {
|
|
118
|
+
request: mockRequest,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
writable: true,
|
|
122
|
+
configurable: true,
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const result = await getDeviceId("LG_TV")
|
|
126
|
+
expect(result).toBe(mockDeviceId)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it("returns null when webOS.service.request fails", async () => {
|
|
130
|
+
const mockRequest = vi.fn().mockImplementation((_uri, options) => {
|
|
131
|
+
options.onFailure?.({ errorText: "LG API error" })
|
|
132
|
+
return { cancel: vi.fn() }
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
Object.defineProperty(window, "webOS", {
|
|
136
|
+
value: {
|
|
137
|
+
service: {
|
|
138
|
+
request: mockRequest,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
writable: true,
|
|
142
|
+
configurable: true,
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
const result = await getDeviceId("LG_TV")
|
|
146
|
+
expect(result).toBeNull()
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
describe("MOBILE platform", () => {
|
|
151
|
+
it("returns device ID from NativeBridge when available", async () => {
|
|
152
|
+
const mockDeviceId = "native-device-123"
|
|
153
|
+
Object.defineProperty(window, "NativeBridge", {
|
|
154
|
+
value: {
|
|
155
|
+
getDeviceId: vi.fn().mockResolvedValue(mockDeviceId),
|
|
156
|
+
},
|
|
157
|
+
writable: true,
|
|
158
|
+
configurable: true,
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const result = await getDeviceId("MOBILE")
|
|
162
|
+
expect(result).toBe(mockDeviceId)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it("returns null when NativeBridge throws error", async () => {
|
|
166
|
+
Object.defineProperty(window, "NativeBridge", {
|
|
167
|
+
value: {
|
|
168
|
+
getDeviceId: vi
|
|
169
|
+
.fn()
|
|
170
|
+
.mockRejectedValue(new Error("Native error")),
|
|
171
|
+
},
|
|
172
|
+
writable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
const result = await getDeviceId("MOBILE")
|
|
177
|
+
expect(result).toBeNull()
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
describe("WEB platform", () => {
|
|
182
|
+
beforeEach(() => {
|
|
183
|
+
localStorage.clear()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it("generates and stores new device ID when none exists", async () => {
|
|
187
|
+
const mockUUID = "web-uuid-123"
|
|
188
|
+
Object.defineProperty(window.crypto, "randomUUID", {
|
|
189
|
+
value: vi.fn().mockReturnValue(mockUUID),
|
|
190
|
+
writable: true,
|
|
191
|
+
configurable: true,
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
const result = await getDeviceId("WEB")
|
|
195
|
+
|
|
196
|
+
expect(result).toBe(mockUUID)
|
|
197
|
+
expect(localStorage.getItem("volley_device_id")).toBe(mockUUID)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it("retrieves existing device ID from localStorage", async () => {
|
|
201
|
+
const existingId = "existing-web-id"
|
|
202
|
+
localStorage.setItem("volley_device_id", existingId)
|
|
203
|
+
|
|
204
|
+
const result = await getDeviceId("WEB")
|
|
205
|
+
|
|
206
|
+
expect(result).toBe(existingId)
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
describe("Unknown platform", () => {
|
|
211
|
+
it("returns null for unknown platform", async () => {
|
|
212
|
+
const result = await getDeviceId("UNKNOWN_PLATFORM")
|
|
213
|
+
expect(result).toBeNull()
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
describe("Case insensitivity", () => {
|
|
218
|
+
it("is case-insensitive for platform parameter", async () => {
|
|
219
|
+
const mockSamsungId = "samsung-case-test"
|
|
220
|
+
Object.defineProperty(window, "webapis", {
|
|
221
|
+
value: {
|
|
222
|
+
productinfo: {
|
|
223
|
+
getDuid: vi.fn().mockReturnValue(mockSamsungId),
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
writable: true,
|
|
227
|
+
configurable: true,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
const result1 = await getDeviceId("samsung_tv")
|
|
231
|
+
const result2 = await getDeviceId("SAMSUNG_TV")
|
|
232
|
+
|
|
233
|
+
expect(result1).toBe(mockSamsungId)
|
|
234
|
+
expect(result2).toBe(mockSamsungId)
|
|
235
|
+
})
|
|
236
|
+
})
|
|
237
|
+
})
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { defaultLogger, type Logger } from "./logger"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get a unique device identifier for the current platform.
|
|
5
|
+
*
|
|
6
|
+
* This function attempts to retrieve a device ID from platform-specific APIs.
|
|
7
|
+
*
|
|
8
|
+
* Platform handling:
|
|
9
|
+
* - FireTV: DeviceInfo (Capacitor plugin)
|
|
10
|
+
* - Android/iOS: NativeBridge
|
|
11
|
+
* - Samsung TV: webapis
|
|
12
|
+
* - LG TV: webOS Luna service
|
|
13
|
+
* - Web: localStorage (with generated UUID fallback)
|
|
14
|
+
*
|
|
15
|
+
* @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'ANDROID_MOBILE', 'IOS_MOBILE', 'WEB')
|
|
16
|
+
* @param logger - Optional logger for error reporting. Defaults to defaultLogger.
|
|
17
|
+
* @returns A promise that resolves to a unique device identifier string, or null if retrieval fails
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const deviceId = await getDeviceId('SAMSUNG_TV', logger)
|
|
22
|
+
* if (!deviceId) {
|
|
23
|
+
* // Handle error
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export async function getDeviceId(
|
|
28
|
+
platform: string,
|
|
29
|
+
logger: Logger = defaultLogger
|
|
30
|
+
): Promise<string | null> {
|
|
31
|
+
const normalizedPlatform = platform.toUpperCase()
|
|
32
|
+
switch (normalizedPlatform) {
|
|
33
|
+
case "FIRE_TV":
|
|
34
|
+
return await getFireTVDeviceId(logger)
|
|
35
|
+
case "SAMSUNG_TV":
|
|
36
|
+
return await getSamsungDeviceId(logger)
|
|
37
|
+
case "LG_TV":
|
|
38
|
+
return await getLGDeviceId(logger)
|
|
39
|
+
case "ANDROID_MOBILE":
|
|
40
|
+
case "IOS_MOBILE":
|
|
41
|
+
case "MOBILE": // Legacy/Generic
|
|
42
|
+
return await getMobileDeviceId(logger)
|
|
43
|
+
case "WEB":
|
|
44
|
+
return getLocalStorageDeviceId()
|
|
45
|
+
default:
|
|
46
|
+
const message = `[getDeviceId] Unknown platform: ${platform}`
|
|
47
|
+
logger.error(message)
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get or create device ID from localStorage (for Web platform)
|
|
54
|
+
*/
|
|
55
|
+
function getLocalStorageDeviceId(): string {
|
|
56
|
+
let deviceId = localStorage.getItem("volley_device_id")
|
|
57
|
+
if (!deviceId) {
|
|
58
|
+
deviceId = crypto.randomUUID()
|
|
59
|
+
localStorage.setItem("volley_device_id", deviceId)
|
|
60
|
+
}
|
|
61
|
+
return deviceId
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Attempt to get device ID from Capacitor DeviceInfo plugin (FireTV)
|
|
66
|
+
*/
|
|
67
|
+
async function getFireTVDeviceId(logger: Logger): Promise<string | null> {
|
|
68
|
+
try {
|
|
69
|
+
if (!window.DeviceInfo?.getAndroidId) {
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const result = await window.DeviceInfo.getAndroidId()
|
|
74
|
+
if (result?.androidId && result.androidId.trim()) {
|
|
75
|
+
return result.androidId
|
|
76
|
+
} else {
|
|
77
|
+
logger.error("DeviceInfo.getAndroidId returned empty")
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
const message = "DeviceInfo.getAndroidId failed:"
|
|
81
|
+
logger.error(message, { error })
|
|
82
|
+
}
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Attempt to get device ID from Native Bridge (Android/iOS)
|
|
88
|
+
*/
|
|
89
|
+
async function getMobileDeviceId(logger: Logger): Promise<string | null> {
|
|
90
|
+
try {
|
|
91
|
+
if (!window.NativeBridge?.getDeviceId) {
|
|
92
|
+
return null
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const id = await window.NativeBridge.getDeviceId()
|
|
96
|
+
if (id && id.trim()) {
|
|
97
|
+
return id
|
|
98
|
+
} else {
|
|
99
|
+
logger.error("NativeBridge.getDeviceId returned empty")
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const message = "NativeBridge.getDeviceId failed:"
|
|
103
|
+
logger.error(message, { error })
|
|
104
|
+
}
|
|
105
|
+
return null
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Attempt to get device ID from Samsung TV webapis
|
|
110
|
+
*/
|
|
111
|
+
async function getSamsungDeviceId(logger: Logger): Promise<string | null> {
|
|
112
|
+
try {
|
|
113
|
+
if (!window.webapis?.productinfo?.getDuid) {
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const id = window.webapis.productinfo.getDuid()
|
|
118
|
+
if (id && id.trim()) {
|
|
119
|
+
return id
|
|
120
|
+
} else {
|
|
121
|
+
logger.error("Samsung webapis.getDuid returned empty")
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const message = "Samsung webapis.getDuid failed:"
|
|
125
|
+
logger.error(message, { error })
|
|
126
|
+
}
|
|
127
|
+
return null
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Attempt to get device ID from LG TV using Luna Service.
|
|
132
|
+
*
|
|
133
|
+
* This implementation is copied from PSDK's LGTVDeviceInfo to ensure
|
|
134
|
+
* the shell and SDK return the exact same device ID.
|
|
135
|
+
*
|
|
136
|
+
* TODO: In the future, PSDK should import this function from vwr-loader
|
|
137
|
+
* to maintain a single source of truth for LG device ID retrieval.
|
|
138
|
+
*/
|
|
139
|
+
const LG_LUNA_SERVICE_TIMEOUT = 5000
|
|
140
|
+
|
|
141
|
+
async function getLGDeviceId(logger: Logger): Promise<string | null> {
|
|
142
|
+
if (!window.webOS?.service?.request) {
|
|
143
|
+
const message = "LG webOS service request not available"
|
|
144
|
+
logger.error(message)
|
|
145
|
+
return null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
|
150
|
+
let request: { cancel: () => void } | undefined
|
|
151
|
+
let resolved = false
|
|
152
|
+
|
|
153
|
+
const cleanup = () => {
|
|
154
|
+
if (timeoutId) {
|
|
155
|
+
clearTimeout(timeoutId)
|
|
156
|
+
timeoutId = undefined
|
|
157
|
+
}
|
|
158
|
+
request?.cancel()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const finish = (value: string | null) => {
|
|
162
|
+
if (resolved) return
|
|
163
|
+
resolved = true
|
|
164
|
+
cleanup()
|
|
165
|
+
resolve(value)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
timeoutId = setTimeout(() => {
|
|
169
|
+
const message = "LG Luna service timed out"
|
|
170
|
+
logger.error(message)
|
|
171
|
+
finish(null)
|
|
172
|
+
}, LG_LUNA_SERVICE_TIMEOUT)
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
request = window.webOS?.service?.request(
|
|
176
|
+
"luna://com.webos.service.sm",
|
|
177
|
+
{
|
|
178
|
+
method: "deviceid/getIDs",
|
|
179
|
+
parameters: { idType: ["LGUDID"] },
|
|
180
|
+
onSuccess: (response: LGDeviceIdResponse) => {
|
|
181
|
+
const deviceId = response.idList?.[0]?.idValue
|
|
182
|
+
if (!deviceId) {
|
|
183
|
+
const message =
|
|
184
|
+
"LG Luna service returned no device ID"
|
|
185
|
+
logger.error(message)
|
|
186
|
+
}
|
|
187
|
+
finish(deviceId || null)
|
|
188
|
+
},
|
|
189
|
+
onFailure: (error) => {
|
|
190
|
+
const message = "LG Luna service failed:"
|
|
191
|
+
logger.error(message, { error })
|
|
192
|
+
finish(null)
|
|
193
|
+
},
|
|
194
|
+
subscribe: false,
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
} catch (error) {
|
|
198
|
+
const message = "LG Luna service request threw error:"
|
|
199
|
+
logger.error(message, { error })
|
|
200
|
+
finish(null)
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Type definitions for LG Luna service response
|
|
206
|
+
interface LGDeviceIdResponse {
|
|
207
|
+
idList?: Array<{
|
|
208
|
+
idValue?: string
|
|
209
|
+
}>
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Type augmentation for platform-specific APIs
|
|
213
|
+
declare global {
|
|
214
|
+
interface Window {
|
|
215
|
+
DeviceInfo?: {
|
|
216
|
+
getAndroidId: () => Promise<{ androidId: string }>
|
|
217
|
+
}
|
|
218
|
+
NativeBridge?: {
|
|
219
|
+
getDeviceId: () => Promise<string>
|
|
220
|
+
}
|
|
221
|
+
webapis?: {
|
|
222
|
+
productinfo?: {
|
|
223
|
+
getDuid: () => string
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
webOS?: {
|
|
227
|
+
service?: {
|
|
228
|
+
request: (
|
|
229
|
+
uri: string,
|
|
230
|
+
options: {
|
|
231
|
+
method?: string
|
|
232
|
+
parameters?: Record<string, unknown>
|
|
233
|
+
onSuccess?: (response: LGDeviceIdResponse) => void
|
|
234
|
+
onFailure?: (error: { errorText?: string }) => void
|
|
235
|
+
subscribe?: boolean
|
|
236
|
+
}
|
|
237
|
+
) => {
|
|
238
|
+
cancel: () => void
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|