UNPKG

hono

Version:

Web framework built on Web Standards

167 lines (166 loc) 5.85 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var streaming_exports = {}; __export(streaming_exports, { Suspense: () => Suspense, renderToReadableStream: () => renderToReadableStream }); module.exports = __toCommonJS(streaming_exports); var import_html = require("../helper/html"); var import_html2 = require("../utils/html"); var import_base = require("./base"); var import_components = require("./components"); var import_constants = require("./constants"); var import_components2 = require("./dom/components"); var import_render = require("./dom/render"); let suspenseCounter = 0; const Suspense = async ({ children, fallback }) => { if (!children) { return fallback.toString(); } if (!Array.isArray(children)) { children = [children]; } let resArray = []; const stackNode = { [import_constants.DOM_STASH]: [0, []] }; const popNodeStack = (value) => { import_render.buildDataStack.pop(); return value; }; try { stackNode[import_constants.DOM_STASH][0] = 0; import_render.buildDataStack.push([[], stackNode]); resArray = children.map( (c) => c == null || typeof c === "boolean" ? "" : c.toString() ); } catch (e) { if (e instanceof Promise) { resArray = [ e.then(() => { stackNode[import_constants.DOM_STASH][0] = 0; import_render.buildDataStack.push([[], stackNode]); return (0, import_components.childrenToString)(children).then(popNodeStack); }) ]; } else { throw e; } } finally { popNodeStack(); } if (resArray.some((res) => res instanceof Promise)) { const index = suspenseCounter++; const fallbackStr = await fallback.toString(); return (0, import_html.raw)(`<template id="H:${index}"></template>${fallbackStr}<!--/$-->`, [ ...fallbackStr.callbacks || [], ({ phase, buffer, context }) => { if (phase === import_html2.HtmlEscapedCallbackPhase.BeforeStream) { return; } return Promise.all(resArray).then(async (htmlArray) => { htmlArray = htmlArray.flat(); const content = htmlArray.join(""); if (buffer) { buffer[0] = buffer[0].replace( new RegExp(`<template id="H:${index}"></template>.*?<!--/\\$-->`), content ); } let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script> ((d,c,n) => { c=d.currentScript.previousSibling d=d.getElementById('H:${index}') if(!d)return do{n=d.nextSibling;n.remove()}while(n.nodeType!=8||n.nodeValue!='/$') d.replaceWith(c.content) })(document) <\/script>`; const callbacks = htmlArray.map((html2) => html2.callbacks || []).flat(); if (!callbacks.length) { return html; } if (phase === import_html2.HtmlEscapedCallbackPhase.Stream) { html = await (0, import_html2.resolveCallback)(html, import_html2.HtmlEscapedCallbackPhase.BeforeStream, true, context); } return (0, import_html.raw)(html, callbacks); }); } ]); } else { return (0, import_html.raw)(resArray.join("")); } }; Suspense[import_constants.DOM_RENDERER] = import_components2.Suspense; const textEncoder = new TextEncoder(); const renderToReadableStream = (content, onError = console.trace) => { const reader = new ReadableStream({ async start(controller) { try { if (content instanceof import_base.JSXNode) { content = content.toString(); } const context = typeof content === "object" ? content : {}; const resolved = await (0, import_html2.resolveCallback)( content, import_html2.HtmlEscapedCallbackPhase.BeforeStream, true, context ); controller.enqueue(textEncoder.encode(resolved)); let resolvedCount = 0; const callbacks = []; const then = (promise) => { callbacks.push( promise.catch((err) => { console.log(err); onError(err); return ""; }).then(async (res) => { res = await (0, import_html2.resolveCallback)( res, import_html2.HtmlEscapedCallbackPhase.BeforeStream, true, context ); res.callbacks?.map((c) => c({ phase: import_html2.HtmlEscapedCallbackPhase.Stream, context })).filter(Boolean).forEach(then); resolvedCount++; controller.enqueue(textEncoder.encode(res)); }) ); }; resolved.callbacks?.map((c) => c({ phase: import_html2.HtmlEscapedCallbackPhase.Stream, context })).filter(Boolean).forEach(then); while (resolvedCount !== callbacks.length) { await Promise.all(callbacks); } } catch (e) { onError(e); } controller.close(); } }); return reader; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Suspense, renderToReadableStream });