More advanced pipeline composition

Operators

Sample

type CreateError = CombinedValidationError | InvalidStateError | ValidationError | ApiError | DbError

// ({ templateId: string, pax: Pax, startDate: string }) => Result<TrainTripId, CreateError>
pipe(
flatMap(validateCreateTrainTripInfo), // R<{ pax: PaxDefinition, startDate: FutureDate, templateId: TemplateId}, CombinedValidationError>
flatMap(toTup(({ templateId }) => getTrip(templateId))), // R<[TripWithSelectedTravelClass, { pax... }], ...>
map(([trip, proposal]) => TrainTrip.create(proposal, trip)), // R<TrainTrip, ...>
tee(db.trainTrips.add), // R<TrainTrip, ...>
map(trainTrip => trainTrip.id), // R<TrainTripId, ...>
)
// ({ templateId: string, pax: Pax, startDate: string}) => Result<({ pax: PaxDefinition, startDate: FutureDate, templateId: TemplateId }), CombinedValidationError>
pipe(
flatMap(({ pax, startDate, templateId }) =>
resultTuple(
PaxDefinition.create(pax).pipe(mapErr(toFieldError("pax"))),
FutureDate.create(startDate).pipe(mapErr(toFieldError("startDate"))),
validateString(templateId).pipe(mapErr(toFieldError("templateId"))),
).pipe(mapErr(combineValidationErrors)),
),
map(([pax, startDate, templateId]) => ({
pax, startDate, templateId,
})),
)

CombinedValidationErrors

if (err instanceof CombinedValidationError) {
ctx.body = {
fields: combineErrors(err.errors),
message,
}
ctx.status = 400
}

const combineErrors = (ers: any[]) => ers.reduce((prev: any, cur) => {
if (cur instanceof FieldValidationError) {
if (cur.error instanceof CombinedValidationError) {
prev[cur.fieldName] = combineErrors(cur.error.errors)
} else {
prev[cur.fieldName] = cur.message
}
}
return prev
}, {})

Source

What’s Next

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store