@@ -64,30 +64,110 @@ export function applyRemoteConfiguration(
6464 }
6565 } )
6666 return appliedConfiguration
67- }
6867
69- function resolveConfigurationProperty ( property : unknown ) : unknown {
70- if ( Array . isArray ( property ) ) {
71- return property . map ( resolveConfigurationProperty )
72- }
73- if ( isObject ( property ) ) {
74- if ( isSerializedOption ( property ) ) {
75- const type = property . rcSerializedType
76- switch ( type ) {
77- case 'string' :
78- return property . value
79- case 'regex' :
80- return resolveRegex ( property . value )
81- case 'dynamic' :
82- return resolveDynamicOption ( property )
83- default :
84- display . error ( `Unsupported remote configuration: "rcSerializedType": "${ type as string } "` )
85- return
68+ // share context to access metrics
69+
70+ function resolveConfigurationProperty ( property : unknown ) : unknown {
71+ if ( Array . isArray ( property ) ) {
72+ return property . map ( resolveConfigurationProperty )
73+ }
74+ if ( isObject ( property ) ) {
75+ if ( isSerializedOption ( property ) ) {
76+ const type = property . rcSerializedType
77+ switch ( type ) {
78+ case 'string' :
79+ return property . value
80+ case 'regex' :
81+ return resolveRegex ( property . value )
82+ case 'dynamic' :
83+ return resolveDynamicOption ( property )
84+ default :
85+ display . error ( `Unsupported remote configuration: "rcSerializedType": "${ type as string } "` )
86+ return
87+ }
8688 }
89+ return mapValues ( property , resolveConfigurationProperty )
90+ }
91+ return property
92+ }
93+
94+ function resolveContextProperty (
95+ contextManager : ReturnType < typeof createContextManager > ,
96+ contextItems : ContextItem [ ]
97+ ) {
98+ contextItems . forEach ( ( { key, value } ) => {
99+ contextManager . setContextProperty ( key , resolveConfigurationProperty ( value ) )
100+ } )
101+ }
102+
103+ function resolveDynamicOption ( property : DynamicOption ) {
104+ const strategy = property . strategy
105+ let resolvedValue : unknown
106+ switch ( strategy ) {
107+ case 'cookie' :
108+ resolvedValue = resolveCookieValue ( property )
109+ break
110+ case 'dom' :
111+ resolvedValue = resolveDomValue ( property )
112+ break
113+ case 'js' :
114+ resolvedValue = resolveJsValue ( property )
115+ break
116+ default :
117+ display . error ( `Unsupported remote configuration: "strategy": "${ strategy as string } "` )
118+ return
119+ }
120+ const extractor = property . extractor
121+ if ( extractor !== undefined && typeof resolvedValue === 'string' ) {
122+ return extractValue ( extractor , resolvedValue )
123+ }
124+ return resolvedValue
125+ }
126+
127+ function resolveCookieValue ( { name } : { name : string } ) {
128+ return getCookie ( name )
129+ }
130+
131+ function resolveDomValue ( { selector, attribute } : { selector : string ; attribute ?: string } ) {
132+ let element : Element | null
133+ try {
134+ element = document . querySelector ( selector )
135+ } catch {
136+ element = null
137+ display . error ( `Invalid selector in the remote configuration: '${ selector } '` )
87138 }
88- return mapValues ( property , resolveConfigurationProperty )
139+ if ( element === null || isForbidden ( element , attribute ) ) {
140+ return
141+ }
142+ const domValue = attribute !== undefined ? element . getAttribute ( attribute ) : element . textContent
143+ return domValue ?? undefined
144+ }
145+
146+ function isForbidden ( element : Element , attribute : string | undefined ) {
147+ return element . getAttribute ( 'type' ) === 'password' && attribute === 'value'
148+ }
149+
150+ function resolveJsValue ( { path } : { path : string } ) : unknown {
151+ let current = window as unknown as { [ key : string ] : unknown }
152+
153+ const pathParts = parseJsonPath ( path )
154+ if ( pathParts . length === 0 ) {
155+ display . error ( `Invalid JSON path in the remote configuration: '${ path } '` )
156+ return
157+ }
158+ for ( const pathPart of pathParts ) {
159+ if ( ! ( pathPart in current ) ) {
160+ return
161+ }
162+ try {
163+ current = current [ pathPart ] as { [ key : string ] : unknown }
164+ } catch ( e ) {
165+ display . error ( `Error accessing: '${ path } '` , e )
166+ return
167+ }
168+ }
169+ return current
89170 }
90- return property
91171}
92172
93173function isObject ( property : unknown ) : property is { [ key : string ] : unknown } {
@@ -106,82 +186,6 @@ function resolveRegex(pattern: string): RegExp | undefined {
106186 }
107187}
108188
109- function resolveContextProperty ( contextManager : ReturnType < typeof createContextManager > , contextItems : ContextItem [ ] ) {
110- contextItems . forEach ( ( { key, value } ) => {
111- contextManager . setContextProperty ( key , resolveConfigurationProperty ( value ) )
112- } )
113- }
114-
115- function resolveDynamicOption ( property : DynamicOption ) {
116- const strategy = property . strategy
117- let resolvedValue : unknown
118- switch ( strategy ) {
119- case 'cookie' :
120- resolvedValue = resolveCookieValue ( property )
121- break
122- case 'dom' :
123- resolvedValue = resolveDomValue ( property )
124- break
125- case 'js' :
126- resolvedValue = resolveJsValue ( property )
127- break
128- default :
129- display . error ( `Unsupported remote configuration: "strategy": "${ strategy as string } "` )
130- return
131- }
132- const extractor = property . extractor
133- if ( extractor !== undefined && typeof resolvedValue === 'string' ) {
134- return extractValue ( extractor , resolvedValue )
135- }
136- return resolvedValue
137- }
138-
139- function resolveCookieValue ( { name } : { name : string } ) {
140- return getCookie ( name )
141- }
142-
143- function resolveDomValue ( { selector, attribute } : { selector : string ; attribute ?: string } ) {
144- let element : Element | null
145- try {
146- element = document . querySelector ( selector )
147- } catch {
148- element = null
149- display . error ( `Invalid selector in the remote configuration: '${ selector } '` )
150- }
151- if ( element === null || isForbidden ( element , attribute ) ) {
152- return
153- }
154- const domValue = attribute !== undefined ? element . getAttribute ( attribute ) : element . textContent
155- return domValue ?? undefined
156- }
157-
158- function isForbidden ( element : Element , attribute : string | undefined ) {
159- return element . getAttribute ( 'type' ) === 'password' && attribute === 'value'
160- }
161-
162- function resolveJsValue ( { path } : { path : string } ) : unknown {
163- let current = window as unknown as { [ key : string ] : unknown }
164-
165- const pathParts = parseJsonPath ( path )
166- if ( pathParts . length === 0 ) {
167- display . error ( `Invalid JSON path in the remote configuration: '${ path } '` )
168- return
169- }
170- for ( const pathPart of pathParts ) {
171- if ( ! ( pathPart in current ) ) {
172- return
173- }
174- try {
175- current = current [ pathPart ] as { [ key : string ] : unknown }
176- } catch ( e ) {
177- display . error ( `Error accessing: '${ path } '` , e )
178- return
179- }
180- }
181-
182- return current
183- }
184-
185189function extractValue ( extractor : SerializedRegex , candidate : string ) {
186190 const resolvedExtractor = resolveRegex ( extractor . value )
187191 if ( resolvedExtractor === undefined ) {
0 commit comments