Skip to content

Instantly share code, notes, and snippets.

@gaspard
Last active June 19, 2018 08:07
Show Gist options
  • Save gaspard/738e5e81a8171ac0b62c5f64f77e6756 to your computer and use it in GitHub Desktop.
Save gaspard/738e5e81a8171ac0b62c5f64f77e6756 to your computer and use it in GitHub Desktop.
import * as cerebral from 'cerebral'
interface BlockDefinition<State, Sequences> {
state: any
sequences: any
}
interface Builder<State, Sequences> {
state: State
sequences: Sequences
root: () => cerebral.ModuleClass
with<St, Se>(
block: BlockDefinition<St, Se>
): Builder<State & St, Sequences & Se>
}
function build<St, Se>(obj: BlockDefinition<St, Se>): Builder<St, Se> {
const allState = cerebral.state as {}
const allSequences = cerebral.sequences as {}
const blocks: Array<any> = []
function root() {
// return the rootModule
return cerebral.Module({})
}
// Add a block to the app
function addBlock<AllSt, AllSe, St, Se>(obj: BlockDefinition<St, Se>) {
// Fake TS types
const state = allState as AllSt & St
const sequences = allSequences as AllSe & Se
// Register the new block
blocks.push(obj)
// Return the root module builder and tag helpers.
return {
state,
sequences,
root,
with<X, Y>(o: BlockDefinition<X, Y>) {
return addBlock<AllSt & St, AllSe & Se, X, Y>(o)
},
}
}
// Add the first block
return addBlock(obj)
}
// ========== app block
interface AppState {
app: {
user: string
}
}
interface AppSequences {
setName(args: { name: string }): void
}
const app: BlockDefinition<AppState, AppSequences> = {
state: {},
sequences: {},
}
// ========== dialog block
interface DialogState {
dialog: {
currentDialog: string
}
}
interface DialogSequences {
showDialog(args: { dialog: string }): void
}
const dialog: BlockDefinition<DialogState, DialogSequences> = {
state: {},
sequences: {},
}
// ========== boot block
interface BootState {
boot: {
phase: string
}
}
interface BootSequences {
reboot(args: {}): void
}
const boot: BlockDefinition<BootState, BootSequences> = {
state: {},
sequences: {},
}
const { state, sequences, root } = build(app)
.with(dialog)
.with(boot)
// root is the rootModule
const foo = connect({ user: state.app.user }, /* ... */) // <== Types are correct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment