@druid-ui/host 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/index.d.ts.map +1 -1
- package/dist/ui.js +54 -18
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
- package/src/host-functions.ts +26 -24
- package/src/ui.ts +61 -5
- package/src/utils.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA;IACE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;IACE,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;IACE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACxE;AAED;gBAOI,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,WAAW,EACzB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAOzB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC;IA+DlB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB;CAKrD;AEhHD;IACE,cAAc,IAAI,MAAM,CAAC;IACzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,mCAAoC,YAAW,eAAe;IAC5D,cAAc,IAAI,MAAM;IAIxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG/B;AAED,kCAAmC,YAAW,eAAe;IAG3D,cAAc,IAAI,MAAM;IAIxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG/B;AAED,OAAO,MAAM,wBACX,MAAM,SAAS,GAAG,QAAQ,KACzB,eAMF,CAAC;AC4BF,OAAO,MAAM,gBACX,MAAM,MAAM,EACZ,YAAY,UAAU,KACrB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,MAAM,CAAC,CAAC,CA4ErE,CAAC;AC9IF;gBAIc,MAAM,GAAE,MAAW,EAAE,QAAQ,GAAE,OAAe;IAK1D,cAAc;IACd,eAAe;IACf,KAAK;IAGL,OAAO;CAGR;AEHD,OAAO,MAAM,QACX,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,IAAI,GAAG,KAAK,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,KAAK,IAAI,SAaxE,CAAC;AAEF,OAAO,MAAM,kBAAmB,CAAC,EAC/B,WAAW,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,MAEjC,GAAG,MAAM,GAAG,EAAE,wDAiBvB,CAAC;
|
|
1
|
+
{"mappings":"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","sources":["packages/host/src/src/file-loader.ts","packages/host/src/src/setup-snabbdom.ts","packages/host/src/src/routing-strategy.ts","packages/host/src/src/transpile.ts","packages/host/src/src/types.ts","packages/host/src/src/host-functions.ts","packages/host/src/src/utils.ts","packages/host/src/src/ui.ts","packages/host/src/src/window.ts","packages/host/src/src/index.ts","packages/host/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,"// Re-export everything for easy access\nexport * from \"./ui\";\nexport * from \"./types\";\nexport * from \"./file-loader\";\nexport * from \"./routing-strategy\";\nexport * from \"./transpile\";\nexport * from \"./utils\";\n\n// Global Window augmentation (side-effect import for declaration output)\nimport \"./window\";\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
package/dist/ui.js
CHANGED
|
@@ -240,17 +240,21 @@ class $3f177c34ffa911f6$export$d61e24a684f9e51 {
|
|
|
240
240
|
|
|
241
241
|
|
|
242
242
|
const $0e97ad6bdcaa9a3e$var$nodes = new Map();
|
|
243
|
+
function $0e97ad6bdcaa9a3e$export$6955262f0426a66b() {
|
|
244
|
+
console.debug(`[clearNodes] Clearing ${$0e97ad6bdcaa9a3e$var$nodes.size} nodes`);
|
|
245
|
+
$0e97ad6bdcaa9a3e$var$nodes.clear();
|
|
246
|
+
}
|
|
243
247
|
function $0e97ad6bdcaa9a3e$export$5833d9be8010042a(id, callback) {
|
|
244
|
-
console.debug(`Setting
|
|
248
|
+
console.debug(`[setHook] Setting "${callback}" hook on node ${id}`);
|
|
245
249
|
const node = $0e97ad6bdcaa9a3e$var$nodes.get(id);
|
|
246
250
|
if (node) {
|
|
247
251
|
node.hooks = node.hooks || [];
|
|
248
252
|
node.hooks.push(callback);
|
|
249
|
-
}
|
|
253
|
+
}
|
|
250
254
|
}
|
|
251
255
|
function $0e97ad6bdcaa9a3e$export$2bfbd9808f953be9(element, props, children) {
|
|
252
|
-
console.debug("Creating DOM node:", element, props, children);
|
|
253
256
|
const id = crypto.randomUUID();
|
|
257
|
+
console.debug(`[dfunc] Creating node: element="${element}", id=${id}`);
|
|
254
258
|
$0e97ad6bdcaa9a3e$var$nodes.set(id, {
|
|
255
259
|
element: element,
|
|
256
260
|
props: props,
|
|
@@ -261,11 +265,11 @@ function $0e97ad6bdcaa9a3e$export$2bfbd9808f953be9(element, props, children) {
|
|
|
261
265
|
function $0e97ad6bdcaa9a3e$export$f570cabd7d9ab9b(msg) {
|
|
262
266
|
console.debug("UI LOG:", msg);
|
|
263
267
|
}
|
|
264
|
-
function $0e97ad6bdcaa9a3e$export$431694b633b87558(id,
|
|
268
|
+
function $0e97ad6bdcaa9a3e$export$431694b633b87558(id, emitEvent, navigate) {
|
|
265
269
|
const node = $0e97ad6bdcaa9a3e$var$nodes.get(id);
|
|
266
270
|
//it is a bit strange to do it like that, in theory we want to better distinguish between text nodes and element nodes
|
|
267
271
|
if (!node) {
|
|
268
|
-
console.debug(
|
|
272
|
+
console.debug(`[createDomFromIdRec] Text node: "${id}"`);
|
|
269
273
|
return id;
|
|
270
274
|
}
|
|
271
275
|
const data = {};
|
|
@@ -275,9 +279,8 @@ function $0e97ad6bdcaa9a3e$export$431694b633b87558(id, rerender, emitEvent, navi
|
|
|
275
279
|
for (const prop of node.props.prop)data.props[prop.key] = prop.value;
|
|
276
280
|
data.on = {};
|
|
277
281
|
for (const eventType of node.props.on)data.on[eventType] = (e)=>{
|
|
278
|
-
console.debug(
|
|
282
|
+
console.debug(`[event] "${eventType}" on node ${id}`);
|
|
279
283
|
emitEvent(id, eventType, new (0, $3f177c34ffa911f6$export$d61e24a684f9e51)(e?.currentTarget?.value, e?.currentTarget?.checked));
|
|
280
|
-
rerender();
|
|
281
284
|
};
|
|
282
285
|
const href = data.props["href"];
|
|
283
286
|
if (href && !data.on["click"]) {
|
|
@@ -286,16 +289,19 @@ function $0e97ad6bdcaa9a3e$export$431694b633b87558(id, rerender, emitEvent, navi
|
|
|
286
289
|
navigate(href);
|
|
287
290
|
};
|
|
288
291
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
292
|
+
}
|
|
293
|
+
// Set hooks (outside props check so hooks work even without props)
|
|
294
|
+
if (node.hooks && node.hooks.length > 0) {
|
|
295
|
+
console.debug(`[createDomFromIdRec] Node ${id} has ${node.hooks.length} hooks: ${node.hooks.join(", ")}`);
|
|
296
|
+
data.hook = {};
|
|
297
|
+
for (const hookName of node.hooks)data.hook[hookName] = ()=>{
|
|
298
|
+
console.debug(`[hook] "${hookName}" fired for node ${id}`);
|
|
299
|
+
emitEvent(id, hookName, new (0, $3f177c34ffa911f6$export$d61e24a684f9e51)());
|
|
300
|
+
};
|
|
295
301
|
}
|
|
296
302
|
const ch = [];
|
|
297
303
|
if (node.children) for (const childId of node.children){
|
|
298
|
-
const childEl = $0e97ad6bdcaa9a3e$export$431694b633b87558(childId,
|
|
304
|
+
const childEl = $0e97ad6bdcaa9a3e$export$431694b633b87558(childId, emitEvent, navigate);
|
|
299
305
|
ch.push(childEl);
|
|
300
306
|
}
|
|
301
307
|
return (0, $k5Hkl$h)(node.element, data, ch);
|
|
@@ -377,6 +383,11 @@ class $7ecf692fb720ca8d$export$6874335aa33ac2fe extends HTMLElement {
|
|
|
377
383
|
console.warn("No file loader set.");
|
|
378
384
|
return;
|
|
379
385
|
}
|
|
386
|
+
// Increment generation to invalidate all pending operations from previous load
|
|
387
|
+
this.reloadGeneration++;
|
|
388
|
+
console.debug(`[reloadComponent] Starting reload, generation: ${this.reloadGeneration}`);
|
|
389
|
+
// Clear nodes map to ensure fresh state
|
|
390
|
+
(0, $0e97ad6bdcaa9a3e$export$6955262f0426a66b)();
|
|
380
391
|
if (this._sandbox) (0, $afa3b9af1178429b$export$76f430ef6626d809)(entrypoint, this.loader).then(([moduleUrl, compile])=>{
|
|
381
392
|
this.loadEntrypointFromWasmUrl(moduleUrl, compile);
|
|
382
393
|
}).catch((e)=>{
|
|
@@ -457,7 +468,7 @@ class $7ecf692fb720ca8d$export$6874335aa33ac2fe extends HTMLElement {
|
|
|
457
468
|
}
|
|
458
469
|
}
|
|
459
470
|
constructor(){
|
|
460
|
-
super(), this.profile = false, this.currentVNode = null, this._routeStrategy = new (0, $47d6f20d5f21b2bd$export$ec331118eb897269)(), this.loader = new (0, $4195f124d99f64a1$export$c104e8094d57b0fc)(), this._sandbox = true, this._extensionObject = {}, this._connected = false;
|
|
471
|
+
super(), this.profile = false, this.currentVNode = null, this._routeStrategy = new (0, $47d6f20d5f21b2bd$export$ec331118eb897269)(), this.loader = new (0, $4195f124d99f64a1$export$c104e8094d57b0fc)(), this._sandbox = true, this._extensionObject = {}, this._connected = false, this.reloadGeneration = 0;
|
|
461
472
|
this.shadow = this.attachShadow({
|
|
462
473
|
mode: "open"
|
|
463
474
|
});
|
|
@@ -490,13 +501,19 @@ class $7ecf692fb720ca8d$export$6874335aa33ac2fe extends HTMLElement {
|
|
|
490
501
|
};
|
|
491
502
|
}
|
|
492
503
|
async loadEntrypointFromJavaScriptUrl(entrypoint) {
|
|
504
|
+
// Capture the generation at the start of this load
|
|
505
|
+
const loadGeneration = this.reloadGeneration;
|
|
506
|
+
console.debug(`[loadEntrypointFromJavaScriptUrl] Starting load for generation ${loadGeneration}`);
|
|
493
507
|
window["druid-ui"] = {
|
|
494
508
|
d: (0, $0e97ad6bdcaa9a3e$export$2bfbd9808f953be9)
|
|
495
509
|
};
|
|
496
510
|
window["druid-extension"] = this.getExtensionObject();
|
|
497
|
-
|
|
511
|
+
// Force no-cache to get fresh content
|
|
512
|
+
const response = await this.loader.load(entrypoint, {
|
|
513
|
+
cache: false
|
|
514
|
+
});
|
|
498
515
|
const bundleContent = response.buffer;
|
|
499
|
-
//
|
|
516
|
+
// Create blob URL to avoid Vite's /public restrictions
|
|
500
517
|
const blob = new Blob([
|
|
501
518
|
bundleContent
|
|
502
519
|
], {
|
|
@@ -504,8 +521,20 @@ class $7ecf692fb720ca8d$export$6874335aa33ac2fe extends HTMLElement {
|
|
|
504
521
|
});
|
|
505
522
|
const moduleUrl = URL.createObjectURL(blob);
|
|
506
523
|
const t = await import(/* @vite-ignore */ moduleUrl);
|
|
524
|
+
console.debug(`[loadEntrypointFromJavaScriptUrl] Module loaded for generation ${loadGeneration}, current generation: ${this.reloadGeneration}`);
|
|
507
525
|
(0, $36561bb1074897e9$export$f4651a9718246ed1)(t.component.asyncComplete);
|
|
526
|
+
// Only proceed if no newer reload has been triggered
|
|
527
|
+
if (this.reloadGeneration !== loadGeneration) {
|
|
528
|
+
console.debug(`[loadEntrypointFromJavaScriptUrl] Aborting stale load (generation ${loadGeneration}, current: ${this.reloadGeneration})`);
|
|
529
|
+
URL.revokeObjectURL(moduleUrl);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
508
532
|
this.rootComponent = t;
|
|
533
|
+
// Reset VNode right before rendering new module to ensure hooks fire
|
|
534
|
+
// This must be done here (not in reloadComponent) to avoid race conditions
|
|
535
|
+
// with pending rerenders from previous module
|
|
536
|
+
this.currentVNode = null;
|
|
537
|
+
console.debug(`[loadEntrypointFromJavaScriptUrl] Rendering generation ${loadGeneration}`);
|
|
509
538
|
this.rerender();
|
|
510
539
|
URL.revokeObjectURL(moduleUrl);
|
|
511
540
|
}
|
|
@@ -533,8 +562,15 @@ class $7ecf692fb720ca8d$export$6874335aa33ac2fe extends HTMLElement {
|
|
|
533
562
|
console.debug(`Init completed in ${(initEnd - renderStart).toFixed(2)} ms`);
|
|
534
563
|
}
|
|
535
564
|
this.mountEl.innerHTML = "";
|
|
536
|
-
const dom = (0, $0e97ad6bdcaa9a3e$export$431694b633b87558)(rootId,
|
|
565
|
+
const dom = (0, $0e97ad6bdcaa9a3e$export$431694b633b87558)(rootId, (nodeId, eventType, e)=>{
|
|
537
566
|
this.rootComponent.component.emit(nodeId, eventType, e);
|
|
567
|
+
// Capture the current generation
|
|
568
|
+
const generation = this.reloadGeneration;
|
|
569
|
+
setTimeout(()=>{
|
|
570
|
+
// Only rerender if we're still in the same generation (no reload happened)
|
|
571
|
+
if (this.reloadGeneration === generation) this.rerender();
|
|
572
|
+
else console.debug(`[setTimeout] Skipping stale rerender (generation ${generation}, current: ${this.reloadGeneration})`);
|
|
573
|
+
}, 0);
|
|
538
574
|
}, (href)=>{
|
|
539
575
|
this._routeStrategy.navigateTo(href);
|
|
540
576
|
this.rerender();
|
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/host/src/index.ts","packages/host/src/ui.ts","packages/host/src/file-loader.ts","packages/host/src/setup-snabbdom.ts","packages/host/src/routing-strategy.ts","packages/host/src/transpile.ts","packages/host/src/host-functions.ts","packages/host/src/types.ts","packages/host/src/utils.ts","packages/host/src/window.ts"],"sourcesContent":["// Re-export everything for easy access\nexport * from \"./ui\";\nexport * from \"./types\";\nexport * from \"./file-loader\";\nexport * from \"./routing-strategy\";\nexport * from \"./transpile\";\nexport * from \"./utils\";\n\n// Global Window augmentation (side-effect import for declaration output)\nimport \"./window\";\n","import { HttpFileLoader } from \"./file-loader\";\nimport { patch } from \"./setup-snabbdom\";\nimport { type VNode } from \"snabbdom\";\nimport {\n HistoryRoutingStrategy,\n type RoutingStrategy,\n} from \"./routing-strategy\";\nimport { loadTranspile } from \"./transpile\";\nimport { createDomFromIdRec, dfunc, logfunc, setHook } from \"./host-functions\";\nimport { Event } from \"./types\";\nimport { setCb } from \"./utils\";\n\nexport interface Props {\n prop: { key: string; value: any }[];\n on: string[]; // [eventType, fnid]\n}\n\n// Dev-time log function exposed for components importing from \"druid:ui/ui\".\nexport function log(msg: string) {\n // Reuse internal logfunc for consistent labeling.\n logfunc(msg);\n}\n\nexport class DruidUI extends HTMLElement {\n private shadow: ShadowRoot;\n private wrapperEl: HTMLElement;\n private mountEl: HTMLElement;\n private profile: boolean = false;\n private currentVNode: VNode | null = null;\n private _routeStrategy: RoutingStrategy = new HistoryRoutingStrategy();\n private loader = new HttpFileLoader();\n private _sandbox: boolean = true;\n private _extensionObject: object = {};\n private _entrypoint?: string;\n private rootComponent: any;\n private _connected: boolean = false;\n\n public connectedCallback() {\n this._connected = true;\n if (this.rootComponent) {\n this.rerender();\n return;\n }\n this.reloadComponent();\n }\n\n public disconnectedCallback() {\n this._connected = false;\n }\n\n public reloadComponent() {\n if (!this._connected) {\n console.warn(\"Component not connected, skipping reload.\");\n return;\n }\n const entrypoint = this._entrypoint;\n if (!entrypoint) {\n console.warn(\"No entrypoint attribute set.\");\n return;\n }\n if (!this.loader) {\n console.warn(\"No file loader set.\");\n return;\n }\n if (this._sandbox) {\n loadTranspile(entrypoint, this.loader)\n .then(([moduleUrl, compile]) => {\n this.loadEntrypointFromWasmUrl(moduleUrl, compile);\n })\n .catch((e) => {\n console.error(\"Failed to load and transpile entrypoint:\", e);\n });\n } else {\n this.loadEntrypointFromJavaScriptUrl(entrypoint);\n }\n }\n\n public getWrapper(): HTMLElement {\n return this.wrapperEl;\n }\n set fileloader(loader: HttpFileLoader) {\n this.loader = loader;\n this.reloadComponent();\n }\n\n set extensionObject(obj: object) {\n this._extensionObject = obj;\n }\n set entrypoint(entrypoint: string) {\n this._entrypoint = entrypoint;\n this.reloadComponent();\n }\n\n set sandbox(sandbox: boolean) {\n this._sandbox = sandbox;\n this.reloadComponent();\n }\n\n set routeStrategy(strategy: RoutingStrategy) {\n this._routeStrategy = strategy;\n this.rerender();\n }\n\n static get observedAttributes() {\n return [\"entrypoint\", \"path\", \"profile\", \"css\", \"style\", \"no-sandbox\"];\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string,\n ) {\n switch (name) {\n case \"no-sandbox\":\n this._sandbox = newValue !== \"true\";\n break;\n case \"entrypoint\":\n this.entrypoint = newValue;\n break;\n case \"path\":\n if (oldValue) {\n this.rerender();\n }\n break;\n case \"profile\":\n this.profile = newValue === \"true\";\n break;\n case \"style\":\n const htmlString = newValue;\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = htmlString.trim();\n\n // Insert style after all link elements\n const lastLink = Array.from(\n this.shadow.querySelectorAll('link[rel=\"stylesheet\"]'),\n ).pop();\n //clear previous style elements\n const existingStyles = this.shadow.querySelectorAll(\"style\");\n existingStyles.forEach((style) => style.remove());\n\n if (lastLink) {\n this.shadow.insertBefore(styleEl, lastLink.nextSibling);\n } else {\n this.shadow.insertBefore(\n styleEl,\n this.shadowRoot?.firstChild || null,\n );\n }\n break;\n case \"css\":\n const css = newValue.split(\",\");\n //clear previous css links\n const existingLinks = this.shadow.querySelectorAll(\n 'link[rel=\"stylesheet\"]',\n );\n existingLinks.forEach((link) => link.remove());\n\n for (const comp of css) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = comp;\n this.shadow.insertBefore(link, this.shadowRoot?.firstChild || null);\n }\n break;\n }\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: \"open\" });\n\n this.wrapperEl = document.createElement(\"div\");\n this.wrapperEl.classList.add(\"druid-wrapper\");\n this.mountEl = document.createElement(\"div\");\n this.mountEl.classList.add(\"druid-mount\");\n this.mountEl.innerText = \"Transpiling...\";\n\n this.wrapperEl.appendChild(this.mountEl);\n this.shadow.appendChild(this.wrapperEl);\n }\n\n private getExtensionObject() {\n return {\n \"druid:ui/ui\": {\n d: (element: string, props: Props, children: string[]) => {\n return dfunc(element, props, children);\n },\n log: (msg: string) => {\n logfunc(msg);\n },\n rerender: () => {\n setTimeout(() => this.rerender(), 0);\n },\n setHook: setHook,\n },\n \"druid:ui/utils\": {\n Event: Event,\n },\n ...this._extensionObject,\n };\n }\n\n async loadEntrypointFromJavaScriptUrl(entrypoint: string) {\n window[\"druid-ui\"] = {\n d: dfunc,\n };\n\n window[\"druid-extension\"] = this.getExtensionObject();\n\n const response = await this.loader.load(entrypoint);\n\n const bundleContent = response.buffer;\n\n //load bundleContent as a module\n const blob = new Blob([bundleContent], { type: \"application/javascript\" });\n const moduleUrl = URL.createObjectURL(blob);\n const t = await import(/* @vite-ignore */ moduleUrl);\n\n setCb(t.component.asyncComplete);\n this.rootComponent = t;\n this.rerender();\n URL.revokeObjectURL(moduleUrl);\n }\n\n async loadEntrypointFromWasmUrl(\n entrypoint: string,\n loadCompile?: (file: string) => Promise<WebAssembly.Module>,\n ) {\n const t = await import(/* @vite-ignore */ entrypoint!);\n\n URL.revokeObjectURL(entrypoint);\n\n const i = await t.instantiate(loadCompile, this.getExtensionObject());\n setCb(i.component.asyncComplete);\n\n this.rootComponent = i;\n this.rerender();\n }\n\n rerender() {\n if (!this.rootComponent) {\n console.warn(\"Root component not initialized yet.\");\n return;\n }\n let renderStart;\n if (this.profile) {\n // Start profiling\n renderStart = performance.now();\n }\n\n const rootId = this.rootComponent.component.init({\n path: this._routeStrategy.getCurrentPath(),\n });\n\n if (this.profile) {\n const initEnd = performance.now();\n console.debug(\n `Init completed in ${(initEnd - renderStart!).toFixed(2)} ms`,\n );\n }\n\n this.mountEl.innerHTML = \"\";\n const dom = createDomFromIdRec(\n rootId,\n this.rerender.bind(this),\n (nodeId, eventType, e) => {\n this.rootComponent.component.emit(nodeId, eventType, e);\n },\n (href: string) => {\n this._routeStrategy.navigateTo(href);\n this.rerender();\n },\n );\n\n if (dom instanceof String) {\n console.warn(\"Root DOM is a string, cannot render:\", dom);\n return;\n }\n if (this.currentVNode) {\n patch(this.currentVNode, dom);\n } else {\n patch(this.mountEl, dom);\n }\n this.currentVNode = dom;\n if (this.profile) {\n const renderEnd = performance.now();\n console.debug(\n `Render completed in ${(renderEnd - renderStart!).toFixed(2)} ms`,\n );\n }\n }\n}\n\ncustomElements.define(\"druid-ui\", DruidUI);\n","interface AuthOptions {\n type: \"bearer\" | \"basic\" | \"api-key\";\n token?: string;\n username?: string;\n password?: string;\n apiKey?: string;\n apiKeyHeader?: string;\n}\n\ninterface FileLoaderOptions {\n auth?: AuthOptions;\n headers?: Record<string, string>;\n cache?: boolean;\n}\n\ninterface HttpResponse {\n buffer: ArrayBuffer;\n headers: Record<string, string>;\n contentType: string | null;\n}\n\nexport interface FileLoader {\n load(path: string, options?: FileLoaderOptions): Promise<HttpResponse>;\n}\n\nexport class HttpFileLoader {\n private authOptions?: AuthOptions | undefined;\n private defaultHeaders?: Record<string, string> | undefined;\n\n private baseUrl?: string | undefined;\n\n constructor(\n baseUrl?: string,\n authOptions?: AuthOptions,\n defaultHeaders?: Record<string, string>\n ) {\n this.baseUrl = baseUrl;\n this.authOptions = authOptions;\n this.defaultHeaders = defaultHeaders;\n }\n\n protected async loadHttp(\n path: string,\n options?: FileLoaderOptions\n ): Promise<HttpResponse> {\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n ...options?.headers,\n };\n\n // Use instance auth options if no options provided, or merge with provided options\n const authToUse = options?.auth || this.authOptions;\n\n // Add authentication headers\n if (authToUse) {\n switch (authToUse.type) {\n case \"bearer\":\n if (authToUse.token) {\n headers[\"Authorization\"] = `Bearer ${authToUse.token}`;\n }\n break;\n case \"basic\":\n if (authToUse.username && authToUse.password) {\n const credentials = btoa(\n `${authToUse.username}:${authToUse.password}`\n );\n headers[\"Authorization\"] = `Basic ${credentials}`;\n }\n break;\n case \"api-key\":\n if (authToUse.apiKey) {\n const headerName = authToUse.apiKeyHeader || \"X-API-Key\";\n headers[headerName] = authToUse.apiKey;\n }\n break;\n }\n }\n\n const res = await fetch(path, {\n headers,\n cache: options?.cache === false ? \"no-store\" : \"default\",\n });\n\n if (!res.ok) {\n throw new Error(`Failed to load file: ${path}, status: ${res.status}`);\n }\n\n // Extract all fetch-specific data\n const text = await res.arrayBuffer();\n\n const responseHeaders: Record<string, string> = {};\n // Handle both real Headers object and mocked headers\n if (res.headers && typeof res.headers.forEach === \"function\") {\n res.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n }\n\n const contentType = res.headers.get(\"Content-Type\");\n\n return {\n buffer: text,\n headers: responseHeaders,\n contentType,\n };\n }\n\n async load(path: string, options?: FileLoaderOptions) {\n const filePath = this.baseUrl ? `${this.baseUrl}/${path}` : path;\n const response = await this.loadHttp(filePath, options);\n return response;\n }\n}\n","import {\n init,\n classModule,\n propsModule,\n styleModule,\n eventListenersModule,\n} from \"snabbdom\";\n\nexport const patch = init([\n // Init patch function with chosen modules\n classModule, // makes it easy to toggle classes\n propsModule, // for setting properties on DOM elements\n styleModule, // handles styling on elements with support for animations\n eventListenersModule, // attaches event listeners\n]);\n","export interface RoutingStrategy {\n getCurrentPath(): string;\n navigateTo(path: string): void;\n}\n\nexport class HistoryRoutingStrategy implements RoutingStrategy {\n getCurrentPath(): string {\n return window.location.pathname;\n }\n\n navigateTo(path: string): void {\n window.history.pushState({}, \"\", path);\n }\n}\n\nexport class CustomRoutingStrategy implements RoutingStrategy {\n private currentPath: string = \"/\";\n\n getCurrentPath(): string {\n return this.currentPath;\n }\n\n navigateTo(path: string): void {\n this.currentPath = path;\n }\n}\n\nexport const createRoutingStrategy = (\n mode: \"history\" | \"custom\"\n): RoutingStrategy => {\n if (mode === \"custom\") {\n return new CustomRoutingStrategy();\n } else {\n return new HistoryRoutingStrategy();\n }\n};\n","import type { FileLoader } from \"./file-loader\";\n\ninterface TranspileResult {\n files: Array<[string, Uint8Array]>;\n}\n\ninterface CacheEntry {\n jsUrl: string;\n fileUrls: Record<string, string>;\n}\n\nconst CACHE_KEY_PREFIX = \"transpile_cache_\";\n\n// Helper functions for localStorage caching\nconst getCachedEntry = (file: string): CacheEntry | null => {\n try {\n const cached = localStorage.getItem(CACHE_KEY_PREFIX + file);\n if (cached) {\n return JSON.parse(cached);\n }\n } catch (e) {\n console.warn(\"Failed to read from cache:\", e);\n }\n return null;\n};\n\nconst setCachedEntry = (file: string, entry: CacheEntry): void => {\n try {\n localStorage.setItem(CACHE_KEY_PREFIX + file, JSON.stringify(entry));\n } catch (e) {\n console.warn(\"Failed to write to cache:\", e);\n }\n};\n\nconst transpileInWorker = async (\n buffer: ArrayBuffer,\n name: string,\n): Promise<TranspileResult> => {\n return new Promise((resolve, reject) => {\n const worker = new Worker(\n new URL(\"./transpile.worker.ts\", import.meta.url),\n { type: \"module\" },\n );\n\n worker.onmessage = (event: MessageEvent) => {\n worker.terminate();\n if (event.data.success) {\n resolve(event.data.data);\n } else {\n reject(new Error(event.data.error));\n }\n };\n\n worker.onerror = (error) => {\n worker.terminate();\n reject(error);\n };\n\n // Transfer the buffer ownership to the worker (zero-copy)\n worker.postMessage({ buffer, name }, [buffer]);\n });\n};\n\nexport const loadTranspile = async (\n file: string,\n fileLoader: FileLoader,\n): Promise<[string, (filename: string) => Promise<WebAssembly.Module>]> => {\n // Check cache first\n const cached = getCachedEntry(file);\n if (cached) {\n // Verify URLs are still valid\n try {\n await fetch(cached.jsUrl, { method: \"HEAD\" });\n return [\n cached.jsUrl,\n async (filename: string) => {\n const url = cached.fileUrls[filename];\n if (!url) {\n throw new Error(`File ${filename} not found in transpiled output.`);\n }\n const wasmResponse = await fetch(url);\n const wasmBuffer = await wasmResponse.arrayBuffer();\n return await WebAssembly.compile(wasmBuffer);\n },\n ];\n } catch (e) {\n // Cache is stale, proceed with transpilation\n console.warn(\"Cached URLs are stale, re-transpiling\");\n }\n }\n\n const response = await fileLoader.load(file);\n if (!response) {\n throw new Error(`Failed to load file: ${file}`);\n }\n const files: Record<string, string> = {};\n const t = await transpileInWorker(response.buffer, \"test\");\n\n for (const file of t.files) {\n const [f, content] = file as [string, Uint8Array];\n\n let blob: Blob | null = null;\n if (f.endsWith(\".js\")) {\n blob = new Blob([new Uint8Array(content)], {\n type: \"application/javascript\",\n });\n } else if (f.endsWith(\".wasm\")) {\n blob = new Blob([new Uint8Array(content)], {\n type: \"application/wasm\",\n });\n }\n if (blob) {\n const url = URL.createObjectURL(blob);\n files[f] = url;\n }\n }\n const jsFileEntry = Object.entries(files).find(([filename]) =>\n filename.endsWith(\".js\"),\n );\n if (!jsFileEntry) {\n throw new Error(\"No JavaScript file found in transpiled output.\");\n }\n\n // Cache the result\n const cacheEntry: CacheEntry = {\n jsUrl: jsFileEntry[1],\n fileUrls: files,\n };\n setCachedEntry(file, cacheEntry);\n\n return [\n jsFileEntry[1],\n async (filename: string) => {\n const url = files[filename];\n if (!url) {\n throw new Error(`File ${filename} not found in transpiled output.`);\n }\n const wasmResponse = await fetch(url);\n const wasmBuffer = await wasmResponse.arrayBuffer();\n return await WebAssembly.compile(wasmBuffer);\n },\n ];\n};\n","import type { Props } from \"druid:ui/ui\";\nimport { h, type VNode, type VNodeChildren, type VNodeData } from \"snabbdom\";\nimport { Event } from \"./types\";\n\nconst nodes = new Map<\n string,\n {\n element: string;\n props?: Props;\n children?: Array<string>;\n hooks?: string[];\n }\n>();\n\nexport function setHook(id: string, callback: string) {\n console.debug(`Setting hook for id ${id} with callback ${callback}`);\n const node = nodes.get(id);\n if (node) {\n node.hooks = node.hooks || [];\n node.hooks.push(callback);\n } else {\n console.warn(`setHook: No node found for id ${id}`);\n }\n}\n\nexport function dfunc(element: string, props: Props, children: string[]) {\n console.debug(\"Creating DOM node:\", element, props, children);\n const id = crypto.randomUUID();\n\n nodes.set(id, { element, props, children });\n return id;\n}\n\nexport function logfunc(msg: string) {\n console.debug(\"UI LOG:\", msg);\n}\n\nexport function createDomFromIdRec(\n id: string,\n rerender: () => void,\n emitEvent: (id: string, eventType: string, event: Event) => void,\n navigate?: (href: string) => void\n): VNode | String {\n const node = nodes.get(id);\n //it is a bit strange to do it like that, in theory we want to better distinguish between text nodes and element nodes\n if (!node) {\n console.debug(\"Creating text node for id:\", id);\n return id;\n }\n\n const data: VNodeData = {};\n\n // Set properties\n if (node.props) {\n data.props = {};\n for (const prop of node.props.prop) {\n data.props[prop.key] = prop.value;\n }\n data.on = {};\n for (const eventType of node.props.on) {\n data.on[eventType] = (e) => {\n console.debug(\"Emitting event:\", id, eventType, e);\n emitEvent(\n id,\n eventType,\n new Event(e?.currentTarget?.value, e?.currentTarget?.checked)\n );\n rerender();\n };\n }\n const href = data.props[\"href\"];\n if (href && !data.on[\"click\"]) {\n if (navigate) {\n data.on.click = (e) => {\n e.preventDefault();\n navigate(href);\n };\n }\n }\n\n if (node.hooks) {\n data.hook = {};\n for (const hookName of node.hooks) {\n data.hook[hookName as keyof typeof data.hook] = () => {\n emitEvent(id, hookName, new Event());\n };\n }\n }\n }\n\n const ch: VNodeChildren = [];\n if (node.children) {\n for (const childId of node.children) {\n const childEl = createDomFromIdRec(\n childId,\n rerender,\n emitEvent,\n navigate\n );\n ch.push(childEl);\n }\n }\n\n return h(node.element, data, ch);\n}\n","export class Event {\n private _value: string;\n private _checked: boolean;\n\n constructor(_value: string = \"\", _checked: boolean = false) {\n this._value = _value;\n this._checked = _checked;\n }\n\n preventDefault() {}\n stopPropagation() {}\n value() {\n return this._value;\n }\n checked() {\n return this._checked;\n }\n}\n","type Callback = (id: string, result: { tag: \"ok\" | \"err\"; val: any }) => void;\n\nlet cb: Callback | undefined;\n\nconst pending: Array<{ id: string; result: Parameters<Callback>[1] }> = [];\n\nconst dispatch = (id: string, result: Parameters<Callback>[1]) => {\n if (cb) {\n cb(id, result);\n return;\n }\n\n pending.push({ id, result });\n};\nexport const setCb = (\n callback: (id: string, result: { tag: \"ok\" | \"err\"; val: any }) => void\n) => {\n cb = callback;\n\n if (pending.length === 0) {\n return;\n }\n\n // Flush any results that arrived before the callback was registered.\n while (pending.length > 0) {\n const { id, result } = pending.shift()!;\n cb(id, result);\n }\n};\n\nexport const PromiseToResult = <T>(\n promiseFn: (...args: any[]) => Promise<T>\n) => {\n return (...args: any[]) => {\n const id = crypto.randomUUID();\n promiseFn(...args)\n .then((result) => {\n dispatch(id, {\n tag: \"ok\",\n val: result,\n });\n })\n .catch((error) => {\n dispatch(id, {\n tag: \"err\",\n val: error instanceof Error ? error.message : String(error),\n });\n });\n return id;\n };\n};\n","// Augment the Window interface to include 'druid'.\n// We define a lightweight shape for better intellisense; extend as needed.\n\ntype DruidAPI = Record<string, any>;\n\ndeclare global {\n interface Window {\n \"druid-ui\": {\n d: (...args: any[]) => any;\n };\n \"druid-extension\"?: DruidAPI;\n }\n}\n\n// Mark this file as a module so global augmentation is always applied reliably.\nexport {};\n"],"names":[],"version":3,"file":"ui.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/host/src/index.ts","packages/host/src/ui.ts","packages/host/src/file-loader.ts","packages/host/src/setup-snabbdom.ts","packages/host/src/routing-strategy.ts","packages/host/src/transpile.ts","packages/host/src/host-functions.ts","packages/host/src/types.ts","packages/host/src/utils.ts","packages/host/src/window.ts"],"sourcesContent":["// Re-export everything for easy access\nexport * from \"./ui\";\nexport * from \"./types\";\nexport * from \"./file-loader\";\nexport * from \"./routing-strategy\";\nexport * from \"./transpile\";\nexport * from \"./utils\";\n\n// Global Window augmentation (side-effect import for declaration output)\nimport \"./window\";\n","import { HttpFileLoader } from \"./file-loader\";\nimport { patch } from \"./setup-snabbdom\";\nimport { type VNode } from \"snabbdom\";\nimport {\n HistoryRoutingStrategy,\n type RoutingStrategy,\n} from \"./routing-strategy\";\nimport { loadTranspile } from \"./transpile\";\nimport {\n clearNodes,\n createDomFromIdRec,\n dfunc,\n logfunc,\n setHook,\n} from \"./host-functions\";\nimport { Event } from \"./types\";\nimport { setCb } from \"./utils\";\n\nexport interface Props {\n prop: { key: string; value: any }[];\n on: string[]; // [eventType, fnid]\n}\n\n// Dev-time log function exposed for components importing from \"druid:ui/ui\".\nexport function log(msg: string) {\n // Reuse internal logfunc for consistent labeling.\n logfunc(msg);\n}\n\nexport class DruidUI extends HTMLElement {\n private shadow: ShadowRoot;\n private wrapperEl: HTMLElement;\n private mountEl: HTMLElement;\n private profile: boolean = false;\n private currentVNode: VNode | null = null;\n private _routeStrategy: RoutingStrategy = new HistoryRoutingStrategy();\n private loader = new HttpFileLoader();\n private _sandbox: boolean = true;\n private _extensionObject: object = {};\n private _entrypoint?: string;\n private rootComponent: any;\n private _connected: boolean = false;\n private reloadGeneration: number = 0;\n\n public connectedCallback() {\n this._connected = true;\n if (this.rootComponent) {\n this.rerender();\n return;\n }\n this.reloadComponent();\n }\n\n public disconnectedCallback() {\n this._connected = false;\n }\n\n public reloadComponent() {\n if (!this._connected) {\n console.warn(\"Component not connected, skipping reload.\");\n return;\n }\n const entrypoint = this._entrypoint;\n if (!entrypoint) {\n console.warn(\"No entrypoint attribute set.\");\n return;\n }\n if (!this.loader) {\n console.warn(\"No file loader set.\");\n return;\n }\n\n // Increment generation to invalidate all pending operations from previous load\n this.reloadGeneration++;\n console.debug(\n `[reloadComponent] Starting reload, generation: ${this.reloadGeneration}`,\n );\n\n // Clear nodes map to ensure fresh state\n clearNodes();\n\n if (this._sandbox) {\n loadTranspile(entrypoint, this.loader)\n .then(([moduleUrl, compile]) => {\n this.loadEntrypointFromWasmUrl(moduleUrl, compile);\n })\n .catch((e) => {\n console.error(\"Failed to load and transpile entrypoint:\", e);\n });\n } else {\n this.loadEntrypointFromJavaScriptUrl(entrypoint);\n }\n }\n\n public getWrapper(): HTMLElement {\n return this.wrapperEl;\n }\n set fileloader(loader: HttpFileLoader) {\n this.loader = loader;\n this.reloadComponent();\n }\n\n set extensionObject(obj: object) {\n this._extensionObject = obj;\n }\n set entrypoint(entrypoint: string) {\n this._entrypoint = entrypoint;\n this.reloadComponent();\n }\n\n set sandbox(sandbox: boolean) {\n this._sandbox = sandbox;\n this.reloadComponent();\n }\n\n set routeStrategy(strategy: RoutingStrategy) {\n this._routeStrategy = strategy;\n this.rerender();\n }\n\n static get observedAttributes() {\n return [\"entrypoint\", \"path\", \"profile\", \"css\", \"style\", \"no-sandbox\"];\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string,\n ) {\n switch (name) {\n case \"no-sandbox\":\n this._sandbox = newValue !== \"true\";\n break;\n case \"entrypoint\":\n this.entrypoint = newValue;\n break;\n case \"path\":\n if (oldValue) {\n this.rerender();\n }\n break;\n case \"profile\":\n this.profile = newValue === \"true\";\n break;\n case \"style\":\n const htmlString = newValue;\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = htmlString.trim();\n\n // Insert style after all link elements\n const lastLink = Array.from(\n this.shadow.querySelectorAll('link[rel=\"stylesheet\"]'),\n ).pop();\n //clear previous style elements\n const existingStyles = this.shadow.querySelectorAll(\"style\");\n existingStyles.forEach((style) => style.remove());\n\n if (lastLink) {\n this.shadow.insertBefore(styleEl, lastLink.nextSibling);\n } else {\n this.shadow.insertBefore(\n styleEl,\n this.shadowRoot?.firstChild || null,\n );\n }\n break;\n case \"css\":\n const css = newValue.split(\",\");\n //clear previous css links\n const existingLinks = this.shadow.querySelectorAll(\n 'link[rel=\"stylesheet\"]',\n );\n existingLinks.forEach((link) => link.remove());\n\n for (const comp of css) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = comp;\n this.shadow.insertBefore(link, this.shadowRoot?.firstChild || null);\n }\n break;\n }\n }\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: \"open\" });\n\n this.wrapperEl = document.createElement(\"div\");\n this.wrapperEl.classList.add(\"druid-wrapper\");\n this.mountEl = document.createElement(\"div\");\n this.mountEl.classList.add(\"druid-mount\");\n this.mountEl.innerText = \"Transpiling...\";\n\n this.wrapperEl.appendChild(this.mountEl);\n this.shadow.appendChild(this.wrapperEl);\n }\n\n private getExtensionObject() {\n return {\n \"druid:ui/ui\": {\n d: (element: string, props: Props, children: string[]) => {\n return dfunc(element, props, children);\n },\n log: (msg: string) => {\n logfunc(msg);\n },\n rerender: () => {\n setTimeout(() => this.rerender(), 0);\n },\n setHook: setHook,\n },\n \"druid:ui/utils\": {\n Event: Event,\n },\n ...this._extensionObject,\n };\n }\n\n async loadEntrypointFromJavaScriptUrl(entrypoint: string) {\n // Capture the generation at the start of this load\n const loadGeneration = this.reloadGeneration;\n console.debug(\n `[loadEntrypointFromJavaScriptUrl] Starting load for generation ${loadGeneration}`,\n );\n\n window[\"druid-ui\"] = {\n d: dfunc,\n };\n\n window[\"druid-extension\"] = this.getExtensionObject();\n\n // Force no-cache to get fresh content\n const response = await this.loader.load(entrypoint, { cache: false });\n const bundleContent = response.buffer;\n\n // Create blob URL to avoid Vite's /public restrictions\n const blob = new Blob([bundleContent], { type: \"application/javascript\" });\n const moduleUrl = URL.createObjectURL(blob);\n const t = await import(/* @vite-ignore */ moduleUrl);\n console.debug(\n `[loadEntrypointFromJavaScriptUrl] Module loaded for generation ${loadGeneration}, current generation: ${this.reloadGeneration}`,\n );\n\n setCb(t.component.asyncComplete);\n\n // Only proceed if no newer reload has been triggered\n if (this.reloadGeneration !== loadGeneration) {\n console.debug(\n `[loadEntrypointFromJavaScriptUrl] Aborting stale load (generation ${loadGeneration}, current: ${this.reloadGeneration})`,\n );\n URL.revokeObjectURL(moduleUrl);\n return;\n }\n\n this.rootComponent = t;\n\n // Reset VNode right before rendering new module to ensure hooks fire\n // This must be done here (not in reloadComponent) to avoid race conditions\n // with pending rerenders from previous module\n this.currentVNode = null;\n console.debug(\n `[loadEntrypointFromJavaScriptUrl] Rendering generation ${loadGeneration}`,\n );\n\n this.rerender();\n URL.revokeObjectURL(moduleUrl);\n }\n\n async loadEntrypointFromWasmUrl(\n entrypoint: string,\n loadCompile?: (file: string) => Promise<WebAssembly.Module>,\n ) {\n const t = await import(/* @vite-ignore */ entrypoint!);\n\n URL.revokeObjectURL(entrypoint);\n\n const i = await t.instantiate(loadCompile, this.getExtensionObject());\n setCb(i.component.asyncComplete);\n\n this.rootComponent = i;\n this.rerender();\n }\n\n rerender() {\n if (!this.rootComponent) {\n console.warn(\"Root component not initialized yet.\");\n return;\n }\n let renderStart;\n if (this.profile) {\n // Start profiling\n renderStart = performance.now();\n }\n\n const rootId = this.rootComponent.component.init({\n path: this._routeStrategy.getCurrentPath(),\n });\n\n if (this.profile) {\n const initEnd = performance.now();\n console.debug(\n `Init completed in ${(initEnd - renderStart!).toFixed(2)} ms`,\n );\n }\n\n this.mountEl.innerHTML = \"\";\n const dom = createDomFromIdRec(\n rootId,\n (nodeId, eventType, e) => {\n this.rootComponent.component.emit(nodeId, eventType, e);\n // Capture the current generation\n const generation = this.reloadGeneration;\n setTimeout(() => {\n // Only rerender if we're still in the same generation (no reload happened)\n if (this.reloadGeneration === generation) {\n this.rerender();\n } else {\n console.debug(\n `[setTimeout] Skipping stale rerender (generation ${generation}, current: ${this.reloadGeneration})`,\n );\n }\n }, 0);\n },\n (href: string) => {\n this._routeStrategy.navigateTo(href);\n this.rerender();\n },\n );\n\n if (dom instanceof String) {\n console.warn(\"Root DOM is a string, cannot render:\", dom);\n return;\n }\n if (this.currentVNode) {\n patch(this.currentVNode, dom);\n } else {\n patch(this.mountEl, dom);\n }\n this.currentVNode = dom;\n if (this.profile) {\n const renderEnd = performance.now();\n console.debug(\n `Render completed in ${(renderEnd - renderStart!).toFixed(2)} ms`,\n );\n }\n }\n}\n\ncustomElements.define(\"druid-ui\", DruidUI);\n","interface AuthOptions {\n type: \"bearer\" | \"basic\" | \"api-key\";\n token?: string;\n username?: string;\n password?: string;\n apiKey?: string;\n apiKeyHeader?: string;\n}\n\ninterface FileLoaderOptions {\n auth?: AuthOptions;\n headers?: Record<string, string>;\n cache?: boolean;\n}\n\ninterface HttpResponse {\n buffer: ArrayBuffer;\n headers: Record<string, string>;\n contentType: string | null;\n}\n\nexport interface FileLoader {\n load(path: string, options?: FileLoaderOptions): Promise<HttpResponse>;\n}\n\nexport class HttpFileLoader {\n private authOptions?: AuthOptions | undefined;\n private defaultHeaders?: Record<string, string> | undefined;\n\n private baseUrl?: string | undefined;\n\n constructor(\n baseUrl?: string,\n authOptions?: AuthOptions,\n defaultHeaders?: Record<string, string>\n ) {\n this.baseUrl = baseUrl;\n this.authOptions = authOptions;\n this.defaultHeaders = defaultHeaders;\n }\n\n protected async loadHttp(\n path: string,\n options?: FileLoaderOptions\n ): Promise<HttpResponse> {\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n ...options?.headers,\n };\n\n // Use instance auth options if no options provided, or merge with provided options\n const authToUse = options?.auth || this.authOptions;\n\n // Add authentication headers\n if (authToUse) {\n switch (authToUse.type) {\n case \"bearer\":\n if (authToUse.token) {\n headers[\"Authorization\"] = `Bearer ${authToUse.token}`;\n }\n break;\n case \"basic\":\n if (authToUse.username && authToUse.password) {\n const credentials = btoa(\n `${authToUse.username}:${authToUse.password}`\n );\n headers[\"Authorization\"] = `Basic ${credentials}`;\n }\n break;\n case \"api-key\":\n if (authToUse.apiKey) {\n const headerName = authToUse.apiKeyHeader || \"X-API-Key\";\n headers[headerName] = authToUse.apiKey;\n }\n break;\n }\n }\n\n const res = await fetch(path, {\n headers,\n cache: options?.cache === false ? \"no-store\" : \"default\",\n });\n\n if (!res.ok) {\n throw new Error(`Failed to load file: ${path}, status: ${res.status}`);\n }\n\n // Extract all fetch-specific data\n const text = await res.arrayBuffer();\n\n const responseHeaders: Record<string, string> = {};\n // Handle both real Headers object and mocked headers\n if (res.headers && typeof res.headers.forEach === \"function\") {\n res.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n }\n\n const contentType = res.headers.get(\"Content-Type\");\n\n return {\n buffer: text,\n headers: responseHeaders,\n contentType,\n };\n }\n\n async load(path: string, options?: FileLoaderOptions) {\n const filePath = this.baseUrl ? `${this.baseUrl}/${path}` : path;\n const response = await this.loadHttp(filePath, options);\n return response;\n }\n}\n","import {\n init,\n classModule,\n propsModule,\n styleModule,\n eventListenersModule,\n} from \"snabbdom\";\n\nexport const patch = init([\n // Init patch function with chosen modules\n classModule, // makes it easy to toggle classes\n propsModule, // for setting properties on DOM elements\n styleModule, // handles styling on elements with support for animations\n eventListenersModule, // attaches event listeners\n]);\n","export interface RoutingStrategy {\n getCurrentPath(): string;\n navigateTo(path: string): void;\n}\n\nexport class HistoryRoutingStrategy implements RoutingStrategy {\n getCurrentPath(): string {\n return window.location.pathname;\n }\n\n navigateTo(path: string): void {\n window.history.pushState({}, \"\", path);\n }\n}\n\nexport class CustomRoutingStrategy implements RoutingStrategy {\n private currentPath: string = \"/\";\n\n getCurrentPath(): string {\n return this.currentPath;\n }\n\n navigateTo(path: string): void {\n this.currentPath = path;\n }\n}\n\nexport const createRoutingStrategy = (\n mode: \"history\" | \"custom\"\n): RoutingStrategy => {\n if (mode === \"custom\") {\n return new CustomRoutingStrategy();\n } else {\n return new HistoryRoutingStrategy();\n }\n};\n","import type { FileLoader } from \"./file-loader\";\n\ninterface TranspileResult {\n files: Array<[string, Uint8Array]>;\n}\n\ninterface CacheEntry {\n jsUrl: string;\n fileUrls: Record<string, string>;\n}\n\nconst CACHE_KEY_PREFIX = \"transpile_cache_\";\n\n// Helper functions for localStorage caching\nconst getCachedEntry = (file: string): CacheEntry | null => {\n try {\n const cached = localStorage.getItem(CACHE_KEY_PREFIX + file);\n if (cached) {\n return JSON.parse(cached);\n }\n } catch (e) {\n console.warn(\"Failed to read from cache:\", e);\n }\n return null;\n};\n\nconst setCachedEntry = (file: string, entry: CacheEntry): void => {\n try {\n localStorage.setItem(CACHE_KEY_PREFIX + file, JSON.stringify(entry));\n } catch (e) {\n console.warn(\"Failed to write to cache:\", e);\n }\n};\n\nconst transpileInWorker = async (\n buffer: ArrayBuffer,\n name: string,\n): Promise<TranspileResult> => {\n return new Promise((resolve, reject) => {\n const worker = new Worker(\n new URL(\"./transpile.worker.ts\", import.meta.url),\n { type: \"module\" },\n );\n\n worker.onmessage = (event: MessageEvent) => {\n worker.terminate();\n if (event.data.success) {\n resolve(event.data.data);\n } else {\n reject(new Error(event.data.error));\n }\n };\n\n worker.onerror = (error) => {\n worker.terminate();\n reject(error);\n };\n\n // Transfer the buffer ownership to the worker (zero-copy)\n worker.postMessage({ buffer, name }, [buffer]);\n });\n};\n\nexport const loadTranspile = async (\n file: string,\n fileLoader: FileLoader,\n): Promise<[string, (filename: string) => Promise<WebAssembly.Module>]> => {\n // Check cache first\n const cached = getCachedEntry(file);\n if (cached) {\n // Verify URLs are still valid\n try {\n await fetch(cached.jsUrl, { method: \"HEAD\" });\n return [\n cached.jsUrl,\n async (filename: string) => {\n const url = cached.fileUrls[filename];\n if (!url) {\n throw new Error(`File ${filename} not found in transpiled output.`);\n }\n const wasmResponse = await fetch(url);\n const wasmBuffer = await wasmResponse.arrayBuffer();\n return await WebAssembly.compile(wasmBuffer);\n },\n ];\n } catch (e) {\n // Cache is stale, proceed with transpilation\n console.warn(\"Cached URLs are stale, re-transpiling\");\n }\n }\n\n const response = await fileLoader.load(file);\n if (!response) {\n throw new Error(`Failed to load file: ${file}`);\n }\n const files: Record<string, string> = {};\n const t = await transpileInWorker(response.buffer, \"test\");\n\n for (const file of t.files) {\n const [f, content] = file as [string, Uint8Array];\n\n let blob: Blob | null = null;\n if (f.endsWith(\".js\")) {\n blob = new Blob([new Uint8Array(content)], {\n type: \"application/javascript\",\n });\n } else if (f.endsWith(\".wasm\")) {\n blob = new Blob([new Uint8Array(content)], {\n type: \"application/wasm\",\n });\n }\n if (blob) {\n const url = URL.createObjectURL(blob);\n files[f] = url;\n }\n }\n const jsFileEntry = Object.entries(files).find(([filename]) =>\n filename.endsWith(\".js\"),\n );\n if (!jsFileEntry) {\n throw new Error(\"No JavaScript file found in transpiled output.\");\n }\n\n // Cache the result\n const cacheEntry: CacheEntry = {\n jsUrl: jsFileEntry[1],\n fileUrls: files,\n };\n setCachedEntry(file, cacheEntry);\n\n return [\n jsFileEntry[1],\n async (filename: string) => {\n const url = files[filename];\n if (!url) {\n throw new Error(`File ${filename} not found in transpiled output.`);\n }\n const wasmResponse = await fetch(url);\n const wasmBuffer = await wasmResponse.arrayBuffer();\n return await WebAssembly.compile(wasmBuffer);\n },\n ];\n};\n","import type { Props } from \"druid:ui/ui\";\nimport { h, type VNode, type VNodeChildren, type VNodeData } from \"snabbdom\";\nimport { Event } from \"./types\";\n\nconst nodes = new Map<\n string,\n {\n element: string;\n props?: Props;\n children?: Array<string>;\n hooks?: string[];\n }\n>();\n\nexport function clearNodes() {\n console.debug(`[clearNodes] Clearing ${nodes.size} nodes`);\n nodes.clear();\n}\n\nexport function setHook(id: string, callback: string) {\n console.debug(`[setHook] Setting \"${callback}\" hook on node ${id}`);\n const node = nodes.get(id);\n if (node) {\n node.hooks = node.hooks || [];\n node.hooks.push(callback);\n }\n}\n\nexport function dfunc(element: string, props: Props, children: string[]) {\n const id = crypto.randomUUID();\n console.debug(`[dfunc] Creating node: element=\"${element}\", id=${id}`);\n\n nodes.set(id, { element, props, children });\n return id;\n}\n\nexport function logfunc(msg: string) {\n console.debug(\"UI LOG:\", msg);\n}\n\nexport function createDomFromIdRec(\n id: string,\n emitEvent: (id: string, eventType: string, event: Event) => void,\n navigate?: (href: string) => void,\n): VNode | String {\n const node = nodes.get(id);\n //it is a bit strange to do it like that, in theory we want to better distinguish between text nodes and element nodes\n if (!node) {\n console.debug(`[createDomFromIdRec] Text node: \"${id}\"`);\n return id;\n }\n\n const data: VNodeData = {};\n\n // Set properties\n if (node.props) {\n data.props = {};\n for (const prop of node.props.prop) {\n data.props[prop.key] = prop.value;\n }\n data.on = {};\n for (const eventType of node.props.on) {\n data.on[eventType] = (e) => {\n console.debug(`[event] \"${eventType}\" on node ${id}`);\n emitEvent(\n id,\n eventType,\n new Event(e?.currentTarget?.value, e?.currentTarget?.checked),\n );\n };\n }\n const href = data.props[\"href\"];\n if (href && !data.on[\"click\"]) {\n if (navigate) {\n data.on.click = (e) => {\n e.preventDefault();\n navigate(href);\n };\n }\n }\n }\n\n // Set hooks (outside props check so hooks work even without props)\n if (node.hooks && node.hooks.length > 0) {\n console.debug(\n `[createDomFromIdRec] Node ${id} has ${\n node.hooks.length\n } hooks: ${node.hooks.join(\", \")}`,\n );\n data.hook = {};\n for (const hookName of node.hooks) {\n data.hook[hookName as keyof typeof data.hook] = () => {\n console.debug(`[hook] \"${hookName}\" fired for node ${id}`);\n emitEvent(id, hookName, new Event());\n };\n }\n }\n const ch: VNodeChildren = [];\n if (node.children) {\n for (const childId of node.children) {\n const childEl = createDomFromIdRec(childId, emitEvent, navigate);\n ch.push(childEl);\n }\n }\n\n return h(node.element, data, ch);\n}\n","export class Event {\n private _value: string;\n private _checked: boolean;\n\n constructor(_value: string = \"\", _checked: boolean = false) {\n this._value = _value;\n this._checked = _checked;\n }\n\n preventDefault() {}\n stopPropagation() {}\n value() {\n return this._value;\n }\n checked() {\n return this._checked;\n }\n}\n","type Callback = (id: string, result: { tag: \"ok\" | \"err\"; val: any }) => void;\n\nlet cb: Callback | undefined;\n\nconst pending: Array<{ id: string; result: Parameters<Callback>[1] }> = [];\n\nconst dispatch = (id: string, result: Parameters<Callback>[1]) => {\n if (cb) {\n cb(id, result);\n return;\n }\n\n pending.push({ id, result });\n};\nexport const setCb = (\n callback: (id: string, result: { tag: \"ok\" | \"err\"; val: any }) => void,\n) => {\n cb = callback;\n\n if (pending.length === 0) {\n return;\n }\n\n // Flush any results that arrived before the callback was registered.\n while (pending.length > 0) {\n const { id, result } = pending.shift()!;\n cb(id, result);\n }\n};\n\nexport const PromiseToResult = <T>(\n promiseFn: (...args: any[]) => Promise<T>,\n) => {\n return (...args: any[]) => {\n const id = crypto.randomUUID();\n promiseFn(...args)\n .then((result) => {\n dispatch(id, {\n tag: \"ok\",\n val: result,\n });\n })\n .catch((error) => {\n dispatch(id, {\n tag: \"err\",\n val: error instanceof Error ? error.message : String(error),\n });\n });\n return id;\n };\n};\n","// Augment the Window interface to include 'druid'.\n// We define a lightweight shape for better intellisense; extend as needed.\n\ntype DruidAPI = Record<string, any>;\n\ndeclare global {\n interface Window {\n \"druid-ui\": {\n d: (...args: any[]) => any;\n };\n \"druid-extension\"?: DruidAPI;\n }\n}\n\n// Mark this file as a module so global augmentation is always applied reliably.\nexport {};\n"],"names":[],"version":3,"file":"ui.js.map"}
|
package/package.json
CHANGED
package/src/host-functions.ts
CHANGED
|
@@ -12,20 +12,23 @@ const nodes = new Map<
|
|
|
12
12
|
}
|
|
13
13
|
>();
|
|
14
14
|
|
|
15
|
+
export function clearNodes() {
|
|
16
|
+
console.debug(`[clearNodes] Clearing ${nodes.size} nodes`);
|
|
17
|
+
nodes.clear();
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export function setHook(id: string, callback: string) {
|
|
16
|
-
console.debug(`Setting
|
|
21
|
+
console.debug(`[setHook] Setting "${callback}" hook on node ${id}`);
|
|
17
22
|
const node = nodes.get(id);
|
|
18
23
|
if (node) {
|
|
19
24
|
node.hooks = node.hooks || [];
|
|
20
25
|
node.hooks.push(callback);
|
|
21
|
-
} else {
|
|
22
|
-
console.warn(`setHook: No node found for id ${id}`);
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export function dfunc(element: string, props: Props, children: string[]) {
|
|
27
|
-
console.debug("Creating DOM node:", element, props, children);
|
|
28
30
|
const id = crypto.randomUUID();
|
|
31
|
+
console.debug(`[dfunc] Creating node: element="${element}", id=${id}`);
|
|
29
32
|
|
|
30
33
|
nodes.set(id, { element, props, children });
|
|
31
34
|
return id;
|
|
@@ -37,14 +40,13 @@ export function logfunc(msg: string) {
|
|
|
37
40
|
|
|
38
41
|
export function createDomFromIdRec(
|
|
39
42
|
id: string,
|
|
40
|
-
rerender: () => void,
|
|
41
43
|
emitEvent: (id: string, eventType: string, event: Event) => void,
|
|
42
|
-
navigate?: (href: string) => void
|
|
44
|
+
navigate?: (href: string) => void,
|
|
43
45
|
): VNode | String {
|
|
44
46
|
const node = nodes.get(id);
|
|
45
47
|
//it is a bit strange to do it like that, in theory we want to better distinguish between text nodes and element nodes
|
|
46
48
|
if (!node) {
|
|
47
|
-
console.debug(
|
|
49
|
+
console.debug(`[createDomFromIdRec] Text node: "${id}"`);
|
|
48
50
|
return id;
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -59,13 +61,12 @@ export function createDomFromIdRec(
|
|
|
59
61
|
data.on = {};
|
|
60
62
|
for (const eventType of node.props.on) {
|
|
61
63
|
data.on[eventType] = (e) => {
|
|
62
|
-
console.debug(
|
|
64
|
+
console.debug(`[event] "${eventType}" on node ${id}`);
|
|
63
65
|
emitEvent(
|
|
64
66
|
id,
|
|
65
67
|
eventType,
|
|
66
|
-
new Event(e?.currentTarget?.value, e?.currentTarget?.checked)
|
|
68
|
+
new Event(e?.currentTarget?.value, e?.currentTarget?.checked),
|
|
67
69
|
);
|
|
68
|
-
rerender();
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
const href = data.props["href"];
|
|
@@ -77,26 +78,27 @@ export function createDomFromIdRec(
|
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
}
|
|
81
|
+
}
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
// Set hooks (outside props check so hooks work even without props)
|
|
84
|
+
if (node.hooks && node.hooks.length > 0) {
|
|
85
|
+
console.debug(
|
|
86
|
+
`[createDomFromIdRec] Node ${id} has ${
|
|
87
|
+
node.hooks.length
|
|
88
|
+
} hooks: ${node.hooks.join(", ")}`,
|
|
89
|
+
);
|
|
90
|
+
data.hook = {};
|
|
91
|
+
for (const hookName of node.hooks) {
|
|
92
|
+
data.hook[hookName as keyof typeof data.hook] = () => {
|
|
93
|
+
console.debug(`[hook] "${hookName}" fired for node ${id}`);
|
|
94
|
+
emitEvent(id, hookName, new Event());
|
|
95
|
+
};
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
|
-
|
|
91
98
|
const ch: VNodeChildren = [];
|
|
92
99
|
if (node.children) {
|
|
93
100
|
for (const childId of node.children) {
|
|
94
|
-
const childEl = createDomFromIdRec(
|
|
95
|
-
childId,
|
|
96
|
-
rerender,
|
|
97
|
-
emitEvent,
|
|
98
|
-
navigate
|
|
99
|
-
);
|
|
101
|
+
const childEl = createDomFromIdRec(childId, emitEvent, navigate);
|
|
100
102
|
ch.push(childEl);
|
|
101
103
|
}
|
|
102
104
|
}
|
package/src/ui.ts
CHANGED
|
@@ -6,7 +6,13 @@ import {
|
|
|
6
6
|
type RoutingStrategy,
|
|
7
7
|
} from "./routing-strategy";
|
|
8
8
|
import { loadTranspile } from "./transpile";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
clearNodes,
|
|
11
|
+
createDomFromIdRec,
|
|
12
|
+
dfunc,
|
|
13
|
+
logfunc,
|
|
14
|
+
setHook,
|
|
15
|
+
} from "./host-functions";
|
|
10
16
|
import { Event } from "./types";
|
|
11
17
|
import { setCb } from "./utils";
|
|
12
18
|
|
|
@@ -34,6 +40,7 @@ export class DruidUI extends HTMLElement {
|
|
|
34
40
|
private _entrypoint?: string;
|
|
35
41
|
private rootComponent: any;
|
|
36
42
|
private _connected: boolean = false;
|
|
43
|
+
private reloadGeneration: number = 0;
|
|
37
44
|
|
|
38
45
|
public connectedCallback() {
|
|
39
46
|
this._connected = true;
|
|
@@ -62,6 +69,16 @@ export class DruidUI extends HTMLElement {
|
|
|
62
69
|
console.warn("No file loader set.");
|
|
63
70
|
return;
|
|
64
71
|
}
|
|
72
|
+
|
|
73
|
+
// Increment generation to invalidate all pending operations from previous load
|
|
74
|
+
this.reloadGeneration++;
|
|
75
|
+
console.debug(
|
|
76
|
+
`[reloadComponent] Starting reload, generation: ${this.reloadGeneration}`,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Clear nodes map to ensure fresh state
|
|
80
|
+
clearNodes();
|
|
81
|
+
|
|
65
82
|
if (this._sandbox) {
|
|
66
83
|
loadTranspile(entrypoint, this.loader)
|
|
67
84
|
.then(([moduleUrl, compile]) => {
|
|
@@ -201,23 +218,51 @@ export class DruidUI extends HTMLElement {
|
|
|
201
218
|
}
|
|
202
219
|
|
|
203
220
|
async loadEntrypointFromJavaScriptUrl(entrypoint: string) {
|
|
221
|
+
// Capture the generation at the start of this load
|
|
222
|
+
const loadGeneration = this.reloadGeneration;
|
|
223
|
+
console.debug(
|
|
224
|
+
`[loadEntrypointFromJavaScriptUrl] Starting load for generation ${loadGeneration}`,
|
|
225
|
+
);
|
|
226
|
+
|
|
204
227
|
window["druid-ui"] = {
|
|
205
228
|
d: dfunc,
|
|
206
229
|
};
|
|
207
230
|
|
|
208
231
|
window["druid-extension"] = this.getExtensionObject();
|
|
209
232
|
|
|
210
|
-
|
|
211
|
-
|
|
233
|
+
// Force no-cache to get fresh content
|
|
234
|
+
const response = await this.loader.load(entrypoint, { cache: false });
|
|
212
235
|
const bundleContent = response.buffer;
|
|
213
236
|
|
|
214
|
-
//
|
|
237
|
+
// Create blob URL to avoid Vite's /public restrictions
|
|
215
238
|
const blob = new Blob([bundleContent], { type: "application/javascript" });
|
|
216
239
|
const moduleUrl = URL.createObjectURL(blob);
|
|
217
240
|
const t = await import(/* @vite-ignore */ moduleUrl);
|
|
241
|
+
console.debug(
|
|
242
|
+
`[loadEntrypointFromJavaScriptUrl] Module loaded for generation ${loadGeneration}, current generation: ${this.reloadGeneration}`,
|
|
243
|
+
);
|
|
218
244
|
|
|
219
245
|
setCb(t.component.asyncComplete);
|
|
246
|
+
|
|
247
|
+
// Only proceed if no newer reload has been triggered
|
|
248
|
+
if (this.reloadGeneration !== loadGeneration) {
|
|
249
|
+
console.debug(
|
|
250
|
+
`[loadEntrypointFromJavaScriptUrl] Aborting stale load (generation ${loadGeneration}, current: ${this.reloadGeneration})`,
|
|
251
|
+
);
|
|
252
|
+
URL.revokeObjectURL(moduleUrl);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
220
256
|
this.rootComponent = t;
|
|
257
|
+
|
|
258
|
+
// Reset VNode right before rendering new module to ensure hooks fire
|
|
259
|
+
// This must be done here (not in reloadComponent) to avoid race conditions
|
|
260
|
+
// with pending rerenders from previous module
|
|
261
|
+
this.currentVNode = null;
|
|
262
|
+
console.debug(
|
|
263
|
+
`[loadEntrypointFromJavaScriptUrl] Rendering generation ${loadGeneration}`,
|
|
264
|
+
);
|
|
265
|
+
|
|
221
266
|
this.rerender();
|
|
222
267
|
URL.revokeObjectURL(moduleUrl);
|
|
223
268
|
}
|
|
@@ -262,9 +307,20 @@ export class DruidUI extends HTMLElement {
|
|
|
262
307
|
this.mountEl.innerHTML = "";
|
|
263
308
|
const dom = createDomFromIdRec(
|
|
264
309
|
rootId,
|
|
265
|
-
this.rerender.bind(this),
|
|
266
310
|
(nodeId, eventType, e) => {
|
|
267
311
|
this.rootComponent.component.emit(nodeId, eventType, e);
|
|
312
|
+
// Capture the current generation
|
|
313
|
+
const generation = this.reloadGeneration;
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
// Only rerender if we're still in the same generation (no reload happened)
|
|
316
|
+
if (this.reloadGeneration === generation) {
|
|
317
|
+
this.rerender();
|
|
318
|
+
} else {
|
|
319
|
+
console.debug(
|
|
320
|
+
`[setTimeout] Skipping stale rerender (generation ${generation}, current: ${this.reloadGeneration})`,
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
}, 0);
|
|
268
324
|
},
|
|
269
325
|
(href: string) => {
|
|
270
326
|
this._routeStrategy.navigateTo(href);
|
package/src/utils.ts
CHANGED
|
@@ -13,7 +13,7 @@ const dispatch = (id: string, result: Parameters<Callback>[1]) => {
|
|
|
13
13
|
pending.push({ id, result });
|
|
14
14
|
};
|
|
15
15
|
export const setCb = (
|
|
16
|
-
callback: (id: string, result: { tag: "ok" | "err"; val: any }) => void
|
|
16
|
+
callback: (id: string, result: { tag: "ok" | "err"; val: any }) => void,
|
|
17
17
|
) => {
|
|
18
18
|
cb = callback;
|
|
19
19
|
|
|
@@ -29,7 +29,7 @@ export const setCb = (
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export const PromiseToResult = <T>(
|
|
32
|
-
promiseFn: (...args: any[]) => Promise<T
|
|
32
|
+
promiseFn: (...args: any[]) => Promise<T>,
|
|
33
33
|
) => {
|
|
34
34
|
return (...args: any[]) => {
|
|
35
35
|
const id = crypto.randomUUID();
|