mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 22:26:38 +03:00
36 lines
1.4 KiB
JavaScript
36 lines
1.4 KiB
JavaScript
/** The boot contract: one fetch that tells the page how to start.
|
|
*
|
|
* Both scripts on the page read it, so it is fetched once and shared. A server
|
|
* that predates the contract answers 404, and the page starts the way it always
|
|
* did: a blank questionnaire.
|
|
*/
|
|
|
|
let bootPromise = null;
|
|
|
|
export function getBoot() {
|
|
bootPromise ??= fetch('/boot.json')
|
|
.then((response) => (response.ok ? response.json() : null))
|
|
.catch(() => null)
|
|
.then((data) => ({
|
|
mode: data?.mode === 'doc' ? 'doc' : 'questionnaire',
|
|
prior: data?.prior && typeof data.prior === 'object' && !Array.isArray(data.prior) ? data.prior : null,
|
|
priorSource: data?.priorSource || null,
|
|
doc: data?.doc || null,
|
|
}));
|
|
return bootPromise;
|
|
}
|
|
|
|
/* Restoring a previous run happens inside the questionnaire, which owns the
|
|
state being restored. The document waits on this before it renders, so it
|
|
never reads a form that is still half filled. It resolves either way: a run
|
|
with nothing to restore is ready immediately. */
|
|
let settle;
|
|
export const hydrationReady = new Promise((resolve) => { settle = resolve; });
|
|
|
|
/* The attribute is the observable half: it drives the note on the start screen
|
|
and gives anything watching the page one thing to wait for. */
|
|
export function markHydrated(source) {
|
|
document.body.dataset.hydrated = source || 'none';
|
|
settle(source || null);
|
|
}
|