@@ -20,6 +20,9 @@ import { wellknownApi } from './wellknown.api.js';
2020import type { InternalErrorResponse , PollingStatus } from './client.types.js' ;
2121import { PollingCollector } from './collector.types.js' ;
2222
23+ const isRecord = ( value : unknown ) : value is Record < string , unknown > =>
24+ typeof value === 'object' && value !== null ;
25+
2326export function createClientStore < ActionType extends ActionTypes > ( {
2427 requestMiddleware,
2528 logger,
@@ -133,7 +136,8 @@ export async function handleChallengePolling({
133136 message : 'Not in a continue node state, must be in a continue node to use poll method' ,
134137 type : 'state_error' ,
135138 } ,
136- } as InternalErrorResponse ;
139+ type : 'internal_error' ,
140+ } ;
137141 }
138142
139143 // Construct the challenge polling endpoint
@@ -144,7 +148,8 @@ export async function handleChallengePolling({
144148 message : 'No self link found in server info for challenge polling operation' ,
145149 type : 'internal_error' ,
146150 } ,
147- } as InternalErrorResponse ;
151+ type : 'internal_error' ,
152+ } ;
148153 }
149154
150155 const selfUrl = links [ 'self' ] . href ;
@@ -160,7 +165,8 @@ export async function handleChallengePolling({
160165 'Failed to construct challenge polling endpoint. Requires host and environment ID.' ,
161166 type : 'parse_error' ,
162167 } ,
163- } as InternalErrorResponse ;
168+ type : 'internal_error' ,
169+ } ;
164170 }
165171
166172 const interactionId = serverSlice . interactionId ;
@@ -170,7 +176,8 @@ export async function handleChallengePolling({
170176 message : 'Missing interactionId in server info for challenge polling' ,
171177 type : 'internal_error' ,
172178 } ,
173- } as InternalErrorResponse ;
179+ type : 'internal_error' ,
180+ } ;
174181 }
175182
176183 const challengeEndpoint = `${ baseUrl } /${ envId } /davinci/user/credentials/challenge/${ challenge } /status` ;
@@ -191,12 +198,10 @@ export async function handleChallengePolling({
191198
192199 const challengePollµ = Micro . repeat ( queryµ , {
193200 while : ( { data, error } ) =>
194- retriesLeft > 0 && ! error && ! ( data as Record < string , unknown > ) [ 'isChallengeComplete' ] ,
201+ retriesLeft > 0 && ! error && isRecord ( data ) && ! data [ 'isChallengeComplete' ] ,
195202 schedule : Micro . scheduleSpaced ( pollInterval ) ,
196203 } ) . pipe (
197204 Micro . flatMap ( ( { data, error } ) => {
198- const pollResponse = data as Record < string , unknown > ;
199-
200205 // Check for any errors and return the appropriate status
201206 if ( error ) {
202207 // SerializedError
@@ -217,26 +222,35 @@ export async function handleChallengePolling({
217222 if ( 'status' in error ) {
218223 status = error . status ;
219224
220- const errorDetails = error . data as Record < string , unknown > ;
221- const serviceName = errorDetails [ 'serviceName' ] ;
225+ if ( isRecord ( error . data ) ) {
226+ const errorDetails = error . data as Record < string , unknown > ;
227+ const serviceName = errorDetails [ 'serviceName' ] ;
222228
223- // Check for an expired challenge
224- if ( status === 400 && serviceName && serviceName === 'challengeExpired' ) {
225- log . debug ( 'Challenge expired for polling' ) ;
226- return Micro . succeed ( 'expired' as PollingStatus ) ;
227- } else {
228- // If we're here there is some other type of network error and status != 200
229- // e.g. A bad challenge can return a httpStatus of 400 with code 4019
230- log . debug ( 'Network error occurred during polling' ) ;
231- return Micro . succeed ( 'error' as PollingStatus ) ;
229+ // Check for an expired challenge
230+ if ( status === 400 && serviceName && serviceName === 'challengeExpired' ) {
231+ log . debug ( 'Challenge expired for polling' ) ;
232+ return Micro . succeed ( 'expired' as PollingStatus ) ;
233+ }
232234 }
235+
236+ // If we're here there is possibly some other type of network error and status != 200
237+ // e.g. A bad challenge can return a httpStatus of 400 with code 4019
238+ log . debug ( 'Unknown error occurred during polling' ) ;
239+ return Micro . succeed ( 'error' as PollingStatus ) ;
233240 }
234241 }
235242
236243 // If a successful response is recieved it can be either a timeout or true success
244+ if ( ! isRecord ( data ) ) {
245+ log . debug ( 'Unable to parse polling response' ) ;
246+ return Micro . succeed ( 'error' as PollingStatus ) ;
247+ }
248+ const pollResponse = data ;
249+
237250 if ( pollResponse [ 'isChallengeComplete' ] === true ) {
238251 const pollStatus = pollResponse [ 'status' ] ;
239252 if ( ! pollStatus ) {
253+ log . debug ( 'Unable to determine polling status' ) ;
240254 return Micro . succeed ( 'error' as PollingStatus ) ;
241255 } else {
242256 return Micro . succeed ( pollStatus as PollingStatus ) ;
0 commit comments