@blinkk/root 1.0.0-beta.6 → 1.0.0-beta.61

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/render/router.ts","../src/render/route-trie.ts","../src/core/pages/ErrorPage.tsx","../src/core/pages/DevNotFoundPage.tsx","../src/core/pages/DevErrorPage.tsx"],"sourcesContent":["import {ComponentChildren, ComponentType} from 'preact';\nimport renderToString from 'preact-render-to-string';\nimport {getRoutes, getAllPathsForRoute} from './router';\nimport {ErrorPage} from '../core/pages/ErrorPage';\nimport {AssetMap} from './asset-map/asset-map';\nimport {RootConfig} from '../core/config';\nimport {RouteTrie} from './route-trie';\nimport {DevNotFoundPage} from '../core/pages/DevNotFoundPage';\nimport {HtmlContext, HTML_CONTEXT} from '../core/components/Html';\nimport {\n Request,\n Response,\n NextFunction,\n HandlerContext,\n RouteParams,\n Route,\n} from '../core/types';\nimport {htmlMinify} from './html-minify';\nimport {htmlPretty} from './html-pretty';\nimport {DevErrorPage} from '../core/pages/DevErrorPage';\nimport {RequestContext, REQUEST_CONTEXT} from '../core/hooks/useRequestContext';\nimport {getTranslations, I18N_CONTEXT} from '../core/hooks/useI18nContext';\nimport type {ElementGraph} from '../node/element-graph';\nimport {parseTagNames} from '../utils/elements';\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;\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 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 = async (props: any) => {\n if (!route.module.default) {\n console.error(`no default component exported in route: ${route.src}`);\n render404();\n return;\n }\n const output = await this.renderComponent(route.module.default, props, {\n route,\n routeParams,\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(req.originalUrl, 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 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 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: {route: Route; routeParams: RouteParams}\n ) {\n const {route, routeParams} = options;\n const locale = route.locale;\n const translations = getTranslations(locale);\n const ctx: RequestContext = {\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 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 }\n return this.renderComponent(Component, props, {route, routeParams});\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() {\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(Component, {}, {route, routeParams});\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 />\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) {\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 {route, routeParams}\n );\n }\n\n const mainHtml = renderToString(\n <ErrorPage\n code={500}\n title=\"Something went wrong\"\n message=\"An unknown error occurred.\"\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 path from 'node:path';\nimport {RootConfig} from '../core/config';\nimport {Route, RouteModule} from '../core/types';\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 routePath,\n 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 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: replaceParams(urlPathFormat, pathParams.params),\n params: pathParams.params || {},\n });\n }\n }\n );\n }\n } else if (pathContainsPlaceholders(urlPathFormat)) {\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: 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\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 paramChild?: 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.paramChild) {\n const paramName = head.slice(1, -1);\n this.paramChild = new ParamChild(paramName);\n }\n nextNode = this.paramChild.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.paramChild) {\n const param = `[${this.paramChild.name}]`;\n this.paramChild.trie.walk((childPath: string, route: T) => {\n const paramUrlPath = `/${param}${childPath}`;\n addPromise(cb(paramUrlPath, route));\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.paramChild = 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.paramChild) {\n const route = this.paramChild.trie.getRoute(tail, params);\n if (route) {\n params[this.paramChild.name] = head;\n return route;\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","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} from '../types';\nimport {ErrorPage} from './ErrorPage';\n\ninterface DevNotFoundPageProps {\n req: Request;\n sitemap: Record<string, {route: Route; params: Record<string, string>}>;\n}\n\nexport function DevNotFoundPage(props: DevNotFoundPageProps) {\n const req = props.req;\n const routesList: Array<{src: string; urlPath: string}> = [];\n let urlMaxLength = 0;\n Object.keys(props.sitemap).forEach((urlPath) => {\n const route = props.sitemap[urlPath].route;\n routesList.push(Object.assign({}, route, {urlPath}));\n if (urlPath.length > urlMaxLength) {\n urlMaxLength = urlPath.length;\n }\n });\n const routesListString = routesList\n .map((route) => {\n return `${route.urlPath.padEnd(urlMaxLength, ' ')} => ${route.src}`;\n })\n .join('\\n');\n return (\n <ErrorPage code={404} title=\"Not found\">\n <h2>Routes</h2>\n {routesList.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","import {Request, Route, RouteParams} from '../types';\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"],"mappings":"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","names":["path","jsx","jsxs","Fragment","jsx","jsxs","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) => 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":"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","names":["Fragment","jsx","jsxs","jsx","jsxs","path","jsx","jsxs","props"]}
@@ -4,32 +4,39 @@ import { PluginOption, UserConfig, ViteDevServer } from 'vite';
4
4
  import { Options } from 'html-minifier-terser';
5
5
  import { HTMLBeautifyOptions } from 'js-beautify';
6
6
 
7
- interface Asset {
8
- /**
9
- * The path to the asset's src file, relative to the project root.
10
- */
11
- src: string;
12
- /**
13
- * The serving URL for the asset.
14
- */
15
- assetUrl: string;
16
- /**
17
- * Recursively walks all deps and returns a list of CSS asset URLs.
18
- */
19
- getCssDeps(): Promise<string[]>;
20
- /**
21
- * Recursively walks all deps and returns a list of JS asset URLs.
22
- */
23
- getJsDeps(): Promise<string[]>;
7
+ declare class Hooks {
8
+ private callbacks;
9
+ add(name: string, cb: (...args: any[]) => any): void;
10
+ trigger(name: string, ...args: any[]): void;
24
11
  }
25
- interface AssetMap {
26
- /**
27
- * Returns the asset for a given src file. The `src` value should be a path
28
- * relative to the project root, e.g. "routes/index.tsx".
29
- */
30
- get: (src: string) => Promise<Asset | null>;
12
+
13
+ declare const SESSION_COOKIE = "__session";
14
+ interface SessionMiddlewareOptions {
15
+ maxAge?: number;
16
+ }
17
+ interface SaveSessionOptions {
18
+ sameSite?: 'strict' | 'lax' | 'none';
19
+ }
20
+ /**
21
+ * Middleware for storing session data stored in an http cookie called
22
+ * `__session`. This cookie is compatible with Firebase Hosting:
23
+ * https://firebase.google.com/docs/hosting/manage-cache#using_cookies
24
+ */
25
+ declare function sessionMiddleware(options?: SessionMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
26
+ declare class Session {
27
+ private data;
28
+ constructor(data?: Record<string, string>);
29
+ static fromCookieValue(cookieValue: string): Session;
30
+ getItem(key: string): string | null;
31
+ setItem(key: string, value: string): void;
32
+ removeItem(key: string): void;
33
+ toString(): string;
31
34
  }
32
35
 
36
+ declare type HtmlMinifyOptions = Options;
37
+
38
+ declare type HtmlPrettyOptions = HTMLBeautifyOptions;
39
+
33
40
  declare type MaybePromise<T> = T | Promise<T>;
34
41
  declare type ConfigureServerHook = (server: Server, options: ConfigureServerOptions) => MaybePromise<void> | MaybePromise<() => void>;
35
42
  interface ConfigureServerOptions {
@@ -70,10 +77,6 @@ interface Plugin {
70
77
  declare function configureServerPlugins(server: Server, callback: () => Promise<void>, plugins: Plugin[], options: ConfigureServerOptions): Promise<void>;
71
78
  declare function getVitePlugins(plugins: Plugin[]): PluginOption[];
72
79
 
73
- declare type HtmlMinifyOptions = Options;
74
-
75
- declare type HtmlPrettyOptions = HTMLBeautifyOptions;
76
-
77
80
  interface RootUserConfig {
78
81
  /**
79
82
  * Canonical domain the website will serve on. Useful for things like the
@@ -137,6 +140,10 @@ interface RootUserConfig {
137
140
  declare type RootConfig = RootUserConfig & {
138
141
  rootDir: string;
139
142
  };
143
+ interface LocaleGroup {
144
+ label?: string;
145
+ locales: string[];
146
+ }
140
147
  interface RootI18nConfig {
141
148
  /**
142
149
  * Locales enabled for the site.
@@ -150,13 +157,32 @@ interface RootI18nConfig {
150
157
  * URL format for localized content. Default is `/{locale}/{path}`.
151
158
  */
152
159
  urlFormat?: string;
160
+ /**
161
+ * Localization groups, to help UIs (like Root.js CMS) logically group
162
+ * locales.
163
+ */
164
+ groups?: Record<string, LocaleGroup>;
153
165
  }
154
166
  interface RootServerConfig {
155
167
  /**
156
168
  * An array of middleware to add to the express server. These middleware are
157
169
  * added to the beginning of the express app.
158
170
  */
159
- middlewares?: Array<(req: Request, res: Response, next: NextFunction) => void | Promise<void>>;
171
+ middlewares?: RequestMiddleware[];
172
+ /**
173
+ * The `trailingSlash` config allows you to control how the server handles
174
+ * trailing slashes. This config only affects URLs that do not have a file
175
+ * extension (i.e. HTML paths).
176
+ *
177
+ * - When `true`, the server redirects URLs to add a trailing slash
178
+ * - When `false`, the server redirects URLs to remove a trailing slash
179
+ * - When unspecified, the server allows URLs with and without trailing slash
180
+ */
181
+ trailingSlash?: boolean;
182
+ /**
183
+ * Cookie secret for the session middleware.
184
+ */
185
+ sessionCookieSecret?: string | string[];
160
186
  }
161
187
  declare function defineConfig(config: RootUserConfig): RootUserConfig;
162
188
 
@@ -184,6 +210,16 @@ declare class ElementGraph {
184
210
  constructor(sourceFiles: {
185
211
  [tagName: string]: ElementSourceFile;
186
212
  });
213
+ toJson(): {
214
+ sourceFiles: {
215
+ [tagName: string]: ElementSourceFile;
216
+ };
217
+ deps: Record<string, string[]>;
218
+ };
219
+ static fromJson(data: {
220
+ deps: any;
221
+ sourceFiles: any;
222
+ }): ElementGraph;
187
223
  getDeps(tagName: string, visited?: Set<string>): string[];
188
224
  /**
189
225
  * Parses an element's source file for usage of other custom elements.
@@ -191,6 +227,32 @@ declare class ElementGraph {
191
227
  private parseDepsFromSource;
192
228
  }
193
229
 
230
+ interface Asset {
231
+ /**
232
+ * The path to the asset's src file, relative to the project root.
233
+ */
234
+ src: string;
235
+ /**
236
+ * The serving URL for the asset.
237
+ */
238
+ assetUrl: string;
239
+ /**
240
+ * Recursively walks all deps and returns a list of CSS asset URLs.
241
+ */
242
+ getCssDeps(): Promise<string[]>;
243
+ /**
244
+ * Recursively walks all deps and returns a list of JS asset URLs.
245
+ */
246
+ getJsDeps(): Promise<string[]>;
247
+ }
248
+ interface AssetMap {
249
+ /**
250
+ * Returns the asset for a given src file. The `src` value should be a path
251
+ * relative to the project root, e.g. "routes/index.tsx".
252
+ */
253
+ get: (src: string) => Promise<Asset | null>;
254
+ }
255
+
194
256
  declare class Renderer {
195
257
  private rootConfig;
196
258
  private routes;
@@ -214,10 +276,14 @@ declare class Renderer {
214
276
  params: Record<string, string>;
215
277
  }>>;
216
278
  private renderHtml;
217
- render404(): Promise<{
279
+ render404(options?: {
280
+ currentPath?: string;
281
+ }): Promise<{
218
282
  html: string;
219
283
  }>;
220
- renderError(err: any): Promise<{
284
+ renderError(err: any, options?: {
285
+ currentPath?: string;
286
+ }): Promise<{
221
287
  html: string;
222
288
  }>;
223
289
  renderDevServer404(req: Request): Promise<{
@@ -249,6 +315,14 @@ declare type GetStaticProps<T = unknown> = (ctx: {
249
315
  }) => Promise<{
250
316
  /** Props to pass to the component. */
251
317
  props?: T;
318
+ /** The rendered locale. */
319
+ locale?: string;
320
+ /**
321
+ * Translations to pass to `useTranslations()`. If provided, the translations
322
+ * map passed here will be merged with the translations from
323
+ * `/translations/{locale}.json`.
324
+ */
325
+ translations?: Record<string, string>;
252
326
  /** Set to true if the route should result in a 404 page. */
253
327
  notFound?: boolean;
254
328
  }>;
@@ -262,8 +336,20 @@ declare type GetStaticPaths<T = RouteParams> = () => Promise<{
262
336
  params: T;
263
337
  }>;
264
338
  }>;
339
+ /** Multipart file type for the multipartMiddleware(). */
340
+ interface MultipartFile {
341
+ fieldname: string;
342
+ originalName: string;
343
+ encoding: string;
344
+ mimetype: string;
345
+ buffer: Buffer;
346
+ }
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);
265
348
  /** Root.js express app. */
266
- declare type Server = Express;
349
+ declare type Server = Express & {
350
+ use(middlewares: RequestMiddleware | RequestMiddleware[]): any;
351
+ use(urlPath: string, middlewares: RequestMiddleware | RequestMiddleware[]): any;
352
+ };
267
353
  /** Root.js express request. */
268
354
  declare type Request = Request$1 & {
269
355
  /** The root.js project config. */
@@ -279,9 +365,21 @@ declare type Request = Request$1 & {
279
365
  * function.
280
366
  */
281
367
  handlerContext?: HandlerContext;
368
+ hooks: Hooks;
369
+ /** Gets and sets session data via cookie. */
370
+ session: Session;
371
+ /** Firebase functions uses rawBody for its multipart data. */
372
+ rawBody?: any;
373
+ /** Map of field name to file. */
374
+ files?: {
375
+ [fieldname: string]: MultipartFile;
376
+ };
282
377
  };
283
378
  /** Root.js express response. */
284
- declare type Response = Response$1;
379
+ declare type Response = Response$1 & {
380
+ session: Session;
381
+ saveSession: () => void;
382
+ };
285
383
  /** Root.js express next function. */
286
384
  declare type NextFunction = NextFunction$1;
287
385
  /**
@@ -298,8 +396,19 @@ interface HandlerContext<T = any> {
298
396
  * pass `{slug: 'foo'}`.
299
397
  */
300
398
  params: RouteParams;
399
+ /**
400
+ * i18n locales to try for the user's http request. The priority order mimics
401
+ * the Firebase Hosting i18n fallback logic.
402
+ * https://firebase.google.com/docs/hosting/i18n-rewrites#priority-order
403
+ */
404
+ i18nFallbackLocales: string[];
405
+ /**
406
+ * Iterates through the i18nFallbackLocales and returns the first available
407
+ * locale.
408
+ */
409
+ getPreferredLocale: (availableLocales: string[]) => string;
301
410
  /** Renders the default exported component from the route. */
302
- render: (props: T) => Promise<void>;
411
+ render: HandlerRenderFn;
303
412
  /** Renders a 404 page. */
304
413
  render404: () => Promise<void>;
305
414
  }
@@ -323,6 +432,13 @@ interface Route {
323
432
  module: RouteModule;
324
433
  /** The locale used for the route. */
325
434
  locale: string;
435
+ /**
436
+ * Returns `true` if the route is the default locale route mapped without the
437
+ * i18n url prefix. For example, a route may be mapped to `/foo` and
438
+ * `/[locale]/foo`. The `/foo` route would have `route.isDefaultLocale` set to
439
+ * `true` whereas for `/[locale]/foo` it would be `false`.
440
+ */
441
+ isDefaultLocale: boolean;
326
442
  /**
327
443
  * The mapped URL path for the route, e.g.:
328
444
  *
@@ -339,5 +455,16 @@ interface Route {
339
455
  */
340
456
  localeRoutePath: string;
341
457
  }
458
+ interface HandlerRenderOptions {
459
+ /** The rendered locale. */
460
+ locale?: string;
461
+ /**
462
+ * Translations to pass to `useTranslations()`. If provided, the translations
463
+ * map passed here will be merged with the translations from
464
+ * `/translations/{locale}.json`.
465
+ */
466
+ translations?: Record<string, string>;
467
+ }
468
+ declare type HandlerRenderFn = (props: any, options?: HandlerRenderOptions) => Promise<void>;
342
469
 
343
- export { ConfigureServerHook as C, GetStaticProps as G, HandlerContext as H, 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, Request as k, Response as l, Handler as m, RouteModule as n, Renderer as o };
470
+ 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-beta.6",
3
+ "version": "1.0.0-beta.61",
4
4
  "author": "s@blinkk.com",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -27,16 +27,38 @@
27
27
  "types": "./dist/core.d.ts",
28
28
  "import": "./dist/core.js"
29
29
  },
30
+ "./cli": {
31
+ "types": "./dist/cli.d.ts",
32
+ "import": "./dist/cli.js"
33
+ },
30
34
  "./client": "./client.d.ts",
31
- "./*": {
32
- "types": "./dist/*.d.ts",
33
- "import": "./dist/*.js"
35
+ "./core": {
36
+ "types": "./dist/core.d.ts",
37
+ "import": "./dist/core.js"
38
+ },
39
+ "./functions": {
40
+ "types": "./dist/functions.d.ts",
41
+ "import": "./dist/functions.js"
42
+ },
43
+ "./middleware": {
44
+ "types": "./dist/middleware.d.ts",
45
+ "import": "./dist/middleware.js"
46
+ },
47
+ "./node": {
48
+ "types": "./dist/node.d.ts",
49
+ "import": "./dist/node.js"
50
+ },
51
+ "./render": {
52
+ "types": "./dist/render.d.ts",
53
+ "import": "./dist/render.js"
34
54
  }
35
55
  },
36
56
  "dependencies": {
37
57
  "bundle-require": "^4.0.1",
58
+ "busboy": "^1.6.0",
38
59
  "commander": "^10.0.0",
39
60
  "compression": "^1.7.4",
61
+ "cookie-parser": "^1.4.6",
40
62
  "esbuild": "0.17.12",
41
63
  "express": "^4.18.1",
42
64
  "fs-extra": "^10.1.0",
@@ -49,17 +71,31 @@
49
71
  "vite": "4.2.0"
50
72
  },
51
73
  "peerDependencies": {
74
+ "firebase-admin": ">=11",
75
+ "firebase-functions": ">=4",
52
76
  "preact": "10.x",
53
77
  "preact-render-to-string": "5.x"
54
78
  },
79
+ "peerDependenciesMeta": {
80
+ "firebase-functions": {
81
+ "optional": true
82
+ },
83
+ "firebase-admin": {
84
+ "optional": true
85
+ }
86
+ },
55
87
  "devDependencies": {
88
+ "@types/busboy": "^1.5.0",
56
89
  "@types/compression": "^1.7.2",
90
+ "@types/cookie-parser": "^1.4.3",
57
91
  "@types/express": "^4.17.13",
58
92
  "@types/fs-extra": "^9.0.13",
59
93
  "@types/html-minifier-terser": "^7.0.0",
60
94
  "@types/js-beautify": "^1.13.3",
61
95
  "@types/node": "^18.7.14",
62
96
  "@types/preact-custom-element": "^4.0.1",
97
+ "firebase-admin": "^11.5.0",
98
+ "firebase-functions": "^4.4.0",
63
99
  "nodemon": "^2.0.19",
64
100
  "preact": "^10.10.6",
65
101
  "preact-custom-element": "^4.2.1",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/plugin.ts"],"sourcesContent":["import {PluginOption as VitePlugin} from 'vite';\nimport {RootConfig} from './config';\nimport {Server} from './types';\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type ConfigureServerHook = (\n server: Server,\n options: ConfigureServerOptions\n) => MaybePromise<void> | MaybePromise<() => void>;\n\nexport interface ConfigureServerOptions {\n type: 'dev' | 'preview' | 'prod';\n rootConfig: RootConfig;\n}\n\nexport interface Plugin {\n [key: string]: any;\n /** The name of the plugin. */\n name?: string;\n /**\n * Configures the root.js express server. Any middleware defined by the plugin\n * will be added to the server first. If a callback fn is returned, it will\n * be called after the root.js middlewares are added.\n */\n configureServer?: ConfigureServerHook;\n /**\n * Returns a list of deps to bundle for ssr. The files will be bundled and\n * output to `dist/server/`. The return value should be a map of\n * `{output filename => input filepath}`.\n *\n * E.g. a value of `{foo: 'path/to/bar.js'}` will output `dist/server/foo.js`.\n *\n * @experimental This config is subject to change to be incorporated into a\n * broader config option called \"ssr\" or \"ssrOptions\".\n */\n ssrInput?: () => {[entryAlias: string]: string};\n /** Adds vite plugins. */\n vitePlugins?: VitePlugin[];\n}\n\n/**\n * Runs the pre-hook configureServer method of every plugin, calls a callback\n * function, and then runs the configureServer's post-hook if provided. Plugins\n * provide a post-hook by returning a callback function from configureServer.\n */\nexport async function configureServerPlugins(\n server: Server,\n callback: () => Promise<void>,\n plugins: Plugin[],\n options: ConfigureServerOptions\n) {\n const postHooks: Array<() => void> = [];\n\n // Call the `configureServer()` method for each plugin.\n for (const plugin of plugins) {\n if (plugin.configureServer) {\n const postHook = await plugin.configureServer(server, options);\n if (postHook) {\n postHooks.push(postHook);\n }\n }\n }\n\n // Register any built-in middleware.\n callback();\n\n // Run any post hooks returned by `plugin.configureServer()`.\n for (const postHook of postHooks) {\n await postHook();\n }\n}\n\nexport function getVitePlugins(plugins: Plugin[]): VitePlugin[] {\n const vitePlugins: VitePlugin[] = [];\n for (const plugin of plugins) {\n if (plugin.vitePlugins) {\n vitePlugins.push(...plugin.vitePlugins);\n }\n }\n return vitePlugins;\n}\n"],"mappings":";AA8CA,eAAsB,uBACpB,QACA,UACA,SACA,SACA;AACA,QAAM,YAA+B,CAAC;AAGtC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,iBAAiB;AAC1B,YAAM,WAAW,MAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC7D,UAAI,UAAU;AACZ,kBAAU,KAAK,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAGA,WAAS;AAGT,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS;AAAA,EACjB;AACF;AAEO,SAAS,eAAe,SAAiC;AAC9D,QAAM,cAA4B,CAAC;AACnC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,aAAa;AACtB,kBAAY,KAAK,GAAG,OAAO,WAAW;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/node/load-config.ts","../src/utils/fsutils.ts","../src/node/vite.ts"],"sourcesContent":["import path from 'node:path';\nimport {bundleRequire} from 'bundle-require';\nimport {RootConfig} from '../core/config';\nimport {fileExists} from '../utils/fsutils';\n\nexport interface ConfigOptions {\n command: string;\n}\n\nexport async function loadRootConfig(\n rootDir: string,\n options: ConfigOptions\n): Promise<RootConfig> {\n const configPath = path.resolve(rootDir, 'root.config.ts');\n const exists = await fileExists(configPath);\n if (!exists) {\n throw new Error(`${configPath} does not exist`);\n }\n const configBundle = await bundleRequire({\n filepath: configPath,\n });\n let config = configBundle.mod.default || {};\n if (typeof config === 'function') {\n config = (await config(options)) || {};\n }\n return Object.assign({}, config, {rootDir});\n}\n","import {promises as fs} from 'node:fs';\nimport path from 'node:path';\nimport fsExtra from 'fs-extra';\nimport glob from 'tiny-glob';\n\nexport function isJsFile(filename: string) {\n return !!filename.match(/\\.(j|t)sx?$/);\n}\n\nexport async function writeFile(filepath: string, content: string) {\n const dirPath = path.dirname(filepath);\n await makeDir(dirPath);\n await fs.writeFile(filepath, content);\n}\n\nexport async function makeDir(dirpath: string) {\n try {\n await fs.access(dirpath);\n } catch (e) {\n await fs.mkdir(dirpath, {recursive: true});\n }\n}\n\nexport async function copyDir(srcdir: string, dstdir: string) {\n if (!fsExtra.existsSync(srcdir)) {\n return;\n }\n fsExtra.copySync(srcdir, dstdir, {recursive: true, overwrite: true});\n}\n\n/**\n * Copies a glob of files from one directory to another.\n *\n * Example:\n *\n * ```\n * await copyGlob('*.css', 'src/styles', 'dist/html/styles');\n * ```\n */\nexport async function copyGlob(\n pattern: string,\n srcdir: string,\n dstdir: string\n) {\n const files = await glob(pattern, {cwd: srcdir});\n if (files.length > 0) {\n await makeDir(dstdir);\n }\n files.forEach((file) => {\n fsExtra.copySync(path.resolve(srcdir, file), path.resolve(dstdir, file));\n });\n}\n\nexport async function rmDir(dirpath: string) {\n await fs.rm(dirpath, {recursive: true, force: true});\n}\n\nexport async function loadJson<T = unknown>(filepath: string): Promise<T> {\n const content = await fs.readFile(filepath, 'utf-8');\n return JSON.parse(content);\n}\n\nexport async function isDirectory(dirpath: string) {\n return fs\n .stat(dirpath)\n .then((fsStat) => {\n return fsStat.isDirectory();\n })\n .catch((err) => {\n if (err.code === 'ENOENT') {\n return false;\n }\n throw err;\n });\n}\n\nexport function fileExists(filepath: string): Promise<boolean> {\n return fs\n .access(filepath)\n .then(() => true)\n .catch(() => false);\n}\n\nexport async function directoryContains(\n dirpath: string,\n subpath: string\n): Promise<boolean> {\n const outer = await fs.realpath(dirpath);\n const inner = await fs.realpath(subpath);\n const rel = path.relative(outer, inner);\n return !rel.startsWith('..');\n}\n","import path from 'node:path';\nimport {createServer, ViteDevServer} from 'vite';\nimport {getVitePlugins} from '../core/plugin.js';\nimport {RootConfig} from '../core/config.js';\n\nexport interface CreateViteServerOptions {\n /** Override HMR settings. */\n hmr?: boolean;\n /** The port the server will run on. */\n port?: number;\n /** List of files to include in the optimizeDeps.include config. */\n optimizeDeps?: string[];\n}\n\n/**\n * Returns a vite dev server.\n */\nexport async function createViteServer(\n rootConfig: RootConfig,\n options?: CreateViteServerOptions\n): Promise<ViteDevServer> {\n const rootDir = rootConfig.rootDir;\n const viteConfig = rootConfig.vite || {};\n\n let hmrOptions = viteConfig.server?.hmr;\n if (options?.hmr === false) {\n hmrOptions = false;\n } else if (typeof hmrOptions === 'undefined' && options?.port) {\n // Automatically set the HMR port to `port + 10`. This allows multiple\n // root.js dev servers to run without conflicts.\n hmrOptions = {port: options.port + 10};\n }\n\n const viteServer = await createServer({\n ...viteConfig,\n mode: 'development',\n root: rootDir,\n publicDir: path.join(rootDir, 'public'),\n server: {\n ...(viteConfig.server || {}),\n middlewareMode: true,\n hmr: hmrOptions,\n },\n appType: 'custom',\n optimizeDeps: {\n ...(viteConfig.optimizeDeps || {}),\n include: [\n ...(options?.optimizeDeps || []),\n ...(viteConfig.optimizeDeps?.include || []),\n ],\n },\n ssr: {\n ...(viteConfig.ssr || {}),\n noExternal: ['@blinkk/root'],\n },\n esbuild: {\n ...(viteConfig.esbuild || {}),\n jsx: 'automatic',\n jsxImportSource: 'preact',\n },\n plugins: [\n ...(viteConfig.plugins || []),\n ...getVitePlugins(rootConfig.plugins || []),\n ],\n });\n return viteServer;\n}\n\n/**\n * Shortcut `viteServer.ssrLoadModule()` without starting an actual dev server.\n */\nexport async function viteSsrLoadModule(\n rootConfig: RootConfig,\n file: string\n): Promise<Record<string, any>> {\n const viteServer = await createViteServer(rootConfig, {hmr: false});\n const module = await viteServer.ssrLoadModule(file);\n await viteServer.close();\n return module;\n}\n"],"mappings":"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","names":["path","path","path","path"]}