UNPKG

@azure-utils/storybooks

Version:

Utils to upload and manage Storybooks via Azure Functions and storage.

1,113 lines (1,072 loc) 36 kB
const require_chunk = require('./chunk-DWy1uDak.cjs'); const require_constants = require('./constants-94H7Co6A.cjs'); const require_error_utils = require('./error-utils-DFTvM-wv.cjs'); const require_url_utils = require('./url-utils-Dy7KiQmB.cjs'); const node_async_hooks = require_chunk.__toESM(require("node:async_hooks")); //#region ../../node_modules/@kitajs/html/index.js var require_html = require_chunk.__commonJS({ "../../node_modules/@kitajs/html/index.js"(exports) { const ESCAPED_REGEX = /[<"'&]/; const CAMEL_REGEX = /[a-z][A-Z]/; /** @type {import('.').isUpper} */ function isUpper(input, index) { const code = input.charCodeAt(index); return code >= 65 && code <= 90; } /** @type {import('.').toKebabCase} */ function toKebabCase(camel) { if (!CAMEL_REGEX.test(camel)) return camel; const length = camel.length; let start = 0, end = 0, kebab = "", prev = true, curr = isUpper(camel, 0), next; for (; end < length; end++) { next = isUpper(camel, end + 1); if (!prev && curr && !next) { kebab += camel.slice(start, end) + "-" + camel[end].toLowerCase(); start = end + 1; } prev = curr; curr = next; } kebab += camel.slice(start, end); return kebab; } /** @type {import('.').escape} */ function escape(strings, ...values) { const stringsLength = strings.length, valuesLength = values.length; let index = 0, result = ""; for (; index < stringsLength; index++) { result += strings[index]; if (index < valuesLength) result += values[index]; } return escapeHtml(result); } /** @type {import('.').escapeHtml} */ let escapeHtml = function(value) { if (typeof value !== "string") value = value.toString(); if (!ESCAPED_REGEX.test(value)) return value; const length = value.length; let escaped = "", start = 0, end = 0; for (; end < length; end++) switch (value[end]) { case "&": escaped += value.slice(start, end) + "&amp;"; start = end + 1; continue; case "<": escaped += value.slice(start, end) + "&lt;"; start = end + 1; continue; case "\"": escaped += value.slice(start, end) + "&#34;"; start = end + 1; continue; case "'": escaped += value.slice(start, end) + "&#39;"; start = end + 1; continue; } escaped += value.slice(start, end); return escaped; }; /* c8 ignore next 2 */ if (typeof Bun !== "undefined") escapeHtml = Bun.escapeHTML; /** @type {import('.').isVoidElement} */ function isVoidElement$1(tag) { return tag === "meta" || tag === "link" || tag === "img" || tag === "br" || tag === "input" || tag === "hr" || tag === "area" || tag === "base" || tag === "col" || tag === "command" || tag === "embed" || tag === "keygen" || tag === "param" || tag === "source" || tag === "track" || tag === "wbr"; } /** @type {import('.').styleToString} */ function styleToString(style) { if (typeof style === "string") { let end$1 = style.indexOf("\""); if (end$1 === -1) return style; const length$1 = style.length; let escaped = "", start$1 = 0; for (; end$1 < length$1; end$1++) if (style[end$1] === "\"") { escaped += style.slice(start$1, end$1) + "&#34;"; start$1 = end$1 + 1; } escaped += style.slice(start$1, end$1); return escaped; } const keys = Object.keys(style), length = keys.length; let key, value, end, start, index = 0, result = ""; for (; index < length; index++) { key = keys[index]; value = style[key]; if (value === null || value === void 0) continue; result += toKebabCase(key) + ":"; if (typeof value !== "string") { result += value.toString() + ";"; continue; } end = value.indexOf("\""); if (end === -1) { result += value + ";"; continue; } const length$1 = value.length; start = 0; for (; end < length$1; end++) if (value[end] === "\"") { result += value.slice(start, end) + "&#34;"; start = end + 1; } result += value.slice(start, end) + ";"; } return result; } /** @type {import('.').attributesToString} */ function attributesToString$1(attributes) { const keys = Object.keys(attributes); const length = keys.length; let key, value, type, end, start, classItems, valueLength, result = "", index = 0; for (; index < length; index++) { key = keys[index]; if (key === "children" || key === "safe" || key === "of") continue; value = attributes[key]; if (value === null || value === void 0) continue; if (key === "className") { if (attributes.class !== void 0) continue; key = "class"; } else if (key === "class" && Array.isArray(value)) { classItems = value; valueLength = value.length; value = ""; for (let i = 0; i < valueLength; i++) if (classItems[i] && classItems[i].length > 0) if (value) value += " " + classItems[i].trim(); else value += classItems[i].trim(); if (value.length === 0) continue; } else if (key === "style") { result += " style=\"" + styleToString(value) + "\""; continue; } else if (key === "attrs") { if (typeof value === "string") result += " " + value; else result += attributesToString$1(value); continue; } type = typeof value; if (type === "boolean") { if (value) result += " " + key; continue; } result += " " + key; if (type !== "string") { if (type !== "object") { result += "=\"" + value.toString() + "\""; continue; } if (value instanceof Date) { result += "=\"" + value.toISOString() + "\""; continue; } value = value.toString(); } end = value.indexOf("\""); if (end === -1) { result += "=\"" + value + "\""; continue; } result += "=\""; valueLength = value.length; start = 0; for (; end < valueLength; end++) if (value[end] === "\"") { result += value.slice(start, end) + "&#34;"; start = end + 1; } result += value.slice(start, end) + "\""; } return result; } /** * @type {import('.').contentsToString} * @returns {any} */ function contentsToString$2(contents, escape$1) { let length = contents.length; let result = ""; for (let index = 0; index < length; index++) { const content = contents[index]; switch (typeof content) { case "string": case "number": case "bigint": result += content; continue; case "boolean": continue; } if (!content) continue; if (Array.isArray(content)) { contents.splice(index--, 1, ...content); length += content.length - 1; continue; } if (typeof content.then === "function") return Promise.all(contents.slice(index)).then(function resolveContents(resolved) { resolved.unshift(result); return contentsToString$2(resolved, escape$1); }); throw new Error("Objects are not valid as a KitaJSX child"); } if (escape$1 === true) return escapeHtml(result); return result; } /** * @param {import('./index').Children} content * @param {boolean} safe * @returns {JSX.Element} */ function contentToString$2(content, safe) { switch (typeof content) { case "string": return safe ? escapeHtml(content) : content; case "number": case "bigint": return content.toString(); case "boolean": return ""; } if (!content) return ""; if (Array.isArray(content)) return contentsToString$2(content, safe); if (typeof content.then === "function") return content.then(function resolveContent(resolved) { return contentToString$2(resolved, safe); }); throw new Error("Objects are not valid as a KitaJSX child"); } /** * Just to stop TS from complaining about the type. * * @type {import('.').createElement} * @param {any} name * @returns {any} */ function createElement(name, attrs, ...children) { const hasAttrs = attrs !== null; if (typeof name === "function") { if (!hasAttrs) return name({ children: children.length > 1 ? children : children[0] }); attrs.children = children.length > 1 ? children : children[0]; return name(attrs); } if (hasAttrs && name === "tag") name = attrs.of; const attributes = hasAttrs ? attributesToString$1(attrs) : ""; if (children.length === 0) return isVoidElement$1(name) ? "<" + name + attributes + "/>" : "<" + name + attributes + "></" + name + ">"; const contents = contentsToString$2(children, hasAttrs && attrs.safe); if (typeof contents === "string") return "<" + name + attributes + ">" + contents + "</" + name + ">"; return contents.then(function resolveContents(contents$1) { return "<" + name + attributes + ">" + contents$1 + "</" + name + ">"; }); } /** @type {import('.').Fragment} */ function Fragment$1(props) { return contentsToString$2([props.children]); } exports.escape = escape; exports.e = escape; exports.escapeHtml = escapeHtml; exports.isVoidElement = isVoidElement$1; exports.attributesToString = attributesToString$1; exports.toKebabCase = toKebabCase; exports.isUpper = isUpper; exports.styleToString = styleToString; exports.createElement = createElement; exports.h = createElement; exports.contentsToString = contentsToString$2; exports.contentToString = contentToString$2; exports.Fragment = Fragment$1; exports.Html = { ...exports }; } }); //#endregion //#region ../../node_modules/@kitajs/html/suspense.js var require_suspense = require_chunk.__commonJS({ "../../node_modules/@kitajs/html/suspense.js"(exports) { const { contentsToString: contentsToString$1, contentToString: contentToString$1 } = require_html(); const { Readable, PassThrough } = require("node:stream"); if (!globalThis.SUSPENSE_ROOT) globalThis.SUSPENSE_ROOT = { requests: /* @__PURE__ */ new Map(), requestCounter: 1, autoScript: true }; function noop() {} /** * Simple IE11 compatible replace child scripts to replace the template streamed by the * server. * * As this script is the only residue of this package that is actually sent to the client, * it's important to keep it as small as possible and also include the license to avoid * legal issues. */ const SuspenseScript = ` <script id="kita-html-suspense"> /*! MIT License https://kita.js.org */ function $KITA_RC(i){ // simple aliases var d=document,q=d.querySelector.bind(d), // div sent as the fallback wrapper v=q('div[id="B:'+i+'"][data-sf]'), // template and script sent after promise finishes t=q('template[id="N:'+i+'"][data-sr]'),s=q('script[id="S:'+i+'"][data-ss]'), // fragment created to avoid inserting element one by one f=d.createDocumentFragment(), // used by iterators c,j, // all pending hydrations r; // if div or template is not found, let this hydration as pending if(t&&v&&s){ // appends into the fragment while(c=t.content.firstChild) f.appendChild(c); // replaces the div and removes the script and template v.parentNode.replaceChild(f,v); t.remove(); s.remove(); // looks for pending templates r=d.querySelectorAll('template[id][data-sr]'); do{ // resets j & c from previous loop c=j=0; // loops over every found pending template and for(;c<r.length;c++) if(r[c]!=t) // let j as true while at least on $KITA_RC call returns true j=$KITA_RC(r[c].id.slice(2))?!0:j; }while(j) // we know at least the original template was substituted return!0; } } <\/script> `.replace(/^\s*\/\/.*/gm, "").replace(/\n\s*/g, ""); /** @type {import('./suspense').Suspense} */ function Suspense(props) { const children = Array.isArray(props.children) ? contentsToString$1(props.children) : contentToString$1(props.children); if (typeof children === "string") return children; if (!props.rid) throw new Error("Suspense requires a `rid` to be specified."); let data = SUSPENSE_ROOT.requests.get(props.rid); if (!data) { data = { stream: new Readable({ read: noop }), running: 0, sent: false }; SUSPENSE_ROOT.requests.set(props.rid, data); } const run = ++data.running; children.then(writeStreamTemplate).catch(function errorRecover(error) { if (!props.catch) throw error; let html; if (typeof props.catch === "function") html = props.catch(error); else html = props.catch; if (typeof html === "string") return writeStreamTemplate(html); return html.then(writeStreamTemplate); }).catch(function writeFatalError(error) { data.stream.emit("error", error); }).finally(function clearRequestData() { if (data && data.running > 1) { data.running -= 1; return; } if (data && !data.stream.closed) data.stream.push(null); SUSPENSE_ROOT.requests.delete(props.rid); }); const fallback = contentToString$1(props.fallback); if (typeof fallback === "string") return "<div id=\"B:" + run + "\" data-sf>" + fallback + "</div>"; return fallback.then(function resolveCallback(resolved) { return "<div id=\"B:" + run + "\" data-sf>" + resolved + "</div>"; }); /** * This function may be called by the catch handler in case the error could be handled. * * @param {string} result */ function writeStreamTemplate(result) { if (!SUSPENSE_ROOT.requests.has(props.rid) || !data || data.stream.closed) return; if (SUSPENSE_ROOT.autoScript && data.sent === false) { data.stream.push(SuspenseScript); data.sent = true; } data.stream.push(`<template id="N:${run}" data-sr>${result}</template><script id="S:${run}" data-ss>$KITA_RC(${run})<\/script>`); } } /** @type {import('./suspense').renderToStream} */ function renderToStream$1(html, rid) { if (!rid) rid = SUSPENSE_ROOT.requestCounter++; else if (SUSPENSE_ROOT.requests.has(rid)) { const error = /* @__PURE__ */ new Error(`The provided Request Id is already in use: ${rid}.`); return new Readable({ read() { this.emit("error", error); this.push(null); } }); } if (typeof html === "function") try { html = html(rid); } catch (error) { SUSPENSE_ROOT.requests.delete(rid); return new Readable({ read() { this.emit("error", error); this.push(null); } }); } const requestData = SUSPENSE_ROOT.requests.get(rid); if (!requestData) { if (typeof html === "string") return Readable.from([html]); return new Readable({ read() { html.then((result) => { this.push(result); this.push(null); }).catch((error) => { this.emit("error", error); }); } }); } return resolveHtmlStream(html, requestData); } /** @type {import('./suspense').resolveHtmlStream} */ function resolveHtmlStream(template, requestData) { if (typeof template === "string") { requestData.stream.push(template); return requestData.stream; } const prepended = new PassThrough(); template.then((result) => { prepended.push(result); requestData.stream.pipe(prepended); }, (error) => { prepended.emit("error", error); }); return prepended; } exports.Suspense = Suspense; exports.renderToStream = renderToStream$1; exports.resolveHtmlStream = resolveHtmlStream; exports.SuspenseScript = SuspenseScript; } }); //#endregion //#region src/utils/url-builder.ts /** * URL builder for the Storybooks router. * @private */ const urlBuilder = { root: (...pathnames) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, ...pathnames), base); return url.toString(); }, staticFile: (filepath) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, filepath), base); return url.toString(); }, allProjects: () => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects"), base); return url.toString(); }, projectCreate: () => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects"), base); url.searchParams.set(require_constants.QUERY_PARAMS.mode, require_constants.QUERY_PARAMS.newResource); return url.toString(); }, projectId: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId), base); return url.toString(); }, projectIdEdit: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId), base); url.searchParams.set(require_constants.QUERY_PARAMS.mode, require_constants.QUERY_PARAMS.editResource); return url.toString(); }, allBuilds: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "builds"), base); return url.toString(); }, buildSHA: (projectId, sha, labelSlug) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "builds", sha), base); if (labelSlug) url.searchParams.set(require_constants.QUERY_PARAMS.labelSlug, labelSlug); return url.toString(); }, buildUpload: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "builds"), base); url.searchParams.set(require_constants.QUERY_PARAMS.mode, require_constants.QUERY_PARAMS.newResource); return url.toString(); }, allLabels: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "labels"), base); return url.toString(); }, labelCreate: (projectId) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "labels"), base); url.searchParams.set(require_constants.QUERY_PARAMS.mode, require_constants.QUERY_PARAMS.newResource); return url.toString(); }, labelSlug: (projectId, labelSlug) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "labels", labelSlug), base); return url.toString(); }, labelSlugEdit: (projectId, labelSlug) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "labels", labelSlug), base); url.searchParams.set(require_constants.QUERY_PARAMS.mode, require_constants.QUERY_PARAMS.editResource); return url.toString(); }, labelSlugLatest: (projectId, labelSlug) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "projects", projectId, "labels", labelSlug, "latest"), base); return url.toString(); }, storybookIndexHtml: (projectId, sha) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "_", projectId, sha, "index.html"), base); return url.toString(); }, storybookTestReport: (projectId, sha) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "_", projectId, sha, "report", "index.html"), base); return url.toString(); }, storybookCoverage: (projectId, sha) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "_", projectId, sha, "coverage", "index.html"), base); return url.toString(); }, storybookZip: (projectId, sha) => { const { baseRoute, url: base } = getStore(); const url = new URL(require_url_utils.joinUrl(baseRoute, "_", projectId, sha, "storybook.zip"), base); return url.toString(); }, gitHub: (gitHubRepo, ...pathnames) => { const url = new URL(require_url_utils.joinUrl(gitHubRepo, ...pathnames), "https://github.com"); return url.toString(); } }; //#endregion //#region ../../node_modules/@kitajs/html/jsx-runtime.js var require_jsx_runtime = require_chunk.__commonJS({ "../../node_modules/@kitajs/html/jsx-runtime.js"(exports) { const { Fragment, attributesToString, isVoidElement, contentsToString, contentToString } = require_html(); /** @type {import('./jsx-runtime').jsx} */ function jsx(name, attrs) { if (typeof name === "function") return name(attrs); if (name === "tag") name = attrs.of; const attributes = attributesToString(attrs); if (attrs.children === void 0) return isVoidElement(name) ? "<" + name + attributes + "/>" : "<" + name + attributes + "></" + name + ">"; const contents = contentToString(attrs.children, attrs.safe); if (contents instanceof Promise) return contents.then(function resolveContents(child) { return "<" + name + attributes + ">" + child + "</" + name + ">"; }); return "<" + name + attributes + ">" + contents + "</" + name + ">"; } /** @type {import('./jsx-runtime').jsxs} */ function jsxs(name, attrs) { if (typeof name === "function") return name(attrs); if (name === "tag") name = attrs.of; const attributes = attributesToString(attrs); if (attrs.children.length === 0) return isVoidElement(name) ? "<" + name + attributes + "/>" : "<" + name + attributes + "></" + name + ">"; const contents = contentsToString(attrs.children, attrs.safe); if (contents instanceof Promise) return contents.then(function resolveContents(child) { return "<" + name + attributes + ">" + child + "</" + name + ">"; }); return "<" + name + attributes + ">" + contents + "</" + name + ">"; } exports.jsx = jsx; exports.jsxs = jsxs; exports.Fragment = Fragment; } }); //#endregion //#region src/components/layout.tsx var import_jsx_runtime$2 = require_chunk.__toESM(require_jsx_runtime()); function DocumentLayout({ title, breadcrumbs = [], children, footer, toolbar }) { const safeStylesheet = globalStyleSheet(); const store$1 = getStore(); return /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)(import_jsx_runtime$2.Fragment, { children: ["<!DOCTYPE html>", /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("html", { lang: "en", children: [/* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("head", { children: [ /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("title", { safe: true, children: [ title, " |", " ", store$1.serviceName === require_constants.DEFAULT_SERVICE_NAME ? "StoryBooks" : store$1.serviceName ] }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("style", { children: safeStylesheet }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("script", { src: "https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js", crossorigin: "anonymous" }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("script", { src: "https://cdn.jsdelivr.net/npm/htmx-ext-response-targets@2.0.2", crossorigin: "anonymous" }) ] }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("body", { children: [ /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("header", { children: [ /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("div", { style: { borderRight: "1px solid var(--color-border)", paddingRight: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("a", { href: urlBuilder.root(), title: "Home", children: store$1.serviceName === require_constants.DEFAULT_SERVICE_NAME ? /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("strong", { style: { fontFamily: "monospace", display: "block", textAlign: "center", color: "var(--color-text-primary)" }, children: [ "STORY", /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("br", {}), "BOOKS" ] }) : /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("strong", { safe: true, children: store$1.serviceName }) }) }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("div", { class: "page-heading", style: { flex: 1 }, children: [breadcrumbs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("ul", { children: breadcrumbs.map((crumb, i, arr) => { const href = (typeof crumb === "object" ? crumb.href : "") || require_url_utils.joinUrl(store$1.url, ...Array.from({ length: arr.length - i }).map(() => "..")); return /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("a", { safe: true, href, children: typeof crumb === "object" ? crumb.label : crumb }) }); }) }) : null, /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("div", { safe: true, children: title })] }), toolbar ? /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("div", { children: toolbar }) : null ] }), /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("main", { children }), footer ? /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("footer", { children: footer }) : null, /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("script", { defer: true, src: "https://unpkg.com/htmx-toaster/dist/htmx-toaster.min.js" }) ] })] })] }); } function globalStyleSheet() { return ` :root { --color-bg-base: #f2f2f2; --color-bg-card: #ffffff; --color-text-primary: #09090b; --color-text-secondary: #71717b; --color-text-accent: #2b7fff; --color-border: #e4e4e7; } @media (prefers-color-scheme: dark) { :root { --color-bg-base: #09090b; --color-bg-card: #18181b; --color-text-primary: #fafafa; --color-text-secondary: #9f9fa9; --color-text-accent: #2b7fff; --color-border: #ffffff1a; } } * { box-sizing: border-box; color-scheme: light dark; font-family: system-ui; border-color: var(--color-border); } body { font-size: 1rem; padding: 0px; margin: 0px; display: flex; flex-direction: column; gap: 1rem; min-height: 100vh; overflow-y: auto; overflow-x: hidden; background-color: var(--color-bg-base); color: var(--color-text-secondary); } body > header, body > footer, body > main, body > aside { margin: 0 1rem; background-color: var(--color-bg-card); color: var(--color-text-primary); border-radius: 0.5rem; overflow: hidden; padding: 1rem; } body > header { margin-top: 1rem; display: flex; align-items: center; gap: 1rem; } body > main { flex: 1; display: flex; flex-direction: column; gap: 1rem; overflow: auto; } body > footer { margin-bottom: 1rem; } hr { color: var(--color-border); background: var(--color-border); border-color: var(--color-border); } table { height: 100%; width: 100%; border-radius: 0.25rem; overflow: hidden; } table caption { font-weight: bold; font-size: 1.25rem; padding: 0.5rem 1rem; text-align: start; } thead { background-color: var(--color-bg-base); color: var(--color-text-secondary); } th { color: var(--color-text-secondary); font-weight: medium; font-size: 0.9rem; text-align: start; padding: 0.25rem 1rem; } td { text-align: start; height: max-content; padding: 0.5rem 1rem; color: var(--color-text-primary); } time { font-family: monospace; font-size: 0.9rem; color: var(--color-text-secondary); } a, a:visited { color: var(--color-text-accent); text-decoration: none; } a:hover { color: var(--color-text-accent); text-decoration: underline; } .raw-data { margin: 0; background-color: #00000010; border: 1px solid var(--color-border); border-radius: 0.25rem; font-family: monospace; font-size: 0.9rem; white-space: pre-wrap; padding: 0.5rem; } .raw-data:empty{ display: none; } .page-heading { display: flex; flex-direction: column; gap: 0.25rem; font-weight: bold; } .page-heading > ul { display: flex; align-items: center; padding: 0; margin: 0; list-style: none; } .page-heading > ul > li { font-weight: normal; list-style: none; font-size: 0.9em; } .page-heading > ul > li::after { content: \"/\"; color: inherit; margin: 0 0.5rem; opacity: 0.5; } .description { color: var(--color-text-secondary); font-size: 0.9rem; } form { display: flex; flex-direction: column; gap: 1rem; } form fieldset { display: flex; flex-direction:column; gap: 1rem; border-radius: 0.5rem; } form legend { font-size:0.9rem; } form .field { display: flex; flex-direction: column; gap: 0.25rem; } form label { font-size:0.9rem; font-weight:600; } form input, form select, form textarea, form button { border-radius: 0.25rem; padding: 0.25rem 0.5rem; color: inherit; } form button[type="submit"] { font-weight:bold; } form .description { font-size: 0.8rem; color: var(--color-text-secondary); } `.replace(/\s+/g, " "); } //#endregion //#region src/components/error-message.tsx var import_jsx_runtime$1 = require_chunk.__toESM(require_jsx_runtime()); function ErrorMessage({ children = "", id }) { return /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("pre", { id, class: "error-message raw-data", style: { background: "#ff000020" }, safe: true, children: children.includes("{") ? JSON.stringify(JSON.parse(children), null, 2) : children }); } //#endregion //#region src/utils/request-utils.ts function checkIsHXRequest(request) { const req = request || getStore().request; return req.headers.get("hx-request") === "true"; } function checkIsHTMLRequest(request) { const req = request || getStore().request; const accept = req.headers.get("accept"); return !!accept?.includes(require_constants.CONTENT_TYPES.HTML); } function checkIsNewMode(request) { const req = request || getStore().request; return req.query.get(require_constants.QUERY_PARAMS.mode) === require_constants.QUERY_PARAMS.newResource; } function checkIsEditMode(request) { const req = request || getStore().request; return req.query.get(require_constants.QUERY_PARAMS.mode) === require_constants.QUERY_PARAMS.editResource; } //#endregion //#region src/utils/response-utils.tsx var import_suspense = require_chunk.__toESM(require_suspense()); var import_jsx_runtime = require_chunk.__toESM(require_jsx_runtime()); function responseHTML(html) { return { status: 200, headers: { "Content-Type": require_constants.CONTENT_TYPES.HTML }, body: (0, import_suspense.renderToStream)(html) }; } function responseError(error, context, init) { try { const { errorMessage, errorStatus, errorType } = require_error_utils.parseErrorMessage(error); context.error(`[${errorType}]`, errorMessage, error instanceof Error ? error.stack : ""); const status = errorStatus ?? (typeof init === "number" ? init : init?.status ?? 500); const headers = new Headers(typeof init === "number" ? {} : init?.headers); if (checkIsHXRequest()) { try { headers.set("HXToaster-Type", "error"); headers.set("HXToaster-Body", errorMessage); } catch {} return { status, headers, body: errorMessage }; } if (checkIsHTMLRequest()) { headers.set("Content-Type", require_constants.CONTENT_TYPES.HTML); return { status, headers, body: (0, import_suspense.renderToStream)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DocumentLayout, { title: `Error ${status}`, breadcrumbs: [{ label: "< Back", href: "javascript:history.back()" }], children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorMessage, { children: errorMessage }) })) }; } headers.set("Content-Type", "application/json"); const jsonBody = { errorMessage }; return { jsonBody, status, headers }; } catch (err) { context.error(`[ErrOnErr]`, err); return { status: 500, body: typeof err === "string" ? err : void 0, jsonBody: typeof err === "string" ? void 0 : err }; } } function responseRedirect(location, init) { const status = typeof init === "number" ? init : init?.status ?? 303; const headers = new Headers(typeof init === "number" ? {} : init?.headers); if (checkIsHXRequest()) headers.set("HX-redirect", location); else headers.set("Location", location); return { status, headers }; } //#endregion //#region src/utils/store.ts const store = new node_async_hooks.AsyncLocalStorage(); function getStore(throwError) { const value = store.getStore(); if (!value && throwError !== false) throw new Error("Request store not found."); return value; } function wrapHttpHandlerWithStore(options, handler, permissions) { return function(request, context) { const locale = request.headers.get("accept-language")?.split(",")[0]; const accept = request.headers.get("accept"); const storeValue = { ...options, accept, locale, url: request.url, request, context }; return store.run(storeValue, async () => { if (!permissions || permissions.length === 0) return handler(request, context); const { checkPermissions } = options; const { projectId } = request.params; const permitted = await checkPermissions(permissions.map((p) => ({ projectId, ...p })), context, request); if (permitted === true) return handler(request, context); const message = `Permission denied [${permissions.map((p) => `'${p.resource}:${p.action}'`).join(", ")}] (project: ${projectId})`; if (permitted === false) return responseError(message, context, 403); if (typeof permitted === "object" && "status" in permitted) { context.warn(message); return permitted; } if (permitted instanceof Response) { context.warn(message); return permitted; } return handler(request, context); }); }; } //#endregion Object.defineProperty(exports, 'DocumentLayout', { enumerable: true, get: function () { return DocumentLayout; } }); Object.defineProperty(exports, 'ErrorMessage', { enumerable: true, get: function () { return ErrorMessage; } }); Object.defineProperty(exports, 'checkIsEditMode', { enumerable: true, get: function () { return checkIsEditMode; } }); Object.defineProperty(exports, 'checkIsHTMLRequest', { enumerable: true, get: function () { return checkIsHTMLRequest; } }); Object.defineProperty(exports, 'checkIsHXRequest', { enumerable: true, get: function () { return checkIsHXRequest; } }); Object.defineProperty(exports, 'checkIsNewMode', { enumerable: true, get: function () { return checkIsNewMode; } }); Object.defineProperty(exports, 'getStore', { enumerable: true, get: function () { return getStore; } }); Object.defineProperty(exports, 'require_jsx_runtime', { enumerable: true, get: function () { return require_jsx_runtime; } }); Object.defineProperty(exports, 'responseError', { enumerable: true, get: function () { return responseError; } }); Object.defineProperty(exports, 'responseHTML', { enumerable: true, get: function () { return responseHTML; } }); Object.defineProperty(exports, 'responseRedirect', { enumerable: true, get: function () { return responseRedirect; } }); Object.defineProperty(exports, 'urlBuilder', { enumerable: true, get: function () { return urlBuilder; } }); Object.defineProperty(exports, 'wrapHttpHandlerWithStore', { enumerable: true, get: function () { return wrapHttpHandlerWithStore; } });