@volley/vwr-loader 1.0.5 → 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.
Files changed (55) hide show
  1. package/README.md +21 -0
  2. package/dist/amplitudeFlagFetcher.d.ts +4 -2
  3. package/dist/amplitudeFlagFetcher.d.ts.map +1 -1
  4. package/dist/amplitudeFlagFetcher.js +26 -19
  5. package/dist/amplitudeFlagFetcher.js.map +1 -1
  6. package/dist/cli.js +234 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/envDefaults.d.ts +3 -0
  9. package/dist/envDefaults.d.ts.map +1 -1
  10. package/dist/envDefaults.js +26 -4
  11. package/dist/envDefaults.js.map +1 -1
  12. package/dist/getDeviceId.d.ts +2 -10
  13. package/dist/getDeviceId.d.ts.map +1 -1
  14. package/dist/getDeviceId.js +31 -18
  15. package/dist/getDeviceId.js.map +1 -1
  16. package/dist/getEnvironment.d.ts +1 -1
  17. package/dist/getEnvironment.d.ts.map +1 -1
  18. package/dist/getEnvironment.js +10 -7
  19. package/dist/getEnvironment.js.map +1 -1
  20. package/dist/getShellVersion.d.ts +2 -2
  21. package/dist/getShellVersion.d.ts.map +1 -1
  22. package/dist/getShellVersion.js +5 -3
  23. package/dist/getShellVersion.js.map +1 -1
  24. package/dist/index.html +1 -1
  25. package/dist/loadVwr.d.ts.map +1 -1
  26. package/dist/loadVwr.js +8 -6
  27. package/dist/loadVwr.js.map +1 -1
  28. package/dist/main.js +1 -1
  29. package/dist/main.js.map +1 -1
  30. package/dist/vwrConfig.d.ts +2 -0
  31. package/dist/vwrConfig.d.ts.map +1 -1
  32. package/dist/vwrConfig.js +148 -119
  33. package/dist/vwrConfig.js.map +1 -1
  34. package/package.json +16 -5
  35. package/src/amplitudeFlagFetcher.test.ts +36 -59
  36. package/src/amplitudeFlagFetcher.ts +31 -22
  37. package/src/envDefaults.ts +33 -4
  38. package/src/getDeviceId.test.ts +79 -24
  39. package/src/getDeviceId.ts +47 -22
  40. package/src/getEnvironment.test.ts +457 -0
  41. package/src/getEnvironment.ts +12 -9
  42. package/src/getShellVersion.test.ts +1 -1
  43. package/src/getShellVersion.ts +7 -3
  44. package/src/loadVwr.ts +13 -6
  45. package/src/main.ts +3 -1
  46. package/src/vite-env.d.ts +3 -0
  47. package/src/vwrConfig.test.ts +2 -2
  48. package/src/vwrConfig.ts +202 -199
  49. package/eslint.config.mjs +0 -23
  50. package/scripts/build.js +0 -2
  51. package/scripts/build.ts +0 -207
  52. package/tsconfig.eslint.json +0 -16
  53. package/tsconfig.json +0 -17
  54. package/vite.config.ts +0 -24
  55. package/vitest.config.ts +0 -8
@@ -0,0 +1,457 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
2
+
3
+ import { type Environment, getEnvironment } from "./getEnvironment"
4
+
5
+ describe("getEnvironment", () => {
6
+ const mockLogger = {
7
+ info: vi.fn(),
8
+ warn: vi.fn(),
9
+ error: vi.fn(),
10
+ }
11
+
12
+ beforeEach(() => {
13
+ vi.clearAllMocks()
14
+ mockLogger.info.mockClear()
15
+ mockLogger.warn.mockClear()
16
+ mockLogger.error.mockClear()
17
+ // Clean up window properties
18
+ delete (window as any).Capacitor
19
+ })
20
+
21
+ afterEach(() => {
22
+ vi.restoreAllMocks()
23
+ delete (window as any).Capacitor
24
+ })
25
+
26
+ describe("Fire TV - Native Environment Detection", () => {
27
+ it("should read environment from native BuildConfig for Fire TV", async () => {
28
+ // Setup Capacitor plugin mock
29
+ Object.defineProperty(window, "Capacitor", {
30
+ value: {
31
+ Plugins: {
32
+ DeviceInfo: {
33
+ getNativeShellAppEnvironment: vi
34
+ .fn()
35
+ .mockResolvedValue({
36
+ environment: "development",
37
+ }),
38
+ },
39
+ },
40
+ },
41
+ writable: true,
42
+ configurable: true,
43
+ })
44
+
45
+ const result = await getEnvironment(
46
+ "FIRE_TV",
47
+ undefined,
48
+ mockLogger
49
+ )
50
+
51
+ expect(result.environment).toBe("dev")
52
+ expect(result.source).toBe("native")
53
+ expect(mockLogger.info).toHaveBeenCalledWith(
54
+ expect.stringContaining(
55
+ 'Environment: "dev" (source: native BuildConfig.ENVIRONMENT="development")'
56
+ )
57
+ )
58
+ })
59
+
60
+ it("should map 'production' to 'prod'", async () => {
61
+ Object.defineProperty(window, "Capacitor", {
62
+ value: {
63
+ Plugins: {
64
+ DeviceInfo: {
65
+ getNativeShellAppEnvironment: vi
66
+ .fn()
67
+ .mockResolvedValue({
68
+ environment: "production",
69
+ }),
70
+ },
71
+ },
72
+ },
73
+ writable: true,
74
+ configurable: true,
75
+ })
76
+
77
+ const result = await getEnvironment(
78
+ "FIRE_TV",
79
+ undefined,
80
+ mockLogger
81
+ )
82
+
83
+ expect(result.environment).toBe("prod")
84
+ expect(result.source).toBe("native")
85
+ })
86
+
87
+ it("should map 'staging' to 'staging'", async () => {
88
+ Object.defineProperty(window, "Capacitor", {
89
+ value: {
90
+ Plugins: {
91
+ DeviceInfo: {
92
+ getNativeShellAppEnvironment: vi
93
+ .fn()
94
+ .mockResolvedValue({
95
+ environment: "staging",
96
+ }),
97
+ },
98
+ },
99
+ },
100
+ writable: true,
101
+ configurable: true,
102
+ })
103
+
104
+ const result = await getEnvironment(
105
+ "FIRE_TV",
106
+ undefined,
107
+ mockLogger
108
+ )
109
+
110
+ expect(result.environment).toBe("staging")
111
+ expect(result.source).toBe("native")
112
+ })
113
+
114
+ it("should handle native env already in vwr format (dev)", async () => {
115
+ Object.defineProperty(window, "Capacitor", {
116
+ value: {
117
+ Plugins: {
118
+ DeviceInfo: {
119
+ getNativeShellAppEnvironment: vi
120
+ .fn()
121
+ .mockResolvedValue({
122
+ environment: "dev",
123
+ }),
124
+ },
125
+ },
126
+ },
127
+ writable: true,
128
+ configurable: true,
129
+ })
130
+
131
+ const result = await getEnvironment(
132
+ "FIRE_TV",
133
+ undefined,
134
+ mockLogger
135
+ )
136
+
137
+ expect(result.environment).toBe("dev")
138
+ expect(result.source).toBe("native")
139
+ })
140
+
141
+ it("should fallback to dev when native returns unknown value", async () => {
142
+ Object.defineProperty(window, "Capacitor", {
143
+ value: {
144
+ Plugins: {
145
+ DeviceInfo: {
146
+ getNativeShellAppEnvironment: vi
147
+ .fn()
148
+ .mockResolvedValue({
149
+ environment: "unknown-env",
150
+ }),
151
+ },
152
+ },
153
+ },
154
+ writable: true,
155
+ configurable: true,
156
+ })
157
+
158
+ const result = await getEnvironment(
159
+ "FIRE_TV",
160
+ undefined,
161
+ mockLogger
162
+ )
163
+
164
+ expect(result.environment).toBe("dev")
165
+ expect(result.source).toBe("native")
166
+ })
167
+
168
+ it("should fallback to build-time when native plugin unavailable", async () => {
169
+ // No Capacitor plugin available
170
+ const result = await getEnvironment(
171
+ "FIRE_TV",
172
+ "staging",
173
+ mockLogger
174
+ )
175
+
176
+ expect(result.environment).toBe("staging")
177
+ expect(result.source).toBe("build-time")
178
+ expect(mockLogger.warn).toHaveBeenCalledWith(
179
+ expect.stringContaining(
180
+ "Failed to read environment from native, falling back to build-time"
181
+ )
182
+ )
183
+ })
184
+
185
+ it("should fallback to build-time when native plugin throws error", async () => {
186
+ Object.defineProperty(window, "Capacitor", {
187
+ value: {
188
+ Plugins: {
189
+ DeviceInfo: {
190
+ getNativeShellAppEnvironment: vi
191
+ .fn()
192
+ .mockRejectedValue(
193
+ new Error("Native plugin error")
194
+ ),
195
+ },
196
+ },
197
+ },
198
+ writable: true,
199
+ configurable: true,
200
+ })
201
+
202
+ const result = await getEnvironment("FIRE_TV", "prod", mockLogger)
203
+
204
+ expect(result.environment).toBe("prod")
205
+ expect(result.source).toBe("build-time")
206
+ expect(mockLogger.error).toHaveBeenCalled()
207
+ expect(mockLogger.warn).toHaveBeenCalledWith(
208
+ expect.stringContaining("falling back to build-time")
209
+ )
210
+ })
211
+
212
+ it("should fallback to build-time when native returns empty", async () => {
213
+ Object.defineProperty(window, "Capacitor", {
214
+ value: {
215
+ Plugins: {
216
+ DeviceInfo: {
217
+ getNativeShellAppEnvironment: vi
218
+ .fn()
219
+ .mockResolvedValue({
220
+ environment: "",
221
+ }),
222
+ },
223
+ },
224
+ },
225
+ writable: true,
226
+ configurable: true,
227
+ })
228
+
229
+ const result = await getEnvironment("FIRE_TV", "dev", mockLogger)
230
+
231
+ expect(result.environment).toBe("dev")
232
+ expect(result.source).toBe("build-time")
233
+ expect(mockLogger.error).toHaveBeenCalledWith(
234
+ expect.stringContaining(
235
+ "DeviceInfo.getNativeShellAppEnvironment returned empty"
236
+ )
237
+ )
238
+ })
239
+
240
+ it("should fallback to default when both native and build-time fail", async () => {
241
+ // No Capacitor plugin, no build-time env
242
+ const result = await getEnvironment(
243
+ "FIRE_TV",
244
+ undefined,
245
+ mockLogger
246
+ )
247
+
248
+ expect(result.environment).toBe("dev")
249
+ expect(result.source).toBe("default")
250
+ expect(mockLogger.warn).toHaveBeenCalledWith(
251
+ expect.stringContaining(
252
+ 'Environment: "dev" (source: default fallback'
253
+ )
254
+ )
255
+ })
256
+
257
+ it("should be case-insensitive for Fire TV platform", async () => {
258
+ Object.defineProperty(window, "Capacitor", {
259
+ value: {
260
+ Plugins: {
261
+ DeviceInfo: {
262
+ getNativeShellAppEnvironment: vi
263
+ .fn()
264
+ .mockResolvedValue({
265
+ environment: "production",
266
+ }),
267
+ },
268
+ },
269
+ },
270
+ writable: true,
271
+ configurable: true,
272
+ })
273
+
274
+ const result1 = await getEnvironment(
275
+ "fire_tv",
276
+ undefined,
277
+ mockLogger
278
+ )
279
+ const result2 = await getEnvironment(
280
+ "FIRE_TV",
281
+ undefined,
282
+ mockLogger
283
+ )
284
+
285
+ expect(result1.environment).toBe("prod")
286
+ expect(result2.environment).toBe("prod")
287
+ })
288
+ })
289
+
290
+ describe("Non-Fire TV Platforms - Build-time Environment", () => {
291
+ const platforms = ["SAMSUNG_TV", "LG_TV", "MOBILE", "WEB"]
292
+
293
+ platforms.forEach((platform) => {
294
+ describe(`${platform}`, () => {
295
+ it("should use build-time environment when provided", async () => {
296
+ const result = await getEnvironment(
297
+ platform,
298
+ "staging",
299
+ mockLogger
300
+ )
301
+
302
+ expect(result.environment).toBe("staging")
303
+ expect(result.source).toBe("build-time")
304
+ expect(mockLogger.info).toHaveBeenCalledWith(
305
+ expect.stringContaining(
306
+ 'Environment: "staging" (source: build-time CLI injection)'
307
+ )
308
+ )
309
+ })
310
+
311
+ it("should use build-time 'prod' environment", async () => {
312
+ const result = await getEnvironment(
313
+ platform,
314
+ "prod",
315
+ mockLogger
316
+ )
317
+
318
+ expect(result.environment).toBe("prod")
319
+ expect(result.source).toBe("build-time")
320
+ })
321
+
322
+ it("should use build-time 'dev' environment", async () => {
323
+ const result = await getEnvironment(
324
+ platform,
325
+ "dev",
326
+ mockLogger
327
+ )
328
+
329
+ expect(result.environment).toBe("dev")
330
+ expect(result.source).toBe("build-time")
331
+ })
332
+
333
+ it("should use build-time 'local' environment", async () => {
334
+ const result = await getEnvironment(
335
+ platform,
336
+ "local",
337
+ mockLogger
338
+ )
339
+
340
+ expect(result.environment).toBe("local")
341
+ expect(result.source).toBe("build-time")
342
+ })
343
+
344
+ it("should fallback to default when build-time not provided", async () => {
345
+ const result = await getEnvironment(
346
+ platform,
347
+ undefined,
348
+ mockLogger
349
+ )
350
+
351
+ expect(result.environment).toBe("dev")
352
+ expect(result.source).toBe("default")
353
+ expect(mockLogger.warn).toHaveBeenCalledWith(
354
+ expect.stringContaining(
355
+ 'Environment: "dev" (source: default fallback'
356
+ )
357
+ )
358
+ })
359
+
360
+ it("should fallback to default when build-time is invalid", async () => {
361
+ const result = await getEnvironment(
362
+ platform,
363
+ "invalid-env",
364
+ mockLogger
365
+ )
366
+
367
+ expect(result.environment).toBe("dev")
368
+ expect(result.source).toBe("default")
369
+ })
370
+ })
371
+ })
372
+ })
373
+
374
+ describe("Environment Validation", () => {
375
+ it("should accept valid environments", async () => {
376
+ const validEnvs: Environment[] = [
377
+ "local",
378
+ "dev",
379
+ "qa",
380
+ "staging",
381
+ "prod",
382
+ ]
383
+
384
+ for (const env of validEnvs) {
385
+ const result = await getEnvironment("WEB", env, mockLogger)
386
+ expect(result.environment).toBe(env)
387
+ expect(result.source).toBe("build-time")
388
+ }
389
+ })
390
+
391
+ it("should reject invalid environments", async () => {
392
+ const invalidEnvs = [
393
+ "development",
394
+ "production",
395
+ "test",
396
+ "",
397
+ "random",
398
+ ]
399
+
400
+ for (const env of invalidEnvs) {
401
+ const result = await getEnvironment("WEB", env, mockLogger)
402
+ expect(result.environment).toBe("dev")
403
+ expect(result.source).toBe("default")
404
+ }
405
+ })
406
+ })
407
+
408
+ describe("Logging", () => {
409
+ it("should log native environment source", async () => {
410
+ Object.defineProperty(window, "Capacitor", {
411
+ value: {
412
+ Plugins: {
413
+ DeviceInfo: {
414
+ getNativeShellAppEnvironment: vi
415
+ .fn()
416
+ .mockResolvedValue({
417
+ environment: "production",
418
+ }),
419
+ },
420
+ },
421
+ },
422
+ writable: true,
423
+ configurable: true,
424
+ })
425
+
426
+ await getEnvironment("FIRE_TV", undefined, mockLogger)
427
+
428
+ expect(mockLogger.info).toHaveBeenCalledWith(
429
+ '[Shell] Environment: "prod" (source: native BuildConfig.ENVIRONMENT="production")'
430
+ )
431
+ })
432
+
433
+ it("should log build-time environment source", async () => {
434
+ await getEnvironment("SAMSUNG_TV", "staging", mockLogger)
435
+
436
+ expect(mockLogger.info).toHaveBeenCalledWith(
437
+ '[Shell] Environment: "staging" (source: build-time CLI injection)'
438
+ )
439
+ })
440
+
441
+ it("should warn when falling back to default", async () => {
442
+ await getEnvironment("LG_TV", undefined, mockLogger)
443
+
444
+ expect(mockLogger.warn).toHaveBeenCalledWith(
445
+ '[Shell] Environment: "dev" (source: default fallback - no native or build-time env found)'
446
+ )
447
+ })
448
+
449
+ it("should warn when native fails and falls back", async () => {
450
+ await getEnvironment("FIRE_TV", "prod", mockLogger)
451
+
452
+ expect(mockLogger.warn).toHaveBeenCalledWith(
453
+ "[Shell] Failed to read environment from native, falling back to build-time"
454
+ )
455
+ })
456
+ })
457
+ })
@@ -1,6 +1,6 @@
1
1
  import { defaultLogger, type Logger } from "./logger"
2
2
 
3
- export type Environment = "local" | "dev" | "staging" | "prod"
3
+ export type Environment = "local" | "dev" | "qa" | "staging" | "prod"
4
4
  export type EnvironmentSource = "native" | "build-time" | "default"
5
5
 
6
6
  export interface EnvironmentResult {
@@ -48,13 +48,16 @@ export async function getEnvironment(
48
48
  }
49
49
 
50
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",
51
+ if (buildTimeEnv) {
52
+ const normalizedBuildTimeEnv = buildTimeEnv.toLowerCase()
53
+ if (isValidEnvironment(normalizedBuildTimeEnv)) {
54
+ logger.info(
55
+ `[Shell] Environment: "${normalizedBuildTimeEnv}" (source: build-time CLI injection)`
56
+ )
57
+ return {
58
+ environment: normalizedBuildTimeEnv as Environment,
59
+ source: "build-time",
60
+ }
58
61
  }
59
62
  }
60
63
 
@@ -130,7 +133,7 @@ function mapNativeEnvironment(nativeEnv: string): Environment {
130
133
  }
131
134
 
132
135
  function isValidEnvironment(env: string): boolean {
133
- return ["local", "dev", "staging", "prod"].includes(env)
136
+ return ["local", "dev", "qa", "staging", "prod"].includes(env)
134
137
  }
135
138
 
136
139
  // Note: Window.Capacitor type is declared in getDeviceId.ts
@@ -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
- expect.any(Error)
271
+ { error: 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
- * - MOBILE: Native bridge (future implementation)
10
+ * - ANDROID_MOBILE/IOS_MOBILE: Native bridge (future implementation)
11
11
  * - WEB/Unknown: Returns 'unknown'
12
12
  *
13
- * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, MOBILE, WEB)
13
+ * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, ANDROID_MOBILE, IOS_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,7 +66,11 @@ export async function getShellVersion(
66
66
  }
67
67
 
68
68
  // Mobile: Future implementation via native bridge
69
- if (normalizedPlatform === "MOBILE") {
69
+ if (
70
+ normalizedPlatform === "ANDROID_MOBILE" ||
71
+ normalizedPlatform === "IOS_MOBILE" ||
72
+ normalizedPlatform === "MOBILE"
73
+ ) {
70
74
  // TODO: Implement native bridge version retrieval when available
71
75
  return "unknown"
72
76
  }
package/src/loadVwr.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type * as VWR from "@volley/vwr"
2
+
1
3
  import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
2
4
  import { ENV_DEFAULTS } from "./envDefaults"
3
5
  import { getDeviceId } from "./getDeviceId"
@@ -83,7 +85,8 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
83
85
  apiKey: amplitudeKey,
84
86
  timeout: 2000,
85
87
  },
86
- shellVersion
88
+ shellVersion,
89
+ logger
87
90
  )
88
91
 
89
92
  logger.info("[Shell] Flags fetched", { flags })
@@ -115,7 +118,10 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
115
118
  vwrUrl: vwrConfig.vwrUrl,
116
119
  })
117
120
  try {
118
- const vwr = await import(/* @vite-ignore */ vwrConfig.vwrUrl)
121
+ const vwr = (await import(
122
+ /* @vite-ignore */ vwrConfig.vwrUrl
123
+ )) as typeof VWR
124
+
119
125
  logger.info("[Shell] VWR module loaded successfully")
120
126
 
121
127
  if (typeof vwr.init !== "function") {
@@ -124,11 +130,12 @@ export const loadVwr = async (logger: Logger = defaultLogger) => {
124
130
 
125
131
  await vwr.init({
126
132
  hubUrl: vwrConfig.hubUrl,
127
- launchUrl: vwrConfig.launchUrl,
128
133
  platform: PLATFORM,
129
- deviceId,
130
- environment: ENVIRONMENT,
131
- trustedDomains: vwrConfig.trustedDomains,
134
+ stage: ENVIRONMENT,
135
+ appVersion: shellVersion,
136
+ platformApiUrl: vwrConfig.platformApiUrl,
137
+ platformAuthApiUrl: vwrConfig.platformAuthApiUrl,
138
+ trustedOrigins: new Set(vwrConfig.trustedDomains),
132
139
  nativeShellVersion: shellVersion,
133
140
  })
134
141
  logger.info("[Shell] VWR initialized successfully")
package/src/main.ts CHANGED
@@ -18,7 +18,9 @@ async function init() {
18
18
  }
19
19
  } finally {
20
20
  //Fallback, can't trust config exists
21
- window.location.href = HUB_URL
21
+ const fallbackUrl = new URL(HUB_URL)
22
+ fallbackUrl.searchParams.set("volley_platform", PLATFORM)
23
+ window.location.href = fallbackUrl.toString()
22
24
  }
23
25
  }
24
26
  }
package/src/vite-env.d.ts CHANGED
@@ -8,6 +8,9 @@ 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
11
14
  }
12
15
 
13
16
  interface ImportMeta {
@@ -90,8 +90,8 @@ describe("vwrConfig", async () => {
90
90
  expect(config.hubUrl).toBe("https://game-clients.volley.tv/hub")
91
91
  expect(config.launchUrl).toBeUndefined() // Optional, not set by default
92
92
  expect(config.trustedDomains).toEqual([
93
- "https://game-clients.volley.tv/hub",
94
- "https://vwr.volley.tv/v1/latest/vwr.js",
93
+ "https://game-clients.volley.tv",
94
+ "https://vwr.volley.tv",
95
95
  ])
96
96
  })
97
97