Skip to content

Instantly share code, notes, and snippets.

@hasparus
Created August 25, 2019 10:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasparus/3f637decd567d9743ddae652e1bf41a0 to your computer and use it in GitHub Desktop.
Save hasparus/3f637decd567d9743ddae652e1bf41a0 to your computer and use it in GitHub Desktop.
import * as t from "io-ts";
import { record } from "fp-ts/lib/Record";
const handler = <I, A, R>(decoder: t.Decoder<I, A>, f: (_: A) => R) => ({
decoder,
f,
});
type Handler = ReturnType<typeof handler>;
const isHandler = (x: object): x is Handler =>
"decoder" in x && "f" in x && typeof x["f"] === "function";
const db = {
songs: [
{
title: "Chwile ulotne",
artist: "Paktofonika",
},
{
title: "Ja to Ja",
artist: "Paktofonika",
},
],
};
const handlers = {
songs: handler(
t.type({
where: t.type({
artist: t.string,
}),
}),
({ where: { artist } }) => {
return db.songs.filter(song => song.artist === artist);
}
),
};
interface HandlersMap extends Record<string, Handler | HandlersMap> {}
type Api<T extends HandlersMap> = {
[P in keyof T]: T[P] extends Handler
? T[P]["f"]
: T[P] extends HandlersMap
? Api<T[P]>
: never;
};
const makeApi = <T extends HandlersMap>(hx: T): Api<T> => {
return record.map(hx, h => {
if (isHandler(h)) {
return h.f;
}
return makeApi(h);
}) as Api<T>;
};
type SchemaDocs<T extends HandlersMap> = {
[P in keyof T]: T[P] extends Handler
? string
: T[P] extends HandlersMap
? SchemaDocs<T[P]>
: never;
};
// This should really use typescript and get TSDoc comments, but it's PoC
const makeSchemaDocs = <T extends HandlersMap>(hx: T): SchemaDocs<T> => {
return record.map(hx, h => {
if (isHandler(h)) {
return h.decoder.name;
}
return makeSchemaDocs(h);
}) as SchemaDocs<T>;
};
const api = makeApi(handlers);
// ['Chwile ulotne', 'Ja to Ja']
console.log(
api.songs({ where: { artist: 'Paktofonika' }}).map(song => song.title)
)
// { songs: '{ where: { artist: string } }' }
console.log(
makeSchemaDocs(handlers)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment