// `Lacuna` comes from `@tlecommunity/client`, whose broken `exports` map means it // cannot be imported by bare specifier under Node - see `./load-lacuna.js` for the // Node-side resolution and `./load-lacuna.browser.js` (swapped in by the `browser` // field under Vite) for the web build. import { Lacuna } from './load-lacuna' import log from './log' import { resolveServerUrl } from './server-url' const lacuna = new Lacuna() lacuna.log.setLogLevel('debug') // The client discards the empire name/password after `authenticate`, so keep // them here (in memory, like the old `memory-cache`) for `relogin()`. let creds = null /** * Point the client at `server`, remember the credentials, and log in. * * @param {Object} config * @param {string} config.empire * @param {string} config.password * @param {string} config.server * @param {?string} config.apiKey * @return {Promise} the session id */ export async function login({ empire, password, server, apiKey }) { lacuna.config.serverUrl = resolveServerUrl(server) if (apiKey) { lacuna.config.apiKey = apiKey } creds = { empire, password } const { error } = await lacuna.authenticate(empire, password) if (error) { throw error.message } return lacuna.session.get() } /** * Drop the current session and log in again with the remembered credentials. * Used by `call()` to recover from a `Session expired.` error mid-task. */ export async function relogin() { if (!creds) { throw 'Not logged in' } lacuna.session.set('') const { error } = await lacuna.authenticate(creds.empire, creds.password) if (error) { throw error.message } } export function logout() { creds = null lacuna.session.set('') } // Click-limit ("Slow down" / code 1010) handling - parity with the old // `emissary.serverCall`. 1010 is a BLOCKING_ERROR_CODE, so the originating call // waits for this handler and adopts the response it returns: returning // `event.retry()` transparently swaps the retried result in for the caller. // Logs go through core `log` (the pub/sub the web task-runner subscribes to), // not `lacuna.log`. // // NOTE: `lacuna.enableRpcLimitHandler()` is the built-in alternative, but it // uses exponential backoff and its own wording - lower fidelity than the old // "wait 61s, try again" behaviour. Don't also enable it or 1010 gets handled // twice. const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) lacuna.onResponse(async (event) => { const error = event.response.error if (!error) { return } if (error.code === 1010 && /^Slow down/.test(error.message || '')) { log.newline() log.warn('Hit the click limit - waiting for a minute') await sleep(61 * 1000) log.info('Trying again') log.newline() return await event.retry() } }) export default lacuna