import { TodoItem , todoItem } from "./domain" ; import * as L from "lonna" ; export type InitTodos = { type : "init" ; items : TodoItem [ ] ; } ; export type UpsertTodos = { type : "upsert" ; items : TodoItem [ ] ; } ; export type ServerFeedEvent = InitTodos | UpsertTodos ; const initialItems = [ "learn typescript" , "fix handbrake" ] . map ( ( name ) => todoItem ( name ) ) ; const moreItems = [ "buy beer" , "clean the house" , "fix the bike" , "get a lawyer" , "buy a new shovel" , "dispose of the corpses in garage" , "get a haircut" , "shave more often" , "post something smart on twitter" , "understand monad transformers" , "blow up some things" , "have fun" , "visit new reaktor HQ" , ] ; let storedItems = initialItems ; function serverFeed ( ) { console . log ( "Start server feed" ) ; storedItems = initialItems ; const b = L . bus < ServerFeedEvent > ( ) ; ( async ( ) => { await randomDelay ( 2000 ) ; b . push ( { type : "init" , items : storedItems , } ) ; while ( true ) { await randomDelay ( 10000 ) ; if ( Math . random ( ) < 0.3 ) { const index = randomIndex ( storedItems ) ; const existingItem = storedItems [ index ] ; const updated = { ... existingItem , completed : ! existingItem . completed , } ; storedItems [ index ] = updated ; b . push ( { type : "upsert" , items : [ updated ] , } ) ; } else { const newItem = randomItem ( ) ; storedItems . push ( newItem ) ; b . push ( { type : "upsert" , items : [ newItem ] } ) ; } } } ) ( ) ; return b ; } export async function listenToServerEvents ( listener ) { serverFeed ( ) . forEach ( listener ) ; } export async function saveChangesToServer ( item ) { await randomDelay ( 1000 ) ; if ( Math . random ( ) < 0.5 ) throw new Error ( "Oops, random error occurred on server" ) ; const index = findIndex ( storedItems , ( c ) => c . id === item . id ) ; if ( index < 0 ) { storedItems . push ( item ) ; console . log ( "Insert" , item ) ; } else { storedItems [ index ] = item ; console . log ( "Update" , item ) ; } } function randomDelay ( max ) { return new Promise ( ( resolve , reject ) => { setTimeout ( resolve , Math . random ( ) * max ) ; } ) ; } function randomIndex ( options ) { return Math . floor ( Math . random ( ) * options . length ) ; } const randomItem = ( ) => todoItem ( moreItems [ randomIndex ( moreItems ) ] ) ; export function findIndex < A > ( xs , predicate ) { for ( let i = 0 ; i < xs . length ; i ++ ) { if ( predicate ( xs [ i ] ) ) return i ; } return - 1 ; }