tinylib-sdk/kits
Your page imports these from tinylib-sdk/kits, and publish bundles them into the version. Your rules import the ones that need no tinylib: the rule kits below, addDays, seeded, shuffled, clock, and today given a date. Games shows them in use.
'YYYY-MM-DD'.Parameters
- dateDateoptional
- Defaults to now on Tinylib's clock.
days after day, both as 'YYYY-MM-DD'. A negative days counts back.Throws
- TypeError
- When
dayisn't a date as'YYYY-MM-DD'.
Math.random whose sequence is fixed by seed. The same seed gives the same sequence on every device, so seeding with the date deals everyone the same puzzle.items.Parameters
- itemsreadonly T[]
- The items to shuffle.
- random() => numberoptional
- A function like
Math.random, such as one fromseeded. Defaults toMath.random.
name, which saves one result per date in tinylib.data with audience: 'friends', so leaderboard can rank it among friends' results. Saving needs "friends" in uses.Parameters
- namestring
- The puzzle's name: letters, digits,
-and_, starting with a letter or digit.
Throws
- TypeError
- When
nameisn't a valid name.
daily.Methods
- key(day?)
- Returns the
tinylib.datakey the result fordayis saved under,'day/<name>/YYYY-MM-DD'. - get(day?)
- Returns the user's result for
day, orundefinedwhen they have none. - save(result, day?)
- Saves
resultfordaywithaudience: 'friends'and returns true. - played()
- Returns the dates the user has a result for, as
'YYYY-MM-DD', oldest first. - streak(from?)
- Returns how many days in a row the user has a result for, ending at
from.
tinylib.data key the result for day is saved under, 'day/<name>/YYYY-MM-DD'. Pass it to leaderboard or friendsWith for friends' results that day.Parameters
- daystringoptional
'YYYY-MM-DD'. Defaults to today.
day, or undefined when they have none.Parameters
- daystringoptional
'YYYY-MM-DD'. Defaults to today.
result for day with audience: 'friends' and returns true. When this device already has a result for day, it keeps that one and returns false.Parameters
- resultunknown
- Any JSON value, such as
{ seconds: 312, mistakes: 1 }. - daystringoptional
'YYYY-MM-DD'. Defaults to today.
Throws
- TypeError
- When
resultcan't be saved as JSON. - limit
- When it would take the user's data from your client past 1 MB.
'YYYY-MM-DD', oldest first.from. When from has no result yet, it counts from the day before, so a streak lasts until a whole day is missed.Parameters
- fromstringoptional
'YYYY-MM-DD'. Defaults to today.
key, best first by compare. On a tie, the user's row comes first.Parameters
- keystring
- The key each value is saved under, such as
daily('hard').key(). - compare(a: T, b: T) => number
- As
Array.prototype.sorttakes: negative whenais better thanb. - options{ mine?: T; valid?: (value: unknown) => boolean }optional
- options.mineToptional
- The user's value, for example to rank a result before it's saved. Defaults to
tinylib.data.get(key). When it'sundefined, the user has no row. - options.valid(value: unknown) => booleanoptional
- Returns false for a friend's value to leave out, such as one saved by an older version of your app.
Rejects with
- offline
- When the device is offline.
- refused
- When your app doesn't list
"friends"inuses, or the user is a guest.
leaderboard: the user's or a friend's.Properties
- idstring
- The user's or the friend's id.
- namestring
- The user's or the friend's name.
- valueT
- The value under the key, or
options.minein the user's row whenleaderboardwas given it. - youboolean
- True for the user's own row.
key, with the friend's name, in the order of tinylib.friends.list(). Friends without a value are left out.Parameters
- keystring
- A key friends save values under with
audience: 'friends', such asdaily('hard').key().
Rejects with
- offline
- When the device is offline.
- refused
- When your app doesn't list
"friends"inuses, or the user is a guest.
friendsWith.Properties
- idstring
- The friend's id.
- namestring
- The friend's name.
- valueunknown
- The value the friend saved.
- changedAtnumber
- When the value last changed, in milliseconds on Tinylib's clock. Compare it with
tinylib.now().
name.Parameters
- namestring
- The puzzle, as
dailytakes it. - better(a: any, b: any) => booleanoptional
- Says whether score
abeatsb. Lower wins by default.
solo.Properties
- resultsDaily
- The day's results, from
daily(name).
Methods
- key(mode)
- Returns the data key of the game kept in
mode, for watching it change. - saved(mode)
- Returns the game kept in
mode, or null. - keep(mode, game)
- Keeps
gameinmode. - clear(mode)
- Removes the game kept in
mode. - best(mode)
- Returns the best score in
mode, or null. - record(mode, score, options?)
- Keeps
scoreas the best inmodewhen it beats it, withoptionsastinylib.data.settakes them, and returns the best from before it and whether this is a record. - week(day?)
- Returns the seven days ending
day, each with its date, its result, and whether it's that day.
mode, for watching it change.mode, or null. Today's counts only on its day.game in mode. Today's stays on game.day, or on today when it has none.mode.mode, or null.score as the best in mode when it beats it, with options as tinylib.data.set takes them, and returns the best from before it and whether this is a record.day, each with its date, its result, and whether it's that day.key names, best first by compare, with options as leaderboard takes them. Calls fn now and each time the connection changes, and returns a function that stops it.followFriendsToday calls its function with.Properties
- rowsStanding<T>[]
- loadingboolean
- onlineboolean
- guestboolean
- errorTinylibError | null
key, such as games.results.key(day) or best/classic, the player's own among them and marked, best first by compare, filled in when online. A friend's name opens Block and Report.The list is a section of className, with lis that have .you for the player's own, and .place, .name,
.result, and .tools inside them, a p.note, and a button.send with .loud or .quiet. Your page styles them.
friendsToday takes.Properties
- classNamestringoptional
- titlestringoptional
- The list's heading.
Default:
'Friends today'- alonestringoptional
- What the list says when no friend has played.
- mineToptional
- The user's value, as
leaderboardtakes it.
Methods
- compare(a: T, b: T) => number
- As
leaderboardtakes: negative whenais better thanb. - show(result: T) => Node | string
- Turns one result into text or an element.
- valid(value: unknown) => booleanoptional
- Returns false for a friend's value to leave out, as
leaderboardtakes it.
Parameters
- options{ title: string; text?: string; className?: string; address?: string }
- options.titlestring
- The reminder's title.
- options.textstringoptional
- The reminder's text.
- options.classNamestringoptional
- The switch's class.
- options.addressstringoptional
- The address the reminder opens. Defaults to
'today'.
Properties
- nodeHTMLElement
Methods
- stop() => void
start until pause. It doesn't count while the page is hidden, so time the user spends in another app is left out.Parameters
- onTick(seconds: number) => voidoptional
- Called with the seconds counted, every
everymilliseconds while the stopwatch counts. - everynumberoptional
- Milliseconds between calls to
onTick. Defaults to 1000.
stopwatch.Properties
- secondsnumber
- The seconds counted, with their fraction. Set it to carry on from a time saved earlier.
- runningbooleanread-only
- True after
startand beforepause, except while the page is hidden.
fn now and every second with the milliseconds left until midnight. When the date changes, it calls fn with 0 and stops. Returns a function that stops the calls.now until the next midnight in the device's time zone, when today changes.Parameters
- nowDateoptional
- Defaults to now on Tinylib's clock.
seconds as 'M:SS', or 'H:MM:SS' from an hour on. Fractions of a second are dropped.name. Calls fn with the reminder now, and again after each set, when the device goes online or offline, and when the user changes your app's switches in Tinylib.set(time) makes the reminder go off every day at time, 'HH:MM' on a 24-hour clock,
or cancels it when time is null. If that fails, set rejects with the error and calls fn with the reminder
unchanged, so your toggle flips back. stop stops the calls.
Needs "reminders" in uses.
Parameters
- namestring
- The reminder's name, as
tinylib.reminders.settakes it. - optionsOmit<ReminderOptions, 'at' | 'repeat'>
- What the reminder says and the address it opens, as
tinylib.reminders.settakes them. - fn(reminder: DailyReminder) => void
- Called with the reminder, as
DailyReminder.
followDailyReminder.Properties
- availableboolean
- False until the reminder has been read, and again while the device is offline or when reading fails. Hide your toggle while it's false.
- timestring | null
- The time it goes off each day, as
'HH:MM', or null when it's off. - mutedboolean
- True when it's on but the user has turned off your app's Reminders switch in Tinylib, so it doesn't go off.
wins, which goes in rulesKeys in tinylib.json.In a move, ctx.random() is the only randomness and ctx.now the only clock.
defineGame takes it.Properties
- addressstringoptional
- The kind's address, which notifications and links open.
Default:
'game/:id'- idleMsnumberoptional
- How long a room lasts with nobody in it. Defaults to 30 days.
- migrateKind<S>['migrate']optional
- presenceKind<S>['presence']optional
- guestsbooleanoptional
- seats{ min: number; max: number; wait?: boolean }
- The table starts when
maxis reached, or when the host starts it frommin.wait: trueleaves a full table for the host to start. - turnGameTurn<S> | false
- The game's turns, or false for a game with none.
- show{ table?(state: S): object; seat?(seat: GameSeat, state: S): object }optional
- What everyone sees besides
table, such as how many cards are in a hidden hand. Runs once the game has started, and may also shape whattableshows. - movesRecord<string, Move<S>>
- What the players can do, by name.
Methods
- prepare(state, options, ctx)optional
- Runs when the room is made, for what the page draws while waiting: settings, an empty board.
- setup(state, ctx)optional
- Deals when the game starts, and may return what happened, for
saidand to tell the first player. - first(state, ctx)optional
- Returns the seat index to start at, or 0 if you leave it out.
- left(state, seat, ctx)optional
- Tidies up after a player who left or ran out of time, such as cards back in the deck.
- over(state, turn)optional
- Returns
{ winners, why }when the game is over, or null. - score(state, outcome)optional
- Returns what to add to any outcome, however the game ended, such as scores.
- text(outcome, id, name)optional
- Words the result for
id, which is null for nobody in particular, or returns undefined for the default.
said and to tell the first player.{ winners, why } when the game is over, or null. by is the seat that just moved, or null, and canMove says whether the player whose turn it is has a move. Anything else returned stays on the outcome.id, which is null for nobody in particular, or returns undefined for the default. name names a player.Properties
- limitnumber | null | ((state: S) => number | null)
- The milliseconds a turn may take, null for no clock, or a function of the state for a limit the room chose.
- timeoutstring[]optional
- The moves tried in order when the time runs out, each with
options, and the first option is played. With none, the turn passes. - strikesnumber | nulloptional
- How many times in a row a player can run out of time before they're out. Defaults to 3, and to 1 for a game with no
timeout; null is never. - warnnumber | nulloptional
- How many milliseconds before the limit to remind the player.
Methods
- passed(state)optional
- Runs whenever the turn moves on, for what a turn keeps count of.
options or check.Properties
- who'turn' | 'any' | 'host'optional
- Who may make it. Defaults to
'turn'in a game with turns, and to'any'in one without. - when'playing' | 'waiting'optional
- When it can be made.
Default:
'playing'- keepsbooleanoptional
- Leaves the turn, the clock,
moved, andsaidalone, for a turn shared as it's built, and doesn't askover. - refusestringoptional
- The sentence for data that isn't on the list.
Methods
- options(state, seat)optional
- Returns the list of what the player may send.
- check(state, seat, data)optional
- Refuses what the player sent by returning a sentence, for a move too open to list.
- run(state, seat, data, ctx)
- Makes the move, and may return what happened, as words after the player's name.
[null].ctx.stay().Omit.Properties
- timedOutboolean
- Whether a timeout played this move.
Methods
- stay()
- Keeps the turn with this player.
- turnTo(seat)
- Says who goes next, or the next still in after them.
defineGame made. Keep a game's own state in table, hidden, and each seat.private.Properties
- namestring
- guestboolean
- movedboolean
- Whether they've made a move of their own.
- outboolean
- Whether they're out of the game. A move that knocks a player out sets it.
- latenumber
- How many times in a row their time ran out.
- privatePrivate
- What only this player sees.
by and name say who did it, when someone did.Properties
- bystring | null
- namestring | null
- textstring
over and score added.Properties
- winnersstring[]
- whystring | null
over'swhy, or the kit's own:'left','time','unplayed', or'stuck'.- leaverstring | null
- The id of the player who left or ran out of time.
- timedOutbooleanoptional
- With
'unplayed', whether the player ran out of time rather than left.
Properties
- phaseGameState['phase']
- youstring | null
- hoststring | null
- turnstring | null
- deadlinenumber | null
- When this turn runs out, or null.
- clocknumber
- Counts the turns.
- saidSaid | null
- linestring | null
saidas a sentence for this member: "You drew a card."- playersSeatView[]
- Who's still in.
- seatsSeatView[]
- Everyone who sat down.
- limits{ min: number; max: number }
- The seats the table holds.
- tableany
state.tableplusshow.table. Before the game starts, only whatprepareset.- privateany
- The member's own
seat.private, or null. - legalRecord<string, unknown[] | true>
- What the member may do now, by move: the list of what they may send, or true for a move with
check. The host'sstartis there once the table can start. - outcomeOutcome | null
- statusstring
- The member's own sentence.
show.seat.Properties
- idstring
- atnumber
- The seat's index.
- namestring
- guestboolean
- colornumber
- movedboolean
- outboolean
final in the room's data, with each player's own sentence.GameView, so it also has phase, you, host, turn, deadline, clock, said, line, players, seats, limits, table, private, legal, outcome, and status.Properties
- resultsRecord<string, string>
seat going would do to a game in play, from seats of a state or a view and the table's min: 'on' when the rest play on, 'rest' when the game goes to the rest, and 'void' when it ends with no winner.most is taken.id.fn with the user's games and game invitations now, and again whenever they change or the device goes online or offline. Returns a function that stops the calls.While it or followGame runs, Tinylib doesn't show those invitations on its own
sheet, so draw invitations yourself, as in
Show invitations.
followGames.Properties
- currentRoomListItem[]
- Games still going, the ones waiting on the user first.
- pastRoomListItem[]
- Games that ended, most recently ended first, then games the user left, most recently left first.
- invitationsInvitation[]
- The user's invitations to games of this kind, newest first.
- loadingboolean
- True until the games have been read, and again after the device goes online or offline until they're read again. While it's true, empty lists don't mean the user has no games.
- onlineboolean
- Whether the device is online. Offline,
currentis empty. - errorTinylibError | null
- Why the list couldn't be read, or null.
id and calls fn with the game on each new view, each change to its invitations, and each time the device goes online or offline. Until the game has been read, view, room, error, and past are null. Returns a function that closes the room and stops the calls.While it runs, Tinylib doesn't show the invitations in invitations, rematch, and duplicate on its own sheet.
Draw them yourself without covering the game, with a way to block and report the sender.
followGame.Properties
- viewRoomView<K> | null
- The user's latest view, or null before the first.
- roomOpenRoom<K> | null
- The open room, or null when it couldn't be opened. Its
endedsays whether the room has ended, andleftwhether the user left it. - errorTinylibError | null
- Why the game couldn't be opened, or null.
- pastRoomListItem | null
The game's entry in
tinylib.rooms.list()once it has ended or the user has left it, or null. A game that's over can't be opened again, so whenfollowGamestarts on one,viewstays null anderrorhas the codeended, ornot_memberif the user left.past.leftis true when the user left or was removed. Itsstatusandmembersare as they were then.- Otherwise the game ended, and its
membersleave out anyone who left before then. past.closedis true when the game ended without the rules callingctx.end: nobody played it for the kind'sidleMs, or its last player left. No handler ran then, so the rules saved nothing at the end, and itsstatusis the last one they gave.
- rematchInvitation | null
- Another member's invitation to a rematch of this game, or null. When several members asked for one, everyone gets the same one.
- duplicateInvitation | null
- The invitation to the rematch everyone keeps, or null. It's set when the user started this game with
playAgainat the same moment another member started a rematch of the same game.playAgain(game)then joins the kept game and leaves this one. - invitationsInvitation[]
- The user's other invitations to games of this game's kind, or of a kind
followGameshas listed, newest first. - onlineboolean
- Whether the device is online.
{ id }, the room to open.- With
game.duplicate, it joins that member's room and leaves this one. - With
game.rematch, it accepts it. - For a game the user left, or one that ended more than a day ago, it creates a room of the same kind and invites the
members
game.pastlists, except guests. - Otherwise it accepts another member's invitation to a rematch of this game, if there is one. If not, it creates a
room of the same kind with
tinylib.rooms.createandrematchOf, which invites the game's other members who have an account. To play again with guests, don't end the room: reset it with an action.
Parameters
- gamePick<Game, 'room' | 'past' | 'rematch'> & Partial<Pick<Game, 'duplicate'>>
- The game, from
followGame. - optionsunknownoptional
- Passed to the kind's
createwhen this makes the room.
Rejects with
- TypeError
- When
gamehas noroom,past,rematch, orduplicate, oroptionscan't be saved as JSON. - not_found
- When the invitation it accepts no longer lets the user in.
- refused
- When the user is a guest, or the kind's
createrefuses. A rematch withrematchOfis also refused when the user has blocked a member or been blocked by one. - limit
- When the user is already in 50 rooms of your app, has created rooms faster than 60 per hour in your app, or the room it joins already has 64 members.
- failed
- When the kind's
createthrows. - offline
- When the device is offline.
address, as its kind says it.gamePages words a game.Properties
- invitationstringoptional
- What an invitation says after the sender's name, unless it's for a rematch.
Default:
'wants to play'- nounstringoptional
- What the game calls a game, such as "table", for its buttons.
Default:
'game'- loadingstringoptional
- What shows until the game is read.
Default:
'Loading…'
Methods
- rematch(name: string) => stringoptional
- Words the button for a rematch someone sent.
- settings(view: GameView) => unknownoptional
- A new game's settings, from a view of this one.
gamePages.Methods
- open(id, replace?)
- Goes to the game
id, replacing this address withreplace. - invited(invitation)
- Returns what
invitationsays, and its two answers, which open the game or dismiss it. - follow(id, fn)
- Follows the game
idasfollowGamedoes, and callsfnwith what to draw of it.
id, replacing this address with replace.invitation says, and its two answers, which open the game or dismiss it.id as followGame does, and calls fn with what to draw of it. Returns a function that stops it.GamePages's follow. Exactly one of view, gone, and message says what the screen is.Omit.Properties
- viewGameView | null
- The board: the live view, or the one the rules kept once the game is over.
- endedboolean
- Whether the game is over, or has no open room to play in, as while it loads.
- peoplePerson[]
- Everyone else seen in this game, kept after they leave so Block and Report stay.
- gone{ text: string; people: Person[] } | null
- For a game with no board: what to say, and who else played.
- messagestring | null
- A line to show alone: the game loading, its error, or no connection.
- againButtonProps
- The rematch button, hidden until the game ends. It invites whoever has an account, or starts a new game with nobody to invite.
- twin{ text: string; join: ButtonProps }
- For a room waiting while someone else's rematch of the same game waits too: what to say, or nothing, and the button that joins theirs.
Properties
- hiddenboolean
- textContentstring
Methods
- onclick() => Promise<void>
Properties
- idstring
- namestringoptional
- guestbooleanoptional
strip with row of each invitation, only when the invitations change.fn with how many games the user has won, now and whenever it changes. Returns a function that stops it.view, or null when leaving costs nothing. playsOn is the question for a table that carries on without them.id and goes back to the first page.room, its title with their names or else empty, and its status.kind on this device, for a game against bots with no signal. It's your rules, unchanged, with what Tinylib does around them done here. Nothing it keeps is saved, notifications go nowhere, and everyone in it has it open.Parameters
- kindKind
- The kind your rules export.
- config{ players: { id: string; name: string }[]; options?: unknown; now?: () => number; random?: () => number }
- config.players{ id: string; name: string }[]
- Who's in it. The first makes it.
- config.optionsunknownoptional
- What
creategets. - config.now() => numberoptional
- The clock. Defaults to Tinylib's.
- config.random() => numberoptional
- The random numbers
ctx.randomgives.
localRoom.Properties
- endedbooleanread-only
- namestring | nullread-only
- The name the rules gave the room.
- roomDataValuesread-only
- What the rules wrote to the room's data.
Methods
- port(id)
- Returns the member
id's way into the room. - tick()
- Runs what's due.
- values(id)
- What the rules wrote for the member
id.
id's way into the room.id.Properties
- idstring
- endedbooleanread-only
- leftbooleanread-only
Methods
- view()
- Returns what the rules'
viewgives this member. - flush()
- Tells
onView's functions, if the view changed, and thenonEvent's. - onView(fn)
- Calls
fnwith the view whenever it changes.
view gives this member.onView's functions, if the view changed, and then onEvent's.fn with the view whenever it changes. Returns a function that stops it.localRoom that stops while the page is hidden, so a game waits for the user. stop ends the watching.elements without a connection and enables it when one returns. Returns a function that stops it.{ online, error } it was called with: NO_CONNECTION without one, its error, or nothing.person's rows: Block, and Report between accounts, not by a guest and not of one. after gets what Tinylib's sheet answered, and an error goes to the toast.label, and run to do it.Properties
- labelstring
Methods
- run() => Promise<void>
person's rows as buttons with className.panel, with the rest of its properties in props. With key, a room's or a person's id, a panel drawn again comes back as it was left.tinylib.places.address before the first /. When the address changes, it stops the current screen and shows the next. Screens get the address without its query; read the query from tinylib.places.address.Returns a function that stops the current screen and stops switching.
Parameters
- screensRecord<string, Screen>
- Screens keyed by the part of the address before the first
/. Each is called with the rest of the address. The screen under''shows the start address and any address no other key matches, and is called with the whole address. When a screen throws, nothing shows until the address changes again. - options{ keep?: boolean }optional
- options.keepbooleanoptional
- When true, going to the address already showing leaves its screen as it is instead of starting it again.
route shows. It draws itself and can return a function that stops it.id.props set on it and children inside it.text for a moment in the element with the id toast, which it adds if the page has none.catch.names in a sentence.'?' for a blank name.count of word, with an s unless there's one.