THIN_CLIENT

Constant THIN_CLIENT 

Source
pub const THIN_CLIENT: &str = "// The thin client: `fold(apply_patch, initial_html, patch_stream)`.\n//\n// This file is compiler residue. Nothing here is application-specific \u{2014} no todo, no command\n// names, no view logic \u{2014} which is the point: \"the JavaScript never appears in the source at all\"\n// (docs/00-original-idea.md). It applies patches, captures declarative handlers, follows links,\n// and resumes a subscription by (subscription, seq). That is the whole of Mode A on the browser\n// side.\n//\n// The patch interpreter, the socket, the router and the id source are in `beck-patch.js`, because\n// Mode B needs the same four and produces the same patch ops \u{2014} it just produces them in the\n// browser instead of receiving them (docs/93).\n(() => {\n  const root = document.getElementById(\"b-root\");\n  if (!root) return;\n\n  // `state` is shared with the socket rather than copied into it: `state.seq` is what a *reconnect*\n  // resumes from, so it has to be the position of the last frame applied and not the position the\n  // document was painted at. The two are the same only until the first patch arrives.\n  const state = {\n    sub: beck.uuid7(),\n    actor: root.dataset.bActor || \"dev\",\n    // The seq the server-rendered HTML reflects. The socket resumes from here, so first paint and\n    // first patch cannot disagree, and hydration costs zero DOM work.\n    seq: Number(root.dataset.bSeq) || 0,\n  };\n\n  // Commands proposed and not yet answered. In Mode A this is the whole of \"pending\": the server\n  // holds the state, so a client has nothing to show for a command until the patch comes back, and\n  // what it can say is *how many it is waiting on* \u{2014} which is what a devtools panel means by\n  // pending and what a page could show as a spinner.\n  const pending = new Map();\n\n  const send = beck.connect(state, (msg) => {\n    if (msg.t === \"p\") {\n      beck.apply(root, msg.o);\n      state.seq = msg.q;\n    } else if (msg.t === \"u\" || msg.t === \"w\") {\n      // \"current as of q, nothing changed\" \u{2014} keeps `seq` moving so a later reconnect does not ask\n      // the server to replay a gap that turns out to be empty.\n      state.seq = msg.q;\n      // A welcome means the subscription exists, which is the whole of readiness in Mode A: the\n      // handlers were installed synchronously and the page was rendered by the server.\n      if (msg.t === \"w\") beck.ready(root, \"a\");\n    } else if (msg.t === \"a\" || msg.t === \"n\") {\n      pending.delete(msg.id);\n      beck.stats.pending = pending.size;\n      if (msg.t === \"n\") beck.announce(root, \"beck:rejected\", msg);\n    }\n  });\n\n  beck.capture((command) => {\n    const id = beck.uuid7();\n    pending.set(id, command);\n    beck.stats.pending = pending.size;\n    send({ t: \"c\", id, command });\n  });\n\n  // A link is a route, and a route is `session.path`. In Mode A the server re-renders for the new\n  // session and answers with a patch, so a navigation costs exactly what any other change costs:\n  // the difference between two pages.\n  beck.route((path) => {\n    beck.stats.navigations += 1;\n    send({ t: \"g\", path });\n  });\n\n  beck.inspect.describe = () => ({\n    mode: \"A\",\n    seq: state.seq,\n    actor: state.actor,\n    path: beck.here(),\n    pending: Array.from(pending.keys()),\n  });\n\n  beck.devtools();\n})();\n";
Expand description

Mode A: apply the patches the server sends, post commands back up the socket.