@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.
Files changed (54) hide show
  1. package/README.md +205 -0
  2. package/dist/amplitudeFlagFetcher.d.ts +23 -0
  3. package/dist/amplitudeFlagFetcher.d.ts.map +1 -0
  4. package/dist/amplitudeFlagFetcher.js +60 -0
  5. package/dist/amplitudeFlagFetcher.js.map +1 -0
  6. package/dist/cli.js +177 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/envDefaults.d.ts +9 -0
  9. package/dist/envDefaults.d.ts.map +1 -0
  10. package/dist/envDefaults.js +36 -0
  11. package/dist/envDefaults.js.map +1 -0
  12. package/dist/getDeviceId.d.ts +65 -0
  13. package/dist/getDeviceId.d.ts.map +1 -0
  14. package/dist/getDeviceId.js +196 -0
  15. package/dist/getDeviceId.js.map +1 -0
  16. package/dist/getShellVersion.d.ts +34 -0
  17. package/dist/getShellVersion.d.ts.map +1 -0
  18. package/dist/getShellVersion.js +84 -0
  19. package/dist/getShellVersion.js.map +1 -0
  20. package/dist/index.d.ts +9 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.html +25 -0
  23. package/dist/index.js +6 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/loadVwr.d.ts +19 -0
  26. package/dist/loadVwr.d.ts.map +1 -0
  27. package/dist/loadVwr.js +104 -0
  28. package/dist/loadVwr.js.map +1 -0
  29. package/dist/logger.d.ts +7 -0
  30. package/dist/logger.d.ts.map +1 -0
  31. package/dist/logger.js +6 -0
  32. package/dist/logger.js.map +1 -0
  33. package/dist/main.js +2 -0
  34. package/dist/main.js.map +1 -0
  35. package/dist/vwrConfig.d.ts +19 -0
  36. package/dist/vwrConfig.d.ts.map +1 -0
  37. package/dist/vwrConfig.js +172 -0
  38. package/dist/vwrConfig.js.map +1 -0
  39. package/package.json +54 -0
  40. package/src/amplitudeFlagFetcher.test.ts +209 -0
  41. package/src/amplitudeFlagFetcher.ts +88 -0
  42. package/src/envDefaults.ts +45 -0
  43. package/src/getDeviceId.test.ts +237 -0
  44. package/src/getDeviceId.ts +243 -0
  45. package/src/getShellVersion.test.ts +278 -0
  46. package/src/getShellVersion.ts +114 -0
  47. package/src/index.html +25 -0
  48. package/src/index.ts +8 -0
  49. package/src/loadVwr.ts +126 -0
  50. package/src/logger.ts +14 -0
  51. package/src/main.ts +26 -0
  52. package/src/vite-env.d.ts +15 -0
  53. package/src/vwrConfig.test.ts +316 -0
  54. package/src/vwrConfig.ts +293 -0
@@ -0,0 +1,278 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
2
+
3
+ import { getShellVersion } from "./getShellVersion"
4
+
5
+ describe("getShellVersion", () => {
6
+ const originalLocation = window.location
7
+
8
+ beforeEach(() => {
9
+ // Mock window.location
10
+ delete (window as any).location
11
+ window.location = {
12
+ ...originalLocation,
13
+ href: "http://localhost:3000/",
14
+ } as Location
15
+ })
16
+
17
+ afterEach(() => {
18
+ window.location = originalLocation
19
+ vi.restoreAllMocks()
20
+ })
21
+
22
+ describe("Samsung TV", () => {
23
+ afterEach(() => {
24
+ delete (window as any).tizen
25
+ })
26
+
27
+ it("returns version from Tizen Application API", async () => {
28
+ ;(window as any).tizen = {
29
+ application: {
30
+ getAppInfo: vi.fn().mockReturnValue({ version: "1.2.3" }),
31
+ },
32
+ }
33
+
34
+ const version = await getShellVersion("SAMSUNG_TV")
35
+
36
+ expect(version).toBe("1.2.3")
37
+ })
38
+
39
+ it("returns unknown when tizen is not available", async () => {
40
+ const version = await getShellVersion("SAMSUNG_TV")
41
+
42
+ expect(version).toBe("unknown")
43
+ })
44
+
45
+ it("returns unknown when version is missing from appInfo", async () => {
46
+ ;(window as any).tizen = {
47
+ application: {
48
+ getAppInfo: vi.fn().mockReturnValue({}),
49
+ },
50
+ }
51
+
52
+ const version = await getShellVersion("SAMSUNG_TV")
53
+
54
+ expect(version).toBe("unknown")
55
+ })
56
+
57
+ it("is case insensitive", async () => {
58
+ ;(window as any).tizen = {
59
+ application: {
60
+ getAppInfo: vi.fn().mockReturnValue({ version: "2.0.0" }),
61
+ },
62
+ }
63
+
64
+ const version = await getShellVersion("samsung_tv")
65
+
66
+ expect(version).toBe("2.0.0")
67
+ })
68
+ })
69
+
70
+ describe("LG TV", () => {
71
+ afterEach(() => {
72
+ delete (window as any).webOS
73
+ })
74
+
75
+ it("returns version from webOS.fetchAppInfo", async () => {
76
+ ;(window as any).webOS = {
77
+ fetchAppInfo: vi.fn((callback) => {
78
+ callback({ version: "3.4.5" })
79
+ }),
80
+ }
81
+
82
+ const version = await getShellVersion("LG_TV")
83
+
84
+ expect(version).toBe("3.4.5")
85
+ })
86
+
87
+ it("returns unknown when webOS is not available", async () => {
88
+ const version = await getShellVersion("LG_TV")
89
+
90
+ expect(version).toBe("unknown")
91
+ })
92
+
93
+ it("returns unknown when fetchAppInfo returns no version", async () => {
94
+ ;(window as any).webOS = {
95
+ fetchAppInfo: vi.fn((callback) => {
96
+ callback({})
97
+ }),
98
+ }
99
+
100
+ const version = await getShellVersion("LG_TV")
101
+
102
+ expect(version).toBe("unknown")
103
+ })
104
+
105
+ it("returns unknown when fetchAppInfo callback receives undefined", async () => {
106
+ ;(window as any).webOS = {
107
+ fetchAppInfo: vi.fn((callback) => {
108
+ callback(undefined)
109
+ }),
110
+ }
111
+
112
+ const version = await getShellVersion("LG_TV")
113
+
114
+ expect(version).toBe("unknown")
115
+ })
116
+
117
+ it("is case insensitive", async () => {
118
+ ;(window as any).webOS = {
119
+ fetchAppInfo: vi.fn((callback) => {
120
+ callback({ version: "4.0.0" })
121
+ }),
122
+ }
123
+
124
+ const version = await getShellVersion("lg_tv")
125
+
126
+ expect(version).toBe("4.0.0")
127
+ })
128
+ })
129
+
130
+ describe("FireTV", () => {
131
+ it("returns version from Capacitor DeviceInfo plugin", async () => {
132
+ const mockGetDeviceInfo = vi.fn().mockResolvedValue({
133
+ versionName: "5.6.7",
134
+ })
135
+
136
+ ;(window as any).Capacitor = {
137
+ Plugins: {
138
+ DeviceInfo: {
139
+ getDeviceInfo: mockGetDeviceInfo,
140
+ },
141
+ },
142
+ }
143
+
144
+ const version = await getShellVersion("FIRE_TV")
145
+
146
+ expect(version).toBe("5.6.7")
147
+ expect(mockGetDeviceInfo).toHaveBeenCalled()
148
+
149
+ delete (window as any).Capacitor
150
+ })
151
+
152
+ it("returns unknown when Capacitor is not available", async () => {
153
+ const version = await getShellVersion("FIRE_TV")
154
+
155
+ expect(version).toBe("unknown")
156
+ })
157
+
158
+ it("returns unknown when DeviceInfo plugin is not available", async () => {
159
+ ;(window as any).Capacitor = {
160
+ Plugins: {},
161
+ }
162
+
163
+ const version = await getShellVersion("FIRE_TV")
164
+
165
+ expect(version).toBe("unknown")
166
+
167
+ delete (window as any).Capacitor
168
+ })
169
+
170
+ it("returns unknown when getDeviceInfo is not available", async () => {
171
+ ;(window as any).Capacitor = {
172
+ Plugins: {
173
+ DeviceInfo: {},
174
+ },
175
+ }
176
+
177
+ const version = await getShellVersion("FIRE_TV")
178
+
179
+ expect(version).toBe("unknown")
180
+
181
+ delete (window as any).Capacitor
182
+ })
183
+
184
+ it("returns unknown when versionName is missing", async () => {
185
+ const mockGetDeviceInfo = vi.fn().mockResolvedValue({})
186
+
187
+ ;(window as any).Capacitor = {
188
+ Plugins: {
189
+ DeviceInfo: {
190
+ getDeviceInfo: mockGetDeviceInfo,
191
+ },
192
+ },
193
+ }
194
+
195
+ const version = await getShellVersion("FIRE_TV")
196
+
197
+ expect(version).toBe("unknown")
198
+
199
+ delete (window as any).Capacitor
200
+ })
201
+
202
+ it("is case insensitive", async () => {
203
+ const mockGetDeviceInfo = vi.fn().mockResolvedValue({
204
+ versionName: "6.0.0",
205
+ })
206
+
207
+ ;(window as any).Capacitor = {
208
+ Plugins: {
209
+ DeviceInfo: {
210
+ getDeviceInfo: mockGetDeviceInfo,
211
+ },
212
+ },
213
+ }
214
+
215
+ const version = await getShellVersion("fire_tv")
216
+
217
+ expect(version).toBe("6.0.0")
218
+
219
+ delete (window as any).Capacitor
220
+ })
221
+ })
222
+
223
+ describe("Mobile", () => {
224
+ it("returns unknown (not yet implemented)", async () => {
225
+ const version = await getShellVersion("MOBILE")
226
+
227
+ expect(version).toBe("unknown")
228
+ })
229
+ })
230
+
231
+ describe("Web and Unknown Platforms", () => {
232
+ it("returns unknown for web platform", async () => {
233
+ const version = await getShellVersion("WEB")
234
+
235
+ expect(version).toBe("unknown")
236
+ })
237
+
238
+ it("returns unknown for unknown platform", async () => {
239
+ const version = await getShellVersion("unknown-platform")
240
+
241
+ expect(version).toBe("unknown")
242
+ })
243
+
244
+ it("returns unknown for empty string", async () => {
245
+ const version = await getShellVersion("")
246
+
247
+ expect(version).toBe("unknown")
248
+ })
249
+ })
250
+
251
+ describe("Error Handling", () => {
252
+ it("returns unknown and logs warning on error", async () => {
253
+ const consoleWarnSpy = vi
254
+ .spyOn(console, "warn")
255
+ .mockImplementation(() => {})
256
+
257
+ // Force an error by making tizen.application.getAppInfo throw
258
+ ;(window as any).tizen = {
259
+ application: {
260
+ getAppInfo: vi.fn(() => {
261
+ throw new Error("Tizen API error")
262
+ }),
263
+ },
264
+ }
265
+
266
+ const version = await getShellVersion("SAMSUNG_TV")
267
+
268
+ expect(version).toBe("unknown")
269
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
270
+ "[Shell] Failed to get shell version:",
271
+ { error: expect.any(Error) }
272
+ )
273
+
274
+ consoleWarnSpy.mockRestore()
275
+ delete (window as any).tizen
276
+ })
277
+ })
278
+ })
@@ -0,0 +1,114 @@
1
+ import { defaultLogger, type Logger } from "./logger"
2
+
3
+ /**
4
+ * Retrieve shell app version for different platforms.
5
+ *
6
+ * Platform-specific methods:
7
+ * - SAMSUNG_TV: Tizen Application API `tizen.application.getAppInfo().version`
8
+ * - LG_TV: webOS Application API `webOS.fetchAppInfo()`
9
+ * - FIRE_TV: Native bridge via Capacitor DeviceInfo plugin
10
+ * - ANDROID_MOBILE/IOS_MOBILE: Native bridge (future implementation)
11
+ * - WEB/Unknown: Returns 'unknown'
12
+ *
13
+ * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, ANDROID_MOBILE, IOS_MOBILE, WEB)
14
+ * @param logger - Optional logger for warning reporting. Defaults to defaultLogger.
15
+ * @returns Shell version string or 'unknown' if not available
16
+ */
17
+ export async function getShellVersion(
18
+ platform: string,
19
+ logger: Logger = defaultLogger
20
+ ): Promise<string> {
21
+ try {
22
+ const normalizedPlatform = platform.toUpperCase()
23
+
24
+ // Samsung TV: Get version from Tizen Application API
25
+ if (normalizedPlatform === "SAMSUNG_TV") {
26
+ if (typeof window !== "undefined" && (window as any).tizen) {
27
+ const tizen = (window as any).tizen
28
+ if (tizen.application?.getAppInfo) {
29
+ const appInfo = tizen.application.getAppInfo()
30
+ return appInfo?.version ?? "unknown"
31
+ }
32
+ }
33
+ return "unknown"
34
+ }
35
+
36
+ // LG TV: Get version from webOS API
37
+ // Note: webOS.fetchAppInfo(callback, path) takes a single callback and optional path.
38
+ // The callback receives the parsed appinfo.json or undefined on failure.
39
+ if (normalizedPlatform === "LG_TV") {
40
+ if (typeof window !== "undefined" && (window as any).webOS) {
41
+ const webOS = (window as any).webOS
42
+ if (webOS.fetchAppInfo) {
43
+ return new Promise((resolve) => {
44
+ webOS.fetchAppInfo((appInfo?: { version?: string }) => {
45
+ resolve(appInfo?.version ?? "unknown")
46
+ })
47
+ })
48
+ }
49
+ }
50
+ return "unknown"
51
+ }
52
+
53
+ // FireTV: Get version from Capacitor DeviceInfo plugin
54
+ if (normalizedPlatform === "FIRE_TV") {
55
+ // Check if Capacitor is available
56
+ if (typeof window !== "undefined" && (window as any).Capacitor) {
57
+ const Capacitor = (window as any).Capacitor
58
+ const DeviceInfo = Capacitor.Plugins?.DeviceInfo
59
+
60
+ if (DeviceInfo?.getDeviceInfo) {
61
+ const deviceInfo = await DeviceInfo.getDeviceInfo()
62
+ return deviceInfo?.versionName ?? "unknown"
63
+ }
64
+ }
65
+ return "unknown"
66
+ }
67
+
68
+ // Mobile: Future implementation via native bridge
69
+ if (
70
+ normalizedPlatform === "ANDROID_MOBILE" ||
71
+ normalizedPlatform === "IOS_MOBILE" ||
72
+ normalizedPlatform === "MOBILE"
73
+ ) {
74
+ // TODO: Implement native bridge version retrieval when available
75
+ return "unknown"
76
+ }
77
+
78
+ // Web platform: Check for injected version at build time
79
+ if (normalizedPlatform === "WEB") {
80
+ if (
81
+ typeof import.meta.env !== "undefined" &&
82
+ import.meta.env.VITE_SHELL_VERSION
83
+ ) {
84
+ return import.meta.env.VITE_SHELL_VERSION
85
+ }
86
+ }
87
+
88
+ // Other unknown platforms
89
+ return "unknown"
90
+ } catch (error) {
91
+ const message = "[Shell] Failed to get shell version:"
92
+ logger.warn(message, { error })
93
+ return "unknown"
94
+ }
95
+ }
96
+
97
+ // Global type declarations for platform APIs
98
+ declare global {
99
+ interface Window {
100
+ Capacitor?: {
101
+ Plugins?: {
102
+ DeviceInfo?: {
103
+ getDeviceInfo(): Promise<{
104
+ versionName?: string
105
+ [key: string]: any
106
+ }>
107
+ [key: string]: any
108
+ }
109
+ [key: string]: any
110
+ }
111
+ [key: string]: any
112
+ }
113
+ }
114
+ }
package/src/index.html ADDED
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Volley</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ background: #010020;
12
+ }
13
+ #loading {
14
+ color: #ffec37;
15
+ text-align: center;
16
+ padding-top: 40vh;
17
+ font-family: sans-serif;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <div id="loading">Loading...</div>
23
+ <script type="module" src="./main.ts"></script>
24
+ </body>
25
+ </html>
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export type { AmplitudeConfig, FlagResult } from "./amplitudeFlagFetcher"
2
+ export { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
3
+ export { getDeviceId } from "./getDeviceId"
4
+ export { getShellVersion } from "./getShellVersion"
5
+ export type { Logger } from "./loadVwr"
6
+ export { loadVwr } from "./loadVwr"
7
+ export type { VWRConfig, VWRConfigRequest } from "./vwrConfig"
8
+ export { getVWRConfig } from "./vwrConfig"
package/src/loadVwr.ts ADDED
@@ -0,0 +1,126 @@
1
+ import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher"
2
+ import { ENV_DEFAULTS } from "./envDefaults"
3
+ import { getDeviceId } from "./getDeviceId"
4
+ import { getShellVersion } from "./getShellVersion"
5
+ import { defaultLogger, type Logger } from "./logger"
6
+ import type { VWRConfig, VWRConfigRequest } from "./vwrConfig"
7
+ import { getVWRConfig, validateConfig } from "./vwrConfig"
8
+
9
+ // Vite injects these at build time
10
+ const ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT
11
+ const PLATFORM = import.meta.env.VITE_PLATFORM
12
+ const CONFIG_URL = import.meta.env.VITE_CONFIG_URL
13
+ const CONFIG_FILE = import.meta.env.VITE_CONFIG_FILE
14
+
15
+ // AMPLITUDE_KEY can be optionally injected at build time (via build.ts script)
16
+ // Falls back to envDefaults if not injected (e.g., vite.config.dev.ts)
17
+ const AMPLITUDE_KEY = import.meta.env.VITE_AMPLITUDE_DEPLOYMENT_KEY
18
+
19
+ export type { Logger }
20
+
21
+ /**
22
+ * Load VWR runtime.
23
+ *
24
+ * Optimized flow: checks vwr-enabled flag FIRST using baked-in Amplitude key,
25
+ * before doing any config fetches. For flag-OFF users (100% at initial launch),
26
+ * this reduces startup latency from ~2-4s to ~500ms by skipping config fetches.
27
+ *
28
+ * Flow:
29
+ * 1. Get deviceId, shellVersion (fast, local)
30
+ * 2. Check vwr-enabled flag (single request, ~500ms)
31
+ * 3. If OFF → throw immediately (no config fetches)
32
+ * 4. If ON → fetch config, load VWR module, initialize
33
+ *
34
+ * @param logger - Optional logger, defaults to console
35
+ */
36
+ export const loadVwr = async (logger: Logger = defaultLogger) => {
37
+ if (!ENVIRONMENT || !PLATFORM || !CONFIG_URL || !CONFIG_FILE) {
38
+ throw new Error("[Shell] Build config not injected properly")
39
+ }
40
+
41
+ const deviceId = await getDeviceId(PLATFORM, logger)
42
+ if (!deviceId) {
43
+ const message = `[Shell] Failed to retrieve device ID for platform: ${PLATFORM}`
44
+ logger.error(message)
45
+ throw new Error(message)
46
+ }
47
+ const shellVersion = await getShellVersion(PLATFORM, logger)
48
+
49
+ // Get amplitude key: injected at build time OR from envDefaults
50
+ // Precedence: build-time injection > envDefaults
51
+ let amplitudeKey = AMPLITUDE_KEY
52
+ if (!amplitudeKey) {
53
+ const envDefaults = ENV_DEFAULTS[ENVIRONMENT]
54
+ if (!envDefaults) {
55
+ throw new Error(`[Shell] Unknown environment: ${ENVIRONMENT}`)
56
+ }
57
+ amplitudeKey = envDefaults.amplitudeKey
58
+ }
59
+
60
+ // FAST PATH: Check flag first using amplitude key
61
+ // This avoids config fetches for flag-OFF users (majority at launch)
62
+ const flags = await fetchAmplitudeFlags(
63
+ deviceId,
64
+ PLATFORM,
65
+ {
66
+ apiKey: amplitudeKey,
67
+ timeout: 2000,
68
+ },
69
+ shellVersion
70
+ )
71
+
72
+ logger.info("[Shell] Flags fetched", { flags })
73
+
74
+ if (!flags["vwr-enabled"]) {
75
+ // Flag OFF: skip all config fetches, fail fast
76
+ throw new Error("[Shell] VWR not enabled via Amplitude flags")
77
+ }
78
+
79
+ // Flag ON: proceed with full config loading
80
+ logger.info("[Shell] VWR flag enabled, fetching config...")
81
+
82
+ const vwrConfigRequest: VWRConfigRequest = {
83
+ configUrl: CONFIG_URL,
84
+ configFile: CONFIG_FILE,
85
+ platform: PLATFORM,
86
+ deviceId: deviceId,
87
+ environment: ENVIRONMENT,
88
+ shellVersion: shellVersion,
89
+ }
90
+
91
+ const vwrConfig: VWRConfig = await getVWRConfig(vwrConfigRequest, logger)
92
+
93
+ if (!validateConfig(vwrConfig)) {
94
+ throw new Error("Invalid config, falling back to default hub")
95
+ }
96
+
97
+ logger.info("[Shell] VWR enabled, loading module", {
98
+ vwrUrl: vwrConfig.vwrUrl,
99
+ })
100
+ try {
101
+ const vwr = await import(/* @vite-ignore */ vwrConfig.vwrUrl)
102
+ logger.info("[Shell] VWR module loaded successfully")
103
+
104
+ if (typeof vwr.init !== "function") {
105
+ throw new Error("[Shell] VWR module missing init() function")
106
+ }
107
+
108
+ await vwr.init({
109
+ hubUrl: vwrConfig.hubUrl,
110
+ launchUrl: vwrConfig.launchUrl,
111
+ platform: PLATFORM,
112
+ deviceId,
113
+ environment: ENVIRONMENT,
114
+ trustedDomains: vwrConfig.trustedDomains,
115
+ nativeShellVersion: shellVersion,
116
+ })
117
+ logger.info("[Shell] VWR initialized successfully")
118
+ } catch (vwrError) {
119
+ logger.error("[Shell] VWR load failed", {
120
+ error:
121
+ vwrError instanceof Error ? vwrError.message : String(vwrError),
122
+ vwrUrl: vwrConfig.vwrUrl,
123
+ })
124
+ throw vwrError // Re-throw to outer catch for fallback
125
+ }
126
+ }
package/src/logger.ts ADDED
@@ -0,0 +1,14 @@
1
+ export interface Logger {
2
+ info: (message: string, context?: Record<string, unknown>) => void
3
+ warn: (message: string, context?: Record<string, unknown>) => void
4
+ error: (message: string, context?: Record<string, unknown>) => void
5
+ }
6
+
7
+ export const defaultLogger: Logger = {
8
+ info: (message, context) =>
9
+ context ? console.log(message, context) : console.log(message),
10
+ warn: (message, context) =>
11
+ context ? console.warn(message, context) : console.warn(message),
12
+ error: (message, context) =>
13
+ context ? console.error(message, context) : console.error(message),
14
+ }
package/src/main.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { loadVwr } from "./loadVwr"
2
+
3
+ const PLATFORM = import.meta.env.VITE_PLATFORM
4
+ const HUB_URL = import.meta.env.VITE_HUB_URL
5
+
6
+ async function init() {
7
+ try {
8
+ await loadVwr()
9
+ } catch (error) {
10
+ try {
11
+ console.error("[Shell] ⚠️ FALLBACK TO HUB - Init failed:", error)
12
+
13
+ if ((window as any).DD_LOGS) {
14
+ ;(window as any).DD_LOGS.logger.error("shell_init_failed", {
15
+ error: (error as Error).message,
16
+ platform: PLATFORM,
17
+ })
18
+ }
19
+ } finally {
20
+ //Fallback, can't trust config exists
21
+ window.location.href = HUB_URL
22
+ }
23
+ }
24
+ }
25
+
26
+ init()
@@ -0,0 +1,15 @@
1
+ interface ImportMetaEnv {
2
+ readonly VITE_HUB_URL: string
3
+ readonly VITE_VWR_URL: string
4
+ readonly VITE_LAUNCH_URL: string
5
+ readonly VITE_AMPLITUDE_DEPLOYMENT_KEY: string
6
+ readonly VITE_ENVIRONMENT: string
7
+ readonly VITE_PLATFORM: string
8
+ readonly VITE_SHELL_VERSION: string
9
+ readonly VITE_CONFIG_URL: string
10
+ readonly VITE_CONFIG_FILE: string
11
+ }
12
+
13
+ interface ImportMeta {
14
+ readonly env: ImportMetaEnv
15
+ }