@blinkk/root 1.0.0-rc.0 → 1.0.0-rc.10

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/render/render.tsx","../src/core/pages/ErrorPage.tsx","../src/core/pages/DevErrorPage.tsx","../src/core/pages/DevNotFoundPage.tsx","../src/render/accept-language.ts","../src/render/i18n-fallbacks.ts","../src/render/router.ts","../src/render/route-trie.ts"],"sourcesContent":["import {ComponentChildren, ComponentType} from 'preact';\nimport renderToString from 'preact-render-to-string';\n\nimport {HtmlContext, HTML_CONTEXT} from '../core/components/Html';\nimport {RootConfig} from '../core/config';\nimport {getTranslations, I18N_CONTEXT} from '../core/hooks/useI18nContext';\nimport {RequestContext, REQUEST_CONTEXT} from '../core/hooks/useRequestContext';\nimport {DevErrorPage} from '../core/pages/DevErrorPage';\nimport {DevNotFoundPage} from '../core/pages/DevNotFoundPage';\nimport {ErrorPage} from '../core/pages/ErrorPage';\nimport {\n Request,\n Response,\n NextFunction,\n HandlerContext,\n RouteParams,\n Route,\n HandlerRenderFn,\n HandlerRenderOptions,\n} from '../core/types';\nimport type {ElementGraph} from '../node/element-graph';\nimport {parseTagNames} from '../utils/elements';\n\nimport {AssetMap} from './asset-map/asset-map';\nimport {htmlMinify} from './html-minify';\nimport {htmlPretty} from './html-pretty';\nimport {getFallbackLocales} from './i18n-fallbacks';\nimport {RouteTrie} from './route-trie';\nimport {getRoutes, getAllPathsForRoute, replaceParams} from './router';\n\ninterface RenderHtmlOptions {\n /** Attrs passed to the <html> tag, e.g. `{lang: 'en'}`. */\n htmlAttrs?: preact.JSX.HTMLAttributes<HTMLHtmlElement>;\n /** Attrs passed to the <head> tag. */\n headAttrs?: preact.JSX.HTMLAttributes<HTMLHeadElement>;\n /** Child components for the <head> tag. */\n headComponents?: ComponentChildren[];\n /** Attrs passed to the <body> tag. */\n bodyAttrs?: preact.JSX.HTMLAttributes<HTMLBodyElement>;\n}\n\nexport class Renderer {\n private rootConfig: RootConfig;\n private routes: RouteTrie<Route>;\n private assetMap: AssetMap;\n private elementGraph: ElementGraph;\n\n constructor(\n rootConfig: RootConfig,\n options: {assetMap: AssetMap; elementGraph: ElementGraph}\n ) {\n this.rootConfig = rootConfig;\n this.routes = getRoutes(this.rootConfig);\n this.assetMap = options.assetMap;\n this.elementGraph = options.elementGraph;\n }\n\n async handle(req: Request, res: Response, next: NextFunction) {\n // TODO(stevenle): handle baseUrl config.\n const url = req.path.toLowerCase();\n const [route, routeParams] = this.routes.get(url);\n if (!route) {\n next();\n return;\n }\n if (route.locale) {\n routeParams.$locale = route.locale;\n }\n\n const fallbackLocales = route.isDefaultLocale\n ? getFallbackLocales(req)\n : [route.locale];\n const getPreferredLocale = (availableLocales: string[]) => {\n const lowerLocales = availableLocales.map((l) => l.toLowerCase());\n for (const fallbackLocale of fallbackLocales) {\n if (lowerLocales.includes(fallbackLocale.toLowerCase())) {\n return fallbackLocale;\n }\n }\n return req.rootConfig?.i18n?.defaultLocale || 'en';\n };\n\n const render404 = async () => {\n // Calling next() will allow the dev server or prod server handle the 404\n // page as appropriate for the env.\n next();\n };\n\n const render: HandlerRenderFn = async (\n props: any,\n options?: HandlerRenderOptions\n ) => {\n if (!route.module.default) {\n console.error(`no default component exported in route: ${route.src}`);\n render404();\n return;\n }\n const currentPath = req.path;\n const locale = options?.locale || route.locale;\n const translations = options?.translations;\n const output = await this.renderComponent(route.module.default, props, {\n currentPath,\n route,\n routeParams,\n locale,\n translations,\n });\n let html = output.html;\n if (this.rootConfig.prettyHtml) {\n html = await htmlPretty(html, this.rootConfig.prettyHtmlOptions);\n } else if (this.rootConfig.minifyHtml !== false) {\n html = await htmlMinify(html, this.rootConfig.minifyHtmlOptions);\n }\n if (req.viteServer) {\n html = await req.viteServer.transformIndexHtml(currentPath, html);\n }\n // Override the status code for 404 and 500 routes, which are defined at\n // routes/404.tsx and routes/500.tsx respectively.\n let statusCode = 200;\n if (route.src === 'routes/404.tsx') {\n statusCode = 404;\n } else if (route.src === 'routes/500.tsx') {\n statusCode = 500;\n }\n req.hooks.trigger('preRender');\n res.status(statusCode).set({'Content-Type': 'text/html'}).end(html);\n };\n\n if (route.module.handle) {\n const handlerContext: HandlerContext = {\n route: route,\n params: routeParams,\n i18nFallbackLocales: fallbackLocales,\n getPreferredLocale: getPreferredLocale,\n render: render,\n render404: render404,\n };\n req.handlerContext = handlerContext;\n return route.module.handle(req, res, next);\n }\n\n let props = {};\n if (route.module.getStaticProps) {\n const propsData = await route.module.getStaticProps({\n rootConfig: this.rootConfig,\n params: routeParams,\n });\n if (propsData.notFound) {\n return render404();\n }\n if (propsData.props) {\n props = propsData.props;\n }\n }\n await render(props);\n }\n\n private async renderComponent(\n Component: ComponentType,\n props: any,\n options: {\n currentPath: string;\n route: Route;\n routeParams: RouteParams;\n locale: string;\n translations?: Record<string, string>;\n }\n ) {\n const {currentPath, route, routeParams} = options;\n const locale = options.locale;\n const translations = {\n ...getTranslations(locale),\n ...(options.translations || {}),\n };\n const ctx: RequestContext = {\n currentPath,\n route,\n props,\n routeParams,\n locale,\n translations,\n };\n const htmlContext: HtmlContext = {\n htmlAttrs: {},\n headAttrs: {},\n headComponents: [],\n bodyAttrs: {},\n scriptDeps: [],\n };\n const vdom = (\n <REQUEST_CONTEXT.Provider value={ctx}>\n <I18N_CONTEXT.Provider value={{locale, translations}}>\n <HTML_CONTEXT.Provider value={htmlContext}>\n <Component {...props} />\n </HTML_CONTEXT.Provider>\n </I18N_CONTEXT.Provider>\n </REQUEST_CONTEXT.Provider>\n );\n const mainHtml = renderToString(vdom);\n\n const jsDeps = new Set<string>();\n const cssDeps = new Set<string>();\n\n // Walk the route's dependency tree for CSS dependencies that are added via\n // `import 'foo.scss'` or `import 'foo.module.scss'`.\n const routeAsset = await this.assetMap.get(route.src);\n if (routeAsset) {\n const routeCssDeps = await routeAsset.getCssDeps();\n routeCssDeps.forEach((dep) => cssDeps.add(dep));\n }\n\n // Parse the HTML for custom elements that are found within the project\n // and automatically inject the script deps for them.\n await this.collectElementDeps(mainHtml, jsDeps, cssDeps);\n\n // Add user defined scripts added via the `<Script>` component.\n await Promise.all(\n htmlContext.scriptDeps.map(async (scriptDep) => {\n if (!scriptDep.src) {\n return;\n }\n const scriptAsset = await this.assetMap.get(scriptDep.src.slice(1));\n if (scriptAsset) {\n jsDeps.add(scriptAsset.assetUrl);\n const scriptJsDeps = await scriptAsset.getJsDeps();\n scriptJsDeps.forEach((dep) => jsDeps.add(dep));\n }\n })\n );\n\n const styleTags = Array.from(cssDeps).map((cssUrl) => {\n return <link rel=\"stylesheet\" href={cssUrl} />;\n });\n const scriptTags = Array.from(jsDeps).map((jsUrls) => {\n return <script type=\"module\" src={jsUrls} />;\n });\n\n const html = await this.renderHtml(mainHtml, {\n htmlAttrs: htmlContext.htmlAttrs,\n headAttrs: htmlContext.headAttrs,\n bodyAttrs: htmlContext.bodyAttrs,\n headComponents: [\n ...htmlContext.headComponents,\n ...styleTags,\n ...scriptTags,\n ],\n });\n return {html};\n }\n\n /** SSG renders a route. */\n async renderRoute(\n route: Route,\n options: {routeParams: Record<string, string>}\n ): Promise<{html?: string; notFound?: boolean}> {\n const routeParams = options.routeParams;\n if (route.locale) {\n routeParams.$locale = route.locale;\n }\n const Component = route.module.default;\n if (!Component) {\n throw new Error(\n 'unable to render route. the route should have a default export that renders a jsx component.'\n );\n }\n let props = {};\n let locale = route.locale;\n let translations = undefined;\n if (route.module.getStaticProps) {\n const propsData = await route.module.getStaticProps({\n rootConfig: this.rootConfig,\n params: routeParams,\n });\n if (propsData.notFound) {\n return {notFound: true};\n }\n if (propsData.props) {\n props = propsData.props;\n }\n if (propsData.locale) {\n locale = propsData.locale;\n }\n if (propsData.translations) {\n translations = propsData.translations;\n }\n }\n const routePath = route.isDefaultLocale\n ? route.routePath\n : route.localeRoutePath;\n const currentPath = replaceParams(routePath, {\n ...routeParams,\n locale: locale,\n });\n return this.renderComponent(Component, props, {\n currentPath,\n route,\n routeParams,\n locale,\n translations,\n });\n }\n\n async getSitemap(): Promise<\n Record<string, {route: Route; params: Record<string, string>}>\n > {\n const sitemap: Record<\n string,\n {route: Route; params: Record<string, string>}\n > = {};\n await this.routes.walk(async (urlPath: string, route: Route) => {\n const routePaths = await getAllPathsForRoute(urlPath, route);\n routePaths.forEach((routePath) => {\n sitemap[routePath.urlPath] = {\n route,\n params: routePath.params,\n };\n });\n });\n return sitemap;\n }\n\n private async renderHtml(html: string, options?: RenderHtmlOptions) {\n const htmlAttrs = options?.htmlAttrs || {};\n const headAttrs = options?.headAttrs || {};\n const bodyAttrs = options?.bodyAttrs || {};\n const page = (\n <html {...htmlAttrs}>\n <head {...headAttrs}>\n <meta charSet=\"utf-8\" />\n {options?.headComponents}\n </head>\n <body {...bodyAttrs} dangerouslySetInnerHTML={{__html: html}} />\n </html>\n );\n return `<!doctype html>\\n${renderToString(page)}\\n`;\n }\n\n async render404(options?: {currentPath?: string}) {\n const currentPath = options?.currentPath || '/404';\n const [route, routeParams] = this.routes.get('/404');\n if (route && route.src === 'routes/404.tsx' && route.module.default) {\n const Component = route.module.default;\n return this.renderComponent(\n Component,\n {},\n {currentPath, route, routeParams, locale: 'en'}\n );\n }\n\n const mainHtml = renderToString(\n <ErrorPage\n code={404}\n title=\"Not found\"\n message=\"Double-check the URL entered and try again.\"\n align=\"center\"\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [\n <title>404 Not Found</title>,\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n />,\n ],\n });\n return {html};\n }\n\n async renderError(err: any, options?: {currentPath?: string}) {\n const currentPath = options?.currentPath || '/500';\n const [route, routeParams] = this.routes.get('/500');\n if (route && route.src === 'routes/500.tsx' && route.module.default) {\n const Component = route.module.default;\n return this.renderComponent(\n Component,\n {error: err},\n {currentPath, route, routeParams, locale: 'en'}\n );\n }\n\n const mainHtml = renderToString(\n <ErrorPage\n code={500}\n title=\"Something went wrong\"\n message=\"An unknown error occurred.\"\n align=\"center\"\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [\n <title>500 Error</title>,\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n />,\n ],\n });\n return {html};\n }\n\n async renderDevServer404(req: Request) {\n const sitemap = await this.getSitemap();\n const mainHtml = renderToString(\n <DevNotFoundPage req={req} sitemap={sitemap} />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [<title>404 Not found | Root.js</title>],\n });\n return {html};\n }\n\n async renderDevServer500(req: Request, error: unknown) {\n const [route, routeParams] = this.routes.get(req.path);\n const mainHtml = renderToString(\n <DevErrorPage\n req={req}\n route={route}\n routeParams={routeParams}\n error={error}\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [<title>500 Error | Root.js</title>],\n });\n return {html};\n }\n\n /**\n * Parses rendered HTML for custom element tags used on the page and\n * automatically adds the JS/CSS deps to the page.\n */\n private async collectElementDeps(\n html: string,\n jsDeps: Set<string>,\n cssDeps: Set<string>\n ): Promise<{jsDeps: Set<string>; cssDeps: Set<string>}> {\n const elementsMap = this.elementGraph.sourceFiles;\n const assetMap = this.assetMap;\n\n const tagNames = new Set<string>();\n for (const tagName of parseTagNames(html)) {\n if (tagName && tagName in elementsMap) {\n tagNames.add(tagName);\n for (const depTagName of this.elementGraph.getDeps(tagName)) {\n tagNames.add(depTagName);\n }\n }\n }\n\n await Promise.all(\n Array.from(tagNames).map(async (tagName: string) => {\n const elementModule = elementsMap[tagName];\n const asset = await assetMap.get(elementModule.relPath);\n if (!asset) {\n return;\n }\n const assetJsDeps = await asset.getJsDeps();\n assetJsDeps.forEach((dep) => jsDeps.add(dep));\n const assetCssDeps = await asset.getCssDeps();\n assetCssDeps.forEach((dep) => cssDeps.add(dep));\n })\n );\n\n return {jsDeps, cssDeps};\n }\n}\n","import {ComponentChildren} from 'preact';\n\nconst STYLES = `\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');\n\n:root {\n --font-family-text: \"Inter\", sans-serif;\n}\n\nbody {\n font-family: var(--font-family-text);\n background: #F5F5F5;\n padding: 40px 16px;\n}\n\n.root {\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.root.align-center {\n text-align: center;\n}\n\nh1.title {\n margin-top: 0;\n margin-bottom: 24px;\n}\n\np.message {\n margin-top: 0;\n margin-bottom: 0;\n}\n\n.box {\n font-size: 16px;\n line-height: 1.5;\n padding: 16px;\n border-radius: 12px;\n background: #ffffff;\n}\n\npre.box {\n white-space: pre-wrap;\n}\n\n@media (min-width: 500px) {\n body {\n padding: 40px;\n }\n\n .box {\n padding: 24px;\n }\n}\n\n@media (min-width: 1024px) {\n body {\n padding: 100px;\n }\n}\n`;\n\nexport interface ErrorPageProps {\n code: number;\n title?: string;\n message?: string;\n children?: ComponentChildren;\n align?: 'center';\n}\n\nexport function ErrorPage(props: ErrorPageProps) {\n const {code, message} = props;\n const title = props.title || code;\n return (\n <>\n <style dangerouslySetInnerHTML={{__html: STYLES}}></style>\n <div className={`root align-${props.align || 'left'}`}>\n <h1 className=\"title\">{title}</h1>\n {message && <p className=\"message\">{message}</p>}\n {props.children}\n </div>\n </>\n );\n}\n","import {Request, Route, RouteParams} from '../types';\n\nimport {ErrorPage} from './ErrorPage';\n\ninterface DevErrorPageProps {\n req: Request;\n route?: Route;\n routeParams?: RouteParams;\n error: any;\n}\n\nexport function DevErrorPage(props: DevErrorPageProps) {\n const req = props.req;\n const err = props.error;\n const route = props.route;\n const routeParams = props.routeParams;\n\n let errMsg = String(err);\n if (err && err.stack) {\n // Obfuscate some user info from the stack trace so that when people send\n // error reports and screenshots, less identifiable information is sent.\n errMsg = err.stack\n .replace(/\\(.*node_modules/g, '(node_modules')\n .replace(/at \\/.*node_modules/g, 'at node_modules');\n if (req.rootConfig?.rootDir) {\n errMsg = errMsg.replaceAll(req.rootConfig.rootDir, '<root>');\n }\n if (process.env.HOME) {\n errMsg = errMsg.replaceAll(process.env.HOME, '$HOME');\n }\n }\n return (\n <ErrorPage code={500} title=\"Something went wrong\">\n {errMsg && (\n <>\n <h2>Error</h2>\n <pre className=\"box\">\n <code>{errMsg}</code>\n </pre>\n </>\n )}\n <h2>Debug Info</h2>\n <pre className=\"box\">\n <code>{`url: ${req.originalUrl}\nroute: ${route?.src || 'null'}\nrouteParams: ${(routeParams && JSON.stringify(routeParams)) || 'null'}`}</code>\n </pre>\n </ErrorPage>\n );\n}\n","import {Request, Route} from '../types';\n\nimport {ErrorPage} from './ErrorPage';\n\ninterface DevNotFoundPageProps {\n req: Request;\n sitemap: Record<string, {route: Route; params: Record<string, string>}>;\n}\n\ninterface RoutesListMap {\n [src: string]: Array<RouteURLPath>;\n}\n\ninterface RouteURLPath {\n route: Route;\n urlPath: string;\n}\n\nexport function DevNotFoundPage(props: DevNotFoundPageProps) {\n const req = props.req;\n const routesListMap: RoutesListMap = {};\n let srcMaxLength = 0;\n Object.keys(props.sitemap).forEach((urlPath) => {\n const route = props.sitemap[urlPath].route;\n routesListMap[route.src] ??= [];\n routesListMap[route.src].push({route, urlPath});\n if (route.src.length > srcMaxLength) {\n srcMaxLength = route.src.length;\n }\n });\n const routeSrcs = Object.keys(routesListMap).sort(sortRouteFiles);\n const lines: string[] = [];\n routeSrcs.forEach((routeSrc) => {\n const routeUrls = routesListMap[routeSrc].sort(sortRouteURLs);\n routeUrls.forEach((routeUrl, i) => {\n const urlPath = routeUrl.urlPath;\n if (i === 0) {\n lines.push(`${routeSrc.padEnd(srcMaxLength, ' ')} => ${urlPath}`);\n } else {\n lines.push(`${''.padEnd(srcMaxLength, ' ')} => ${urlPath}`);\n }\n });\n });\n const routesListString = lines.join('\\n');\n // const routesListString = routesList\n // .map((route) => {\n // return `${route.urlPath.padEnd(srcMaxLength, ' ')} => ${route.src}`;\n // })\n // .join('\\n');\n return (\n <ErrorPage code={404} title=\"Not found\">\n <h2>Routes</h2>\n {Object.keys(routesListMap).length > 0 ? (\n <pre className=\"box\">\n <code>{routesListString}</code>\n </pre>\n ) : (\n <div className=\"box\">\n Add your first route at <code>/routes/index.tsx</code>\n </div>\n )}\n\n <h2>Debug Info</h2>\n <pre className=\"box\">\n <code>{`url: ${req.originalUrl}`}</code>\n </pre>\n </ErrorPage>\n );\n}\n\nfunction sortRouteFiles(a: string, b: string): number {\n if (a === 'routes/index.tsx') {\n return -1;\n }\n if (b === 'routes/index.tsx') {\n return 1;\n }\n return a.localeCompare(b);\n}\n\nfunction sortRouteURLs(a: RouteURLPath, b: RouteURLPath): number {\n if (a.route.isDefaultLocale && !b.route.isDefaultLocale) {\n return -1;\n }\n if (!a.route.isDefaultLocale && b.route.isDefaultLocale) {\n return 1;\n }\n return a.urlPath.localeCompare(b.urlPath);\n}\n","export const ACCEPT_LANG_RE =\n /((([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\\*)(;q=[0-1](\\.[0-9]+)?)?)*/g;\n\nexport interface AcceptLanguage {\n code: string;\n script?: string;\n region?: string;\n quality: number;\n}\n\nexport function parseAcceptLanguage(value: string): AcceptLanguage[] {\n const matches = String(value).match(ACCEPT_LANG_RE);\n if (!matches) {\n return [];\n }\n const results: AcceptLanguage[] = [];\n matches.forEach((m) => {\n if (!m) {\n return;\n }\n\n const parts = m.split(';');\n const ietf = parts[0].split('-');\n const hasScript = ietf.length === 3;\n\n results.push({\n code: ietf[0],\n script: hasScript ? ietf[1] : undefined,\n region: hasScript ? ietf[2] : ietf[1],\n quality: parts[1] ? parseFloat(parts[1].split('=')[1]) : 1.0,\n });\n });\n results.sort((a, b) => b.quality - a.quality);\n return results;\n}\n","/**\n * Utility functions for handling requests that mimic the Firebase Hosting i18n\n * fallback logic.\n * https://firebase.google.com/docs/hosting/i18n-rewrites\n */\n\nimport {Request} from '../core/types';\nimport {parseAcceptLanguage} from './accept-language';\n\nexport const UNKNOWN_COUNTRY = 'zz';\n\nexport function getFallbackLocales(req: Request): string[] {\n const hl = getFirstQueryParam(req, 'hl');\n const countryCode = getCountry(req);\n\n // Web crawlers should only use the default locale.\n if (isWebCrawler(req)) {\n const defaultLocale = req.rootConfig?.i18n?.defaultLocale || 'en';\n if (hl && hl !== defaultLocale) {\n return [hl, defaultLocale];\n }\n return [defaultLocale];\n }\n\n const locales = new Set<string>();\n\n // Add locales from ?hl= query parameter.\n if (hl) {\n const langCode = hl;\n locales.add(`${langCode}_${countryCode}`);\n locales.add(`${langCode}_ALL`);\n locales.add(langCode);\n }\n\n const langs = getFallbackLanguages(req);\n\n // Add `{lang}_{country}` locales.\n langs.forEach((langCode) => {\n locales.add(`${langCode}_${countryCode}`);\n });\n\n // Add ALL_{country} locale.\n locales.add(`ALL_${countryCode}`);\n\n // Add `{lang}_ALL` and `{lang}` locales.\n langs.forEach((langCode) => {\n locales.add(`${langCode}_ALL`);\n locales.add(langCode);\n });\n\n return Array.from(locales) as string[];\n}\n\nexport function getCountry(req: Request) {\n const normalize = (countryCode: string) => String(countryCode).toLowerCase();\n // Check the ?gl= query param.\n const gl = getFirstQueryParam(req, 'gl');\n if (gl) {\n return normalize(gl);\n }\n const gaeCountry =\n req.get('x-country-code') || req.get('x-appengine-country');\n if (gaeCountry) {\n return normalize(gaeCountry);\n }\n return UNKNOWN_COUNTRY;\n}\n\nfunction getFallbackLanguages(req: Request): string[] {\n const langs = new Set<string>();\n // Add languages from the Accept-Language header.\n const acceptLangHeader = req.get('accept-language') || '';\n if (acceptLangHeader) {\n parseAcceptLanguage(acceptLangHeader).forEach((lang) => {\n // For a lang like `en-US`, add both `en-US` and `en`.\n if (lang.region) {\n langs.add(`${lang.code}-${lang.region}`);\n }\n langs.add(lang.code);\n });\n }\n // Fall back to \"en\" as a last resort.\n langs.add('en');\n return Array.from(langs);\n}\n\n/**\n * Returns the first query param value in a given request.\n *\n * For example, for a URL like `/?foo=bar&foo=baz`, calling\n * `getFirstQueryParam(req, 'foo')` would return `\"bar\"`.\n */\nfunction getFirstQueryParam(req: Request, key: string): string | null {\n const val = req.query[key];\n if (val === null || val === undefined) {\n return null;\n }\n if (Array.isArray(val)) {\n if (val.length === 0) {\n return null;\n }\n return String(val[0]);\n }\n return String(val);\n}\n\nfunction isWebCrawler(req: Request): boolean {\n const userAgentHeader = req.get('User-Agent');\n if (!userAgentHeader) {\n return false;\n }\n const userAgent = userAgentHeader.toLowerCase();\n return (\n userAgent.includes('googlebot') ||\n userAgent.includes('bingbot') ||\n userAgent.includes('twitterbot')\n );\n}\n","import path from 'node:path';\n\nimport {RootConfig} from '../core/config';\nimport {Route, RouteModule} from '../core/types';\n\nimport {RouteTrie} from './route-trie';\n\nexport function getRoutes(config: RootConfig) {\n const locales = config.i18n?.locales || [];\n const i18nUrlFormat = config.i18n?.urlFormat || '/{locale}/{path}';\n const defaultLocale = config.i18n?.defaultLocale || 'en';\n\n const routes = import.meta.glob(\n ['/routes/*.ts', '/routes/**/*.ts', '/routes/*.tsx', '/routes/**/*.tsx'],\n {\n eager: true,\n }\n );\n const trie = new RouteTrie<Route>();\n Object.keys(routes).forEach((modulePath) => {\n const src = modulePath.slice(1);\n let routePath = modulePath.replace(/^\\/routes/, '');\n const parts = path.parse(routePath);\n if (parts.name.startsWith('_')) {\n return;\n }\n if (parts.name === 'index') {\n routePath = parts.dir;\n } else {\n routePath = path.join(parts.dir, parts.name);\n }\n\n const localeRoutePath = i18nUrlFormat\n .replace('{locale}', '[locale]')\n .replace('{path}', routePath.replace(/^\\/*/, ''));\n\n trie.add(routePath, {\n src,\n module: routes[modulePath] as RouteModule,\n locale: defaultLocale,\n isDefaultLocale: true,\n routePath: normalizeUrlPath(routePath),\n localeRoutePath: normalizeUrlPath(localeRoutePath),\n });\n\n // At the moment, all routes are assumed to use the site-wide i18n config.\n // TODO(stevenle): provide routes with a way to override the default\n // i18n serving behavior.\n locales.forEach((locale) => {\n const localePath = localeRoutePath.replace('[locale]', locale);\n if (localePath !== routePath) {\n trie.add(localePath, {\n src,\n module: routes[modulePath] as RouteModule,\n locale: locale,\n isDefaultLocale: false,\n routePath,\n localeRoutePath,\n });\n }\n });\n });\n return trie;\n}\n\nexport async function getAllPathsForRoute(\n urlPathFormat: string,\n route: Route\n): Promise<Array<{urlPath: string; params: Record<string, string>}>> {\n const routeModule = route.module;\n if (!routeModule.default) {\n return [];\n }\n\n const urlPaths: Array<{urlPath: string; params: Record<string, string>}> = [];\n if (routeModule.getStaticPaths) {\n const staticPaths = await routeModule.getStaticPaths();\n if (staticPaths.paths) {\n staticPaths.paths.forEach(\n (pathParams: {params: Record<string, string>}) => {\n const urlPath = replaceParams(urlPathFormat, pathParams.params || {});\n if (pathContainsPlaceholders(urlPath)) {\n console.warn(\n `path contains placeholders: ${urlPathFormat}, double check getStaticPaths() and ensure all params are returned. more info: https://rootjs.dev/guide/routes#getStaticPaths`\n );\n } else {\n urlPaths.push({\n urlPath: normalizeUrlPath(urlPath),\n params: pathParams.params || {},\n });\n }\n }\n );\n }\n } else if (pathContainsPlaceholders(urlPathFormat) && !routeModule.handle) {\n console.warn(\n `path contains placeholders: ${urlPathFormat}, did you forget to define getStaticPaths()? more info: https://rootjs.dev/guide/routes#getStaticPaths`\n );\n } else {\n urlPaths.push({urlPath: normalizeUrlPath(urlPathFormat), params: {}});\n }\n return urlPaths;\n}\n\nexport function replaceParams(\n urlPathFormat: string,\n params: Record<string, string>\n) {\n const urlPath = urlPathFormat.replaceAll(\n /\\[(\\.\\.\\.)?([\\w\\-_]*)\\]/g,\n (match: string, _wildcard: string, key: string) => {\n const val = params[key];\n if (!val) {\n throw new Error(`unreplaced param ${match} in url: ${urlPathFormat}`);\n }\n return val;\n }\n );\n return urlPath;\n}\n\nexport function normalizeUrlPath(urlPath: string) {\n if (urlPath !== '/' && urlPath.endsWith('/')) {\n urlPath = urlPath.replace(/\\/*$/g, '');\n }\n return urlPath;\n}\n\nfunction pathContainsPlaceholders(urlPath: string) {\n const segments = urlPath.split('/');\n return segments.some((segment) => {\n return segment.startsWith('[') && segment.endsWith(']');\n });\n}\n","/**\n * A trie data structure that stores routes. The trie supports `:param` and\n * `*wildcard` values.\n */\nexport class RouteTrie<T> {\n private children: Record<string, RouteTrie<T>> = {};\n private paramChildren?: {[param: string]: ParamChild<T>};\n private wildcardChild?: WildcardChild<T>;\n private route?: T;\n\n /**\n * Adds a route to the trie.\n */\n add(path: string, route: T) {\n path = this.normalizePath(path);\n\n // If the end was reached, save the value to the node.\n if (path === '') {\n this.route = route;\n return;\n }\n\n const [head, tail] = this.splitPath(path);\n if (head.startsWith('[...') && head.endsWith(']')) {\n const paramName = head.slice(4, -1);\n this.wildcardChild = new WildcardChild(paramName, route);\n return;\n }\n\n let nextNode: RouteTrie<T>;\n if (head.startsWith('[') && head.endsWith(']')) {\n if (!this.paramChildren) {\n this.paramChildren = {};\n }\n const paramName = head.slice(1, -1);\n if (!this.paramChildren[paramName]) {\n this.paramChildren[paramName] = new ParamChild(paramName);\n }\n nextNode = this.paramChildren[paramName].trie;\n } else {\n nextNode = this.children[head];\n if (!nextNode) {\n nextNode = new RouteTrie();\n this.children[head] = nextNode;\n }\n }\n nextNode.add(tail, route);\n }\n\n /**\n * Returns a route mapped to the given path and any parameter values from the\n * URL.\n */\n get(path: string): [T | undefined, Record<string, string>] {\n const params = {};\n const route = this.getRoute(path, params);\n return [route, params];\n }\n\n /**\n * Walks the route trie and calls a callback function for each route.\n */\n walk(cb: (urlPath: string, route: T) => Promise<void> | void): Promise<void> {\n const promises: Array<Promise<void>> = [];\n const addPromise = (promise: Promise<void> | void) => {\n if (promise) {\n promises.push(promise);\n }\n };\n if (this.route) {\n addPromise(cb('/', this.route));\n }\n if (this.paramChildren) {\n Object.values(this.paramChildren).forEach((paramChild) => {\n const param = `[${paramChild.name}]`;\n paramChild.trie.walk((childPath: string, route: T) => {\n const paramUrlPath = `/${param}${childPath}`;\n addPromise(cb(paramUrlPath, route));\n });\n });\n }\n if (this.wildcardChild) {\n const wildcardUrlPath = `/[...${this.wildcardChild.name}]`;\n addPromise(cb(wildcardUrlPath, this.wildcardChild.route));\n }\n for (const subpath of Object.keys(this.children)) {\n const childTrie = this.children[subpath];\n childTrie.walk((childPath: string, childRoute: T) => {\n addPromise(cb(`/${subpath}${childPath}`, childRoute));\n });\n }\n return Promise.all(promises).then(() => {});\n }\n\n /**\n * Removes all routes from the trie.\n */\n clear() {\n this.children = {};\n this.paramChildren = undefined;\n this.wildcardChild = undefined;\n this.route = undefined;\n }\n\n private getRoute(\n urlPath: string,\n params: Record<string, string>\n ): T | undefined {\n urlPath = this.normalizePath(urlPath);\n if (urlPath === '') {\n return this.route;\n }\n\n const [head, tail] = this.splitPath(urlPath);\n\n const child = this.children[head];\n if (child) {\n const route = child.getRoute(tail, params);\n if (route) {\n return route;\n }\n }\n\n if (this.paramChildren) {\n for (const paramChild of Object.values(this.paramChildren)) {\n const route = paramChild.trie.getRoute(tail, params);\n if (route) {\n params[paramChild.name] = head;\n return route;\n }\n }\n }\n\n if (this.wildcardChild) {\n params[this.wildcardChild.name] = urlPath;\n return this.wildcardChild.route;\n }\n\n return undefined;\n }\n\n /**\n * Normalizes a path for inclusion into the route trie.\n */\n private normalizePath(path: string) {\n // Remove leading slashes.\n return path.replace(/^\\/+/g, '');\n }\n\n /**\n * Splits the parent directory from its children, e.g.:\n *\n * splitPath(\"foo/bar/baz\") -> [\"foo\", \"bar/baz\"]\n */\n private splitPath(path: string): [string, string] {\n const i = path.indexOf('/');\n if (i === -1) {\n return [path, ''];\n }\n return [path.slice(0, i), path.slice(i + 1)];\n }\n}\n\n/**\n * A node in the RouteTrie for a :param child.\n */\nclass ParamChild<T> {\n readonly name: string;\n readonly trie: RouteTrie<T> = new RouteTrie();\n\n constructor(name: string) {\n this.name = name;\n }\n}\n\n/**\n * A node in the RouteTrie for a *wildcard child.\n */\nclass WildcardChild<T> {\n readonly name: string;\n readonly route: T;\n\n constructor(name: string, route: T) {\n this.name = name;\n this.route = route;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AACA,OAAO,oBAAoB;;;AC0EvB,mBACE,KACA,YAFF;AAzEJ,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqER,SAAS,UAAU,OAAuB;AAC/C,QAAM,EAAC,MAAM,QAAO,IAAI;AACxB,QAAM,QAAQ,MAAM,SAAS;AAC7B,SACE,iCACE;AAAA,wBAAC,WAAM,yBAAyB,EAAC,QAAQ,OAAM,GAAG;AAAA,IAClD,qBAAC,SAAI,WAAW,cAAc,MAAM,SAAS,MAAM,IACjD;AAAA,0BAAC,QAAG,WAAU,SAAS,iBAAM;AAAA,MAC5B,WAAW,oBAAC,OAAE,WAAU,WAAW,mBAAQ;AAAA,MAC3C,MAAM;AAAA,OACT;AAAA,KACF;AAEJ;;;AClDQ,qBAAAA,WACE,OAAAC,MADF,QAAAC,aAAA;AAvBD,SAAS,aAAa,OAA0B;AAXvD;AAYE,QAAM,MAAM,MAAM;AAClB,QAAM,MAAM,MAAM;AAClB,QAAM,QAAQ,MAAM;AACpB,QAAM,cAAc,MAAM;AAE1B,MAAI,SAAS,OAAO,GAAG;AACvB,MAAI,OAAO,IAAI,OAAO;AAGpB,aAAS,IAAI,MACV,QAAQ,qBAAqB,eAAe,EAC5C,QAAQ,wBAAwB,iBAAiB;AACpD,SAAI,SAAI,eAAJ,mBAAgB,SAAS;AAC3B,eAAS,OAAO,WAAW,IAAI,WAAW,SAAS,QAAQ;AAAA,IAC7D;AACA,QAAI,QAAQ,IAAI,MAAM;AACpB,eAAS,OAAO,WAAW,QAAQ,IAAI,MAAM,OAAO;AAAA,IACtD;AAAA,EACF;AACA,SACE,gBAAAA,MAAC,aAAU,MAAM,KAAK,OAAM,wBACzB;AAAA,cACC,gBAAAA,MAAAF,WAAA,EACE;AAAA,sBAAAC,KAAC,QAAG,mBAAK;AAAA,MACT,gBAAAA,KAAC,SAAI,WAAU,OACb,0BAAAA,KAAC,UAAM,kBAAO,GAChB;AAAA,OACF;AAAA,IAEF,gBAAAA,KAAC,QAAG,wBAAU;AAAA,IACd,gBAAAA,KAAC,SAAI,WAAU,OACb,0BAAAA,KAAC,UAAM,kBAAQ,IAAI,WAAW;AAAA,UAC7B,+BAAO,QAAO,MAAM;AAAA,eACb,eAAe,KAAK,UAAU,WAAW,KAAM,MAAM,IAAG,GAClE;AAAA,KACF;AAEJ;;;ACEM,gBAAAE,MAME,QAAAC,aANF;AAjCC,SAAS,gBAAgB,OAA6B;AAC3D,QAAM,MAAM,MAAM;AAClB,QAAM,gBAA+B,CAAC;AACtC,MAAI,eAAe;AACnB,SAAO,KAAK,MAAM,OAAO,EAAE,QAAQ,CAAC,YAAY;AAC9C,UAAM,QAAQ,MAAM,QAAQ,OAAO,EAAE;AACrC,kBAAc,MAAM,GAAG,MAAM,CAAC;AAC9B,kBAAc,MAAM,GAAG,EAAE,KAAK,EAAC,OAAO,QAAO,CAAC;AAC9C,QAAI,MAAM,IAAI,SAAS,cAAc;AACnC,qBAAe,MAAM,IAAI;AAAA,IAC3B;AAAA,EACF,CAAC;AACD,QAAM,YAAY,OAAO,KAAK,aAAa,EAAE,KAAK,cAAc;AAChE,QAAM,QAAkB,CAAC;AACzB,YAAU,QAAQ,CAAC,aAAa;AAC9B,UAAM,YAAY,cAAc,QAAQ,EAAE,KAAK,aAAa;AAC5D,cAAU,QAAQ,CAAC,UAAU,MAAM;AACjC,YAAM,UAAU,SAAS;AACzB,UAAI,MAAM,GAAG;AACX,cAAM,KAAK,GAAG,SAAS,OAAO,cAAc,GAAG,CAAC,SAAS,OAAO,EAAE;AAAA,MACpE,OAAO;AACL,cAAM,KAAK,GAAG,GAAG,OAAO,cAAc,GAAG,CAAC,SAAS,OAAO,EAAE;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,QAAM,mBAAmB,MAAM,KAAK,IAAI;AAMxC,SACE,gBAAAA,MAAC,aAAU,MAAM,KAAK,OAAM,aAC1B;AAAA,oBAAAD,KAAC,QAAG,oBAAM;AAAA,IACT,OAAO,KAAK,aAAa,EAAE,SAAS,IACnC,gBAAAA,KAAC,SAAI,WAAU,OACb,0BAAAA,KAAC,UAAM,4BAAiB,GAC1B,IAEA,gBAAAC,MAAC,SAAI,WAAU,OAAM;AAAA;AAAA,MACK,gBAAAD,KAAC,UAAK,+BAAiB;AAAA,OACjD;AAAA,IAGF,gBAAAA,KAAC,QAAG,wBAAU;AAAA,IACd,gBAAAA,KAAC,SAAI,WAAU,OACb,0BAAAA,KAAC,UAAM,kBAAQ,IAAI,WAAW,IAAG,GACnC;AAAA,KACF;AAEJ;AAEA,SAAS,eAAe,GAAW,GAAmB;AACpD,MAAI,MAAM,oBAAoB;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,oBAAoB;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,EAAE,cAAc,CAAC;AAC1B;AAEA,SAAS,cAAc,GAAiB,GAAyB;AAC/D,MAAI,EAAE,MAAM,mBAAmB,CAAC,EAAE,MAAM,iBAAiB;AACvD,WAAO;AAAA,EACT;AACA,MAAI,CAAC,EAAE,MAAM,mBAAmB,EAAE,MAAM,iBAAiB;AACvD,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,cAAc,EAAE,OAAO;AAC1C;;;ACxFO,IAAM,iBACX;AASK,SAAS,oBAAoB,OAAiC;AACnE,QAAM,UAAU,OAAO,KAAK,EAAE,MAAM,cAAc;AAClD,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC;AAAA,EACV;AACA,QAAM,UAA4B,CAAC;AACnC,UAAQ,QAAQ,CAAC,MAAM;AACrB,QAAI,CAAC,GAAG;AACN;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,MAAM,GAAG;AACzB,UAAM,OAAO,MAAM,CAAC,EAAE,MAAM,GAAG;AAC/B,UAAM,YAAY,KAAK,WAAW;AAElC,YAAQ,KAAK;AAAA,MACX,MAAM,KAAK,CAAC;AAAA,MACZ,QAAQ,YAAY,KAAK,CAAC,IAAI;AAAA,MAC9B,QAAQ,YAAY,KAAK,CAAC,IAAI,KAAK,CAAC;AAAA,MACpC,SAAS,MAAM,CAAC,IAAI,WAAW,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,IAAI;AAAA,IAC3D,CAAC;AAAA,EACH,CAAC;AACD,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAC5C,SAAO;AACT;;;ACzBO,IAAM,kBAAkB;AAExB,SAAS,mBAAmB,KAAwB;AAX3D;AAYE,QAAM,KAAK,mBAAmB,KAAK,IAAI;AACvC,QAAM,cAAc,WAAW,GAAG;AAGlC,MAAI,aAAa,GAAG,GAAG;AACrB,UAAM,kBAAgB,eAAI,eAAJ,mBAAgB,SAAhB,mBAAsB,kBAAiB;AAC7D,QAAI,MAAM,OAAO,eAAe;AAC9B,aAAO,CAAC,IAAI,aAAa;AAAA,IAC3B;AACA,WAAO,CAAC,aAAa;AAAA,EACvB;AAEA,QAAM,UAAU,oBAAI,IAAY;AAGhC,MAAI,IAAI;AACN,UAAM,WAAW;AACjB,YAAQ,IAAI,GAAG,QAAQ,IAAI,WAAW,EAAE;AACxC,YAAQ,IAAI,GAAG,QAAQ,MAAM;AAC7B,YAAQ,IAAI,QAAQ;AAAA,EACtB;AAEA,QAAM,QAAQ,qBAAqB,GAAG;AAGtC,QAAM,QAAQ,CAAC,aAAa;AAC1B,YAAQ,IAAI,GAAG,QAAQ,IAAI,WAAW,EAAE;AAAA,EAC1C,CAAC;AAGD,UAAQ,IAAI,OAAO,WAAW,EAAE;AAGhC,QAAM,QAAQ,CAAC,aAAa;AAC1B,YAAQ,IAAI,GAAG,QAAQ,MAAM;AAC7B,YAAQ,IAAI,QAAQ;AAAA,EACtB,CAAC;AAED,SAAO,MAAM,KAAK,OAAO;AAC3B;AAEO,SAAS,WAAW,KAAc;AACvC,QAAM,YAAY,CAAC,gBAAwB,OAAO,WAAW,EAAE,YAAY;AAE3E,QAAM,KAAK,mBAAmB,KAAK,IAAI;AACvC,MAAI,IAAI;AACN,WAAO,UAAU,EAAE;AAAA,EACrB;AACA,QAAM,aACJ,IAAI,IAAI,gBAAgB,KAAK,IAAI,IAAI,qBAAqB;AAC5D,MAAI,YAAY;AACd,WAAO,UAAU,UAAU;AAAA,EAC7B;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAwB;AACpD,QAAM,QAAQ,oBAAI,IAAY;AAE9B,QAAM,mBAAmB,IAAI,IAAI,iBAAiB,KAAK;AACvD,MAAI,kBAAkB;AACpB,wBAAoB,gBAAgB,EAAE,QAAQ,CAAC,SAAS;AAEtD,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,EAAE;AAAA,MACzC;AACA,YAAM,IAAI,KAAK,IAAI;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,QAAM,IAAI,IAAI;AACd,SAAO,MAAM,KAAK,KAAK;AACzB;AAQA,SAAS,mBAAmB,KAAc,KAA4B;AACpE,QAAM,MAAM,IAAI,MAAM,GAAG;AACzB,MAAI,QAAQ,QAAQ,QAAQ,QAAW;AACrC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,QAAI,IAAI,WAAW,GAAG;AACpB,aAAO;AAAA,IACT;AACA,WAAO,OAAO,IAAI,CAAC,CAAC;AAAA,EACtB;AACA,SAAO,OAAO,GAAG;AACnB;AAEA,SAAS,aAAa,KAAuB;AAC3C,QAAM,kBAAkB,IAAI,IAAI,YAAY;AAC5C,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,gBAAgB,YAAY;AAC9C,SACE,UAAU,SAAS,WAAW,KAC9B,UAAU,SAAS,SAAS,KAC5B,UAAU,SAAS,YAAY;AAEnC;;;ACrHA,OAAO,UAAU;;;ACIV,IAAM,YAAN,MAAM,WAAa;AAAA,EAAnB;AACL,SAAQ,WAAyC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlD,IAAIE,OAAc,OAAU;AAC1B,IAAAA,QAAO,KAAK,cAAcA,KAAI;AAG9B,QAAIA,UAAS,IAAI;AACf,WAAK,QAAQ;AACb;AAAA,IACF;AAEA,UAAM,CAAC,MAAM,IAAI,IAAI,KAAK,UAAUA,KAAI;AACxC,QAAI,KAAK,WAAW,MAAM,KAAK,KAAK,SAAS,GAAG,GAAG;AACjD,YAAM,YAAY,KAAK,MAAM,GAAG,EAAE;AAClC,WAAK,gBAAgB,IAAI,cAAc,WAAW,KAAK;AACvD;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAC9C,UAAI,CAAC,KAAK,eAAe;AACvB,aAAK,gBAAgB,CAAC;AAAA,MACxB;AACA,YAAM,YAAY,KAAK,MAAM,GAAG,EAAE;AAClC,UAAI,CAAC,KAAK,cAAc,SAAS,GAAG;AAClC,aAAK,cAAc,SAAS,IAAI,IAAI,WAAW,SAAS;AAAA,MAC1D;AACA,iBAAW,KAAK,cAAc,SAAS,EAAE;AAAA,IAC3C,OAAO;AACL,iBAAW,KAAK,SAAS,IAAI;AAC7B,UAAI,CAAC,UAAU;AACb,mBAAW,IAAI,WAAU;AACzB,aAAK,SAAS,IAAI,IAAI;AAAA,MACxB;AAAA,IACF;AACA,aAAS,IAAI,MAAM,KAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAIA,OAAuD;AACzD,UAAM,SAAS,CAAC;AAChB,UAAM,QAAQ,KAAK,SAASA,OAAM,MAAM;AACxC,WAAO,CAAC,OAAO,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,IAAwE;AAC3E,UAAM,WAAiC,CAAC;AACxC,UAAM,aAAa,CAAC,YAAkC;AACpD,UAAI,SAAS;AACX,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AACd,iBAAW,GAAG,KAAK,KAAK,KAAK,CAAC;AAAA,IAChC;AACA,QAAI,KAAK,eAAe;AACtB,aAAO,OAAO,KAAK,aAAa,EAAE,QAAQ,CAAC,eAAe;AACxD,cAAM,QAAQ,IAAI,WAAW,IAAI;AACjC,mBAAW,KAAK,KAAK,CAAC,WAAmB,UAAa;AACpD,gBAAM,eAAe,IAAI,KAAK,GAAG,SAAS;AAC1C,qBAAW,GAAG,cAAc,KAAK,CAAC;AAAA,QACpC,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AACA,QAAI,KAAK,eAAe;AACtB,YAAM,kBAAkB,QAAQ,KAAK,cAAc,IAAI;AACvD,iBAAW,GAAG,iBAAiB,KAAK,cAAc,KAAK,CAAC;AAAA,IAC1D;AACA,eAAW,WAAW,OAAO,KAAK,KAAK,QAAQ,GAAG;AAChD,YAAM,YAAY,KAAK,SAAS,OAAO;AACvC,gBAAU,KAAK,CAAC,WAAmB,eAAkB;AACnD,mBAAW,GAAG,IAAI,OAAO,GAAG,SAAS,IAAI,UAAU,CAAC;AAAA,MACtD,CAAC;AAAA,IACH;AACA,WAAO,QAAQ,IAAI,QAAQ,EAAE,KAAK,MAAM;AAAA,IAAC,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,WAAW,CAAC;AACjB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,SACN,SACA,QACe;AACf,cAAU,KAAK,cAAc,OAAO;AACpC,QAAI,YAAY,IAAI;AAClB,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,CAAC,MAAM,IAAI,IAAI,KAAK,UAAU,OAAO;AAE3C,UAAM,QAAQ,KAAK,SAAS,IAAI;AAChC,QAAI,OAAO;AACT,YAAM,QAAQ,MAAM,SAAS,MAAM,MAAM;AACzC,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,iBAAW,cAAc,OAAO,OAAO,KAAK,aAAa,GAAG;AAC1D,cAAM,QAAQ,WAAW,KAAK,SAAS,MAAM,MAAM;AACnD,YAAI,OAAO;AACT,iBAAO,WAAW,IAAI,IAAI;AAC1B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,aAAO,KAAK,cAAc,IAAI,IAAI;AAClC,aAAO,KAAK,cAAc;AAAA,IAC5B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAcA,OAAc;AAElC,WAAOA,MAAK,QAAQ,SAAS,EAAE;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,UAAUA,OAAgC;AAChD,UAAM,IAAIA,MAAK,QAAQ,GAAG;AAC1B,QAAI,MAAM,IAAI;AACZ,aAAO,CAACA,OAAM,EAAE;AAAA,IAClB;AACA,WAAO,CAACA,MAAK,MAAM,GAAG,CAAC,GAAGA,MAAK,MAAM,IAAI,CAAC,CAAC;AAAA,EAC7C;AACF;AAKA,IAAM,aAAN,MAAoB;AAAA,EAIlB,YAAY,MAAc;AAF1B,SAAS,OAAqB,IAAI,UAAU;AAG1C,SAAK,OAAO;AAAA,EACd;AACF;AAKA,IAAM,gBAAN,MAAuB;AAAA,EAIrB,YAAY,MAAc,OAAU;AAClC,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;;;ADnLO,SAAS,UAAU,QAAoB;AAP9C;AAQE,QAAM,YAAU,YAAO,SAAP,mBAAa,YAAW,CAAC;AACzC,QAAM,kBAAgB,YAAO,SAAP,mBAAa,cAAa;AAChD,QAAM,kBAAgB,YAAO,SAAP,mBAAa,kBAAiB;AAEpD,QAAM,SAAS,YAAY;AAAA,IACzB,CAAC,gBAAgB,mBAAmB,iBAAiB,kBAAkB;AAAA,IACvE;AAAA,MACE,OAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,OAAO,IAAI,UAAiB;AAClC,SAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,eAAe;AAC1C,UAAM,MAAM,WAAW,MAAM,CAAC;AAC9B,QAAI,YAAY,WAAW,QAAQ,aAAa,EAAE;AAClD,UAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,QAAI,MAAM,KAAK,WAAW,GAAG,GAAG;AAC9B;AAAA,IACF;AACA,QAAI,MAAM,SAAS,SAAS;AAC1B,kBAAY,MAAM;AAAA,IACpB,OAAO;AACL,kBAAY,KAAK,KAAK,MAAM,KAAK,MAAM,IAAI;AAAA,IAC7C;AAEA,UAAM,kBAAkB,cACrB,QAAQ,YAAY,UAAU,EAC9B,QAAQ,UAAU,UAAU,QAAQ,QAAQ,EAAE,CAAC;AAElD,SAAK,IAAI,WAAW;AAAA,MAClB;AAAA,MACA,QAAQ,OAAO,UAAU;AAAA,MACzB,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,WAAW,iBAAiB,SAAS;AAAA,MACrC,iBAAiB,iBAAiB,eAAe;AAAA,IACnD,CAAC;AAKD,YAAQ,QAAQ,CAAC,WAAW;AAC1B,YAAM,aAAa,gBAAgB,QAAQ,YAAY,MAAM;AAC7D,UAAI,eAAe,WAAW;AAC5B,aAAK,IAAI,YAAY;AAAA,UACnB;AAAA,UACA,QAAQ,OAAO,UAAU;AAAA,UACzB;AAAA,UACA,iBAAiB;AAAA,UACjB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AACT;AAEA,eAAsB,oBACpB,eACA,OACmE;AACnE,QAAM,cAAc,MAAM;AAC1B,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAqE,CAAC;AAC5E,MAAI,YAAY,gBAAgB;AAC9B,UAAM,cAAc,MAAM,YAAY,eAAe;AACrD,QAAI,YAAY,OAAO;AACrB,kBAAY,MAAM;AAAA,QAChB,CAAC,eAAiD;AAChD,gBAAM,UAAU,cAAc,eAAe,WAAW,UAAU,CAAC,CAAC;AACpE,cAAI,yBAAyB,OAAO,GAAG;AACrC,oBAAQ;AAAA,cACN,+BAA+B,aAAa;AAAA,YAC9C;AAAA,UACF,OAAO;AACL,qBAAS,KAAK;AAAA,cACZ,SAAS,iBAAiB,OAAO;AAAA,cACjC,QAAQ,WAAW,UAAU,CAAC;AAAA,YAChC,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,yBAAyB,aAAa,KAAK,CAAC,YAAY,QAAQ;AACzE,YAAQ;AAAA,MACN,+BAA+B,aAAa;AAAA,IAC9C;AAAA,EACF,OAAO;AACL,aAAS,KAAK,EAAC,SAAS,iBAAiB,aAAa,GAAG,QAAQ,CAAC,EAAC,CAAC;AAAA,EACtE;AACA,SAAO;AACT;AAEO,SAAS,cACd,eACA,QACA;AACA,QAAM,UAAU,cAAc;AAAA,IAC5B;AAAA,IACA,CAAC,OAAe,WAAmB,QAAgB;AACjD,YAAM,MAAM,OAAO,GAAG;AACtB,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,oBAAoB,KAAK,YAAY,aAAa,EAAE;AAAA,MACtE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,SAAiB;AAChD,MAAI,YAAY,OAAO,QAAQ,SAAS,GAAG,GAAG;AAC5C,cAAU,QAAQ,QAAQ,SAAS,EAAE;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,SAAiB;AACjD,QAAM,WAAW,QAAQ,MAAM,GAAG;AAClC,SAAO,SAAS,KAAK,CAAC,YAAY;AAChC,WAAO,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG;AAAA,EACxD,CAAC;AACH;;;AN4DY,gBAAAC,MAsIJ,QAAAC,aAtII;AAxJL,IAAM,WAAN,MAAe;AAAA,EAMpB,YACE,YACA,SACA;AACA,SAAK,aAAa;AAClB,SAAK,SAAS,UAAU,KAAK,UAAU;AACvC,SAAK,WAAW,QAAQ;AACxB,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEA,MAAM,OAAO,KAAc,KAAe,MAAoB;AAE5D,UAAM,MAAM,IAAI,KAAK,YAAY;AACjC,UAAM,CAAC,OAAO,WAAW,IAAI,KAAK,OAAO,IAAI,GAAG;AAChD,QAAI,CAAC,OAAO;AACV,WAAK;AACL;AAAA,IACF;AACA,QAAI,MAAM,QAAQ;AAChB,kBAAY,UAAU,MAAM;AAAA,IAC9B;AAEA,UAAM,kBAAkB,MAAM,kBAC1B,mBAAmB,GAAG,IACtB,CAAC,MAAM,MAAM;AACjB,UAAM,qBAAqB,CAAC,qBAA+B;AAxE/D;AAyEM,YAAM,eAAe,iBAAiB,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAChE,iBAAW,kBAAkB,iBAAiB;AAC5C,YAAI,aAAa,SAAS,eAAe,YAAY,CAAC,GAAG;AACvD,iBAAO;AAAA,QACT;AAAA,MACF;AACA,eAAO,eAAI,eAAJ,mBAAgB,SAAhB,mBAAsB,kBAAiB;AAAA,IAChD;AAEA,UAAM,YAAY,YAAY;AAG5B,WAAK;AAAA,IACP;AAEA,UAAM,SAA0B,OAC9BC,QACA,YACG;AACH,UAAI,CAAC,MAAM,OAAO,SAAS;AACzB,gBAAQ,MAAM,2CAA2C,MAAM,GAAG,EAAE;AACpE,kBAAU;AACV;AAAA,MACF;AACA,YAAM,cAAc,IAAI;AACxB,YAAM,UAAS,mCAAS,WAAU,MAAM;AACxC,YAAM,eAAe,mCAAS;AAC9B,YAAM,SAAS,MAAM,KAAK,gBAAgB,MAAM,OAAO,SAASA,QAAO;AAAA,QACrE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,UAAI,OAAO,OAAO;AAClB,UAAI,KAAK,WAAW,YAAY;AAC9B,eAAO,MAAM,WAAW,MAAM,KAAK,WAAW,iBAAiB;AAAA,MACjE,WAAW,KAAK,WAAW,eAAe,OAAO;AAC/C,eAAO,MAAM,WAAW,MAAM,KAAK,WAAW,iBAAiB;AAAA,MACjE;AACA,UAAI,IAAI,YAAY;AAClB,eAAO,MAAM,IAAI,WAAW,mBAAmB,aAAa,IAAI;AAAA,MAClE;AAGA,UAAI,aAAa;AACjB,UAAI,MAAM,QAAQ,kBAAkB;AAClC,qBAAa;AAAA,MACf,WAAW,MAAM,QAAQ,kBAAkB;AACzC,qBAAa;AAAA,MACf;AACA,UAAI,MAAM,QAAQ,WAAW;AAC7B,UAAI,OAAO,UAAU,EAAE,IAAI,EAAC,gBAAgB,YAAW,CAAC,EAAE,IAAI,IAAI;AAAA,IACpE;AAEA,QAAI,MAAM,OAAO,QAAQ;AACvB,YAAM,iBAAiC;AAAA,QACrC;AAAA,QACA,QAAQ;AAAA,QACR,qBAAqB;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,iBAAiB;AACrB,aAAO,MAAM,OAAO,OAAO,KAAK,KAAK,IAAI;AAAA,IAC3C;AAEA,QAAI,QAAQ,CAAC;AACb,QAAI,MAAM,OAAO,gBAAgB;AAC/B,YAAM,YAAY,MAAM,MAAM,OAAO,eAAe;AAAA,QAClD,YAAY,KAAK;AAAA,QACjB,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,UAAU,UAAU;AACtB,eAAO,UAAU;AAAA,MACnB;AACA,UAAI,UAAU,OAAO;AACnB,gBAAQ,UAAU;AAAA,MACpB;AAAA,IACF;AACA,UAAM,OAAO,KAAK;AAAA,EACpB;AAAA,EAEA,MAAc,gBACZ,WACA,OACA,SAOA;AACA,UAAM,EAAC,aAAa,OAAO,YAAW,IAAI;AAC1C,UAAM,SAAS,QAAQ;AACvB,UAAM,eAAe;AAAA,MACnB,GAAG,gBAAgB,MAAM;AAAA,MACzB,GAAI,QAAQ,gBAAgB,CAAC;AAAA,IAC/B;AACA,UAAM,MAAsB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,cAA2B;AAAA,MAC/B,WAAW,CAAC;AAAA,MACZ,WAAW,CAAC;AAAA,MACZ,gBAAgB,CAAC;AAAA,MACjB,WAAW,CAAC;AAAA,MACZ,YAAY,CAAC;AAAA,IACf;AACA,UAAM,OACJ,gBAAAF,KAAC,gBAAgB,UAAhB,EAAyB,OAAO,KAC/B,0BAAAA,KAAC,aAAa,UAAb,EAAsB,OAAO,EAAC,QAAQ,aAAY,GACjD,0BAAAA,KAAC,aAAa,UAAb,EAAsB,OAAO,aAC5B,0BAAAA,KAAC,aAAW,GAAG,OAAO,GACxB,GACF,GACF;AAEF,UAAM,WAAW,eAAe,IAAI;AAEpC,UAAM,SAAS,oBAAI,IAAY;AAC/B,UAAM,UAAU,oBAAI,IAAY;AAIhC,UAAM,aAAa,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG;AACpD,QAAI,YAAY;AACd,YAAM,eAAe,MAAM,WAAW,WAAW;AACjD,mBAAa,QAAQ,CAAC,QAAQ,QAAQ,IAAI,GAAG,CAAC;AAAA,IAChD;AAIA,UAAM,KAAK,mBAAmB,UAAU,QAAQ,OAAO;AAGvD,UAAM,QAAQ;AAAA,MACZ,YAAY,WAAW,IAAI,OAAO,cAAc;AAC9C,YAAI,CAAC,UAAU,KAAK;AAClB;AAAA,QACF;AACA,cAAM,cAAc,MAAM,KAAK,SAAS,IAAI,UAAU,IAAI,MAAM,CAAC,CAAC;AAClE,YAAI,aAAa;AACf,iBAAO,IAAI,YAAY,QAAQ;AAC/B,gBAAM,eAAe,MAAM,YAAY,UAAU;AACjD,uBAAa,QAAQ,CAAC,QAAQ,OAAO,IAAI,GAAG,CAAC;AAAA,QAC/C;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,YAAY,MAAM,KAAK,OAAO,EAAE,IAAI,CAAC,WAAW;AACpD,aAAO,gBAAAA,KAAC,UAAK,KAAI,cAAa,MAAM,QAAQ;AAAA,IAC9C,CAAC;AACD,UAAM,aAAa,MAAM,KAAK,MAAM,EAAE,IAAI,CAAC,WAAW;AACpD,aAAO,gBAAAA,KAAC,YAAO,MAAK,UAAS,KAAK,QAAQ;AAAA,IAC5C,CAAC;AAED,UAAM,OAAO,MAAM,KAAK,WAAW,UAAU;AAAA,MAC3C,WAAW,YAAY;AAAA,MACvB,WAAW,YAAY;AAAA,MACvB,WAAW,YAAY;AAAA,MACvB,gBAAgB;AAAA,QACd,GAAG,YAAY;AAAA,QACf,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF,CAAC;AACD,WAAO,EAAC,KAAI;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,YACJ,OACA,SAC8C;AAC9C,UAAM,cAAc,QAAQ;AAC5B,QAAI,MAAM,QAAQ;AAChB,kBAAY,UAAU,MAAM;AAAA,IAC9B;AACA,UAAM,YAAY,MAAM,OAAO;AAC/B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,QAAQ,CAAC;AACb,QAAI,SAAS,MAAM;AACnB,QAAI,eAAe;AACnB,QAAI,MAAM,OAAO,gBAAgB;AAC/B,YAAM,YAAY,MAAM,MAAM,OAAO,eAAe;AAAA,QAClD,YAAY,KAAK;AAAA,QACjB,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,UAAU,UAAU;AACtB,eAAO,EAAC,UAAU,KAAI;AAAA,MACxB;AACA,UAAI,UAAU,OAAO;AACnB,gBAAQ,UAAU;AAAA,MACpB;AACA,UAAI,UAAU,QAAQ;AACpB,iBAAS,UAAU;AAAA,MACrB;AACA,UAAI,UAAU,cAAc;AAC1B,uBAAe,UAAU;AAAA,MAC3B;AAAA,IACF;AACA,UAAM,YAAY,MAAM,kBACpB,MAAM,YACN,MAAM;AACV,UAAM,cAAc,cAAc,WAAW;AAAA,MAC3C,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AACD,WAAO,KAAK,gBAAgB,WAAW,OAAO;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAEJ;AACA,UAAM,UAGF,CAAC;AACL,UAAM,KAAK,OAAO,KAAK,OAAO,SAAiB,UAAiB;AAC9D,YAAM,aAAa,MAAM,oBAAoB,SAAS,KAAK;AAC3D,iBAAW,QAAQ,CAAC,cAAc;AAChC,gBAAQ,UAAU,OAAO,IAAI;AAAA,UAC3B;AAAA,UACA,QAAQ,UAAU;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,WAAW,MAAc,SAA6B;AAClE,UAAM,aAAY,mCAAS,cAAa,CAAC;AACzC,UAAM,aAAY,mCAAS,cAAa,CAAC;AACzC,UAAM,aAAY,mCAAS,cAAa,CAAC;AACzC,UAAM,OACJ,gBAAAC,MAAC,UAAM,GAAG,WACR;AAAA,sBAAAA,MAAC,UAAM,GAAG,WACR;AAAA,wBAAAD,KAAC,UAAK,SAAQ,SAAQ;AAAA,QACrB,mCAAS;AAAA,SACZ;AAAA,MACA,gBAAAA,KAAC,UAAM,GAAG,WAAW,yBAAyB,EAAC,QAAQ,KAAI,GAAG;AAAA,OAChE;AAEF,WAAO;AAAA,EAAoB,eAAe,IAAI,CAAC;AAAA;AAAA,EACjD;AAAA,EAEA,MAAM,UAAU,SAAkC;AAChD,UAAM,eAAc,mCAAS,gBAAe;AAC5C,UAAM,CAAC,OAAO,WAAW,IAAI,KAAK,OAAO,IAAI,MAAM;AACnD,QAAI,SAAS,MAAM,QAAQ,oBAAoB,MAAM,OAAO,SAAS;AACnE,YAAM,YAAY,MAAM,OAAO;AAC/B,aAAO,KAAK;AAAA,QACV;AAAA,QACA,CAAC;AAAA,QACD,EAAC,aAAa,OAAO,aAAa,QAAQ,KAAI;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,OAAM;AAAA,UACN,SAAQ;AAAA,UACR,OAAM;AAAA;AAAA,MACR;AAAA,IACF;AACA,UAAM,OAAO,MAAM,KAAK,WAAW,UAAU;AAAA,MAC3C,gBAAgB;AAAA,QACd,gBAAAA,KAAC,WAAM,2BAAa;AAAA,QACpB,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,EAAC,KAAI;AAAA,EACd;AAAA,EAEA,MAAM,YAAY,KAAU,SAAkC;AAC5D,UAAM,eAAc,mCAAS,gBAAe;AAC5C,UAAM,CAAC,OAAO,WAAW,IAAI,KAAK,OAAO,IAAI,MAAM;AACnD,QAAI,SAAS,MAAM,QAAQ,oBAAoB,MAAM,OAAO,SAAS;AACnE,YAAM,YAAY,MAAM,OAAO;AAC/B,aAAO,KAAK;AAAA,QACV;AAAA,QACA,EAAC,OAAO,IAAG;AAAA,QACX,EAAC,aAAa,OAAO,aAAa,QAAQ,KAAI;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,OAAM;AAAA,UACN,SAAQ;AAAA,UACR,OAAM;AAAA;AAAA,MACR;AAAA,IACF;AACA,UAAM,OAAO,MAAM,KAAK,WAAW,UAAU;AAAA,MAC3C,gBAAgB;AAAA,QACd,gBAAAA,KAAC,WAAM,uBAAS;AAAA,QAChB,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,EAAC,KAAI;AAAA,EACd;AAAA,EAEA,MAAM,mBAAmB,KAAc;AACrC,UAAM,UAAU,MAAM,KAAK,WAAW;AACtC,UAAM,WAAW;AAAA,MACf,gBAAAA,KAAC,mBAAgB,KAAU,SAAkB;AAAA,IAC/C;AACA,UAAM,OAAO,MAAM,KAAK,WAAW,UAAU;AAAA,MAC3C,gBAAgB,CAAC,gBAAAA,KAAC,WAAM,qCAAuB,CAAQ;AAAA,IACzD,CAAC;AACD,WAAO,EAAC,KAAI;AAAA,EACd;AAAA,EAEA,MAAM,mBAAmB,KAAc,OAAgB;AACrD,UAAM,CAAC,OAAO,WAAW,IAAI,KAAK,OAAO,IAAI,IAAI,IAAI;AACrD,UAAM,WAAW;AAAA,MACf,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,IACF;AACA,UAAM,OAAO,MAAM,KAAK,WAAW,UAAU;AAAA,MAC3C,gBAAgB,CAAC,gBAAAA,KAAC,WAAM,iCAAmB,CAAQ;AAAA,IACrD,CAAC;AACD,WAAO,EAAC,KAAI;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBACZ,MACA,QACA,SACsD;AACtD,UAAM,cAAc,KAAK,aAAa;AACtC,UAAM,WAAW,KAAK;AAEtB,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,WAAW,cAAc,IAAI,GAAG;AACzC,UAAI,WAAW,WAAW,aAAa;AACrC,iBAAS,IAAI,OAAO;AACpB,mBAAW,cAAc,KAAK,aAAa,QAAQ,OAAO,GAAG;AAC3D,mBAAS,IAAI,UAAU;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,MAAM,KAAK,QAAQ,EAAE,IAAI,OAAO,YAAoB;AAClD,cAAM,gBAAgB,YAAY,OAAO;AACzC,cAAM,QAAQ,MAAM,SAAS,IAAI,cAAc,OAAO;AACtD,YAAI,CAAC,OAAO;AACV;AAAA,QACF;AACA,cAAM,cAAc,MAAM,MAAM,UAAU;AAC1C,oBAAY,QAAQ,CAAC,QAAQ,OAAO,IAAI,GAAG,CAAC;AAC5C,cAAM,eAAe,MAAM,MAAM,WAAW;AAC5C,qBAAa,QAAQ,CAAC,QAAQ,QAAQ,IAAI,GAAG,CAAC;AAAA,MAChD,CAAC;AAAA,IACH;AAEA,WAAO,EAAC,QAAQ,QAAO;AAAA,EACzB;AACF;","names":["Fragment","jsx","jsxs","jsx","jsxs","path","jsx","jsxs","props"]}
1
+ {"version":3,"sources":["../src/render/render.tsx","../src/core/pages/ErrorPage.tsx","../src/core/pages/DevErrorPage.tsx","../src/core/pages/DevNotFoundPage.tsx","../src/render/accept-language.ts","../src/render/i18n-fallbacks.ts","../src/render/router.ts","../src/render/route-trie.ts"],"sourcesContent":["import {ComponentChildren, ComponentType} from 'preact';\nimport renderToString from 'preact-render-to-string';\n\nimport {HtmlContext, HTML_CONTEXT} from '../core/components/Html';\nimport {RootConfig} from '../core/config';\nimport {getTranslations, I18N_CONTEXT} from '../core/hooks/useI18nContext';\nimport {RequestContext, REQUEST_CONTEXT} from '../core/hooks/useRequestContext';\nimport {DevErrorPage} from '../core/pages/DevErrorPage';\nimport {DevNotFoundPage} from '../core/pages/DevNotFoundPage';\nimport {ErrorPage} from '../core/pages/ErrorPage';\nimport {\n Request,\n Response,\n NextFunction,\n HandlerContext,\n RouteParams,\n Route,\n HandlerRenderFn,\n HandlerRenderOptions,\n} from '../core/types';\nimport type {ElementGraph} from '../node/element-graph';\nimport {parseTagNames} from '../utils/elements';\n\nimport {AssetMap} from './asset-map/asset-map';\nimport {htmlMinify} from './html-minify';\nimport {htmlPretty} from './html-pretty';\nimport {getFallbackLocales} from './i18n-fallbacks';\nimport {RouteTrie} from './route-trie';\nimport {getRoutes, getAllPathsForRoute, replaceParams} from './router';\n\ninterface RenderHtmlOptions {\n /** Attrs passed to the <html> tag, e.g. `{lang: 'en'}`. */\n htmlAttrs?: preact.JSX.HTMLAttributes<HTMLHtmlElement>;\n /** Attrs passed to the <head> tag. */\n headAttrs?: preact.JSX.HTMLAttributes<HTMLHeadElement>;\n /** Child components for the <head> tag. */\n headComponents?: ComponentChildren[];\n /** Attrs passed to the <body> tag. */\n bodyAttrs?: preact.JSX.HTMLAttributes<HTMLBodyElement>;\n}\n\nexport class Renderer {\n private rootConfig: RootConfig;\n private routes: RouteTrie<Route>;\n private assetMap: AssetMap;\n private elementGraph: ElementGraph;\n\n constructor(\n rootConfig: RootConfig,\n options: {assetMap: AssetMap; elementGraph: ElementGraph}\n ) {\n this.rootConfig = rootConfig;\n this.routes = getRoutes(this.rootConfig);\n this.assetMap = options.assetMap;\n this.elementGraph = options.elementGraph;\n }\n\n async handle(req: Request, res: Response, next: NextFunction) {\n // TODO(stevenle): handle baseUrl config.\n const url = req.path.toLowerCase();\n const [route, routeParams] = this.routes.get(url);\n if (!route) {\n next();\n return;\n }\n if (route.locale) {\n routeParams.$locale = route.locale;\n }\n\n const fallbackLocales = route.isDefaultLocale\n ? getFallbackLocales(req)\n : [route.locale];\n const getPreferredLocale = (availableLocales: string[]) => {\n const lowerLocales = availableLocales.map((l) => l.toLowerCase());\n for (const fallbackLocale of fallbackLocales) {\n if (lowerLocales.includes(fallbackLocale.toLowerCase())) {\n return fallbackLocale;\n }\n }\n return req.rootConfig?.i18n?.defaultLocale || 'en';\n };\n\n const render404 = async () => {\n // Calling next() will allow the dev server or prod server handle the 404\n // page as appropriate for the env.\n next();\n };\n\n const render: HandlerRenderFn = async (\n props: any,\n options?: HandlerRenderOptions\n ) => {\n if (!route.module.default) {\n console.error(`no default component exported in route: ${route.src}`);\n render404();\n return;\n }\n const currentPath = req.path;\n const locale = options?.locale || route.locale;\n const translations = options?.translations;\n const output = await this.renderComponent(route.module.default, props, {\n currentPath,\n route,\n routeParams,\n locale,\n translations,\n });\n let html = output.html;\n if (this.rootConfig.prettyHtml) {\n html = await htmlPretty(html, this.rootConfig.prettyHtmlOptions);\n } else if (this.rootConfig.minifyHtml !== false) {\n html = await htmlMinify(html, this.rootConfig.minifyHtmlOptions);\n }\n if (req.viteServer) {\n html = await req.viteServer.transformIndexHtml(currentPath, html);\n }\n // Override the status code for 404 and 500 routes, which are defined at\n // routes/404.tsx and routes/500.tsx respectively.\n let statusCode = 200;\n if (route.src === 'routes/404.tsx') {\n statusCode = 404;\n } else if (route.src === 'routes/500.tsx') {\n statusCode = 500;\n }\n req.hooks.trigger('preRender');\n res.status(statusCode).set({'Content-Type': 'text/html'}).end(html);\n };\n\n if (route.module.handle) {\n const handlerContext: HandlerContext = {\n route: route,\n params: routeParams,\n i18nFallbackLocales: fallbackLocales,\n getPreferredLocale: getPreferredLocale,\n render: render,\n render404: render404,\n };\n req.handlerContext = handlerContext;\n return route.module.handle(req, res, next);\n }\n\n let props = {};\n if (route.module.getStaticProps) {\n const propsData = await route.module.getStaticProps({\n rootConfig: this.rootConfig,\n params: routeParams,\n });\n if (propsData.notFound) {\n return render404();\n }\n if (propsData.props) {\n props = propsData.props;\n }\n }\n await render(props);\n }\n\n private async renderComponent(\n Component: ComponentType,\n props: any,\n options: {\n currentPath: string;\n route: Route;\n routeParams: RouteParams;\n locale: string;\n translations?: Record<string, string>;\n }\n ) {\n const {currentPath, route, routeParams} = options;\n const locale = options.locale;\n const translations = {\n ...getTranslations(locale),\n ...(options.translations || {}),\n };\n const ctx: RequestContext = {\n currentPath,\n route,\n props,\n routeParams,\n locale,\n translations,\n };\n const htmlContext: HtmlContext = {\n htmlAttrs: {},\n headAttrs: {},\n headComponents: [],\n bodyAttrs: {},\n scriptDeps: [],\n };\n const vdom = (\n <REQUEST_CONTEXT.Provider value={ctx}>\n <I18N_CONTEXT.Provider value={{locale, translations}}>\n <HTML_CONTEXT.Provider value={htmlContext}>\n <Component {...props} />\n </HTML_CONTEXT.Provider>\n </I18N_CONTEXT.Provider>\n </REQUEST_CONTEXT.Provider>\n );\n const mainHtml = renderToString(vdom);\n\n const jsDeps = new Set<string>();\n const cssDeps = new Set<string>();\n\n // Walk the route's dependency tree for CSS dependencies that are added via\n // `import 'foo.scss'` or `import 'foo.module.scss'`.\n const routeAsset = await this.assetMap.get(route.src);\n if (routeAsset) {\n const routeCssDeps = await routeAsset.getCssDeps();\n routeCssDeps.forEach((dep) => {\n // Ignore ?inline css deps.\n if (dep.endsWith('?inline')) {\n return;\n }\n cssDeps.add(dep);\n });\n }\n\n // Parse the HTML for custom elements that are found within the project\n // and automatically inject the script deps for them.\n await this.collectElementDeps(mainHtml, jsDeps, cssDeps);\n\n // Add user defined scripts added via the `<Script>` component.\n await Promise.all(\n htmlContext.scriptDeps.map(async (scriptDep) => {\n if (!scriptDep.src) {\n return;\n }\n const assetId = String(scriptDep.src).slice(1);\n const scriptAsset = await this.assetMap.get(assetId);\n if (scriptAsset) {\n jsDeps.add(scriptAsset.assetUrl);\n const scriptJsDeps = await scriptAsset.getJsDeps();\n scriptJsDeps.forEach((dep) => jsDeps.add(dep));\n }\n })\n );\n\n const styleTags = Array.from(cssDeps).map((cssUrl) => {\n return <link rel=\"stylesheet\" href={cssUrl} />;\n });\n const scriptTags = Array.from(jsDeps).map((jsUrls) => {\n return <script type=\"module\" src={jsUrls} />;\n });\n\n const html = await this.renderHtml(mainHtml, {\n htmlAttrs: htmlContext.htmlAttrs,\n headAttrs: htmlContext.headAttrs,\n bodyAttrs: htmlContext.bodyAttrs,\n headComponents: [\n ...htmlContext.headComponents,\n ...styleTags,\n ...scriptTags,\n ],\n });\n return {html};\n }\n\n /** SSG renders a route. */\n async renderRoute(\n route: Route,\n options: {routeParams: Record<string, string>}\n ): Promise<{html?: string; notFound?: boolean}> {\n const routeParams = options.routeParams;\n if (route.locale) {\n routeParams.$locale = route.locale;\n }\n const Component = route.module.default;\n if (!Component) {\n throw new Error(\n 'unable to render route. the route should have a default export that renders a jsx component.'\n );\n }\n let props = {};\n let locale = route.locale;\n let translations = undefined;\n if (route.module.getStaticProps) {\n const propsData = await route.module.getStaticProps({\n rootConfig: this.rootConfig,\n params: routeParams,\n });\n if (propsData.notFound) {\n return {notFound: true};\n }\n if (propsData.props) {\n props = propsData.props;\n }\n if (propsData.locale) {\n locale = propsData.locale;\n }\n if (propsData.translations) {\n translations = propsData.translations;\n }\n }\n const routePath = route.isDefaultLocale\n ? route.routePath\n : route.localeRoutePath;\n const currentPath = replaceParams(routePath, {\n ...routeParams,\n locale: locale,\n });\n return this.renderComponent(Component, props, {\n currentPath,\n route,\n routeParams,\n locale,\n translations,\n });\n }\n\n async getSitemap(): Promise<\n Record<string, {route: Route; params: Record<string, string>}>\n > {\n const sitemap: Record<\n string,\n {route: Route; params: Record<string, string>}\n > = {};\n await this.routes.walk(async (urlPath: string, route: Route) => {\n const routePaths = await getAllPathsForRoute(urlPath, route);\n routePaths.forEach((routePath) => {\n sitemap[routePath.urlPath] = {\n route,\n params: routePath.params,\n };\n });\n });\n return sitemap;\n }\n\n private async renderHtml(html: string, options?: RenderHtmlOptions) {\n const htmlAttrs = options?.htmlAttrs || {};\n const headAttrs = options?.headAttrs || {};\n const bodyAttrs = options?.bodyAttrs || {};\n const page = (\n <html {...htmlAttrs}>\n <head {...headAttrs}>\n <meta charSet=\"utf-8\" />\n {options?.headComponents}\n </head>\n <body {...bodyAttrs} dangerouslySetInnerHTML={{__html: html}} />\n </html>\n );\n return `<!doctype html>\\n${renderToString(page)}\\n`;\n }\n\n async render404(options?: {currentPath?: string}) {\n const currentPath = options?.currentPath || '/404';\n const [route, routeParams] = this.routes.get('/404');\n if (route && route.src === 'routes/404.tsx' && route.module.default) {\n const Component = route.module.default;\n return this.renderComponent(\n Component,\n {},\n {currentPath, route, routeParams, locale: 'en'}\n );\n }\n\n const mainHtml = renderToString(\n <ErrorPage\n code={404}\n title=\"Not found\"\n message=\"Double-check the URL entered and try again.\"\n align=\"center\"\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [\n <title>404 Not Found</title>,\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n />,\n ],\n });\n return {html};\n }\n\n async renderError(err: any, options?: {currentPath?: string}) {\n const currentPath = options?.currentPath || '/500';\n const [route, routeParams] = this.routes.get('/500');\n if (route && route.src === 'routes/500.tsx' && route.module.default) {\n const Component = route.module.default;\n return this.renderComponent(\n Component,\n {error: err},\n {currentPath, route, routeParams, locale: 'en'}\n );\n }\n\n const mainHtml = renderToString(\n <ErrorPage\n code={500}\n title=\"Something went wrong\"\n message=\"An unknown error occurred.\"\n align=\"center\"\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [\n <title>500 Error</title>,\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1.0\"\n />,\n ],\n });\n return {html};\n }\n\n async renderDevServer404(req: Request) {\n const sitemap = await this.getSitemap();\n const mainHtml = renderToString(\n <DevNotFoundPage req={req} sitemap={sitemap} />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [<title>404 Not found | Root.js</title>],\n });\n return {html};\n }\n\n async renderDevServer500(req: Request, error: unknown) {\n const [route, routeParams] = this.routes.get(req.path);\n const mainHtml = renderToString(\n <DevErrorPage\n req={req}\n route={route}\n routeParams={routeParams}\n error={error}\n />\n );\n const html = await this.renderHtml(mainHtml, {\n headComponents: [<title>500 Error | Root.js</title>],\n });\n return {html};\n }\n\n /**\n * Parses rendered HTML for custom element tags used on the page and\n * automatically adds the JS/CSS deps to the page.\n */\n private async collectElementDeps(\n html: string,\n jsDeps: Set<string>,\n cssDeps: Set<string>\n ): Promise<{jsDeps: Set<string>; cssDeps: Set<string>}> {\n const elementsMap = this.elementGraph.sourceFiles;\n const assetMap = this.assetMap;\n\n const tagNames = new Set<string>();\n for (const tagName of parseTagNames(html)) {\n if (tagName && tagName in elementsMap) {\n tagNames.add(tagName);\n for (const depTagName of this.elementGraph.getDeps(tagName)) {\n tagNames.add(depTagName);\n }\n }\n }\n\n await Promise.all(\n Array.from(tagNames).map(async (tagName: string) => {\n const elementModule = elementsMap[tagName];\n const asset = await assetMap.get(elementModule.relPath);\n if (!asset) {\n return;\n }\n const assetJsDeps = await asset.getJsDeps();\n assetJsDeps.forEach((dep) => jsDeps.add(dep));\n const assetCssDeps = await asset.getCssDeps();\n assetCssDeps.forEach((dep) => {\n // Ignore ?inline css deps.\n if (dep.endsWith('?inline')) {\n return;\n }\n cssDeps.add(dep);\n });\n })\n );\n\n return {jsDeps, cssDeps};\n }\n}\n","import {ComponentChildren} from 'preact';\n\nconst STYLES = `\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');\n\n:root {\n --font-family-text: \"Inter\", sans-serif;\n}\n\nbody {\n font-family: var(--font-family-text);\n background: #F5F5F5;\n padding: 40px 16px;\n}\n\n.root {\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.root.align-center {\n text-align: center;\n}\n\nh1.title {\n margin-top: 0;\n margin-bottom: 24px;\n}\n\np.message {\n margin-top: 0;\n margin-bottom: 0;\n}\n\n.box {\n font-size: 16px;\n line-height: 1.5;\n padding: 16px;\n border-radius: 12px;\n background: #ffffff;\n}\n\npre.box {\n white-space: pre-wrap;\n}\n\n@media (min-width: 500px) {\n body {\n padding: 40px;\n }\n\n .box {\n padding: 24px;\n }\n}\n\n@media (min-width: 1024px) {\n body {\n padding: 100px;\n }\n}\n`;\n\nexport interface ErrorPageProps {\n code: number;\n title?: string;\n message?: string;\n children?: ComponentChildren;\n align?: 'center';\n}\n\nexport function ErrorPage(props: ErrorPageProps) {\n const {code, message} = props;\n const title = props.title || code;\n return (\n <>\n <style dangerouslySetInnerHTML={{__html: STYLES}}></style>\n <div className={`root align-${props.align || 'left'}`}>\n <h1 className=\"title\">{title}</h1>\n {message && <p className=\"message\">{message}</p>}\n {props.children}\n </div>\n </>\n );\n}\n","import {Request, Route, RouteParams} from '../types';\n\nimport {ErrorPage} from './ErrorPage';\n\ninterface DevErrorPageProps {\n req: Request;\n route?: Route;\n routeParams?: RouteParams;\n error: any;\n}\n\nexport function DevErrorPage(props: DevErrorPageProps) {\n const req = props.req;\n const err = props.error;\n const route = props.route;\n const routeParams = props.routeParams;\n\n let errMsg = String(err);\n if (err && err.stack) {\n // Obfuscate some user info from the stack trace so that when people send\n // error reports and screenshots, less identifiable information is sent.\n errMsg = err.stack\n .replace(/\\(.*node_modules/g, '(node_modules')\n .replace(/at \\/.*node_modules/g, 'at node_modules');\n if (req.rootConfig?.rootDir) {\n errMsg = errMsg.replaceAll(req.rootConfig.rootDir, '<root>');\n }\n if (process.env.HOME) {\n errMsg = errMsg.replaceAll(process.env.HOME, '$HOME');\n }\n }\n return (\n <ErrorPage code={500} title=\"Something went wrong\">\n {errMsg && (\n <>\n <h2>Error</h2>\n <pre className=\"box\">\n <code>{errMsg}</code>\n </pre>\n </>\n )}\n <h2>Debug Info</h2>\n <pre className=\"box\">\n <code>{`url: ${req.originalUrl}\nroute: ${route?.src || 'null'}\nrouteParams: ${(routeParams && JSON.stringify(routeParams)) || 'null'}`}</code>\n </pre>\n </ErrorPage>\n );\n}\n","import {Request, Route} from '../types';\n\nimport {ErrorPage} from './ErrorPage';\n\ninterface DevNotFoundPageProps {\n req: Request;\n sitemap: Record<string, {route: Route; params: Record<string, string>}>;\n}\n\ninterface RoutesListMap {\n [src: string]: Array<RouteURLPath>;\n}\n\ninterface RouteURLPath {\n route: Route;\n urlPath: string;\n}\n\nexport function DevNotFoundPage(props: DevNotFoundPageProps) {\n const req = props.req;\n const routesListMap: RoutesListMap = {};\n let srcMaxLength = 0;\n Object.keys(props.sitemap).forEach((urlPath) => {\n const route = props.sitemap[urlPath].route;\n routesListMap[route.src] ??= [];\n routesListMap[route.src].push({route, urlPath});\n if (route.src.length > srcMaxLength) {\n srcMaxLength = route.src.length;\n }\n });\n const routeSrcs = Object.keys(routesListMap).sort(sortRouteFiles);\n const lines: string[] = [];\n routeSrcs.forEach((routeSrc) => {\n const routeUrls = routesListMap[routeSrc].sort(sortRouteURLs);\n routeUrls.forEach((routeUrl, i) => {\n const urlPath = routeUrl.urlPath;\n if (i === 0) {\n lines.push(`${routeSrc.padEnd(srcMaxLength, ' ')} => ${urlPath}`);\n } else {\n lines.push(`${''.padEnd(srcMaxLength, ' ')} => ${urlPath}`);\n }\n });\n });\n const routesListString = lines.join('\\n');\n // const routesListString = routesList\n // .map((route) => {\n // return `${route.urlPath.padEnd(srcMaxLength, ' ')} => ${route.src}`;\n // })\n // .join('\\n');\n return (\n <ErrorPage code={404} title=\"Not found\">\n <h2>Routes</h2>\n {Object.keys(routesListMap).length > 0 ? (\n <pre className=\"box\">\n <code>{routesListString}</code>\n </pre>\n ) : (\n <div className=\"box\">\n Add your first route at <code>/routes/index.tsx</code>\n </div>\n )}\n\n <h2>Debug Info</h2>\n <pre className=\"box\">\n <code>{`url: ${req.originalUrl}`}</code>\n </pre>\n </ErrorPage>\n );\n}\n\nfunction sortRouteFiles(a: string, b: string): number {\n if (a === 'routes/index.tsx') {\n return -1;\n }\n if (b === 'routes/index.tsx') {\n return 1;\n }\n return a.localeCompare(b);\n}\n\nfunction sortRouteURLs(a: RouteURLPath, b: RouteURLPath): number {\n if (a.route.isDefaultLocale && !b.route.isDefaultLocale) {\n return -1;\n }\n if (!a.route.isDefaultLocale && b.route.isDefaultLocale) {\n return 1;\n }\n return a.urlPath.localeCompare(b.urlPath);\n}\n","export const ACCEPT_LANG_RE =\n /((([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\\*)(;q=[0-1](\\.[0-9]+)?)?)*/g;\n\nexport interface AcceptLanguage {\n code: string;\n script?: string;\n region?: string;\n quality: number;\n}\n\nexport function parseAcceptLanguage(value: string): AcceptLanguage[] {\n const matches = String(value).match(ACCEPT_LANG_RE);\n if (!matches) {\n return [];\n }\n const results: AcceptLanguage[] = [];\n matches.forEach((m) => {\n if (!m) {\n return;\n }\n\n const parts = m.split(';');\n const ietf = parts[0].split('-');\n const hasScript = ietf.length === 3;\n\n results.push({\n code: ietf[0],\n script: hasScript ? ietf[1] : undefined,\n region: hasScript ? ietf[2] : ietf[1],\n quality: parts[1] ? parseFloat(parts[1].split('=')[1]) : 1.0,\n });\n });\n results.sort((a, b) => b.quality - a.quality);\n return results;\n}\n","/**\n * Utility functions for handling requests that mimic the Firebase Hosting i18n\n * fallback logic.\n * https://firebase.google.com/docs/hosting/i18n-rewrites\n */\n\nimport {Request} from '../core/types';\nimport {parseAcceptLanguage} from './accept-language';\n\nexport const UNKNOWN_COUNTRY = 'zz';\nexport const ES_419_COUNTRIES = [\n 'ar', // Argentina\n 'bo', // Bolivia\n 'cl', // Chile\n 'co', // Colombia\n 'cr', // Costa Rica\n 'cu', // Cuba\n 'do', // Dominican Republic\n 'ec', // Ecuador\n 'sv', // El Salvador\n 'gt', // Guatemala\n 'hn', // Honduras\n 'mx', // Mexico\n 'ni', // Nicaragua\n 'pa', // Panama\n 'py', // Paraguay\n 'pe', // Peru\n 'pr', // Puerto Rico\n 'uy', // Uruguay\n 've', // Venezuela\n];\n\nexport function getFallbackLocales(req: Request): string[] {\n const hl = getFirstQueryParam(req, 'hl');\n const countryCode = getCountry(req);\n\n // Web crawlers should only use the default locale.\n if (isWebCrawler(req)) {\n const defaultLocale = req.rootConfig?.i18n?.defaultLocale || 'en';\n if (hl && hl !== defaultLocale) {\n return [hl, defaultLocale];\n }\n return [defaultLocale];\n }\n\n const locales = new Set<string>();\n\n // Add locales from ?hl= query parameter.\n if (hl) {\n const langCode = hl;\n locales.add(`${langCode}_${countryCode}`);\n locales.add(`${langCode}_ALL`);\n locales.add(langCode);\n }\n\n const langs = getFallbackLanguages(req);\n\n // Add `{lang}_{country}` locales.\n langs.forEach((langCode) => {\n locales.add(`${langCode}_${countryCode}`);\n });\n\n // Add ALL_{country} locale.\n locales.add(`ALL_${countryCode}`);\n\n // Add `{lang}_ALL` and `{lang}` locales.\n // For Spanish-speaking LATAM countries, also add es-419.\n const isEs419Country = test419Country(countryCode);\n langs.forEach((langCode) => {\n locales.add(`${langCode}_ALL`);\n locales.add(langCode);\n if (langCode === 'es' && isEs419Country) {\n locales.add('es-419_ALL');\n locales.add('es-419');\n }\n });\n\n return Array.from(locales) as string[];\n}\n\nexport function getCountry(req: Request) {\n const normalize = (countryCode: string) => String(countryCode).toLowerCase();\n // Check the ?gl= query param.\n const gl = getFirstQueryParam(req, 'gl');\n if (gl) {\n return normalize(gl);\n }\n const gaeCountry =\n req.get('x-country-code') || req.get('x-appengine-country');\n if (gaeCountry) {\n return normalize(gaeCountry);\n }\n return UNKNOWN_COUNTRY;\n}\n\nfunction getFallbackLanguages(req: Request): string[] {\n const langs = new Set<string>();\n // Add languages from the Accept-Language header.\n const acceptLangHeader = req.get('accept-language') || '';\n if (acceptLangHeader) {\n parseAcceptLanguage(acceptLangHeader).forEach((lang) => {\n // For a lang like `en-US`, add both `en-US` and `en`.\n if (lang.region) {\n langs.add(`${lang.code}-${lang.region}`);\n // For Spanish-speaking LATAM countries, also add es-419.\n if (lang.code === 'es' && test419Country(lang.region)) {\n langs.add('es-419');\n }\n }\n langs.add(lang.code);\n });\n }\n // Fall back to \"en\" as a last resort.\n langs.add('en');\n return Array.from(langs);\n}\n\n/**\n * Returns the first query param value in a given request.\n *\n * For example, for a URL like `/?foo=bar&foo=baz`, calling\n * `getFirstQueryParam(req, 'foo')` would return `\"bar\"`.\n */\nfunction getFirstQueryParam(req: Request, key: string): string | null {\n const val = req.query[key];\n if (val === null || val === undefined) {\n return null;\n }\n if (Array.isArray(val)) {\n if (val.length === 0) {\n return null;\n }\n return String(val[0]);\n }\n return String(val);\n}\n\nfunction isWebCrawler(req: Request): boolean {\n const userAgentHeader = req.get('User-Agent');\n if (!userAgentHeader) {\n return false;\n }\n const userAgent = userAgentHeader.toLowerCase();\n return (\n userAgent.includes('googlebot') ||\n userAgent.includes('bingbot') ||\n userAgent.includes('twitterbot')\n );\n}\n\nexport function test419Country(countryCode: string) {\n return ES_419_COUNTRIES.includes(countryCode);\n}\n","import path from 'node:path';\n\nimport {RootConfig} from '../core/config';\nimport {Route, RouteModule} from '../core/types';\n\nimport {RouteTrie} from './route-trie';\n\nexport function getRoutes(rootConfig: RootConfig) {\n const locales = rootConfig.i18n?.locales || [];\n const basePath = rootConfig.base || '/';\n\n const defaultLocale = rootConfig.i18n?.defaultLocale || 'en';\n\n const routes = import.meta.glob(\n ['/routes/*.ts', '/routes/**/*.ts', '/routes/*.tsx', '/routes/**/*.tsx'],\n {\n eager: true,\n }\n );\n const trie = new RouteTrie<Route>();\n Object.keys(routes).forEach((modulePath) => {\n const src = modulePath.slice(1);\n let relativeRoutePath = modulePath.replace(/^\\/routes/, '');\n const parts = path.parse(relativeRoutePath);\n if (parts.name.startsWith('_')) {\n return;\n }\n if (parts.name === 'index') {\n relativeRoutePath = parts.dir;\n } else {\n relativeRoutePath = path.join(parts.dir, parts.name);\n }\n\n const urlFormat = '/[base]/[path]';\n const i18nUrlFormat = toSquareBrackets(\n rootConfig.i18n?.urlFormat || '/[locale]/[base]/[path]'\n );\n const placeholders = {\n base: removeSlashes(basePath),\n path: removeSlashes(relativeRoutePath),\n };\n\n const formatUrl = (format: string) => {\n const url = format\n .replaceAll('[base]', placeholders.base)\n .replaceAll('[path]', placeholders.path);\n return normalizeUrlPath(url, {\n trailingSlash: rootConfig.server?.trailingSlash,\n });\n };\n\n const routePath = formatUrl(urlFormat);\n const localeRoutePath = formatUrl(i18nUrlFormat);\n\n trie.add(routePath, {\n src,\n module: routes[modulePath] as RouteModule,\n locale: defaultLocale,\n isDefaultLocale: true,\n routePath: routePath,\n localeRoutePath: localeRoutePath,\n });\n\n // At the moment, all routes are assumed to use the site-wide i18n config.\n // TODO(stevenle): provide routes with a way to override the default\n // i18n serving behavior.\n if (i18nUrlFormat.includes('[locale]')) {\n locales.forEach((locale) => {\n const localePath = localeRoutePath.replace('[locale]', locale);\n if (localePath !== relativeRoutePath) {\n trie.add(localePath, {\n src,\n module: routes[modulePath] as RouteModule,\n locale: locale,\n isDefaultLocale: false,\n routePath,\n localeRoutePath,\n });\n }\n });\n }\n });\n return trie;\n}\n\nexport async function getAllPathsForRoute(\n urlPathFormat: string,\n route: Route\n): Promise<Array<{urlPath: string; params: Record<string, string>}>> {\n const routeModule = route.module;\n if (!routeModule.default) {\n return [];\n }\n\n const urlPaths: Array<{urlPath: string; params: Record<string, string>}> = [];\n if (routeModule.getStaticPaths) {\n const staticPaths = await routeModule.getStaticPaths();\n if (staticPaths.paths) {\n staticPaths.paths.forEach(\n (pathParams: {params: Record<string, string>}) => {\n const urlPath = replaceParams(urlPathFormat, pathParams.params || {});\n if (pathContainsPlaceholders(urlPath)) {\n console.warn(\n `path contains placeholders: ${urlPathFormat}, double check getStaticPaths() and ensure all params are returned. more info: https://rootjs.dev/guide/routes#getStaticPaths`\n );\n } else {\n urlPaths.push({\n urlPath: normalizeUrlPath(urlPath),\n params: pathParams.params || {},\n });\n }\n }\n );\n }\n } else if (\n routeModule.getStaticProps &&\n !pathContainsPlaceholders(urlPathFormat)\n ) {\n urlPaths.push({urlPath: normalizeUrlPath(urlPathFormat), params: {}});\n } else if (!routeModule.handle && !pathContainsPlaceholders(urlPathFormat)) {\n urlPaths.push({urlPath: normalizeUrlPath(urlPathFormat), params: {}});\n } else if (\n pathContainsPlaceholders(urlPathFormat) &&\n !routeModule.handle &&\n !routeModule.getStaticPaths\n ) {\n console.warn(\n [\n `warning: path contains placeholders: ${urlPathFormat}.`,\n `define either ssg getStaticPaths() or ssr handle() for route: ${route.src}.`,\n 'more info: https://rootjs.dev/guide/routes',\n ].join('\\n')\n );\n }\n\n return urlPaths;\n}\n\nexport function replaceParams(\n urlPathFormat: string,\n params: Record<string, string>\n) {\n const urlPath = urlPathFormat.replaceAll(\n /\\[\\[?(\\.\\.\\.)?([\\w\\-_]*)\\]?\\]/g,\n (match: string, _wildcard: string, key: string) => {\n const val = params[key];\n if (!val) {\n throw new Error(`unreplaced param ${match} in url: ${urlPathFormat}`);\n }\n return val;\n }\n );\n return urlPath;\n}\n\nexport function normalizeUrlPath(\n urlPath: string,\n options?: {trailingSlash?: boolean}\n) {\n // Collapse multiple slashes, e.g. `/foo//bar` => `/foo/bar`;\n urlPath = urlPath.replace(/\\/+/g, '/');\n // Remove trailing slash.\n if (\n options?.trailingSlash === false &&\n urlPath !== '/' &&\n urlPath.endsWith('/')\n ) {\n urlPath = urlPath.replace(/\\/*$/g, '');\n }\n // Add leading slash if needed.\n if (!urlPath.startsWith('/')) {\n urlPath = `/${urlPath}`;\n }\n return urlPath;\n}\n\nfunction pathContainsPlaceholders(urlPath: string) {\n const segments = urlPath.split('/');\n return segments.some((segment) => {\n return segment.startsWith('[') && segment.endsWith(']');\n });\n}\n\nfunction removeSlashes(str: string) {\n return str.replace(/^\\/*/g, '').replace(/\\/*$/g, '');\n}\n\n/**\n * Older path formats used `/{locale}/{path}` and should be converted to\n * `/[locale]/[base]/[path]`.\n */\nfunction toSquareBrackets(str: string) {\n if (str.includes('{') || str.includes('}')) {\n const val = str.replaceAll('{', '[').replaceAll('}', ']');\n console.warn(`\"${str}\" is a deprecated format, please switch to \"${val}\"`);\n return val;\n }\n return str;\n}\n","/**\n * A trie data structure that stores routes. Supports Next-style routing using\n * [param], [...catchall], and [[...optcatchall]] placeholders.\n */\nexport class RouteTrie<T> {\n private children: Record<string, RouteTrie<T>> = {};\n private paramNodes?: {[param: string]: ParamNode<T>};\n private catchAllNodes?: CatchAllNode<T>;\n private optCatchAllNodes?: CatchAllNode<T>;\n private route?: T;\n\n /**\n * Adds a route to the trie.\n */\n add(path: string, route: T) {\n path = this.normalizePath(path);\n\n // If the end was reached, save the value to the node.\n if (path === '') {\n this.route = route;\n return;\n }\n\n const [head, tail] = this.splitPath(path);\n\n if (head.startsWith('[[...') && head.endsWith(']]')) {\n const paramName = head.slice(5, -2);\n this.optCatchAllNodes = new CatchAllNode(paramName, route);\n return;\n }\n if (head.startsWith('[...') && head.endsWith(']')) {\n const paramName = head.slice(4, -1);\n this.catchAllNodes = new CatchAllNode(paramName, route);\n return;\n }\n\n let nextNode: RouteTrie<T>;\n if (head.startsWith('[') && head.endsWith(']')) {\n if (!this.paramNodes) {\n this.paramNodes = {};\n }\n const paramName = head.slice(1, -1);\n if (!this.paramNodes[paramName]) {\n this.paramNodes[paramName] = new ParamNode(paramName);\n }\n nextNode = this.paramNodes[paramName].trie;\n } else {\n nextNode = this.children[head];\n if (!nextNode) {\n nextNode = new RouteTrie();\n this.children[head] = nextNode;\n }\n }\n nextNode.add(tail, route);\n }\n\n /**\n * Returns a route mapped to the given path and any parameter values from the\n * URL.\n */\n get(path: string): [T | undefined, Record<string, string>] {\n const params = {};\n const route = this.getRoute(path, params);\n return [route, params];\n }\n\n /**\n * Walks the route trie and calls a callback function for each route.\n */\n walk(cb: (urlPath: string, route: T) => Promise<void> | void): Promise<void> {\n const promises: Array<Promise<void>> = [];\n const addPromise = (promise: Promise<void> | void) => {\n if (promise) {\n promises.push(promise);\n }\n };\n if (this.route) {\n addPromise(cb('/', this.route));\n }\n if (this.paramNodes) {\n Object.values(this.paramNodes).forEach((paramChild) => {\n const param = `[${paramChild.name}]`;\n paramChild.trie.walk((childPath: string, route: T) => {\n const paramUrlPath = `/${param}${childPath}`;\n addPromise(cb(paramUrlPath, route));\n });\n });\n }\n if (this.catchAllNodes) {\n const wildcardUrlPath = `/[...${this.catchAllNodes.name}]`;\n addPromise(cb(wildcardUrlPath, this.catchAllNodes.route));\n }\n if (this.optCatchAllNodes) {\n const wildcardUrlPath = `/[[...${this.optCatchAllNodes.name}]]`;\n addPromise(cb(wildcardUrlPath, this.optCatchAllNodes.route));\n }\n for (const subpath of Object.keys(this.children)) {\n const childTrie = this.children[subpath];\n childTrie.walk((childPath: string, childRoute: T) => {\n addPromise(cb(`/${subpath}${childPath}`, childRoute));\n });\n }\n return Promise.all(promises).then(() => {});\n }\n\n /**\n * Removes all routes from the trie.\n */\n clear() {\n this.children = {};\n this.paramNodes = undefined;\n this.catchAllNodes = undefined;\n this.optCatchAllNodes = undefined;\n this.route = undefined;\n }\n\n private getRoute(\n urlPath: string,\n params: Record<string, string>\n ): T | undefined {\n urlPath = this.normalizePath(urlPath);\n if (urlPath === '') {\n if (this.route) {\n return this.route;\n }\n if (this.optCatchAllNodes) {\n if (urlPath) {\n params[this.optCatchAllNodes.name] = urlPath;\n }\n return this.optCatchAllNodes.route;\n }\n return undefined;\n }\n\n const [head, tail] = this.splitPath(urlPath);\n\n const child = this.children[head];\n if (child) {\n const route = child.getRoute(tail, params);\n if (route) {\n return route;\n }\n }\n\n if (this.paramNodes) {\n for (const paramChild of Object.values(this.paramNodes)) {\n const route = paramChild.trie.getRoute(tail, params);\n if (route) {\n params[paramChild.name] = head;\n return route;\n }\n }\n }\n\n if (this.catchAllNodes) {\n params[this.catchAllNodes.name] = urlPath;\n return this.catchAllNodes.route;\n }\n\n if (this.optCatchAllNodes) {\n params[this.optCatchAllNodes.name] = urlPath;\n return this.optCatchAllNodes.route;\n }\n\n return undefined;\n }\n\n /**\n * Normalizes a path for inclusion into the route trie.\n */\n private normalizePath(path: string) {\n // Remove leading/trailing slashes.\n return path.replace(/^\\/+/g, '').replace(/\\/+$/g, '');\n }\n\n /**\n * Splits the parent directory from its children, e.g.:\n *\n * splitPath(\"foo/bar/baz\") -> [\"foo\", \"bar/baz\"]\n */\n private splitPath(path: string): [string, string] {\n const i = path.indexOf('/');\n if (i === -1) {\n return [path, ''];\n }\n return [path.slice(0, i), path.slice(i + 1)];\n }\n}\n\n/**\n * A node in the RouteTrie for a :param child.\n */\nclass ParamNode<T> {\n readonly name: string;\n readonly trie: RouteTrie<T> = new RouteTrie();\n\n constructor(name: string) {\n this.name = name;\n }\n}\n\n/**\n * A node in the RouteTrie for a *wildcard child.\n */\nclass CatchAllNode<T> {\n readonly name: string;\n readonly route: T;\n\n constructor(name: string, route: T) {\n this.name = name;\n this.route = route;\n }\n}\n"],"mappings":"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","names":["Fragment","jsx","jsxs","jsx","jsxs","path","_a","jsx","jsxs","props"]}
@@ -33,12 +33,12 @@ declare class Session {
33
33
  toString(): string;
34
34
  }
35
35
 
36
- declare type HtmlMinifyOptions = Options;
36
+ type HtmlMinifyOptions = Options;
37
37
 
38
- declare type HtmlPrettyOptions = HTMLBeautifyOptions;
38
+ type HtmlPrettyOptions = HTMLBeautifyOptions;
39
39
 
40
- declare type MaybePromise<T> = T | Promise<T>;
41
- declare type ConfigureServerHook = (server: Server, options: ConfigureServerOptions) => MaybePromise<void> | MaybePromise<() => void>;
40
+ type MaybePromise<T> = T | Promise<T>;
41
+ type ConfigureServerHook = (server: Server, options: ConfigureServerOptions) => MaybePromise<void> | MaybePromise<() => void>;
42
42
  interface ConfigureServerOptions {
43
43
  type: 'dev' | 'preview' | 'prod';
44
44
  rootConfig: RootConfig;
@@ -83,6 +83,10 @@ interface RootUserConfig {
83
83
  * sitemap, SEO tags, etc.
84
84
  */
85
85
  domain?: string;
86
+ /**
87
+ * The base URL path that the site will serve on. Defaults to `/`;
88
+ */
89
+ base?: string;
86
90
  /**
87
91
  * Config for auto-injecting custom element dependencies.
88
92
  */
@@ -137,7 +141,7 @@ interface RootUserConfig {
137
141
  */
138
142
  plugins?: Plugin[];
139
143
  }
140
- declare type RootConfig = RootUserConfig & {
144
+ type RootConfig = RootUserConfig & {
141
145
  rootDir: string;
142
146
  };
143
147
  interface LocaleGroup {
@@ -154,7 +158,7 @@ interface RootI18nConfig {
154
158
  */
155
159
  defaultLocale?: string;
156
160
  /**
157
- * URL format for localized content. Default is `/{locale}/{path}`.
161
+ * URL format for localized content. Default is `/[locale]/[base]/[path]`.
158
162
  */
159
163
  urlFormat?: string;
160
164
  /**
@@ -303,13 +307,13 @@ declare class Renderer {
303
307
  * Param values from the route, e.g. a route like `/route/[slug].tsx` will pass
304
308
  * `{slug: 'foo'}`.
305
309
  */
306
- declare type RouteParams = Record<string, string>;
310
+ type RouteParams = Record<string, string>;
307
311
  /**
308
312
  * The `getStaticProps()` function is an optional function that routes can
309
313
  * define to fetch and transform props before passing it to the route's
310
314
  * component.
311
315
  */
312
- declare type GetStaticProps<T = unknown> = (ctx: {
316
+ type GetStaticProps<T = unknown> = (ctx: {
313
317
  rootConfig: RootConfig;
314
318
  params: RouteParams;
315
319
  }) => Promise<{
@@ -328,10 +332,10 @@ declare type GetStaticProps<T = unknown> = (ctx: {
328
332
  }>;
329
333
  /**
330
334
  * The `getStaticPaths()` is used by the SSG build to determine all of the
331
- * paths that should exist for a given route. This should be used alongside a
335
+ * paths that exist for a given route. This should be used alongside a
332
336
  * parameterized route, e.g. `/routes/blog/[slug].tsx`.
333
337
  */
334
- declare type GetStaticPaths<T = RouteParams> = () => Promise<{
338
+ type GetStaticPaths<T = RouteParams> = () => Promise<{
335
339
  paths: Array<{
336
340
  params: T;
337
341
  }>;
@@ -344,14 +348,14 @@ interface MultipartFile {
344
348
  mimetype: string;
345
349
  buffer: Buffer;
346
350
  }
347
- declare type RequestMiddleware = ((req: Request, res: Response) => any) | ((req: Request, res: Response, next: NextFunction) => any) | ((err: any, req: Request, res: Response, next: NextFunction) => any);
351
+ type RequestMiddleware = ((req: Request, res: Response) => any) | ((req: Request, res: Response, next: NextFunction) => any) | ((err: any, req: Request, res: Response, next: NextFunction) => any);
348
352
  /** Root.js express app. */
349
- declare type Server = Express & {
353
+ type Server = Express & {
350
354
  use(middlewares: RequestMiddleware | RequestMiddleware[]): any;
351
355
  use(urlPath: string, middlewares: RequestMiddleware | RequestMiddleware[]): any;
352
356
  };
353
357
  /** Root.js express request. */
354
- declare type Request = Request$1 & {
358
+ type Request = Request$1 & {
355
359
  /** The root.js project config. */
356
360
  rootConfig?: RootConfig & {
357
361
  rootDir: string;
@@ -376,12 +380,12 @@ declare type Request = Request$1 & {
376
380
  };
377
381
  };
378
382
  /** Root.js express response. */
379
- declare type Response = Response$1 & {
383
+ type Response = Response$1 & {
380
384
  session: Session;
381
385
  saveSession: () => void;
382
386
  };
383
387
  /** Root.js express next function. */
384
- declare type NextFunction = NextFunction$1;
388
+ type NextFunction = NextFunction$1;
385
389
  /**
386
390
  * A context variable passed to a route's `handle()` method within the req
387
391
  * object.
@@ -418,7 +422,7 @@ interface HandlerContext<T = any> {
418
422
  * contains the route's param values and also a `render()` method that can be
419
423
  * used to render the route's default component.
420
424
  */
421
- declare type Handler = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
425
+ type Handler = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
422
426
  interface RouteModule {
423
427
  default?: ComponentType<unknown>;
424
428
  getStaticPaths?: GetStaticPaths;
@@ -465,6 +469,6 @@ interface HandlerRenderOptions {
465
469
  */
466
470
  translations?: Record<string, string>;
467
471
  }
468
- declare type HandlerRenderFn = (props: any, options?: HandlerRenderOptions) => Promise<void>;
472
+ type HandlerRenderFn = (props: any, options?: HandlerRenderOptions) => Promise<void>;
469
473
 
470
474
  export { ConfigureServerHook as C, GetStaticProps as G, HandlerContext as H, LocaleGroup as L, MultipartFile as M, NextFunction as N, Plugin as P, Route as R, Server as S, RootUserConfig as a, RootConfig as b, RootI18nConfig as c, RootServerConfig as d, defineConfig as e, ConfigureServerOptions as f, configureServerPlugins as g, getVitePlugins as h, RouteParams as i, GetStaticPaths as j, RequestMiddleware as k, Request as l, Response as m, Handler as n, RouteModule as o, HandlerRenderOptions as p, HandlerRenderFn as q, SESSION_COOKIE as r, SessionMiddlewareOptions as s, SaveSessionOptions as t, sessionMiddleware as u, Session as v, Renderer as w };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinkk/root",
3
- "version": "1.0.0-rc.0",
3
+ "version": "1.0.0-rc.10",
4
4
  "author": "s@blinkk.com",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -54,27 +54,27 @@
54
54
  }
55
55
  },
56
56
  "dependencies": {
57
- "bundle-require": "^4.0.1",
57
+ "bundle-require": "^4.0.2",
58
58
  "busboy": "^1.6.0",
59
- "commander": "^10.0.0",
59
+ "commander": "^11.0.0",
60
60
  "compression": "^1.7.4",
61
61
  "cookie-parser": "^1.4.6",
62
62
  "esbuild": "0.19.4",
63
- "express": "^4.18.1",
64
- "fs-extra": "^10.1.0",
65
- "html-minifier-terser": "^7.0.0",
66
- "js-beautify": "^1.14.7",
63
+ "express": "^4.18.2",
64
+ "fs-extra": "^11.1.1",
65
+ "html-minifier-terser": "^7.2.0",
66
+ "js-beautify": "^1.14.9",
67
67
  "kleur": "^4.1.5",
68
- "sass": "^1.49.9",
69
- "sirv": "^2.0.2",
68
+ "sass": "^1.69.3",
69
+ "sirv": "^2.0.3",
70
70
  "tiny-glob": "^0.2.9",
71
- "vite": "4.2.0"
71
+ "vite": "4.5.0"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "firebase-admin": ">=11",
75
75
  "firebase-functions": ">=4",
76
- "preact": "10.x",
77
- "preact-render-to-string": "5.x"
76
+ "preact": ">=10",
77
+ "preact-render-to-string": ">=5"
78
78
  },
79
79
  "peerDependenciesMeta": {
80
80
  "firebase-functions": {
@@ -89,21 +89,20 @@
89
89
  "@types/compression": "^1.7.2",
90
90
  "@types/cookie-parser": "^1.4.3",
91
91
  "@types/express": "^4.17.13",
92
- "@types/fs-extra": "^9.0.13",
92
+ "@types/fs-extra": "^11.0.2",
93
93
  "@types/html-minifier-terser": "^7.0.0",
94
- "@types/js-beautify": "^1.13.3",
95
- "@types/node": "^18.7.14",
96
- "@types/preact-custom-element": "^4.0.1",
97
- "firebase-admin": "^11.5.0",
98
- "firebase-functions": "^4.4.0",
99
- "nodemon": "^2.0.19",
100
- "preact": "^10.10.6",
101
- "preact-custom-element": "^4.2.1",
102
- "preact-render-to-string": "^5.2.3",
103
- "rollup": "^2.79.0",
94
+ "@types/js-beautify": "^1.14.1",
95
+ "@types/node": "^20.8.4",
96
+ "@types/preact-custom-element": "^4.0.2",
97
+ "firebase-admin": "^11.11.0",
98
+ "firebase-functions": "^4.4.1",
99
+ "nodemon": "^3.0.1",
100
+ "preact": "^10.18.1",
101
+ "preact-custom-element": "^4.3.0",
102
+ "preact-render-to-string": "^6.2.2",
104
103
  "tsup": "^7.2.0",
105
- "typescript": "^4.7.4",
106
- "vitest": "^0.18.1"
104
+ "typescript": "^5.2.2",
105
+ "vitest": "^0.34.6"
107
106
  },
108
107
  "scripts": {
109
108
  "build": "rm -rf dist && tsup-node",