@volley/vwr-loader 1.0.4 → 1.0.6

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.
@@ -1,35 +1,20 @@
1
1
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
2
2
 
3
3
  import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
4
- import * as getShellVersionModule from "./getShellVersion"
5
4
 
6
5
  describe("fetchAmplitudeFlags", () => {
7
6
  const mockFetch = vi.fn()
8
- const originalLocation = window.location
9
7
 
10
8
  beforeEach(() => {
11
9
  global.fetch = mockFetch
12
10
  vi.clearAllMocks()
13
-
14
- // Mock window.location for getShellVersion
15
- delete (window as any).location
16
- window.location = {
17
- ...originalLocation,
18
- href: "http://localhost:3000/?version=1.0.0",
19
- } as Location
20
11
  })
21
12
 
22
13
  afterEach(() => {
23
- window.location = originalLocation
24
14
  vi.restoreAllMocks()
25
15
  })
26
16
 
27
17
  it("fetches flags successfully from Amplitude with context", async () => {
28
- // Mock getShellVersion to return expected version for SAMSUNG_TV
29
- vi.spyOn(getShellVersionModule, "getShellVersion").mockResolvedValue(
30
- "1.0.0"
31
- )
32
-
33
18
  mockFetch.mockResolvedValueOnce({
34
19
  ok: true,
35
20
  json: async () => ({
@@ -41,9 +26,12 @@ describe("fetchAmplitudeFlags", () => {
41
26
  }),
42
27
  })
43
28
 
44
- const result = await fetchAmplitudeFlags("device-123", "SAMSUNG_TV", {
45
- apiKey: "test-key",
46
- })
29
+ const result = await fetchAmplitudeFlags(
30
+ "device-123",
31
+ "SAMSUNG_TV",
32
+ { apiKey: "test-key" },
33
+ "1.0.0"
34
+ )
47
35
 
48
36
  expect(result).toEqual({
49
37
  "vwr-enabled": true,
@@ -103,45 +91,17 @@ describe("fetchAmplitudeFlags", () => {
103
91
  })
104
92
  })
105
93
 
106
- it("auto-fetches shell version when not provided", async () => {
107
- const getShellVersionSpy = vi.spyOn(
108
- getShellVersionModule,
109
- "getShellVersion"
110
- )
111
-
112
- mockFetch.mockResolvedValueOnce({
113
- ok: true,
114
- json: async () => ({
115
- "vwr-enabled": {
116
- payload: {
117
- "vwr-enabled": false,
118
- },
119
- },
120
- }),
121
- })
122
-
123
- await fetchAmplitudeFlags("device-456", "LG_TV", {
124
- apiKey: "test-key",
125
- })
126
-
127
- expect(getShellVersionSpy).toHaveBeenCalledWith("LG_TV")
128
-
129
- const callArgs = mockFetch.mock.calls[0]
130
- const url = new URL(callArgs[0])
131
- const context = JSON.parse(url.searchParams.get("context") || "{}")
132
-
133
- expect(context.user_properties).toHaveProperty("nativeShellAppVersion")
134
- })
135
-
136
94
  it("returns safe defaults on timeout", async () => {
137
95
  mockFetch.mockImplementationOnce(
138
96
  () => new Promise((resolve) => setTimeout(resolve, 3000))
139
97
  )
140
98
 
141
- const result = await fetchAmplitudeFlags("device-123", "FIRE_TV", {
142
- apiKey: "test-key",
143
- timeout: 100,
144
- })
99
+ const result = await fetchAmplitudeFlags(
100
+ "device-123",
101
+ "FIRE_TV",
102
+ { apiKey: "test-key", timeout: 100 },
103
+ "1.0.0"
104
+ )
145
105
 
146
106
  expect(result).toEqual({
147
107
  "vwr-enabled": false,
@@ -154,9 +114,12 @@ describe("fetchAmplitudeFlags", () => {
154
114
  status: 500,
155
115
  })
156
116
 
157
- const result = await fetchAmplitudeFlags("device-123", "MOBILE", {
158
- apiKey: "test-key",
159
- })
117
+ const result = await fetchAmplitudeFlags(
118
+ "device-123",
119
+ "MOBILE",
120
+ { apiKey: "test-key" },
121
+ "1.0.0"
122
+ )
160
123
 
161
124
  expect(result).toEqual({
162
125
  "vwr-enabled": false,
@@ -166,9 +129,12 @@ describe("fetchAmplitudeFlags", () => {
166
129
  it("returns safe defaults on network error", async () => {
167
130
  mockFetch.mockRejectedValueOnce(new Error("Network error"))
168
131
 
169
- const result = await fetchAmplitudeFlags("device-123", "MOBILE", {
170
- apiKey: "test-key",
171
- })
132
+ const result = await fetchAmplitudeFlags(
133
+ "device-123",
134
+ "MOBILE",
135
+ { apiKey: "test-key" },
136
+ "1.0.0"
137
+ )
172
138
 
173
139
  expect(result).toEqual({
174
140
  "vwr-enabled": false,
@@ -181,9 +147,12 @@ describe("fetchAmplitudeFlags", () => {
181
147
  json: async () => ({}),
182
148
  })
183
149
 
184
- const result = await fetchAmplitudeFlags("device-123", "LG_TV", {
185
- apiKey: "test-key",
186
- })
150
+ const result = await fetchAmplitudeFlags(
151
+ "device-123",
152
+ "LG_TV",
153
+ { apiKey: "test-key" },
154
+ "1.0.0"
155
+ )
187
156
 
188
157
  expect(result).toEqual({
189
158
  "vwr-enabled": false,
@@ -198,9 +167,12 @@ describe("fetchAmplitudeFlags", () => {
198
167
  }),
199
168
  })
200
169
 
201
- const result = await fetchAmplitudeFlags("device-123", "LG_TV", {
202
- apiKey: "test-key",
203
- })
170
+ const result = await fetchAmplitudeFlags(
171
+ "device-123",
172
+ "LG_TV",
173
+ { apiKey: "test-key" },
174
+ "1.0.0"
175
+ )
204
176
 
205
177
  expect(result).toEqual({
206
178
  "vwr-enabled": false,
@@ -1,4 +1,4 @@
1
- import { getShellVersion } from "./getShellVersion"
1
+ import { defaultLogger, type Logger } from "./logger"
2
2
 
3
3
  export interface AmplitudeConfig {
4
4
  apiKey: string
@@ -20,14 +20,16 @@ export interface FlagResult {
20
20
  * @param deviceId - Unique device identifier
21
21
  * @param platform - Platform name (samsung, lg, firetv, ios, android)
22
22
  * @param config - Amplitude configuration
23
- * @param shellVersion - Optional shell version (if not provided, will be fetched automatically)
23
+ * @param shellVersion - Shell version for flag targeting
24
+ * @param logger - Optional logger, defaults to console
24
25
  * @returns Flag values with safe defaults on error
25
26
  */
26
27
  export async function fetchAmplitudeFlags(
27
28
  deviceId: string,
28
29
  platform: string,
29
30
  config: AmplitudeConfig,
30
- shellVersion?: string
31
+ shellVersion: string,
32
+ logger: Logger = defaultLogger
31
33
  ): Promise<FlagResult> {
32
34
  const {
33
35
  apiKey,
@@ -35,28 +37,26 @@ export async function fetchAmplitudeFlags(
35
37
  timeout = 2000,
36
38
  } = config
37
39
 
40
+ // Build context with user_properties
41
+ const context = {
42
+ user_properties: {
43
+ platformEnum: platform,
44
+ nativeShellAppVersion: shellVersion,
45
+ },
46
+ }
47
+
48
+ // Build query parameters
49
+ const params = new URLSearchParams({
50
+ user_id: deviceId,
51
+ flag_keys: "vwr-enabled",
52
+ context: JSON.stringify(context),
53
+ })
54
+
55
+ // Start timeout immediately before the fetch call for accurate timing
38
56
  const controller = new AbortController()
39
57
  const timeoutId = setTimeout(() => controller.abort(), timeout)
40
58
 
41
59
  try {
42
- // Get shell version if not provided
43
- const version = shellVersion ?? (await getShellVersion(platform))
44
-
45
- // Build context with user_properties
46
- const context = {
47
- user_properties: {
48
- platformEnum: platform,
49
- nativeShellAppVersion: version,
50
- },
51
- }
52
-
53
- // Build query parameters
54
- const params = new URLSearchParams({
55
- user_id: deviceId,
56
- flag_keys: "vwr-enabled",
57
- context: JSON.stringify(context),
58
- })
59
-
60
60
  const response = await fetch(`${apiUrl}?${params}`, {
61
61
  method: "GET",
62
62
  headers: {
@@ -78,7 +78,16 @@ export async function fetchAmplitudeFlags(
78
78
  data["vwr-enabled"]?.payload?.["vwr-enabled"] ?? false,
79
79
  }
80
80
  } catch (error) {
81
- console.error("[Shell] Amplitude flag fetch failed:", error)
81
+ clearTimeout(timeoutId)
82
+
83
+ // Provide clear warning message for abort vs other errors
84
+ if (error instanceof Error && error.name === "AbortError") {
85
+ logger.warn(
86
+ `[Shell] Amplitude flag fetch aborted because it took longer than ${timeout}ms`
87
+ )
88
+ } else {
89
+ logger.warn("[Shell] Amplitude flag fetch failed:", { error })
90
+ }
82
91
 
83
92
  // Return safe defaults - runs legacy path
84
93
  return {
@@ -61,4 +61,14 @@ export const ENV_DEFAULTS: Record<string, EnvConfig> = {
61
61
  },
62
62
  prod: prodConfig,
63
63
  production: prodConfig, // Alias for prod
64
+ qa: {
65
+ // QA uses staging infrastructure
66
+ hubUrl: "https://game-clients-staging.volley.tv/hub",
67
+ vwrUrl: `https://vwr.volley.tv/staging/${VWR_URL_PATH_DEFAULT}`,
68
+ configUrl: CONFIG_URL_DEFAULT,
69
+ configFile: CONFIG_FILE_DEFAULT,
70
+ platformApiUrl: "https://platform-staging.volley-services.net",
71
+ platformAuthApiUrl: "https://auth-staging.volley.tv",
72
+ amplitudeKey: "",
73
+ },
64
74
  }
@@ -66,22 +66,20 @@ function getLocalStorageDeviceId(): string {
66
66
  */
67
67
  async function getFireTVDeviceId(logger: Logger): Promise<string | null> {
68
68
  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) {
69
+ if (!window.Capacitor?.Plugins?.DeviceInfo?.getAndroidId) {
74
70
  return null
75
71
  }
76
72
 
77
- const result = await DeviceInfo.getAndroidId()
73
+ const result = await window.Capacitor.Plugins.DeviceInfo.getAndroidId()
78
74
  if (result?.androidId && result.androidId.trim()) {
79
75
  return result.androidId
80
76
  } else {
81
- logger.error("DeviceInfo.getAndroidId returned empty")
77
+ logger.error(
78
+ "Capacitor.Plugins.DeviceInfo.getAndroidId returned empty"
79
+ )
82
80
  }
83
81
  } catch (error) {
84
- const message = "DeviceInfo.getAndroidId failed:"
82
+ const message = "Capacitor.Plugins.DeviceInfo.getAndroidId failed:"
85
83
  logger.error(message, { error })
86
84
  }
87
85
  return null
@@ -243,7 +241,9 @@ interface ExtendedWindow extends Window {
243
241
  }
244
242
 
245
243
  // Type augmentation for platform-specific APIs
246
- // Note: Capacitor types are declared in getShellVersion.ts with flexible index signatures
244
+ // Note: Capacitor types are declared in getShellVersion.ts with index signatures
245
+ // to allow extensibility. Additional methods used here are accessed via
246
+ // the index signatures [key: string]: any
247
247
  declare global {
248
248
  interface Window {
249
249
  webapis?: {