Skip to content

Commit

Permalink
feat(content-parser): content parsers can now access previous impleme…
Browse files Browse the repository at this point in the history
…ntations
  • Loading branch information
tompahoward committed Jun 27, 2022
1 parent cae526e commit 27ac9ba
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 28 deletions.
10 changes: 7 additions & 3 deletions src/augment-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export function augmentOptions<BaseContent, AdditionalContent>(
handlers: baseHandlers,
defaultHandlers: baseDefaultHandlers,
headers: baseHeaders,
contentParser: baseContentParser,
...baseOther
} = baseOptions
const {
handlers: additionalHandlers,
defaultHandlers: additionalDefaultHandlers,
headers: additionalHeaders,
contentParser: additionalContentParser,
...additionalOther
} = additionalOptions || {}

Expand All @@ -32,15 +34,17 @@ export function augmentOptions<BaseContent, AdditionalContent>(
...(additionalDefaultHandlers || baseDefaultHandlers || [])
])

const finalOptions = {
const mergedContentParser = additionalContentParser ? (response: Response) => additionalContentParser(response, baseContentParser) : baseContentParser

return {
...baseOther,
...additionalOther,
defaultHandlers: mergedHandlers,
handlers: [],
headers: {
...baseHeaders,
...additionalHeaders
}
},
contentParser: mergedContentParser
}
return finalOptions
}
7 changes: 3 additions & 4 deletions src/test/operations.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect } from 'chai'
import { DataTable } from '@cucumber/cucumber'
import logger from './logger'
import { binding, given, then, when } from 'cucumber-tsflow';
import { Validator, waychaser, WayChaserProblem, WayChaserResponse } from '../waychaser'
import { ContentParser, Validator, waychaser, WayChaserProblem, WayChaserResponse } from '../waychaser'
import {
uniqueNamesGenerator,
adjectives,
Expand Down Expand Up @@ -908,13 +908,12 @@ export class OperationSteps {

@given('waychaser has a custom parser for 404s')
public async waychaserHasACustomParserFor404s() {
const existingContentParser = this.waychaser.currentDefaults.contentParser;
this.waychaser = this.waychaser.defaults({
contentParser: async (response: Response) => {
contentParser: async (response: Response, contentParser: ContentParser) => {
return response.status === 404 ? new ProblemDocument({
'title': "Not found",
'type': 'https://waychaser.io/not-found'
}) : existingContentParser(response);
}) : contentParser(response);
}
})
};
Expand Down
48 changes: 27 additions & 21 deletions src/waychaser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,16 @@ export type HandlerSpec = {

export type Stopper = () => void

export type ContentParser = (response: Response, contentParser?: ContentParser) => Promise<unknown | ProblemDocument | undefined>

export type WayChaserOptions<ValidatorContent = null> = RequestInit & {
fetch: typeof fetch
handlers: Array<HandlerSpec>
defaultHandlers: Array<HandlerSpec>
preInterceptors: Array<(uriOrRequest, updateOptions, stopper) => void>
postInterceptors: Array<<InterceptorContent>(response: (WayChaserResponse<InterceptorContent>), stop: Stopper) => void>
postErrorInterceptors: Array<(error: WayChaserProblem | Error, stopper: Stopper) => void>
contentParser: (response: Response) => Promise<unknown | ProblemDocument | undefined>
contentParser: ContentParser
parameters?: Record<string, unknown>
validator?: Validator<ValidatorContent>
}
Expand Down Expand Up @@ -458,27 +460,31 @@ export async function _waychaser<Content>(
updateOptions
)

// TODO allow lazy loading of the content
const content = await mergedOptions.contentParser(baseResponse)
// content is
// 1. unknown,
// 2. a post response client side Problem Document,
// 3. a server side ProblemDocument, or
// 4. undefined


try {
const response = WayChaserResponse.create(baseResponse, content, defaultOptions, mergedOptions)

stop = false
for (const interceptor of updateOptions.postInterceptors) {
interceptor(response, () => (stop = true))
if (stop) {
break
try {
// TODO allow lazy loading of the content
const content = await mergedOptions.contentParser(baseResponse)
// content is
// 1. unknown,
// 4. undefined
const response = WayChaserResponse.create(baseResponse, content, defaultOptions, mergedOptions)

stop = false
for (const interceptor of updateOptions.postInterceptors) {
interceptor(response, () => (stop = true))
if (stop) {
break
}
}
return response
}
catch(error){
throw error instanceof ProblemDocument ? new WayChaserProblem({
response: new WayChaserResponse({ handlers: mergedOptions.defaultHandlers, defaultOptions, baseResponse, content: error, parameters: mergedOptions.parameters }),
problem: error,
}) : error;
}
return response
} catch (error) {
} catch(error) {
stop = false
for (const interceptor of updateOptions.postErrorInterceptors) {
interceptor(error, () => (stop = true))
Expand Down Expand Up @@ -524,15 +530,15 @@ const wayChaserDefaults: WayChaserOptions = {
return contentType === 'application/problem+json' ? Object.assign(new ProblemDocument(jsonContent), jsonContent) : jsonContent;
}
catch (error) {
return new ProblemDocument({
throw new ProblemDocument({
type: "https://waychaser.io/invalid-json",
title: "JSON response could not be parsed",
detail: `The response document with content type '${contentType}' could not be parsed as json`,
content, error
})
}
}
return new ProblemDocument({
throw new ProblemDocument({
type: "https://waychaser.io/unsupported-content-type",
title: "The response has an unsupported content type",
detail: `The response document has a content type of '${contentType}' which is not supported`,
Expand Down

0 comments on commit 27ac9ba

Please sign in to comment.