runtimeSource
tcmts.cli.web.runtimeSource · #45fsqpdj · term · runs anywhere
import { CODEC } from "#codebase/tcmts/cli/web";
export const runtimeSource = `import { encode, decode } from ${JSON.stringify(CODEC)};
const callListeners = new Set();
/** Run \`f\` after each server function call this page makes; returns an unsubscribe function. */
export function onServerCall(f) {
callListeners.add(f);
return () => callListeners.delete(f);
}
/** This page's build was retired: reload to get the current version. */
export function reloadOutdated() {
if (!globalThis.__tcmReloading) {
globalThis.__tcmReloading = true;
location.reload();
}
return new Promise(() => {});
}
/** A function that runs on the server, called by hash. */
export function remote(hash, name, callable) {
const fn = async (...args) => {
if (!callable) throw new Error(name + " runs on the server and this app doesn't call it from the browser");
let res;
try {
res = await fetch((globalThis.__TCM_BASE__ ?? "") + "/__tcm/rpc/" + hash, { method: "POST", headers: { "content-type": "application/json" }, body: encode(args, "arguments to " + name) });
} catch (e) {
throw new Error(name + ": the server is unreachable (" + e.message + ")");
}
// this page's build was retired: reload to get the current version
if (res.status === 410) return reloadOutdated();
const body = decode(await res.text());
// whether it worked or not, the call may have changed what the server shows
for (const f of callListeners) f();
if (!res.ok) {
const err = new Error(body && body.message ? body.message : res.statusText);
err.name = body && body.name ? body.name : "RemoteError";
err.status = res.status;
throw err;
}
return body;
};
Object.defineProperty(fn, "name", { value: name });
return fn;
}
/** A server-side async generator, iterated from the browser: chunks arrive as they're produced. */
export function remoteStream(hash, name) {
const fn = (...args) => ({
[Symbol.asyncIterator]() {
const stop = new AbortController();
const decoder = new TextDecoder();
let reader;
let buf = "";
const opened = (async () => {
const res = await fetch((globalThis.__TCM_BASE__ ?? "") + "/__tcm/rpc/" + hash, { method: "POST", headers: { "content-type": "application/json" }, body: encode(args, "arguments to " + name), signal: stop.signal });
if (res.status === 410 && !globalThis.__tcmReloading) {
globalThis.__tcmReloading = true;
location.reload();
await new Promise(() => {});
}
if (!res.ok) {
const body = decode(await res.text());
const err = new Error(body && body.message ? body.message : res.statusText);
err.name = body && body.name ? body.name : "RemoteError";
err.status = res.status;
throw err;
}
reader = res.body.getReader();
})();
return {
async next() {
await opened;
for (;;) {
const nl = buf.indexOf("\\n");
if (nl >= 0) {
const msg = decode(buf.slice(0, nl));
buf = buf.slice(nl + 1);
if (msg.e) {
const err = new Error(msg.e.message);
err.name = msg.e.name;
err.status = msg.e.status;
throw err;
}
if (msg.done) return { done: true, value: undefined };
return { done: false, value: msg.v };
}
const { value, done } = await reader.read();
if (done) return { done: true, value: undefined };
buf += decoder.decode(value, { stream: true });
}
},
async return() {
stop.abort();
return { done: true, value: undefined };
},
};
},
});
Object.defineProperty(fn, "name", { value: name });
return fn;
}
`
uses
used by