Spaces:
Running
Running
import { invariant } from 'outvariant' | |
import { DeferredPromise } from '@open-draft/deferred-promise' | |
import { InterceptorError } from './InterceptorError' | |
const kRequestHandled = Symbol('kRequestHandled') | |
export const kResponsePromise = Symbol('kResponsePromise') | |
export class RequestController { | |
/** | |
* Internal response promise. | |
* Available only for the library internals to grab the | |
* response instance provided by the developer. | |
* @note This promise cannot be rejected. It's either infinitely | |
* pending or resolved with whichever Response was passed to `respondWith()`. | |
*/ | |
[kResponsePromise]: DeferredPromise<Response | Error | undefined>; | |
/** | |
* Internal flag indicating if this request has been handled. | |
* @note The response promise becomes "fulfilled" on the next tick. | |
*/ | |
[kRequestHandled]: boolean | |
constructor(private request: Request) { | |
this[kRequestHandled] = false | |
this[kResponsePromise] = new DeferredPromise() | |
} | |
/** | |
* Respond to this request with the given `Response` instance. | |
* @example | |
* controller.respondWith(new Response()) | |
* controller.respondWith(Response.json({ id })) | |
* controller.respondWith(Response.error()) | |
*/ | |
public respondWith(response: Response): void { | |
invariant.as( | |
InterceptorError, | |
!this[kRequestHandled], | |
'Failed to respond to the "%s %s" request: the "request" event has already been handled.', | |
this.request.method, | |
this.request.url | |
) | |
this[kRequestHandled] = true | |
this[kResponsePromise].resolve(response) | |
/** | |
* @note The request conrtoller doesn't do anything | |
* apart from letting the interceptor await the response | |
* provided by the developer through the response promise. | |
* Each interceptor implements the actual respondWith/errorWith | |
* logic based on that interceptor's needs. | |
*/ | |
} | |
/** | |
* Error this request with the given error. | |
* @example | |
* controller.errorWith() | |
* controller.errorWith(new Error('Oops!')) | |
*/ | |
public errorWith(error?: Error): void { | |
invariant.as( | |
InterceptorError, | |
!this[kRequestHandled], | |
'Failed to error the "%s %s" request: the "request" event has already been handled.', | |
this.request.method, | |
this.request.url | |
) | |
this[kRequestHandled] = true | |
/** | |
* @note Resolve the response promise, not reject. | |
* This helps us differentiate between unhandled exceptions | |
* and intended errors ("errorWith") while waiting for the response. | |
*/ | |
this[kResponsePromise].resolve(error) | |
} | |
} | |