Created
August 25, 2019 10:47
-
-
Save hasparus/3f637decd567d9743ddae652e1bf41a0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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