Skip to content

Instantly share code, notes, and snippets.

@dgieselaar
Created September 10, 2019 10:29
Show Gist options
  • Save dgieselaar/fa7e5842986d4d480533e6ee0417bb40 to your computer and use it in GitHub Desktop.
Save dgieselaar/fa7e5842986d4d480533e6ee0417bb40 to your computer and use it in GitHub Desktop.
import t from 'io-ts';
import { Request } from 'hapi';
import { PathReporter } from 'io-ts/lib/PathReporter';
import { fold } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/pipeable';
import { identity } from 'fp-ts/lib/function';
interface Params {
path?: t.HasProps;
query?: t.HasProps;
body?: t.Any;
}
type Decode<TParams extends Params> = {
[key in keyof TParams]: TParams[key] extends t.Any
? t.TypeOf<TParams[key]>
: unknown;
};
interface Route<TParams extends Params> {
path: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
params: TParams;
handler: (request: Request, data: Decode<TParams>) => {};
}
export function createRoute<TParams extends Params>(route: Route<TParams>) {
const { params, handler, ...rest } = route;
return {
...rest,
handler: (request: Request) => {
const requestData = {
body: request.payload,
path: request.params,
query: request.query
};
const data = (Object.keys(params) as Array<keyof Params>).reduce(
(prev, key) => {
const codec = params[key];
if (!codec) {
return prev;
}
const result = codec.decode(requestData[key]);
return {
...prev,
[key]: pipe(
result,
fold(() => {
throw new Error(PathReporter.report(result).join('\n'));
}, identity)
)
};
},
{} as Decode<TParams>
);
return handler(request, data);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment