@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,196 @@
1
+ import { defaultLogger } from "./logger";
2
+ /**
3
+ * Get a unique device identifier for the current platform.
4
+ *
5
+ * This function attempts to retrieve a device ID from platform-specific APIs.
6
+ *
7
+ * Platform handling:
8
+ * - FireTV: DeviceInfo (Capacitor plugin)
9
+ * - Android/iOS: NativeBridge
10
+ * - Samsung TV: webapis
11
+ * - LG TV: webOS Luna service
12
+ * - Web: localStorage (with generated UUID fallback)
13
+ *
14
+ * @param platform - Platform identifier ('FIRE_TV', 'SAMSUNG_TV', 'LG_TV', 'ANDROID_MOBILE', 'IOS_MOBILE', 'WEB')
15
+ * @param logger - Optional logger for error reporting. Defaults to defaultLogger.
16
+ * @returns A promise that resolves to a unique device identifier string, or null if retrieval fails
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const deviceId = await getDeviceId('SAMSUNG_TV', logger)
21
+ * if (!deviceId) {
22
+ * // Handle error
23
+ * }
24
+ * ```
25
+ */
26
+ export async function getDeviceId(platform, logger = defaultLogger) {
27
+ const normalizedPlatform = platform.toUpperCase();
28
+ switch (normalizedPlatform) {
29
+ case "FIRE_TV":
30
+ return await getFireTVDeviceId(logger);
31
+ case "SAMSUNG_TV":
32
+ return await getSamsungDeviceId(logger);
33
+ case "LG_TV":
34
+ return await getLGDeviceId(logger);
35
+ case "ANDROID_MOBILE":
36
+ case "IOS_MOBILE":
37
+ case "MOBILE": // Legacy/Generic
38
+ return await getMobileDeviceId(logger);
39
+ case "WEB":
40
+ return getLocalStorageDeviceId();
41
+ default:
42
+ const message = `[getDeviceId] Unknown platform: ${platform}`;
43
+ logger.error(message);
44
+ return null;
45
+ }
46
+ }
47
+ /**
48
+ * Get or create device ID from localStorage (for Web platform)
49
+ */
50
+ function getLocalStorageDeviceId() {
51
+ let deviceId = localStorage.getItem("volley_device_id");
52
+ if (!deviceId) {
53
+ deviceId = crypto.randomUUID();
54
+ localStorage.setItem("volley_device_id", deviceId);
55
+ }
56
+ return deviceId;
57
+ }
58
+ /**
59
+ * Attempt to get device ID from Capacitor DeviceInfo plugin (FireTV)
60
+ */
61
+ async function getFireTVDeviceId(logger) {
62
+ var _a;
63
+ try {
64
+ if (!((_a = window.DeviceInfo) === null || _a === void 0 ? void 0 : _a.getAndroidId)) {
65
+ return null;
66
+ }
67
+ const result = await window.DeviceInfo.getAndroidId();
68
+ if ((result === null || result === void 0 ? void 0 : result.androidId) && result.androidId.trim()) {
69
+ return result.androidId;
70
+ }
71
+ else {
72
+ logger.error("DeviceInfo.getAndroidId returned empty");
73
+ }
74
+ }
75
+ catch (error) {
76
+ const message = "DeviceInfo.getAndroidId failed:";
77
+ logger.error(message, { error });
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Attempt to get device ID from Native Bridge (Android/iOS)
83
+ */
84
+ async function getMobileDeviceId(logger) {
85
+ var _a;
86
+ try {
87
+ if (!((_a = window.NativeBridge) === null || _a === void 0 ? void 0 : _a.getDeviceId)) {
88
+ return null;
89
+ }
90
+ const id = await window.NativeBridge.getDeviceId();
91
+ if (id && id.trim()) {
92
+ return id;
93
+ }
94
+ else {
95
+ logger.error("NativeBridge.getDeviceId returned empty");
96
+ }
97
+ }
98
+ catch (error) {
99
+ const message = "NativeBridge.getDeviceId failed:";
100
+ logger.error(message, { error });
101
+ }
102
+ return null;
103
+ }
104
+ /**
105
+ * Attempt to get device ID from Samsung TV webapis
106
+ */
107
+ async function getSamsungDeviceId(logger) {
108
+ var _a, _b;
109
+ try {
110
+ if (!((_b = (_a = window.webapis) === null || _a === void 0 ? void 0 : _a.productinfo) === null || _b === void 0 ? void 0 : _b.getDuid)) {
111
+ return null;
112
+ }
113
+ const id = window.webapis.productinfo.getDuid();
114
+ if (id && id.trim()) {
115
+ return id;
116
+ }
117
+ else {
118
+ logger.error("Samsung webapis.getDuid returned empty");
119
+ }
120
+ }
121
+ catch (error) {
122
+ const message = "Samsung webapis.getDuid failed:";
123
+ logger.error(message, { error });
124
+ }
125
+ return null;
126
+ }
127
+ /**
128
+ * Attempt to get device ID from LG TV using Luna Service.
129
+ *
130
+ * This implementation is copied from PSDK's LGTVDeviceInfo to ensure
131
+ * the shell and SDK return the exact same device ID.
132
+ *
133
+ * TODO: In the future, PSDK should import this function from vwr-loader
134
+ * to maintain a single source of truth for LG device ID retrieval.
135
+ */
136
+ const LG_LUNA_SERVICE_TIMEOUT = 5000;
137
+ async function getLGDeviceId(logger) {
138
+ var _a, _b;
139
+ if (!((_b = (_a = window.webOS) === null || _a === void 0 ? void 0 : _a.service) === null || _b === void 0 ? void 0 : _b.request)) {
140
+ const message = "LG webOS service request not available";
141
+ logger.error(message);
142
+ return null;
143
+ }
144
+ return new Promise((resolve) => {
145
+ var _a, _b;
146
+ let timeoutId;
147
+ let request;
148
+ let resolved = false;
149
+ const cleanup = () => {
150
+ if (timeoutId) {
151
+ clearTimeout(timeoutId);
152
+ timeoutId = undefined;
153
+ }
154
+ request === null || request === void 0 ? void 0 : request.cancel();
155
+ };
156
+ const finish = (value) => {
157
+ if (resolved)
158
+ return;
159
+ resolved = true;
160
+ cleanup();
161
+ resolve(value);
162
+ };
163
+ timeoutId = setTimeout(() => {
164
+ const message = "LG Luna service timed out";
165
+ logger.error(message);
166
+ finish(null);
167
+ }, LG_LUNA_SERVICE_TIMEOUT);
168
+ try {
169
+ request = (_b = (_a = window.webOS) === null || _a === void 0 ? void 0 : _a.service) === null || _b === void 0 ? void 0 : _b.request("luna://com.webos.service.sm", {
170
+ method: "deviceid/getIDs",
171
+ parameters: { idType: ["LGUDID"] },
172
+ onSuccess: (response) => {
173
+ var _a, _b;
174
+ const deviceId = (_b = (_a = response.idList) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.idValue;
175
+ if (!deviceId) {
176
+ const message = "LG Luna service returned no device ID";
177
+ logger.error(message);
178
+ }
179
+ finish(deviceId || null);
180
+ },
181
+ onFailure: (error) => {
182
+ const message = "LG Luna service failed:";
183
+ logger.error(message, { error });
184
+ finish(null);
185
+ },
186
+ subscribe: false,
187
+ });
188
+ }
189
+ catch (error) {
190
+ const message = "LG Luna service request threw error:";
191
+ logger.error(message, { error });
192
+ finish(null);
193
+ }
194
+ });
195
+ }
196
+ //# sourceMappingURL=getDeviceId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getDeviceId.js","sourceRoot":"","sources":["../src/getDeviceId.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type Logger } from "./logger";
2
+ /**
3
+ * Retrieve shell app version for different platforms.
4
+ *
5
+ * Platform-specific methods:
6
+ * - SAMSUNG_TV: Tizen Application API `tizen.application.getAppInfo().version`
7
+ * - LG_TV: webOS Application API `webOS.fetchAppInfo()`
8
+ * - FIRE_TV: Native bridge via Capacitor DeviceInfo plugin
9
+ * - ANDROID_MOBILE/IOS_MOBILE: Native bridge (future implementation)
10
+ * - WEB/Unknown: Returns 'unknown'
11
+ *
12
+ * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, ANDROID_MOBILE, IOS_MOBILE, WEB)
13
+ * @param logger - Optional logger for warning reporting. Defaults to defaultLogger.
14
+ * @returns Shell version string or 'unknown' if not available
15
+ */
16
+ export declare function getShellVersion(platform: string, logger?: Logger): Promise<string>;
17
+ declare global {
18
+ interface Window {
19
+ Capacitor?: {
20
+ Plugins?: {
21
+ DeviceInfo?: {
22
+ getDeviceInfo(): Promise<{
23
+ versionName?: string;
24
+ [key: string]: any;
25
+ }>;
26
+ [key: string]: any;
27
+ };
28
+ [key: string]: any;
29
+ };
30
+ [key: string]: any;
31
+ };
32
+ }
33
+ }
34
+ //# sourceMappingURL=getShellVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getShellVersion.d.ts","sourceRoot":"","sources":["../src/getShellVersion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAErD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA2EjB;AAGD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,SAAS,CAAC,EAAE;YACR,OAAO,CAAC,EAAE;gBACN,UAAU,CAAC,EAAE;oBACT,aAAa,IAAI,OAAO,CAAC;wBACrB,WAAW,CAAC,EAAE,MAAM,CAAA;wBACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;qBACrB,CAAC,CAAA;oBACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;iBACrB,CAAA;gBACD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;aACrB,CAAA;YACD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;SACrB,CAAA;KACJ;CACJ"}
@@ -0,0 +1,84 @@
1
+ import { defaultLogger } from "./logger";
2
+ /**
3
+ * Retrieve shell app version for different platforms.
4
+ *
5
+ * Platform-specific methods:
6
+ * - SAMSUNG_TV: Tizen Application API `tizen.application.getAppInfo().version`
7
+ * - LG_TV: webOS Application API `webOS.fetchAppInfo()`
8
+ * - FIRE_TV: Native bridge via Capacitor DeviceInfo plugin
9
+ * - ANDROID_MOBILE/IOS_MOBILE: Native bridge (future implementation)
10
+ * - WEB/Unknown: Returns 'unknown'
11
+ *
12
+ * @param platform - Platform identifier (SAMSUNG_TV, LG_TV, FIRE_TV, ANDROID_MOBILE, IOS_MOBILE, WEB)
13
+ * @param logger - Optional logger for warning reporting. Defaults to defaultLogger.
14
+ * @returns Shell version string or 'unknown' if not available
15
+ */
16
+ export async function getShellVersion(platform, logger = defaultLogger) {
17
+ var _a, _b, _c, _d;
18
+ try {
19
+ const normalizedPlatform = platform.toUpperCase();
20
+ // Samsung TV: Get version from Tizen Application API
21
+ if (normalizedPlatform === "SAMSUNG_TV") {
22
+ if (typeof window !== "undefined" && window.tizen) {
23
+ const tizen = window.tizen;
24
+ if ((_a = tizen.application) === null || _a === void 0 ? void 0 : _a.getAppInfo) {
25
+ const appInfo = tizen.application.getAppInfo();
26
+ return (_b = appInfo === null || appInfo === void 0 ? void 0 : appInfo.version) !== null && _b !== void 0 ? _b : "unknown";
27
+ }
28
+ }
29
+ return "unknown";
30
+ }
31
+ // LG TV: Get version from webOS API
32
+ // Note: webOS.fetchAppInfo(callback, path) takes a single callback and optional path.
33
+ // The callback receives the parsed appinfo.json or undefined on failure.
34
+ if (normalizedPlatform === "LG_TV") {
35
+ if (typeof window !== "undefined" && window.webOS) {
36
+ const webOS = window.webOS;
37
+ if (webOS.fetchAppInfo) {
38
+ return new Promise((resolve) => {
39
+ webOS.fetchAppInfo((appInfo) => {
40
+ var _a;
41
+ resolve((_a = appInfo === null || appInfo === void 0 ? void 0 : appInfo.version) !== null && _a !== void 0 ? _a : "unknown");
42
+ });
43
+ });
44
+ }
45
+ }
46
+ return "unknown";
47
+ }
48
+ // FireTV: Get version from Capacitor DeviceInfo plugin
49
+ if (normalizedPlatform === "FIRE_TV") {
50
+ // Check if Capacitor is available
51
+ if (typeof window !== "undefined" && window.Capacitor) {
52
+ const Capacitor = window.Capacitor;
53
+ const DeviceInfo = (_c = Capacitor.Plugins) === null || _c === void 0 ? void 0 : _c.DeviceInfo;
54
+ if (DeviceInfo === null || DeviceInfo === void 0 ? void 0 : DeviceInfo.getDeviceInfo) {
55
+ const deviceInfo = await DeviceInfo.getDeviceInfo();
56
+ return (_d = deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.versionName) !== null && _d !== void 0 ? _d : "unknown";
57
+ }
58
+ }
59
+ return "unknown";
60
+ }
61
+ // Mobile: Future implementation via native bridge
62
+ if (normalizedPlatform === "ANDROID_MOBILE" ||
63
+ normalizedPlatform === "IOS_MOBILE" ||
64
+ normalizedPlatform === "MOBILE") {
65
+ // TODO: Implement native bridge version retrieval when available
66
+ return "unknown";
67
+ }
68
+ // Web platform: Check for injected version at build time
69
+ if (normalizedPlatform === "WEB") {
70
+ if (typeof import.meta.env !== "undefined" &&
71
+ import.meta.env.VITE_SHELL_VERSION) {
72
+ return import.meta.env.VITE_SHELL_VERSION;
73
+ }
74
+ }
75
+ // Other unknown platforms
76
+ return "unknown";
77
+ }
78
+ catch (error) {
79
+ const message = "[Shell] Failed to get shell version:";
80
+ logger.warn(message, { error });
81
+ return "unknown";
82
+ }
83
+ }
84
+ //# sourceMappingURL=getShellVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getShellVersion.js","sourceRoot":"","sources":["../src/getShellVersion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
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";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
@@ -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
+ <script type="module" crossorigin src="/main.js"></script>
21
+ </head>
22
+ <body>
23
+ <div id="loading">Loading...</div>
24
+ </body>
25
+ </html>
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { fetchAmplitudeFlags } from "./amplitudeFlagFetcher";
2
+ export { getDeviceId } from "./getDeviceId";
3
+ export { getShellVersion } from "./getShellVersion";
4
+ export { loadVwr } from "./loadVwr";
5
+ export { getVWRConfig } from "./vwrConfig";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { type Logger } from "./logger";
2
+ export type { Logger };
3
+ /**
4
+ * Load VWR runtime.
5
+ *
6
+ * Optimized flow: checks vwr-enabled flag FIRST using baked-in Amplitude key,
7
+ * before doing any config fetches. For flag-OFF users (100% at initial launch),
8
+ * this reduces startup latency from ~2-4s to ~500ms by skipping config fetches.
9
+ *
10
+ * Flow:
11
+ * 1. Get deviceId, shellVersion (fast, local)
12
+ * 2. Check vwr-enabled flag (single request, ~500ms)
13
+ * 3. If OFF → throw immediately (no config fetches)
14
+ * 4. If ON → fetch config, load VWR module, initialize
15
+ *
16
+ * @param logger - Optional logger, defaults to console
17
+ */
18
+ export declare const loadVwr: (logger?: Logger) => Promise<void>;
19
+ //# sourceMappingURL=loadVwr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadVwr.d.ts","sourceRoot":"","sources":["../src/loadVwr.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAcrD,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,OAAO,GAAU,SAAQ,MAAsB,kBA0F3D,CAAA"}
@@ -0,0 +1,104 @@
1
+ import { fetchAmplitudeFlags } from "./amplitudeFlagFetcher";
2
+ import { ENV_DEFAULTS } from "./envDefaults";
3
+ import { getDeviceId } from "./getDeviceId";
4
+ import { getShellVersion } from "./getShellVersion";
5
+ import { defaultLogger } from "./logger";
6
+ import { getVWRConfig, validateConfig } from "./vwrConfig";
7
+ // Vite injects these at build time
8
+ const ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT;
9
+ const PLATFORM = import.meta.env.VITE_PLATFORM;
10
+ const CONFIG_URL = import.meta.env.VITE_CONFIG_URL;
11
+ const CONFIG_FILE = import.meta.env.VITE_CONFIG_FILE;
12
+ // AMPLITUDE_KEY can be optionally injected at build time (via build.ts script)
13
+ // Falls back to envDefaults if not injected (e.g., vite.config.dev.ts)
14
+ const AMPLITUDE_KEY = import.meta.env.VITE_AMPLITUDE_DEPLOYMENT_KEY;
15
+ /**
16
+ * Load VWR runtime.
17
+ *
18
+ * Optimized flow: checks vwr-enabled flag FIRST using baked-in Amplitude key,
19
+ * before doing any config fetches. For flag-OFF users (100% at initial launch),
20
+ * this reduces startup latency from ~2-4s to ~500ms by skipping config fetches.
21
+ *
22
+ * Flow:
23
+ * 1. Get deviceId, shellVersion (fast, local)
24
+ * 2. Check vwr-enabled flag (single request, ~500ms)
25
+ * 3. If OFF → throw immediately (no config fetches)
26
+ * 4. If ON → fetch config, load VWR module, initialize
27
+ *
28
+ * @param logger - Optional logger, defaults to console
29
+ */
30
+ export const loadVwr = async (logger = defaultLogger) => {
31
+ if (!ENVIRONMENT || !PLATFORM || !CONFIG_URL || !CONFIG_FILE) {
32
+ throw new Error("[Shell] Build config not injected properly");
33
+ }
34
+ const deviceId = await getDeviceId(PLATFORM, logger);
35
+ if (!deviceId) {
36
+ const message = `[Shell] Failed to retrieve device ID for platform: ${PLATFORM}`;
37
+ logger.error(message);
38
+ throw new Error(message);
39
+ }
40
+ const shellVersion = await getShellVersion(PLATFORM, logger);
41
+ // Get amplitude key: injected at build time OR from envDefaults
42
+ // Precedence: build-time injection > envDefaults
43
+ let amplitudeKey = AMPLITUDE_KEY;
44
+ if (!amplitudeKey) {
45
+ const envDefaults = ENV_DEFAULTS[ENVIRONMENT];
46
+ if (!envDefaults) {
47
+ throw new Error(`[Shell] Unknown environment: ${ENVIRONMENT}`);
48
+ }
49
+ amplitudeKey = envDefaults.amplitudeKey;
50
+ }
51
+ // FAST PATH: Check flag first using amplitude key
52
+ // This avoids config fetches for flag-OFF users (majority at launch)
53
+ const flags = await fetchAmplitudeFlags(deviceId, PLATFORM, {
54
+ apiKey: amplitudeKey,
55
+ timeout: 2000,
56
+ }, shellVersion);
57
+ logger.info("[Shell] Flags fetched", { flags });
58
+ if (!flags["vwr-enabled"]) {
59
+ // Flag OFF: skip all config fetches, fail fast
60
+ throw new Error("[Shell] VWR not enabled via Amplitude flags");
61
+ }
62
+ // Flag ON: proceed with full config loading
63
+ logger.info("[Shell] VWR flag enabled, fetching config...");
64
+ const vwrConfigRequest = {
65
+ configUrl: CONFIG_URL,
66
+ configFile: CONFIG_FILE,
67
+ platform: PLATFORM,
68
+ deviceId: deviceId,
69
+ environment: ENVIRONMENT,
70
+ shellVersion: shellVersion,
71
+ };
72
+ const vwrConfig = await getVWRConfig(vwrConfigRequest, logger);
73
+ if (!validateConfig(vwrConfig)) {
74
+ throw new Error("Invalid config, falling back to default hub");
75
+ }
76
+ logger.info("[Shell] VWR enabled, loading module", {
77
+ vwrUrl: vwrConfig.vwrUrl,
78
+ });
79
+ try {
80
+ const vwr = await import(/* @vite-ignore */ vwrConfig.vwrUrl);
81
+ logger.info("[Shell] VWR module loaded successfully");
82
+ if (typeof vwr.init !== "function") {
83
+ throw new Error("[Shell] VWR module missing init() function");
84
+ }
85
+ await vwr.init({
86
+ hubUrl: vwrConfig.hubUrl,
87
+ launchUrl: vwrConfig.launchUrl,
88
+ platform: PLATFORM,
89
+ deviceId,
90
+ environment: ENVIRONMENT,
91
+ trustedDomains: vwrConfig.trustedDomains,
92
+ nativeShellVersion: shellVersion,
93
+ });
94
+ logger.info("[Shell] VWR initialized successfully");
95
+ }
96
+ catch (vwrError) {
97
+ logger.error("[Shell] VWR load failed", {
98
+ error: vwrError instanceof Error ? vwrError.message : String(vwrError),
99
+ vwrUrl: vwrConfig.vwrUrl,
100
+ });
101
+ throw vwrError; // Re-throw to outer catch for fallback
102
+ }
103
+ };
104
+ //# sourceMappingURL=loadVwr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadVwr.js","sourceRoot":"","sources":["../src/loadVwr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
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
+ export declare const defaultLogger: Logger;
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IAClE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CACtE;AAED,eAAO,MAAM,aAAa,EAAE,MAO3B,CAAA"}
package/dist/logger.js ADDED
@@ -0,0 +1,6 @@
1
+ export const defaultLogger = {
2
+ info: (message, context) => context ? console.log(message, context) : console.log(message),
3
+ warn: (message, context) => context ? console.warn(message, context) : console.warn(message),
4
+ error: (message, context) => context ? console.error(message, context) : console.error(message),
5
+ };
6
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,aAAa,GAAW;IACjC,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CACvB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IAClE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CACvB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;IACpE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CACxB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;CACzE,CAAA"}
package/dist/main.js ADDED
@@ -0,0 +1,2 @@
1
+ (function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const t of e)if(t.type==="childList")for(const n of t.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&i(n)}).observe(document,{childList:!0,subtree:!0});function l(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?t.credentials="include":e.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function i(e){if(e.ep)return;e.ep=!0;const t=l(e);fetch(e.href,t)}})();const c={info:(r,o)=>o?console.log(r,o):console.log(r),warn:(r,o)=>o?console.warn(r,o):console.warn(r),error:(r,o)=>o?console.error(r,o):console.error(r)},s=async(r=c)=>{throw new Error("[Shell] Build config not injected properly")},f=void 0,d=void 0;async function u(){try{await s()}catch(r){try{console.error("[Shell] ⚠️ FALLBACK TO HUB - Init failed:",r),window.DD_LOGS&&window.DD_LOGS.logger.error("shell_init_failed",{error:r.message,platform:f})}finally{window.location.href=d}}}u();
2
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sources":["../src/logger.ts","../src/loadVwr.ts","../src/main.ts"],"sourcesContent":["export interface Logger {\n info: (message: string, context?: Record<string, unknown>) => void\n warn: (message: string, context?: Record<string, unknown>) => void\n error: (message: string, context?: Record<string, unknown>) => void\n}\n\nexport const defaultLogger: Logger = {\n info: (message, context) =>\n context ? console.log(message, context) : console.log(message),\n warn: (message, context) =>\n context ? console.warn(message, context) : console.warn(message),\n error: (message, context) =>\n context ? console.error(message, context) : console.error(message),\n}\n","import { fetchAmplitudeFlags } from \"./amplitudeFlagFetcher\"\nimport { ENV_DEFAULTS } from \"./envDefaults\"\nimport { getDeviceId } from \"./getDeviceId\"\nimport { getShellVersion } from \"./getShellVersion\"\nimport { defaultLogger, type Logger } from \"./logger\"\nimport type { VWRConfig, VWRConfigRequest } from \"./vwrConfig\"\nimport { getVWRConfig, validateConfig } from \"./vwrConfig\"\n\n// Vite injects these at build time\nconst ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT\nconst PLATFORM = import.meta.env.VITE_PLATFORM\nconst CONFIG_URL = import.meta.env.VITE_CONFIG_URL\nconst CONFIG_FILE = import.meta.env.VITE_CONFIG_FILE\n\n// AMPLITUDE_KEY can be optionally injected at build time (via build.ts script)\n// Falls back to envDefaults if not injected (e.g., vite.config.dev.ts)\nconst AMPLITUDE_KEY = import.meta.env.VITE_AMPLITUDE_DEPLOYMENT_KEY\n\nexport type { Logger }\n\n/**\n * Load VWR runtime.\n *\n * Optimized flow: checks vwr-enabled flag FIRST using baked-in Amplitude key,\n * before doing any config fetches. For flag-OFF users (100% at initial launch),\n * this reduces startup latency from ~2-4s to ~500ms by skipping config fetches.\n *\n * Flow:\n * 1. Get deviceId, shellVersion (fast, local)\n * 2. Check vwr-enabled flag (single request, ~500ms)\n * 3. If OFF → throw immediately (no config fetches)\n * 4. If ON → fetch config, load VWR module, initialize\n *\n * @param logger - Optional logger, defaults to console\n */\nexport const loadVwr = async (logger: Logger = defaultLogger) => {\n if (!ENVIRONMENT || !PLATFORM || !CONFIG_URL || !CONFIG_FILE) {\n throw new Error(\"[Shell] Build config not injected properly\")\n }\n\n const deviceId = await getDeviceId(PLATFORM, logger)\n if (!deviceId) {\n const message = `[Shell] Failed to retrieve device ID for platform: ${PLATFORM}`\n logger.error(message)\n throw new Error(message)\n }\n const shellVersion = await getShellVersion(PLATFORM, logger)\n\n // Get amplitude key: injected at build time OR from envDefaults\n // Precedence: build-time injection > envDefaults\n let amplitudeKey = AMPLITUDE_KEY\n if (!amplitudeKey) {\n const envDefaults = ENV_DEFAULTS[ENVIRONMENT]\n if (!envDefaults) {\n throw new Error(`[Shell] Unknown environment: ${ENVIRONMENT}`)\n }\n amplitudeKey = envDefaults.amplitudeKey\n }\n\n // FAST PATH: Check flag first using amplitude key\n // This avoids config fetches for flag-OFF users (majority at launch)\n const flags = await fetchAmplitudeFlags(\n deviceId,\n PLATFORM,\n {\n apiKey: amplitudeKey,\n timeout: 2000,\n },\n shellVersion\n )\n\n logger.info(\"[Shell] Flags fetched\", { flags })\n\n if (!flags[\"vwr-enabled\"]) {\n // Flag OFF: skip all config fetches, fail fast\n throw new Error(\"[Shell] VWR not enabled via Amplitude flags\")\n }\n\n // Flag ON: proceed with full config loading\n logger.info(\"[Shell] VWR flag enabled, fetching config...\")\n\n const vwrConfigRequest: VWRConfigRequest = {\n configUrl: CONFIG_URL,\n configFile: CONFIG_FILE,\n platform: PLATFORM,\n deviceId: deviceId,\n environment: ENVIRONMENT,\n shellVersion: shellVersion,\n }\n\n const vwrConfig: VWRConfig = await getVWRConfig(vwrConfigRequest, logger)\n\n if (!validateConfig(vwrConfig)) {\n throw new Error(\"Invalid config, falling back to default hub\")\n }\n\n logger.info(\"[Shell] VWR enabled, loading module\", {\n vwrUrl: vwrConfig.vwrUrl,\n })\n try {\n const vwr = await import(/* @vite-ignore */ vwrConfig.vwrUrl)\n logger.info(\"[Shell] VWR module loaded successfully\")\n\n if (typeof vwr.init !== \"function\") {\n throw new Error(\"[Shell] VWR module missing init() function\")\n }\n\n await vwr.init({\n hubUrl: vwrConfig.hubUrl,\n launchUrl: vwrConfig.launchUrl,\n platform: PLATFORM,\n deviceId,\n environment: ENVIRONMENT,\n trustedDomains: vwrConfig.trustedDomains,\n nativeShellVersion: shellVersion,\n })\n logger.info(\"[Shell] VWR initialized successfully\")\n } catch (vwrError) {\n logger.error(\"[Shell] VWR load failed\", {\n error:\n vwrError instanceof Error ? vwrError.message : String(vwrError),\n vwrUrl: vwrConfig.vwrUrl,\n })\n throw vwrError // Re-throw to outer catch for fallback\n }\n}\n","import { loadVwr } from \"./loadVwr\"\n\nconst PLATFORM = import.meta.env.VITE_PLATFORM\nconst HUB_URL = import.meta.env.VITE_HUB_URL\n\nasync function init() {\n try {\n await loadVwr()\n } catch (error) {\n try {\n console.error(\"[Shell] ⚠️ FALLBACK TO HUB - Init failed:\", error)\n\n if ((window as any).DD_LOGS) {\n ;(window as any).DD_LOGS.logger.error(\"shell_init_failed\", {\n error: (error as Error).message,\n platform: PLATFORM,\n })\n }\n } finally {\n //Fallback, can't trust config exists\n window.location.href = HUB_URL\n }\n }\n}\n\ninit()\n"],"names":["defaultLogger","message","context","loadVwr","logger","PLATFORM","HUB_URL","init","error"],"mappings":"ssBAMO,MAAMA,EAAwB,CACjC,KAAM,CAACC,EAASC,IACZA,EAAU,QAAQ,IAAID,EAASC,CAAO,EAAI,QAAQ,IAAID,CAAO,EACjE,KAAM,CAACA,EAASC,IACZA,EAAU,QAAQ,KAAKD,EAASC,CAAO,EAAI,QAAQ,KAAKD,CAAO,EACnE,MAAO,CAACA,EAASC,IACbA,EAAU,QAAQ,MAAMD,EAASC,CAAO,EAAI,QAAQ,MAAMD,CAAO,CACzE,ECsBaE,EAAU,MAAOC,EAAiBJ,IAAkB,CAEzD,MAAM,IAAI,MAAM,4CAA4C,CAwFpE,EC3HMK,EAAW,OACXC,EAAU,OAEhB,eAAeC,GAAO,CAClB,GAAI,CACA,MAAMJ,EAAA,CACV,OAASK,EAAO,CACZ,GAAI,CACA,QAAQ,MAAM,6CAA8CA,CAAK,EAE5D,OAAe,SACd,OAAe,QAAQ,OAAO,MAAM,oBAAqB,CACvD,MAAQA,EAAgB,QACxB,SAAUH,CAAA,CACb,CAET,QAAA,CAEI,OAAO,SAAS,KAAOC,CAC3B,CACJ,CACJ,CAEAC,EAAA"}
@@ -0,0 +1,19 @@
1
+ import { type Logger } from "./logger";
2
+ export type VWRConfig = {
3
+ hubUrl: string;
4
+ vwrUrl: string;
5
+ launchUrl: string | undefined;
6
+ trustedDomains: Array<string>;
7
+ };
8
+ export type VWRConfigRequest = {
9
+ configUrl: string;
10
+ configFile: string;
11
+ platform: string;
12
+ deviceId: string;
13
+ environment: string;
14
+ shellVersion: string;
15
+ timeout?: number;
16
+ };
17
+ export declare const getVWRConfig: (request: VWRConfigRequest, logger?: Logger) => Promise<VWRConfig>;
18
+ export declare const validateConfig: (config: VWRConfig) => boolean;
19
+ //# sourceMappingURL=vwrConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vwrConfig.d.ts","sourceRoot":"","sources":["../src/vwrConfig.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAErD,MAAM,MAAM,SAAS,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAsBD,eAAO,MAAM,YAAY,GACrB,SAAS,gBAAgB,EACzB,SAAQ,MAAsB,KAC/B,OAAO,CAAC,SAAS,CAmEnB,CAAA;AAyJD,eAAO,MAAM,cAAc,GAAI,QAAQ,SAAS,KAAG,OAWlD,CAAA"}