Errors
try {
const { id } = await tinylib.rooms.join(code)
tinylib.places.go(`game/${id}`)
} catch (error) {
if (error.code === 'not_found') codeField.setCustomValidity(error.message)
else toast(error.message)
}
A call that didn't do what it asked rejects, or throws if it's synchronous, with a TinylibError: a code from ErrorCode and a message written to show the person. A call given arguments it can't take throws or rejects with a TypeError. A rejection nobody catches shows only in the console, and in tinylib dev.
Sheets resolve
if (await tinylib.block(opponent.id)) tinylib.places.go('')
await tinylib.friends.sendApp()
A call that opens one of Tinylib's sheets or cards resolves when it closes, whatever the person chose there. Backing out isn't an error: block and report resolve false, and persona.edit resolves with the switch unchanged.
Without a connection
tinylib.connection.onChange(() => (offline.hidden = tinylib.connection.online))
tinylib.data and tinylib.reminders work without a connection. Opening a room, and the calls that reach Tinylib's servers, reject with offline. An open room drops with the connection and opens again when it's back.
Errors in the rules
on(state, input, ctx) {
if (input.type === 'action' && input.name === 'move') {
if (!state.players.includes(input.from.id)) ctx.refuse('You are watching this game.')
}
}
ctx.refuse is the rules saying no: the member who acted gets the sentence. A throw in the rules changes nothing and sends nothing: a request is refused with Tinylib's own sentence, any other input is dropped, and the room carries on. tinylib dev shows every input, output and error as it happens.