@volley/vwr-loader 1.0.4 → 1.0.5

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.
Files changed (49) hide show
  1. package/README.md +45 -21
  2. package/dist/envDefaults.d.ts +0 -3
  3. package/dist/envDefaults.d.ts.map +1 -1
  4. package/dist/envDefaults.js +4 -16
  5. package/dist/envDefaults.js.map +1 -1
  6. package/dist/getDeviceId.d.ts +10 -2
  7. package/dist/getDeviceId.d.ts.map +1 -1
  8. package/dist/getDeviceId.js +23 -39
  9. package/dist/getDeviceId.js.map +1 -1
  10. package/dist/getEnvironment.d.ts +25 -0
  11. package/dist/getEnvironment.d.ts.map +1 -0
  12. package/dist/getEnvironment.js +102 -0
  13. package/dist/getEnvironment.js.map +1 -0
  14. package/dist/getShellVersion.d.ts +2 -2
  15. package/dist/getShellVersion.d.ts.map +1 -1
  16. package/dist/getShellVersion.js +3 -5
  17. package/dist/getShellVersion.js.map +1 -1
  18. package/dist/index.html +1 -1
  19. package/dist/loadVwr.d.ts +6 -1
  20. package/dist/loadVwr.d.ts.map +1 -1
  21. package/dist/loadVwr.js +18 -10
  22. package/dist/loadVwr.js.map +1 -1
  23. package/dist/main.js +1 -1
  24. package/dist/main.js.map +1 -1
  25. package/dist/vwrConfig.d.ts +0 -2
  26. package/dist/vwrConfig.d.ts.map +1 -1
  27. package/dist/vwrConfig.js +7 -25
  28. package/dist/vwrConfig.js.map +1 -1
  29. package/eslint.config.mjs +23 -0
  30. package/package.json +4 -15
  31. package/scripts/build.js +2 -0
  32. package/scripts/build.ts +207 -0
  33. package/src/amplitudeFlagFetcher.test.ts +0 -5
  34. package/src/envDefaults.ts +4 -23
  35. package/src/getDeviceId.test.ts +24 -79
  36. package/src/getDeviceId.ts +31 -56
  37. package/src/getEnvironment.ts +137 -0
  38. package/src/getShellVersion.test.ts +1 -1
  39. package/src/getShellVersion.ts +3 -7
  40. package/src/loadVwr.ts +25 -14
  41. package/src/main.ts +1 -3
  42. package/src/vite-env.d.ts +0 -3
  43. package/src/vwrConfig.ts +7 -28
  44. package/tsconfig.eslint.json +16 -0
  45. package/tsconfig.json +17 -0
  46. package/vite.config.ts +24 -0
  47. package/vitest.config.ts +8 -0
  48. package/dist/cli.js +0 -190
  49. package/dist/cli.js.map +0 -1
@@ -6,9 +6,8 @@ describe("getDeviceId", () => {
6
6
  beforeEach(() => {
7
7
  vi.clearAllMocks()
8
8
  // Clean up window properties
9
- delete (window as any).Capacitor
10
- delete (window as any).iosAppContext
11
- delete (window as any).androidAppContext
9
+ delete (window as any).DeviceInfo
10
+ delete (window as any).NativeBridge
12
11
  delete (window as any).webapis
13
12
  delete (window as any).webOSDev
14
13
  delete (window as any).webOS
@@ -16,26 +15,21 @@ describe("getDeviceId", () => {
16
15
 
17
16
  afterEach(() => {
18
17
  vi.restoreAllMocks()
19
- delete (window as any).Capacitor
20
- delete (window as any).iosAppContext
21
- delete (window as any).androidAppContext
18
+ delete (window as any).DeviceInfo
19
+ delete (window as any).NativeBridge
22
20
  delete (window as any).webapis
23
21
  delete (window as any).webOSDev
24
22
  delete (window as any).webOS
25
23
  })
26
24
 
27
25
  describe("FIRE_TV platform", () => {
28
- it("returns device ID from Capacitor DeviceInfo.getAndroidId when available", async () => {
26
+ it("returns device ID from DeviceInfo.getAndroidId when available", async () => {
29
27
  const mockAndroidId = "firetv-android-id-123"
30
- Object.defineProperty(window, "Capacitor", {
28
+ Object.defineProperty(window, "DeviceInfo", {
31
29
  value: {
32
- Plugins: {
33
- DeviceInfo: {
34
- getAndroidId: vi.fn().mockResolvedValue({
35
- androidId: mockAndroidId,
36
- }),
37
- },
38
- },
30
+ getAndroidId: vi
31
+ .fn()
32
+ .mockResolvedValue({ androidId: mockAndroidId }),
39
33
  },
40
34
  writable: true,
41
35
  configurable: true,
@@ -46,17 +40,11 @@ describe("getDeviceId", () => {
46
40
  })
47
41
 
48
42
  it("returns null when DeviceInfo throws error", async () => {
49
- Object.defineProperty(window, "Capacitor", {
43
+ Object.defineProperty(window, "DeviceInfo", {
50
44
  value: {
51
- Plugins: {
52
- DeviceInfo: {
53
- getAndroidId: vi
54
- .fn()
55
- .mockRejectedValue(
56
- new Error("DeviceInfo error")
57
- ),
58
- },
59
- },
45
+ getAndroidId: vi
46
+ .fn()
47
+ .mockRejectedValue(new Error("DeviceInfo error")),
60
48
  },
61
49
  writable: true,
62
50
  configurable: true,
@@ -67,15 +55,9 @@ describe("getDeviceId", () => {
67
55
  })
68
56
 
69
57
  it("returns null when DeviceInfo returns empty", async () => {
70
- Object.defineProperty(window, "Capacitor", {
58
+ Object.defineProperty(window, "DeviceInfo", {
71
59
  value: {
72
- Plugins: {
73
- DeviceInfo: {
74
- getAndroidId: vi
75
- .fn()
76
- .mockResolvedValue({ androidId: "" }),
77
- },
78
- },
60
+ getAndroidId: vi.fn().mockResolvedValue({ androidId: "" }),
79
61
  },
80
62
  writable: true,
81
63
  configurable: true,
@@ -166,25 +148,11 @@ describe("getDeviceId", () => {
166
148
  })
167
149
 
168
150
  describe("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("MOBILE")
180
- expect(result).toBe(mockDeviceId)
181
- })
182
-
183
- it("returns device ID from androidAppContext when available", async () => {
184
- const mockDeviceId = "android-device-123"
185
- Object.defineProperty(window, "androidAppContext", {
151
+ it("returns device ID from NativeBridge when available", async () => {
152
+ const mockDeviceId = "native-device-123"
153
+ Object.defineProperty(window, "NativeBridge", {
186
154
  value: {
187
- phoneDeviceId: mockDeviceId,
155
+ getDeviceId: vi.fn().mockResolvedValue(mockDeviceId),
188
156
  },
189
157
  writable: true,
190
158
  configurable: true,
@@ -194,35 +162,12 @@ describe("getDeviceId", () => {
194
162
  expect(result).toBe(mockDeviceId)
195
163
  })
196
164
 
197
- it("prefers iosAppContext over androidAppContext", async () => {
198
- Object.defineProperty(window, "iosAppContext", {
199
- value: {
200
- phoneDeviceId: "ios-id",
201
- },
202
- writable: true,
203
- configurable: true,
204
- })
205
- Object.defineProperty(window, "androidAppContext", {
206
- value: {
207
- phoneDeviceId: "android-id",
208
- },
209
- writable: true,
210
- configurable: true,
211
- })
212
-
213
- const result = await getDeviceId("MOBILE")
214
- expect(result).toBe("ios-id")
215
- })
216
-
217
- it("returns null when no app context is available", async () => {
218
- const result = await getDeviceId("MOBILE")
219
- expect(result).toBeNull()
220
- })
221
-
222
- it("returns null when phoneDeviceId is empty", async () => {
223
- Object.defineProperty(window, "iosAppContext", {
165
+ it("returns null when NativeBridge throws error", async () => {
166
+ Object.defineProperty(window, "NativeBridge", {
224
167
  value: {
225
- phoneDeviceId: "",
168
+ getDeviceId: vi
169
+ .fn()
170
+ .mockRejectedValue(new Error("Native error")),
226
171
  },
227
172
  writable: true,
228
173
  configurable: true,
@@ -7,12 +7,12 @@ import { defaultLogger, type Logger } from "./logger"
7
7
  *
8
8
  * Platform handling:
9
9
  * - FireTV: DeviceInfo (Capacitor plugin)
10
- * - Android/iOS: window.iosAppContext / window.androidAppContext (phoneDeviceId)
10
+ * - Android/iOS: NativeBridge
11
11
  * - Samsung TV: webapis
12
12
  * - LG TV: webOS Luna service
13
13
  * - Web: localStorage (with generated UUID fallback)
14
14
  *
15
- * @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'ANDROID_MOBILE', 'IOS_MOBILE', 'WEB')
15
+ * @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'MOBILE', 'WEB')
16
16
  * @param logger - Optional logger for error reporting. Defaults to defaultLogger.
17
17
  * @returns A promise that resolves to a unique device identifier string, or null if retrieval fails
18
18
  *
@@ -36,9 +36,7 @@ export async function getDeviceId(
36
36
  return await getSamsungDeviceId(logger)
37
37
  case "LG_TV":
38
38
  return await getLGDeviceId(logger)
39
- case "ANDROID_MOBILE":
40
- case "IOS_MOBILE":
41
- case "MOBILE": // Legacy/Generic
39
+ case "MOBILE": // iOS and Android
42
40
  return await getMobileDeviceId(logger)
43
41
  case "WEB":
44
42
  return getLocalStorageDeviceId()
@@ -66,62 +64,44 @@ function getLocalStorageDeviceId(): string {
66
64
  */
67
65
  async function getFireTVDeviceId(logger: Logger): Promise<string | null> {
68
66
  try {
69
- // Access via Capacitor.Plugins (standard Capacitor plugin access)
70
- const Capacitor = (window as any).Capacitor
71
- const DeviceInfo = Capacitor?.Plugins?.DeviceInfo
72
-
73
- if (!DeviceInfo?.getAndroidId) {
67
+ if (!window.Capacitor?.Plugins?.DeviceInfo?.getAndroidId) {
74
68
  return null
75
69
  }
76
70
 
77
- const result = await DeviceInfo.getAndroidId()
71
+ const result = await window.Capacitor.Plugins.DeviceInfo.getAndroidId()
78
72
  if (result?.androidId && result.androidId.trim()) {
79
73
  return result.androidId
80
74
  } else {
81
- logger.error("DeviceInfo.getAndroidId returned empty")
75
+ logger.error(
76
+ "Capacitor.Plugins.DeviceInfo.getAndroidId returned empty"
77
+ )
82
78
  }
83
79
  } catch (error) {
84
- const message = "DeviceInfo.getAndroidId failed:"
80
+ const message = "Capacitor.Plugins.DeviceInfo.getAndroidId failed:"
85
81
  logger.error(message, { error })
86
82
  }
87
83
  return null
88
84
  }
89
85
 
90
86
  /**
91
- * Attempt to get device ID from mobile app context (Android/iOS)
92
- *
93
- * iOS exposes phoneDeviceId via window.iosAppContext
94
- * Android exposes phoneDeviceId via window.androidAppContext (also check window.top for iframes)
87
+ * Attempt to get device ID from Native Bridge (Android/iOS)
95
88
  */
96
- function getMobileDeviceId(logger: Logger): string | null {
97
- // Try iOS first
98
- const iosId = (window as ExtendedWindow).iosAppContext?.phoneDeviceId
99
- if (iosId && iosId.trim()) {
100
- return iosId
101
- }
102
-
103
- // Try Android (check both window and window.top for iframe scenarios)
104
- const androidContext = (window as ExtendedWindow).androidAppContext
89
+ async function getMobileDeviceId(logger: Logger): Promise<string | null> {
105
90
  try {
106
- const androidId =
107
- androidContext?.phoneDeviceId ??
108
- (window.top as ExtendedWindow | null)?.androidAppContext
109
- ?.phoneDeviceId
110
- if (androidId && androidId.trim()) {
111
- return androidId
91
+ if (!window.NativeBridge?.getDeviceId) {
92
+ return null
112
93
  }
113
- } catch {
114
- // window.top access can throw if cross-origin
115
- const androidId = androidContext?.phoneDeviceId
116
- if (androidId && androidId.trim()) {
117
- return androidId
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")
118
100
  }
101
+ } catch (error) {
102
+ const message = "NativeBridge.getDeviceId failed:"
103
+ logger.error(message, { error })
119
104
  }
120
-
121
- logger.error("[VWR:MobileDeviceId] phoneDeviceId not found", {
122
- iosAppContext: !!(window as ExtendedWindow).iosAppContext,
123
- androidAppContext: !!androidContext,
124
- })
125
105
  return null
126
106
  }
127
107
 
@@ -229,23 +209,18 @@ interface LGDeviceIdResponse {
229
209
  }>
230
210
  }
231
211
 
232
- /**
233
- * Extended window interface for mobile app context
234
- * Matches the types from @volley/sdk ExtendedWindow.ts
235
- */
236
- interface ExtendedWindow extends Window {
237
- iosAppContext?: {
238
- phoneDeviceId: string
239
- }
240
- androidAppContext?: {
241
- phoneDeviceId: string
242
- }
243
- }
244
-
245
212
  // Type augmentation for platform-specific APIs
246
- // Note: Capacitor types are declared in getShellVersion.ts with flexible index signatures
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
247
216
  declare global {
248
217
  interface Window {
218
+ DeviceInfo?: {
219
+ getAndroidId: () => Promise<{ androidId: string }>
220
+ }
221
+ NativeBridge?: {
222
+ getDeviceId: () => Promise<string>
223
+ }
249
224
  webapis?: {
250
225
  productinfo?: {
251
226
  getDuid: () => string
@@ -0,0 +1,137 @@
1
+ import { defaultLogger, type Logger } from "./logger"
2
+
3
+ export type Environment = "local" | "dev" | "staging" | "prod"
4
+ export type EnvironmentSource = "native" | "build-time" | "default"
5
+
6
+ export interface EnvironmentResult {
7
+ environment: Environment
8
+ source: EnvironmentSource
9
+ }
10
+
11
+ /**
12
+ * Get the environment for the current platform.
13
+ *
14
+ * Precedence:
15
+ * 1. Native shell (Fire TV only) - reads from BuildConfig.ENVIRONMENT
16
+ * 2. Build-time injection (VITE_ENVIRONMENT) - CLI override
17
+ * 3. Default fallback ("dev")
18
+ *
19
+ * This ensures production APKs cannot accidentally run dev VWR,
20
+ * since the native Android build variant determines the environment.
21
+ *
22
+ * @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'MOBILE', 'WEB')
23
+ * @param buildTimeEnv - Optional build-time injected environment (from CLI)
24
+ * @param logger - Optional logger for reporting
25
+ * @returns Environment result with source information for logging
26
+ */
27
+ export async function getEnvironment(
28
+ platform: string,
29
+ buildTimeEnv: string | undefined,
30
+ logger: Logger = defaultLogger
31
+ ): Promise<EnvironmentResult> {
32
+ const normalizedPlatform = platform.toUpperCase()
33
+
34
+ // For Fire TV, try to read from native first (safest - prevents env mismatch)
35
+ if (normalizedPlatform === "FIRE_TV") {
36
+ const nativeEnv = await getFireTVEnvironment(logger)
37
+ if (nativeEnv) {
38
+ const mapped = mapNativeEnvironment(nativeEnv)
39
+ logger.info(
40
+ `[Shell] Environment: "${mapped}" (source: native BuildConfig.ENVIRONMENT="${nativeEnv}")`
41
+ )
42
+ return { environment: mapped, source: "native" }
43
+ }
44
+ // Fall through to build-time if native fails
45
+ logger.warn(
46
+ "[Shell] Failed to read environment from native, falling back to build-time"
47
+ )
48
+ }
49
+
50
+ // Build-time injection (CLI --env flag)
51
+ if (buildTimeEnv && isValidEnvironment(buildTimeEnv)) {
52
+ logger.info(
53
+ `[Shell] Environment: "${buildTimeEnv}" (source: build-time CLI injection)`
54
+ )
55
+ return {
56
+ environment: buildTimeEnv as Environment,
57
+ source: "build-time",
58
+ }
59
+ }
60
+
61
+ // Default fallback
62
+ const defaultEnv: Environment = "dev"
63
+ logger.warn(
64
+ `[Shell] Environment: "${defaultEnv}" (source: default fallback - no native or build-time env found)`
65
+ )
66
+ return { environment: defaultEnv, source: "default" }
67
+ }
68
+
69
+ /**
70
+ * Read environment from Fire TV native shell via Capacitor plugin.
71
+ */
72
+ async function getFireTVEnvironment(logger: Logger): Promise<string | null> {
73
+ try {
74
+ if (
75
+ !window.Capacitor?.Plugins?.DeviceInfo?.getNativeShellAppEnvironment
76
+ ) {
77
+ logger.warn(
78
+ "[Shell] DeviceInfo.getNativeShellAppEnvironment not available"
79
+ )
80
+ return null
81
+ }
82
+
83
+ const result =
84
+ await window.Capacitor.Plugins.DeviceInfo.getNativeShellAppEnvironment()
85
+ if (result?.environment && result.environment.trim()) {
86
+ return result.environment
87
+ } else {
88
+ logger.error(
89
+ "[Shell] DeviceInfo.getNativeShellAppEnvironment returned empty"
90
+ )
91
+ }
92
+ } catch (error) {
93
+ logger.error(
94
+ "[Shell] DeviceInfo.getNativeShellAppEnvironment failed:",
95
+ { error }
96
+ )
97
+ }
98
+ return null
99
+ }
100
+
101
+ /**
102
+ * Map native Android BuildConfig.ENVIRONMENT values to vwr-loader environment names.
103
+ *
104
+ * Android BuildConfig values:
105
+ * - "development" (debug build)
106
+ * - "staging" (staging build)
107
+ * - "production" (release build)
108
+ *
109
+ * VWR environment names:
110
+ * - "dev"
111
+ * - "staging"
112
+ * - "prod"
113
+ */
114
+ function mapNativeEnvironment(nativeEnv: string): Environment {
115
+ const normalized = nativeEnv.toLowerCase()
116
+ switch (normalized) {
117
+ case "development":
118
+ return "dev"
119
+ case "staging":
120
+ return "staging"
121
+ case "production":
122
+ return "prod"
123
+ default:
124
+ // If it's already in vwr format, use it
125
+ if (isValidEnvironment(normalized)) {
126
+ return normalized as Environment
127
+ }
128
+ return "dev"
129
+ }
130
+ }
131
+
132
+ function isValidEnvironment(env: string): boolean {
133
+ return ["local", "dev", "staging", "prod"].includes(env)
134
+ }
135
+
136
+ // Note: Window.Capacitor type is declared in getDeviceId.ts
137
+ // We just need to add the getNativeShellAppEnvironment method type there
@@ -268,7 +268,7 @@ describe("getShellVersion", () => {
268
268
  expect(version).toBe("unknown")
269
269
  expect(consoleWarnSpy).toHaveBeenCalledWith(
270
270
  "[Shell] Failed to get shell version:",
271
- { error: expect.any(Error) }
271
+ expect.any(Error)
272
272
  )
273
273
 
274
274
  consoleWarnSpy.mockRestore()
@@ -7,10 +7,10 @@ import { defaultLogger, type Logger } from "./logger"
7
7
  * - SAMSUNG_TV: Tizen Application API `tizen.application.getAppInfo().version`
8
8
  * - LG_TV: webOS Application API `webOS.fetchAppInfo()`
9
9
  * - FIRE_TV: Native bridge via Capacitor DeviceInfo plugin
10
- * - ANDROID_MOBILE/IOS_MOBILE: Native bridge (future implementation)
10
+ * - MOBILE: Native bridge (future implementation)
11
11
  * - WEB/Unknown: Returns 'unknown'
12
12
  *
13
- * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, ANDROID_MOBILE, IOS_MOBILE, WEB)
13
+ * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, MOBILE, WEB)
14
14
  * @param logger - Optional logger for warning reporting. Defaults to defaultLogger.
15
15
  * @returns Shell version string or 'unknown' if not available
16
16
  */
@@ -66,11 +66,7 @@ export async function getShellVersion(
66
66
  }
67
67
 
68
68
  // Mobile: Future implementation via native bridge
69
- if (
70
- normalizedPlatform === "ANDROID_MOBILE" ||
71
- normalizedPlatform === "IOS_MOBILE" ||
72
- normalizedPlatform === "MOBILE"
73
- ) {
69
+ if (normalizedPlatform === "MOBILE") {
74
70
  // TODO: Implement native bridge version retrieval when available
75
71
  return "unknown"
76
72
  }
package/src/loadVwr.ts CHANGED
@@ -1,15 +1,17 @@
1
- import type * as VWR from "@volley/vwr"
2
-
3
1
  import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
4
2
  import { ENV_DEFAULTS } from "./envDefaults"
5
3
  import { getDeviceId } from "./getDeviceId"
4
+ import { getEnvironment } from "./getEnvironment"
6
5
  import { getShellVersion } from "./getShellVersion"
7
6
  import { defaultLogger, type Logger } from "./logger"
8
7
  import type { VWRConfig, VWRConfigRequest } from "./vwrConfig"
9
8
  import { getVWRConfig, validateConfig } from "./vwrConfig"
10
9
 
11
10
  // Vite injects these at build time
12
- const ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT
11
+ // VITE_ENVIRONMENT is optional for platforms that support native env reading (Fire TV)
12
+ const BUILD_TIME_ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT as
13
+ | string
14
+ | undefined
13
15
  const PLATFORM = import.meta.env.VITE_PLATFORM
14
16
  const CONFIG_URL = import.meta.env.VITE_CONFIG_URL
15
17
  const CONFIG_FILE = import.meta.env.VITE_CONFIG_FILE
@@ -28,15 +30,20 @@ export type { Logger }
28
30
  * this reduces startup latency from ~2-4s to ~500ms by skipping config fetches.
29
31
  *
30
32
  * Flow:
31
- * 1. Get deviceId, shellVersion (fast, local)
33
+ * 1. Get deviceId, shellVersion, environment (fast, local/native)
32
34
  * 2. Check vwr-enabled flag (single request, ~500ms)
33
35
  * 3. If OFF → throw immediately (no config fetches)
34
36
  * 4. If ON → fetch config, load VWR module, initialize
35
37
  *
38
+ * Environment resolution:
39
+ * - Fire TV: reads from native BuildConfig.ENVIRONMENT (prevents env mismatch)
40
+ * - Other platforms: uses build-time injected VITE_ENVIRONMENT
41
+ * - Fallback: "dev"
42
+ *
36
43
  * @param logger - Optional logger, defaults to console
37
44
  */
38
45
  export const loadVwr = async (logger: Logger = defaultLogger) => {
39
- if (!ENVIRONMENT || !PLATFORM || !CONFIG_URL || !CONFIG_FILE) {
46
+ if (!PLATFORM || !CONFIG_URL || !CONFIG_FILE) {
40
47
  throw new Error("[Shell] Build config not injected properly")
41
48
  }
42
49
 
@@ -48,6 +55,14 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
48
55
  }
49
56
  const shellVersion = await getShellVersion(PLATFORM, logger)
50
57
 
58
+ // Get environment from native (Fire TV) or build-time injection
59
+ // This ensures prod APKs cannot accidentally run dev VWR
60
+ const { environment: ENVIRONMENT } = await getEnvironment(
61
+ PLATFORM,
62
+ BUILD_TIME_ENVIRONMENT,
63
+ logger
64
+ )
65
+
51
66
  // Get amplitude key: injected at build time OR from envDefaults
52
67
  // Precedence: build-time injection > envDefaults
53
68
  let amplitudeKey = AMPLITUDE_KEY
@@ -100,10 +115,7 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
100
115
  vwrUrl: vwrConfig.vwrUrl,
101
116
  })
102
117
  try {
103
- const vwr = (await import(
104
- /* @vite-ignore */ vwrConfig.vwrUrl
105
- )) as typeof VWR
106
-
118
+ const vwr = await import(/* @vite-ignore */ vwrConfig.vwrUrl)
107
119
  logger.info("[Shell] VWR module loaded successfully")
108
120
 
109
121
  if (typeof vwr.init !== "function") {
@@ -112,12 +124,11 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
112
124
 
113
125
  await vwr.init({
114
126
  hubUrl: vwrConfig.hubUrl,
127
+ launchUrl: vwrConfig.launchUrl,
115
128
  platform: PLATFORM,
116
- stage: ENVIRONMENT,
117
- appVersion: shellVersion,
118
- platformApiUrl: vwrConfig.platformApiUrl,
119
- platformAuthApiUrl: vwrConfig.platformAuthApiUrl,
120
- trustedOrigins: new Set(vwrConfig.trustedDomains),
129
+ deviceId,
130
+ environment: ENVIRONMENT,
131
+ trustedDomains: vwrConfig.trustedDomains,
121
132
  nativeShellVersion: shellVersion,
122
133
  })
123
134
  logger.info("[Shell] VWR initialized successfully")
package/src/main.ts CHANGED
@@ -18,9 +18,7 @@ async function init() {
18
18
  }
19
19
  } finally {
20
20
  //Fallback, can't trust config exists
21
- const fallbackUrl = new URL(HUB_URL)
22
- fallbackUrl.searchParams.set("volley_platform", PLATFORM)
23
- window.location.href = fallbackUrl.toString()
21
+ window.location.href = HUB_URL
24
22
  }
25
23
  }
26
24
  }
package/src/vite-env.d.ts CHANGED
@@ -8,9 +8,6 @@ interface ImportMetaEnv {
8
8
  readonly VITE_SHELL_VERSION: string
9
9
  readonly VITE_CONFIG_URL: string
10
10
  readonly VITE_CONFIG_FILE: string
11
- readonly VITE_PLATFORM_API_URL: string
12
- readonly VITE_PLATFORM_AUTH_API_URL: string
13
- readonly VITE_TRUSTED_ORIGINS: string
14
11
  }
15
12
 
16
13
  interface ImportMeta {
package/src/vwrConfig.ts CHANGED
@@ -5,8 +5,6 @@ export type VWRConfig = {
5
5
  hubUrl: string
6
6
  vwrUrl: string
7
7
  launchUrl: string | undefined
8
- platformApiUrl: string
9
- platformAuthApiUrl: string
10
8
  trustedDomains: Array<string>
11
9
  }
12
10
 
@@ -234,14 +232,6 @@ const tryGetVWRConfig = async (
234
232
  const parseConfig = (config: VWRConfig): VWRConfig => {
235
233
  const defaultConfig = getDefaultConfig()
236
234
 
237
- if (!config.platformApiUrl) {
238
- config.platformApiUrl = defaultConfig.platformApiUrl
239
- }
240
-
241
- if (!config.platformAuthApiUrl) {
242
- config.platformAuthApiUrl = defaultConfig.platformAuthApiUrl
243
- }
244
-
245
235
  if (
246
236
  !Array.isArray(config.trustedDomains) ||
247
237
  config.trustedDomains.length === 0
@@ -251,26 +241,21 @@ const parseConfig = (config: VWRConfig): VWRConfig => {
251
241
 
252
242
  if (!config.vwrUrl) {
253
243
  config.vwrUrl = defaultConfig.vwrUrl
254
- const vwrUrlOrigin = new URL(defaultConfig.vwrUrl).origin
255
- if (!config.trustedDomains.includes(vwrUrlOrigin)) {
256
- config.trustedDomains.push(vwrUrlOrigin)
244
+ if (!config.trustedDomains.includes(defaultConfig.vwrUrl)) {
245
+ config.trustedDomains.push(defaultConfig.vwrUrl)
257
246
  }
258
247
  }
259
248
 
260
249
  if (!config.hubUrl) {
261
250
  config.hubUrl = defaultConfig.hubUrl
262
- const hubUrlOrigin = new URL(defaultConfig.hubUrl).origin
263
- if (!config.trustedDomains.includes(hubUrlOrigin)) {
264
- config.trustedDomains.push(hubUrlOrigin)
251
+ if (!config.trustedDomains.includes(defaultConfig.hubUrl)) {
252
+ config.trustedDomains.push(defaultConfig.hubUrl)
265
253
  }
266
254
  }
267
255
 
268
256
  // launchUrl is optional - only add to trustedDomains if explicitly set
269
- if (config.launchUrl) {
270
- const launchUrlOrigin = new URL(config.launchUrl).origin
271
- if (!config.trustedDomains.includes(launchUrlOrigin)) {
272
- config.trustedDomains.push(launchUrlOrigin)
273
- }
257
+ if (config.launchUrl && !config.trustedDomains.includes(config.launchUrl)) {
258
+ config.trustedDomains.push(config.launchUrl)
274
259
  }
275
260
 
276
261
  return config
@@ -303,12 +288,6 @@ const getDefaultConfig = (): VWRConfig => {
303
288
  hubUrl: defaults.hubUrl,
304
289
  vwrUrl: defaults.vwrUrl,
305
290
  launchUrl: undefined,
306
- platformApiUrl: defaults.platformApiUrl,
307
- platformAuthApiUrl: defaults.platformAuthApiUrl,
308
- trustedDomains: [
309
- new URL(defaults.hubUrl).origin,
310
- new URL(defaults.vwrUrl).origin,
311
- ...(defaults.trustedOrigins ?? []),
312
- ],
291
+ trustedDomains: [defaults.hubUrl, defaults.vwrUrl],
313
292
  }
314
293
  }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": [
4
+ "src/**/*",
5
+ "scripts/**/*",
6
+ "vite.config.ts",
7
+ "vitest.config.ts",
8
+ "**/*.test.ts"
9
+ ],
10
+ "exclude": ["node_modules", "dist"],
11
+ "compilerOptions": {
12
+ "noEmit": true,
13
+ "types": ["node", "vite/client", "vitest/globals"]
14
+ }
15
+ }
16
+