Current section

Files

Jump to
lustre priv static lustre-server-component.mjs
Raw

priv/static/lustre-server-component.mjs

// build/dev/javascript/gleam_stdlib/dict.mjs
var SHIFT = 5;
var BUCKET_SIZE = Math.pow(2, SHIFT);
var MASK = BUCKET_SIZE - 1;
var MAX_INDEX_NODE = BUCKET_SIZE / 2;
var MIN_ARRAY_NODE = BUCKET_SIZE / 4;
// build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs
var unicode_whitespaces = [
" ",
// Space
" ",
// Horizontal tab
"\n",
// Line feed
"\v",
// Vertical tab
"\f",
// Form feed
"\r",
// Carriage return
"\x85",
// Next line
"\u2028",
// Line separator
"\u2029"
// Paragraph separator
].join("");
var trim_start_regex = /* @__PURE__ */ new RegExp(
`^[${unicode_whitespaces}]*`
);
var trim_end_regex = /* @__PURE__ */ new RegExp(`[${unicode_whitespaces}]*$`);
// build/dev/javascript/lustre/lustre/internals/constants.ffi.mjs
var document = () => globalThis?.document;
var NAMESPACE_HTML = "http://www.w3.org/1999/xhtml";
var SUPPORTS_MOVE_BEFORE = !!globalThis.HTMLElement?.prototype?.moveBefore;
// build/dev/javascript/lustre/lustre/vdom/vattr.mjs
var attribute_kind = 0;
var property_kind = 1;
var event_kind = 2;
var never_kind = 0;
var always_kind = 2;
// build/dev/javascript/lustre/lustre/vdom/vnode.mjs
var fragment_kind = 0;
var element_kind = 1;
var text_kind = 2;
var unsafe_inner_html_kind = 3;
// build/dev/javascript/lustre/lustre/vdom/path.mjs
var separator_element = " ";
// build/dev/javascript/lustre/lustre/vdom/patch.mjs
var replace_text_kind = 0;
var replace_inner_html_kind = 1;
var update_kind = 2;
var move_kind = 3;
var remove_kind = 4;
var replace_kind = 5;
var insert_kind = 6;
// build/dev/javascript/lustre/lustre/vdom/reconciler.ffi.mjs
var setTimeout = globalThis.setTimeout;
var clearTimeout = globalThis.clearTimeout;
var createElementNS = (ns, name) => document().createElementNS(ns, name);
var createTextNode = (data) => document().createTextNode(data);
var createDocumentFragment = () => document().createDocumentFragment();
var insertBefore = (parent, node, reference) => parent.insertBefore(node, reference);
var moveBefore = SUPPORTS_MOVE_BEFORE ? (parent, node, reference) => parent.moveBefore(node, reference) : insertBefore;
var removeChild = (parent, child) => parent.removeChild(child);
var getAttribute = (node, name) => node.getAttribute(name);
var setAttribute = (node, name, value) => node.setAttribute(name, value);
var removeAttribute = (node, name) => node.removeAttribute(name);
var addEventListener = (node, name, handler, options) => node.addEventListener(name, handler, options);
var removeEventListener = (node, name, handler) => node.removeEventListener(name, handler);
var setInnerHtml = (node, innerHtml) => node.innerHTML = innerHtml;
var setData = (node, data) => node.data = data;
var meta = Symbol("lustre");
var MetadataNode = class {
constructor(kind, parent, node, key) {
this.kind = kind;
this.key = key;
this.parent = parent;
this.children = [];
this.node = node;
this.handlers = /* @__PURE__ */ new Map();
this.throttles = /* @__PURE__ */ new Map();
this.debouncers = /* @__PURE__ */ new Map();
}
get parentNode() {
return this.kind === fragment_kind ? this.node.parentNode : this.node;
}
};
var insertMetadataChild = (kind, parent, node, index2, key) => {
const child = new MetadataNode(kind, parent, node, key);
node[meta] = child;
parent?.children.splice(index2, 0, child);
return child;
};
var getPath = (node) => {
let path = "";
for (let current = node[meta]; current.parent; current = current.parent) {
if (current.key) {
path = `${separator_element}${current.key}${path}`;
} else {
const index2 = current.parent.children.indexOf(current);
path = `${separator_element}${index2}${path}`;
}
}
return path.slice(1);
};
var Reconciler = class {
#root = null;
#dispatch = () => {
};
#useServerEvents = false;
#exposeKeys = false;
constructor(root2, dispatch, { useServerEvents = false, exposeKeys = false } = {}) {
this.#root = root2;
this.#dispatch = dispatch;
this.#useServerEvents = useServerEvents;
this.#exposeKeys = exposeKeys;
}
mount(vdom) {
console.log("mount", vdom);
insertMetadataChild(element_kind, null, this.#root, 0, null);
this.#insertChild(this.#root, null, this.#root[meta], 0, vdom);
}
push(patch) {
this.#stack.push({ node: this.#root[meta], patch });
this.#reconcile();
}
// PATCHING ------------------------------------------------------------------
#stack = [];
#reconcile() {
const stack = this.#stack;
while (stack.length) {
const { node, patch } = stack.pop();
const { children: childNodes } = node;
const { changes, removed, children: childPatches } = patch;
iterate(changes, (change) => this.#patch(node, change));
if (removed) {
this.#removeChildren(node, childNodes.length - removed, removed);
}
iterate(childPatches, (childPatch) => {
const child = childNodes[childPatch.index | 0];
this.#stack.push({ node: child, patch: childPatch });
});
}
}
#patch(node, change) {
switch (change.kind) {
case replace_text_kind:
this.#replaceText(node, change);
break;
case replace_inner_html_kind:
this.#replaceInnerHtml(node, change);
break;
case update_kind:
this.#update(node, change);
break;
case move_kind:
this.#move(node, change);
break;
case remove_kind:
this.#remove(node, change);
break;
case replace_kind:
this.#replace(node, change);
break;
case insert_kind:
this.#insert(node, change);
break;
}
}
// CHANGES -------------------------------------------------------------------
#insert(parent, { children, before }) {
const fragment3 = createDocumentFragment();
const beforeEl = this.#getReference(parent, before);
this.#insertChildren(fragment3, null, parent, before | 0, children);
insertBefore(parent.parentNode, fragment3, beforeEl);
}
#replace(parent, { index: index2, with: child }) {
this.#removeChildren(parent, index2 | 0, 1);
const beforeEl = this.#getReference(parent, index2);
this.#insertChild(parent.parentNode, beforeEl, parent, index2 | 0, child);
}
#getReference(node, index2) {
index2 = index2 | 0;
const { children } = node;
const childCount = children.length;
if (index2 < childCount) {
return children[index2].node;
}
let lastChild = children[childCount - 1];
if (!lastChild && node.kind !== fragment_kind)
return null;
if (!lastChild)
lastChild = node;
while (lastChild.kind === fragment_kind && lastChild.children.length) {
lastChild = lastChild.children[lastChild.children.length - 1];
}
return lastChild.node.nextSibling;
}
#move(parent, { key, before }) {
before = before | 0;
const { children, parentNode } = parent;
const beforeEl = children[before].node;
let prev = children[before];
for (let i = before + 1; i < children.length; ++i) {
const next = children[i];
children[i] = prev;
prev = next;
if (next.key === key) {
children[before] = next;
break;
}
}
const { kind, node, children: prevChildren } = prev;
moveBefore(parentNode, node, beforeEl);
if (kind === fragment_kind) {
this.#moveChildren(parentNode, prevChildren, beforeEl);
}
}
#moveChildren(domParent, children, beforeEl) {
for (let i = 0; i < children.length; ++i) {
const { kind, node, children: nestedChildren } = children[i];
moveBefore(domParent, node, beforeEl);
if (kind === fragment_kind) {
this.#moveChildren(domParent, nestedChildren, beforeEl);
}
}
}
#remove(parent, { index: index2 }) {
this.#removeChildren(parent, index2, 1);
}
#removeChildren(parent, index2, count) {
const { children, parentNode } = parent;
const deleted = children.splice(index2, count);
for (let i = 0; i < deleted.length; ++i) {
const { kind, node, children: nestedChildren } = deleted[i];
removeChild(parentNode, node);
this.#removeDebouncers(deleted[i]);
if (kind === fragment_kind) {
deleted.push(...nestedChildren);
}
}
}
#removeDebouncers(node) {
const { debouncers, children } = node;
for (const { timeout } of debouncers.values()) {
if (timeout) {
clearTimeout(timeout);
}
}
debouncers.clear();
iterate(children, (child) => this.#removeDebouncers(child));
}
#update({ node, handlers, throttles, debouncers }, { added, removed }) {
iterate(removed, ({ name }) => {
if (handlers.delete(name)) {
removeEventListener(node, name, handleEvent);
this.#updateDebounceThrottle(throttles, name, 0);
this.#updateDebounceThrottle(debouncers, name, 0);
} else {
removeAttribute(node, name);
SYNCED_ATTRIBUTES[name]?.removed?.(node, name);
}
});
iterate(added, (attribute3) => this.#createAttribute(node, attribute3));
}
#replaceText({ node }, { content }) {
setData(node, content ?? "");
}
#replaceInnerHtml({ node }, { inner_html }) {
setInnerHtml(node, inner_html ?? "");
}
// INSERT --------------------------------------------------------------------
#insertChildren(domParent, beforeEl, metaParent, index2, children) {
iterate(
children,
(child) => this.#insertChild(domParent, beforeEl, metaParent, index2++, child)
);
}
#insertChild(domParent, beforeEl, metaParent, index2, vnode) {
switch (vnode.kind) {
case element_kind: {
const node = this.#createElement(metaParent, index2, vnode);
this.#insertChildren(node, null, node[meta], 0, vnode.children);
insertBefore(domParent, node, beforeEl);
break;
}
case text_kind: {
const node = this.#createTextNode(metaParent, index2, vnode);
insertBefore(domParent, node, beforeEl);
break;
}
case fragment_kind: {
const head = this.#createTextNode(metaParent, index2, vnode);
insertBefore(domParent, head, beforeEl);
this.#insertChildren(
domParent,
beforeEl,
head[meta],
0,
vnode.children
);
break;
}
case unsafe_inner_html_kind: {
const node = this.#createElement(metaParent, index2, vnode);
this.#replaceInnerHtml({ node }, vnode);
insertBefore(domParent, node, beforeEl);
break;
}
}
}
#createElement(parent, index2, { kind, key, tag, namespace, attributes }) {
const node = createElementNS(namespace || NAMESPACE_HTML, tag);
insertMetadataChild(kind, parent, node, index2, key);
if (this.#exposeKeys && key) {
setAttribute(node, "data-lustre-key", key);
}
iterate(attributes, (attribute3) => this.#createAttribute(node, attribute3));
return node;
}
#createTextNode(parent, index2, { kind, key, content }) {
const node = createTextNode(content ?? "");
insertMetadataChild(kind, parent, node, index2, key);
return node;
}
#createAttribute(node, attribute3) {
const { debouncers, handlers, throttles } = node[meta];
const {
kind,
name,
value,
prevent_default: prevent,
debounce: debounceDelay,
throttle: throttleDelay
} = attribute3;
switch (kind) {
case attribute_kind: {
const valueOrDefault = value ?? "";
if (name === "virtual:defaultValue") {
node.defaultValue = valueOrDefault;
return;
}
if (valueOrDefault !== getAttribute(node, name)) {
setAttribute(node, name, valueOrDefault);
}
SYNCED_ATTRIBUTES[name]?.added?.(node, valueOrDefault);
break;
}
case property_kind:
node[name] = value;
break;
case event_kind: {
if (handlers.has(name)) {
removeEventListener(node, name, handleEvent);
}
const passive = prevent.kind === never_kind;
addEventListener(node, name, handleEvent, { passive });
this.#updateDebounceThrottle(throttles, name, throttleDelay);
this.#updateDebounceThrottle(debouncers, name, debounceDelay);
handlers.set(name, (event2) => this.#handleEvent(attribute3, event2));
break;
}
}
}
#updateDebounceThrottle(map3, name, delay) {
const debounceOrThrottle = map3.get(name);
if (delay > 0) {
if (debounceOrThrottle) {
debounceOrThrottle.delay = delay;
} else {
map3.set(name, { delay });
}
} else if (debounceOrThrottle) {
const { timeout } = debounceOrThrottle;
if (timeout) {
clearTimeout(timeout);
}
map3.delete(name);
}
}
#handleEvent(attribute3, event2) {
const { currentTarget, type } = event2;
const { debouncers, throttles } = currentTarget[meta];
const path = getPath(currentTarget);
const {
prevent_default: prevent,
stop_propagation: stop,
include,
immediate
} = attribute3;
if (prevent.kind === always_kind)
event2.preventDefault();
if (stop.kind === always_kind)
event2.stopPropagation();
if (type === "submit") {
event2.detail ??= {};
event2.detail.formData = [...new FormData(event2.target).entries()];
}
const data = this.#useServerEvents ? createServerEvent(event2, include ?? []) : event2;
const throttle = throttles.get(type);
if (throttle) {
const now = Date.now();
const last = throttle.last || 0;
if (now > last + throttle.delay) {
throttle.last = now;
throttle.lastEvent = event2;
this.#dispatch(data, path, type, immediate);
}
}
const debounce = debouncers.get(type);
if (debounce) {
clearTimeout(debounce.timeout);
debounce.timeout = setTimeout(() => {
if (event2 === throttles.get(type)?.lastEvent)
return;
this.#dispatch(data, path, type, immediate);
}, debounce.delay);
}
if (!throttle && !debounce) {
this.#dispatch(data, path, type, immediate);
}
}
};
var iterate = (list4, callback) => {
if (Array.isArray(list4)) {
for (let i = 0; i < list4.length; i++) {
callback(list4[i]);
}
} else if (list4) {
for (list4; list4.head; list4 = list4.tail) {
callback(list4.head);
}
}
};
var handleEvent = (event2) => {
const { currentTarget, type } = event2;
const handler = currentTarget[meta].handlers.get(type);
handler(event2);
};
var createServerEvent = (event2, include = []) => {
const data = {};
if (event2.type === "input" || event2.type === "change") {
include.push("target.value");
}
if (event2.type === "submit") {
include.push("detail.formData");
}
for (const property2 of include) {
const path = property2.split(".");
for (let i = 0, input = event2, output = data; i < path.length; i++) {
if (i === path.length - 1) {
output[path[i]] = input[path[i]];
break;
}
output = output[path[i]] ??= {};
input = input[path[i]];
}
}
return data;
};
var syncedBooleanAttribute = /* @__NO_SIDE_EFFECTS__ */ (name) => {
return {
added(node) {
node[name] = true;
},
removed(node) {
node[name] = false;
}
};
};
var syncedAttribute = /* @__NO_SIDE_EFFECTS__ */ (name) => {
return {
added(node, value) {
node[name] = value;
}
};
};
var SYNCED_ATTRIBUTES = {
checked: /* @__PURE__ */ syncedBooleanAttribute("checked"),
selected: /* @__PURE__ */ syncedBooleanAttribute("selected"),
value: /* @__PURE__ */ syncedAttribute("value"),
autofocus: {
added(node) {
queueMicrotask(() => {
node.focus?.();
});
}
},
autoplay: {
added(node) {
try {
node.play?.();
} catch (e) {
console.error(e);
}
}
}
};
// build/dev/javascript/lustre/lustre/runtime/client/runtime.ffi.mjs
var copiedStyleSheets = /* @__PURE__ */ new WeakMap();
async function adoptStylesheets(shadowRoot) {
const pendingParentStylesheets = [];
for (const node of document().querySelectorAll(
"link[rel=stylesheet], style"
)) {
if (node.sheet)
continue;
pendingParentStylesheets.push(
new Promise((resolve, reject) => {
node.addEventListener("load", resolve);
node.addEventListener("error", reject);
})
);
}
await Promise.allSettled(pendingParentStylesheets);
if (!shadowRoot.host.isConnected) {
return [];
}
shadowRoot.adoptedStyleSheets = shadowRoot.host.getRootNode().adoptedStyleSheets;
const pending = [];
for (const sheet of document().styleSheets) {
try {
shadowRoot.adoptedStyleSheets.push(sheet);
} catch {
try {
let copiedSheet = copiedStyleSheets.get(sheet);
if (!copiedSheet) {
copiedSheet = new CSSStyleSheet();
for (const rule of sheet.cssRules) {
copiedSheet.insertRule(rule.cssText, copiedSheet.cssRules.length);
}
copiedStyleSheets.set(sheet, copiedSheet);
}
shadowRoot.adoptedStyleSheets.push(copiedSheet);
} catch {
const node = sheet.ownerNode.cloneNode();
shadowRoot.prepend(node);
pending.push(node);
}
}
}
return pending;
}
var ContextRequestEvent = class extends Event {
constructor(context, callback, subscribe) {
super("context-request", { bubbles: true, composed: true });
this.context = context;
this.callback = callback;
this.subscribe = subscribe;
}
};
// build/dev/javascript/lustre/lustre/runtime/transport.mjs
var mount_kind = 0;
var reconcile_kind = 1;
var emit_kind = 2;
var provide_kind = 3;
var attribute_changed_kind = 0;
var event_fired_kind = 1;
var property_changed_kind = 2;
var batch_kind = 3;
var context_provided_kind = 4;
// src/lustre/runtime/client/server_component.ffi.mjs
var ServerComponent = class extends HTMLElement {
static get observedAttributes() {
return ["route", "method"];
}
#shadowRoot;
#method = "ws";
#route = null;
#transport = null;
#adoptedStyleNodes = [];
#reconciler;
#remoteObservedAttributes = /* @__PURE__ */ new Set();
#remoteObservedProperties = /* @__PURE__ */ new Set();
#connected = false;
#changedAttributesQueue = [];
#contexts = /* @__PURE__ */ new Map();
#contextSubscriptions = /* @__PURE__ */ new Set();
#observer = new MutationObserver((mutations) => {
const attributes = [];
for (const mutation of mutations) {
if (mutation.type !== "attributes")
continue;
const name = mutation.attributeName;
if (!this.#connected || this.#remoteObservedAttributes.has(name)) {
attributes.push([name, this.getAttribute(name)]);
}
}
if (attributes.length === 1) {
const [name, value] = attributes[0];
this.#transport?.send({ kind: attribute_changed_kind, name, value });
} else if (attributes.length) {
this.#transport?.send({
kind: batch_kind,
messages: attributes.map(([name, value]) => ({
kind: attribute_changed_kind,
name,
value
}))
});
} else {
this.#changedAttributesQueue.push(...attributes);
}
});
constructor() {
super();
this.internals = this.attachInternals();
this.#observer.observe(this, {
attributes: true
});
}
connectedCallback() {
for (const attribute3 of this.attributes) {
this.#changedAttributesQueue.push([attribute3.name, attribute3.value]);
}
}
attributeChangedCallback(name, prev, next) {
switch (name) {
case (prev !== next && "route"): {
this.#route = new URL(next, location.href);
this.#connect();
return;
}
case "method": {
const normalised = next.toLowerCase();
if (normalised == this.#method)
return;
if (["ws", "sse", "polling"].includes(normalised)) {
this.#method = normalised;
if (this.#method == "ws") {
if (this.#route.protocol == "https:")
this.#route.protocol = "wss:";
if (this.#route.protocol == "http:")
this.#route.protocol = "ws:";
}
this.#connect();
}
return;
}
}
}
async messageReceivedCallback(data) {
switch (data.kind) {
case mount_kind: {
this.#shadowRoot ??= this.attachShadow({
mode: data.open_shadow_root ? "open" : "closed"
});
while (this.#shadowRoot.firstChild) {
this.#shadowRoot.firstChild.remove();
}
this.#reconciler = new Reconciler(
this.#shadowRoot,
(event2, path, name) => {
this.#transport?.send({
kind: event_fired_kind,
path,
name,
event: event2
});
},
{
useServerEvents: true
}
);
this.#remoteObservedAttributes = new Set(data.observed_attributes);
const filteredQueuedAttributes = this.#changedAttributesQueue.filter(
([name]) => this.#remoteObservedAttributes.has(name)
);
const messages = filteredQueuedAttributes.map(([name, value]) => ({
kind: attribute_changed_kind,
name,
value
}));
this.#changedAttributesQueue = [];
this.#remoteObservedProperties = new Set(data.observed_properties);
for (const name of this.#remoteObservedProperties) {
Object.defineProperty(this, name, {
get() {
return this[`_${name}`];
},
set(value) {
this[`_${name}`] = value;
this.#transport?.send({
kind: property_changed_kind,
name,
value
});
}
});
}
for (const [key, value] of Object.entries(data.provided_contexts)) {
this.provide(key, value);
}
for (const key of [...new Set(data.requested_contexts)]) {
this.dispatchEvent(
new ContextRequestEvent(key, (value, unsubscribe) => {
this.#transport?.send({
kind: context_provided_kind,
key,
value
});
this.#contextSubscriptions.add(unsubscribe);
})
);
}
if (messages.length) {
this.#transport.send({
kind: batch_kind,
messages
});
}
if (data.will_adopt_styles) {
await this.#adoptStyleSheets();
}
this.#shadowRoot.addEventListener("context-request", (event2) => {
if (!event2.context || !event2.callback)
return;
if (!this.#contexts.has(event2.context))
return;
event2.stopImmediatePropagation();
const context = this.#contexts.get(event2.context);
if (event2.subscribe) {
const callbackRef = new WeakRef(event2.callback);
const unsubscribe = () => {
context.subscribers = context.subscribers.filter(
(subscriber) => subscriber !== callbackRef
);
};
context.subscribers.push([callbackRef, unsubscribe]);
event2.callback(context.value, unsubscribe);
} else {
event2.callback(context.value);
}
});
this.#reconciler.mount(data.vdom);
this.dispatchEvent(new CustomEvent("lustre:mount"));
break;
}
case reconcile_kind: {
this.#reconciler.push(data.patch);
break;
}
case emit_kind: {
this.dispatchEvent(new CustomEvent(data.name, { detail: data.data }));
break;
}
case provide_kind: {
this.provide(data.key, data.value);
break;
}
}
}
//
disconnectedCallback() {
for (const unsubscribe of this.#contextSubscriptions) {
unsubscribe();
}
this.#contextSubscriptions.clear();
}
// Context provider method
provide(key, value) {
if (!this.#contexts.has(key)) {
this.#contexts.set(key, { value, subscribers: [] });
} else {
const context = this.#contexts.get(key);
context.value = value;
for (let i = context.subscribers.length - 1; i >= 0; i--) {
const [subscriberRef, unsubscribe] = context.subscribers[i];
const subscriber = subscriberRef.deref();
if (!subscriber) {
context.subscribers.splice(i, 1);
continue;
}
subscriber(value, unsubscribe);
}
}
}
#connect() {
if (!this.#route || !this.#method)
return;
if (this.#transport)
this.#transport.close();
const onConnect = () => {
this.#connected = true;
this.dispatchEvent(new CustomEvent("lustre:connect"), {
detail: {
route: this.#route,
method: this.#method
}
});
};
const onMessage = (data) => {
this.messageReceivedCallback(data);
};
const onClose = () => {
this.#connected = false;
this.dispatchEvent(
new CustomEvent("lustre:close", {
detail: {
route: this.#route,
method: this.#method
}
})
);
};
const options = { onConnect, onMessage, onClose };
switch (this.#method) {
case "ws":
this.#transport = new WebsocketTransport(this.#route, options);
break;
case "sse":
this.#transport = new SseTransport(this.#route, options);
break;
case "polling":
this.#transport = new PollingTransport(this.#route, options);
break;
}
}
//
async #adoptStyleSheets() {
while (this.#adoptedStyleNodes.length) {
this.#adoptedStyleNodes.pop().remove();
this.#shadowRoot.firstChild.remove();
}
this.#adoptedStyleNodes = await adoptStylesheets(this.#shadowRoot);
}
};
var WebsocketTransport = class {
#url;
#socket;
#waitingForResponse = false;
#queue = [];
#onConnect;
#onMessage;
#onClose;
constructor(url, { onConnect, onMessage, onClose }) {
this.#url = url;
this.#socket = new WebSocket(this.#url);
this.#onConnect = onConnect;
this.#onMessage = onMessage;
this.#onClose = onClose;
this.#socket.onopen = () => {
this.#onConnect();
};
this.#socket.onmessage = ({ data }) => {
try {
this.#onMessage(JSON.parse(data));
} finally {
if (this.#queue.length) {
this.#socket.send(
JSON.stringify({
kind: batch_kind,
messages: this.#queue
})
);
} else {
this.#waitingForResponse = false;
}
this.#queue = [];
}
};
this.#socket.onclose = () => {
this.#onClose();
};
}
send(data) {
if (this.#waitingForResponse || this.#socket.readyState !== WebSocket.OPEN) {
this.#queue.push(data);
return;
} else {
this.#socket.send(JSON.stringify(data));
this.#waitingForResponse = true;
}
}
close() {
this.#socket.close();
}
};
var SseTransport = class {
#url;
#eventSource;
#onConnect;
#onMessage;
#onClose;
constructor(url, { onConnect, onMessage, onClose }) {
this.#url = url;
this.#eventSource = new EventSource(this.#url);
this.#onConnect = onConnect;
this.#onMessage = onMessage;
this.#onClose = onClose;
this.#eventSource.onopen = () => {
this.#onConnect();
};
this.#eventSource.onmessage = ({ data }) => {
try {
this.#onMessage(JSON.parse(data));
} catch {
}
};
}
send(data) {
}
close() {
this.#eventSource.close();
this.#onClose();
}
};
var PollingTransport = class {
#url;
#interval;
#timer;
#onConnect;
#onMessage;
#onClose;
constructor(url, { onConnect, onMessage, onClose, ...opts }) {
this.#url = url;
this.#onConnect = onConnect;
this.#onMessage = onMessage;
this.#onClose = onClose;
this.#interval = opts.interval ?? 5e3;
this.#fetch().finally(() => {
this.#onConnect();
this.#timer = setInterval(() => this.#fetch(), this.#interval);
});
}
async send(data) {
}
close() {
clearInterval(this.#timer);
this.#onClose();
}
#fetch() {
return fetch(this.#url).then((response) => response.json()).then(this.#onMessage).catch(console.error);
}
};
customElements.define("lustre-server-component", ServerComponent);
export {
ServerComponent
};