declare module "@ajces/idiom" {
  declare type VirtualNode = {
    tag: string,
    data: { [string]: any },
    children: Array<VirtualNode | string>
  };

  declare type Emit = (event: string, data: any) => any;

  declare type Thunk = () => { [string]: any };
  declare type ActionResult = { [string]: any } | Thunk;
  declare type Action = (
    state: { [string]: any },
    actions: { [string]: Action },
    data?: any
  ) => ActionResult;
  declare type Actions = { [string]: Action };

  declare type Event = (
    state: { [string]: any },
    actions: Actions,
    data?: any
  ) => any;
  declare type Events = { [string]: Event };

  declare type Mixin = (
    emit: Emit
  ) => {
    state?: { [string]: any },
    actions?: Actions,
    events?: Events,
    mixins?: Array<Mixin>
  };

  declare type VirtualComponent = (
    data: { [string]: any } | null,
    children: Array<VirtualNode | string> | VirtualNode | string
  ) => VirtualNode;

  declare export function h(
    tag: string | VirtualComponent,
    data?: any,
    ...children: any | Array<any>
  ): VirtualNode;

  declare type Props = {
    root?: HTMLElement | Element, 
    state: { [string]: any },
    view?: any,
    actions?: Actions,
    events?: Events,
    mixins?: Array<Mixin>
  };

  declare export function app(props: Props): Emit;
};