@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.
package/src/vwrConfig.ts CHANGED
@@ -40,240 +40,223 @@ const buildUrl = (path: string, base: string): URL => {
40
40
  return new URL(path, normalizedBase)
41
41
  }
42
42
 
43
- export const getVWRConfig = async (
44
- request: VWRConfigRequest,
45
- logger: Logger = defaultLogger
46
- ): Promise<VWRConfig> => {
47
- const timeout = request.timeout ?? DEFAULT_CONFIG_TIMEOUT
48
-
49
- logger.info(
50
- "[VWR Config] Fetching config with priority: local → device → shellVersion → environment → defaults"
51
- )
52
-
53
- // Fetch all configs in parallel for performance
54
- const [localConfig, deviceConfig, shellVersionConfig, environmentConfig] =
55
- await Promise.all([
56
- tryGetLocalConfig(request.configFile, timeout, logger),
57
- tryGetDeviceConfig(
58
- request.configUrl,
59
- request.configFile,
60
- request.platform,
61
- request.deviceId,
62
- timeout,
63
- logger
64
- ),
65
- tryGetShellVersionConfig(
66
- request.configUrl,
67
- request.configFile,
68
- request.environment,
69
- request.platform,
70
- request.shellVersion,
71
- timeout,
72
- logger
73
- ),
74
- tryGetEnvironmentConfig(
75
- request.configUrl,
76
- request.configFile,
77
- request.environment,
78
- timeout,
79
- logger
80
- ),
81
- ])
82
-
83
- // Return first successful config in priority order
84
- if (localConfig !== null) {
85
- logger.info("[VWR Config] ✓ Using config from: local", localConfig)
86
- return localConfig
87
- }
88
- if (deviceConfig !== null) {
89
- logger.info("[VWR Config] ✓ Using config from: device", deviceConfig)
90
- return deviceConfig
43
+ class VWRConfigFetcher {
44
+ private readonly defaults: VWRConfig
45
+ private readonly timeout: number
46
+ private readonly logger: Logger
47
+ private readonly configUrl: string
48
+ private readonly configFile: string
49
+ private readonly platform: string
50
+ private readonly deviceId: string
51
+ private readonly environment: string
52
+ private readonly shellVersion: string
53
+
54
+ constructor(request: VWRConfigRequest, logger: Logger) {
55
+ this.defaults = getDefaultConfig(request.environment)
56
+ this.timeout = request.timeout ?? DEFAULT_CONFIG_TIMEOUT
57
+ this.logger = logger
58
+ this.configUrl = request.configUrl
59
+ this.configFile = request.configFile
60
+ this.platform = request.platform
61
+ this.deviceId = request.deviceId
62
+ this.environment = request.environment
63
+ this.shellVersion = request.shellVersion
91
64
  }
92
- if (shellVersionConfig !== null) {
93
- logger.info(
94
- "[VWR Config] ✓ Using config from: shellVersion",
95
- shellVersionConfig
96
- )
97
- return shellVersionConfig
98
- }
99
- if (environmentConfig !== null) {
100
- logger.info(
101
- "[VWR Config] ✓ Using config from: environment",
102
- environmentConfig
65
+
66
+ async fetch(): Promise<VWRConfig> {
67
+ this.logger.info(
68
+ "[VWR Config] Fetching config with priority: local → device → shellVersion → environment → defaults"
103
69
  )
104
- return environmentConfig
105
- }
106
70
 
107
- // All fetches failed, use defaults
108
- logger.warn(
109
- "[VWR Config] All config fetches failed, using built-in defaults"
110
- )
111
- const defaultConfig = getDefaultConfig()
112
- return defaultConfig
113
- }
71
+ // Fetch all configs in parallel for performance
72
+ const [
73
+ localConfig,
74
+ deviceConfig,
75
+ shellVersionConfig,
76
+ environmentConfig,
77
+ ] = await Promise.all([
78
+ this.tryGetLocalConfig(),
79
+ this.tryGetDeviceConfig(),
80
+ this.tryGetShellVersionConfig(),
81
+ this.tryGetEnvironmentConfig(),
82
+ ])
114
83
 
115
- const tryGetLocalConfig = async (
116
- configFile: string,
117
- timeout: number,
118
- logger: Logger
119
- ): Promise<VWRConfig | null> => {
120
- try {
121
- const url = buildUrl(configFile, ENV_DEFAULTS["local"]?.configUrl ?? "")
122
- logger.info(`[VWR Config] Trying local: ${url}`)
123
- return tryGetVWRConfig(url, timeout)
124
- } catch (error) {
125
- logger.error(
126
- `[VWR Config] URL construction failed for local config: ${error}`
127
- )
128
- return null
129
- }
130
- }
84
+ // Return first successful config in priority order
85
+ if (localConfig !== null) {
86
+ this.logger.info(
87
+ "[VWR Config] ✓ Using config from: local",
88
+ localConfig
89
+ )
90
+ return localConfig
91
+ }
92
+ if (deviceConfig !== null) {
93
+ this.logger.info(
94
+ "[VWR Config] ✓ Using config from: device",
95
+ deviceConfig
96
+ )
97
+ return deviceConfig
98
+ }
99
+ if (shellVersionConfig !== null) {
100
+ this.logger.info(
101
+ "[VWR Config] ✓ Using config from: shellVersion",
102
+ shellVersionConfig
103
+ )
104
+ return shellVersionConfig
105
+ }
106
+ if (environmentConfig !== null) {
107
+ this.logger.info(
108
+ "[VWR Config] ✓ Using config from: environment",
109
+ environmentConfig
110
+ )
111
+ return environmentConfig
112
+ }
131
113
 
132
- const tryGetDeviceConfig = async (
133
- configUrl: string,
134
- configFile: string,
135
- platform: string,
136
- deviceId: string,
137
- timeout: number,
138
- logger: Logger
139
- ): Promise<VWRConfig | null> => {
140
- try {
141
- const url = buildUrl(
142
- `device/${platform}/${deviceId}/${configFile}`,
143
- configUrl
144
- )
145
- logger.info(`[VWR Config] Trying device: ${url}`)
146
- return tryGetVWRConfig(url, timeout)
147
- } catch (error) {
148
- logger.error(
149
- `[VWR Config] URL construction failed for device config: ${error}`
114
+ // All fetches failed, use defaults
115
+ this.logger.warn(
116
+ "[VWR Config] All config fetches failed, using built-in defaults"
150
117
  )
151
- return null
118
+ return this.defaults
152
119
  }
153
- }
154
120
 
155
- const tryGetEnvironmentConfig = async (
156
- configUrl: string,
157
- configFile: string,
158
- environment: string,
159
- timeout: number,
160
- logger: Logger
161
- ): Promise<VWRConfig | null> => {
162
- try {
163
- const url = buildUrl(
164
- `environments/${environment}/${configFile}`,
165
- configUrl
166
- )
167
- logger.info(`[VWR Config] Trying environment: ${url}`)
168
- return tryGetVWRConfig(url, timeout)
169
- } catch (error) {
170
- logger.error(
171
- `[VWR Config] URL construction failed for environment config: ${error}`
172
- )
173
- return null
121
+ private async tryGetLocalConfig(): Promise<VWRConfig | null> {
122
+ try {
123
+ const url = buildUrl(
124
+ this.configFile,
125
+ ENV_DEFAULTS["local"]?.configUrl ?? ""
126
+ )
127
+ this.logger.info(`[VWR Config] Trying local: ${url}`)
128
+ return this.tryFetchConfig(url)
129
+ } catch (error) {
130
+ this.logger.error(
131
+ `[VWR Config] URL construction failed for local config: ${error}`
132
+ )
133
+ return null
134
+ }
174
135
  }
175
- }
176
136
 
177
- const tryGetShellVersionConfig = async (
178
- configUrl: string,
179
- configFile: string,
180
- environment: string,
181
- platform: string,
182
- shellVersion: string,
183
- timeout: number,
184
- logger: Logger
185
- ): Promise<VWRConfig | null> => {
186
- try {
187
- const url = buildUrl(
188
- `shellVersion/${environment}/${platform}/${shellVersion}/${configFile}`,
189
- configUrl
190
- )
191
- logger.info(`[VWR Config] Trying shellVersion: ${url}`)
192
- return tryGetVWRConfig(url, timeout)
193
- } catch (error) {
194
- logger.error(
195
- `[VWR Config] URL construction failed for shellVersion config: ${error}`
196
- )
197
- return null
137
+ private async tryGetDeviceConfig(): Promise<VWRConfig | null> {
138
+ try {
139
+ const url = buildUrl(
140
+ `device/${this.platform}/${this.deviceId}/${this.configFile}`,
141
+ this.configUrl
142
+ )
143
+ this.logger.info(`[VWR Config] Trying device: ${url}`)
144
+ return this.tryFetchConfig(url)
145
+ } catch (error) {
146
+ this.logger.error(
147
+ `[VWR Config] URL construction failed for device config: ${error}`
148
+ )
149
+ return null
150
+ }
198
151
  }
199
- }
200
152
 
201
- const tryGetVWRConfig = async (
202
- url: URL,
203
- timeout: number
204
- ): Promise<VWRConfig | null> => {
205
- const controller = new AbortController()
206
- const timeoutId = setTimeout(() => controller.abort(), timeout)
207
-
208
- try {
209
- const response = await fetch(
210
- new Request(url, {
211
- headers: {
212
- "Content-Type": "application/json",
213
- },
214
- signal: controller.signal,
215
- })
216
- )
217
-
218
- if (!response.ok) {
219
- clearTimeout(timeoutId)
153
+ private async tryGetEnvironmentConfig(): Promise<VWRConfig | null> {
154
+ try {
155
+ const url = buildUrl(
156
+ `environments/${this.environment}/${this.configFile}`,
157
+ this.configUrl
158
+ )
159
+ this.logger.info(`[VWR Config] Trying environment: ${url}`)
160
+ return this.tryFetchConfig(url)
161
+ } catch (error) {
162
+ this.logger.error(
163
+ `[VWR Config] URL construction failed for environment config: ${error}`
164
+ )
220
165
  return null
221
166
  }
167
+ }
222
168
 
223
- let config = await response.json()
224
- config = parseConfig(config)
225
-
226
- clearTimeout(timeoutId)
227
- return config as VWRConfig
228
- } catch {
229
- clearTimeout(timeoutId)
230
- return null
169
+ private async tryGetShellVersionConfig(): Promise<VWRConfig | null> {
170
+ try {
171
+ const url = buildUrl(
172
+ `shellVersion/${this.environment}/${this.platform}/${this.shellVersion}/${this.configFile}`,
173
+ this.configUrl
174
+ )
175
+ this.logger.info(`[VWR Config] Trying shellVersion: ${url}`)
176
+ return this.tryFetchConfig(url)
177
+ } catch (error) {
178
+ this.logger.error(
179
+ `[VWR Config] URL construction failed for shellVersion config: ${error}`
180
+ )
181
+ return null
182
+ }
231
183
  }
232
- }
233
184
 
234
- const parseConfig = (config: VWRConfig): VWRConfig => {
235
- const defaultConfig = getDefaultConfig()
185
+ private async tryFetchConfig(url: URL): Promise<VWRConfig | null> {
186
+ const controller = new AbortController()
187
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout)
236
188
 
237
- if (!config.platformApiUrl) {
238
- config.platformApiUrl = defaultConfig.platformApiUrl
239
- }
189
+ try {
190
+ const response = await fetch(
191
+ new Request(url, {
192
+ headers: { "Content-Type": "application/json" },
193
+ signal: controller.signal,
194
+ })
195
+ )
240
196
 
241
- if (!config.platformAuthApiUrl) {
242
- config.platformAuthApiUrl = defaultConfig.platformAuthApiUrl
243
- }
197
+ if (!response.ok) {
198
+ clearTimeout(timeoutId)
199
+ return null
200
+ }
244
201
 
245
- if (
246
- !Array.isArray(config.trustedDomains) ||
247
- config.trustedDomains.length === 0
248
- ) {
249
- config.trustedDomains = defaultConfig.trustedDomains
202
+ const config = await response.json()
203
+ clearTimeout(timeoutId)
204
+ return this.parseConfig(config)
205
+ } catch {
206
+ clearTimeout(timeoutId)
207
+ return null
208
+ }
250
209
  }
251
210
 
252
- if (!config.vwrUrl) {
253
- config.vwrUrl = defaultConfig.vwrUrl
254
- const vwrUrlOrigin = new URL(defaultConfig.vwrUrl).origin
255
- if (!config.trustedDomains.includes(vwrUrlOrigin)) {
256
- config.trustedDomains.push(vwrUrlOrigin)
211
+ private parseConfig(config: Partial<VWRConfig>): VWRConfig {
212
+ const result: VWRConfig = {
213
+ hubUrl: config.hubUrl || this.defaults.hubUrl,
214
+ vwrUrl: config.vwrUrl || this.defaults.vwrUrl,
215
+ launchUrl: config.launchUrl,
216
+ platformApiUrl:
217
+ config.platformApiUrl || this.defaults.platformApiUrl,
218
+ platformAuthApiUrl:
219
+ config.platformAuthApiUrl || this.defaults.platformAuthApiUrl,
220
+ trustedDomains:
221
+ Array.isArray(config.trustedDomains) &&
222
+ config.trustedDomains.length > 0
223
+ ? [...config.trustedDomains]
224
+ : [...this.defaults.trustedDomains],
257
225
  }
258
- }
259
226
 
260
- if (!config.hubUrl) {
261
- config.hubUrl = defaultConfig.hubUrl
262
- const hubUrlOrigin = new URL(defaultConfig.hubUrl).origin
263
- if (!config.trustedDomains.includes(hubUrlOrigin)) {
264
- config.trustedDomains.push(hubUrlOrigin)
227
+ // Ensure vwrUrl origin is in trustedDomains
228
+ const vwrUrlOrigin = new URL(result.vwrUrl).origin
229
+ if (!result.trustedDomains.includes(vwrUrlOrigin)) {
230
+ result.trustedDomains.push(vwrUrlOrigin)
231
+ }
232
+
233
+ // Ensure hubUrl origin is in trustedDomains
234
+ const hubUrlOrigin = new URL(result.hubUrl).origin
235
+ if (!result.trustedDomains.includes(hubUrlOrigin)) {
236
+ result.trustedDomains.push(hubUrlOrigin)
265
237
  }
266
- }
267
238
 
268
- // 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)
239
+ // launchUrl is optional - only add to trustedDomains if explicitly set
240
+ if (result.launchUrl) {
241
+ try {
242
+ const launchUrlOrigin = new URL(result.launchUrl).origin
243
+ if (!result.trustedDomains.includes(launchUrlOrigin)) {
244
+ result.trustedDomains.push(launchUrlOrigin)
245
+ }
246
+ } catch {
247
+ // Invalid launchUrl - skip adding to trustedDomains
248
+ }
273
249
  }
250
+
251
+ return result
274
252
  }
253
+ }
275
254
 
276
- return config
255
+ export const getVWRConfig = async (
256
+ request: VWRConfigRequest,
257
+ logger: Logger = defaultLogger
258
+ ): Promise<VWRConfig> => {
259
+ return new VWRConfigFetcher(request, logger).fetch()
277
260
  }
278
261
 
279
262
  export const validateConfig = (config: VWRConfig): boolean => {
@@ -289,13 +272,12 @@ export const validateConfig = (config: VWRConfig): boolean => {
289
272
  return true
290
273
  }
291
274
 
292
- const getDefaultConfig = (): VWRConfig => {
293
- const ENVIRONMENT = import.meta.env.VITE_ENVIRONMENT || "dev"
294
- const defaults = ENV_DEFAULTS[ENVIRONMENT]
275
+ const getDefaultConfig = (environment: string): VWRConfig => {
276
+ const defaults = ENV_DEFAULTS[environment]
295
277
 
296
278
  if (!defaults) {
297
279
  throw new Error(
298
- `[VWR Config] Unknown environment: ${ENVIRONMENT}. Valid: local, dev, staging, prod`
280
+ `[VWR Config] Unknown environment: ${environment}. Valid: local, dev, staging, prod`
299
281
  )
300
282
  }
301
283