UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

1 lines • 8.93 kB
{"version":3,"file":"createSsrServerlessFunction.js","names":[],"sources":["esm/vercel/build/generate/createSsrServerlessFunction.js"],"sourcesContent":["import { join, resolve } from \"node:path\";\nimport fs from \"fs-extra\";\nimport { serverlessVercelNodeJsConfig } from \"../config/vc-config-base\";\nimport { serverlessVercelPackageJson } from \"../config/vc-package-base\";\nimport { getPathFromRoute } from \"../getPathFromRoute\";\nasync function createSsrServerlessFunction(route, buildInfo, oneOptionsRoot, postBuildLogs) {\n try {\n const path = getPathFromRoute(route, { includeIndex: true });\n postBuildLogs.push(`[one.build][vercel.createSsrServerlessFunction] path: ${path}`);\n const buildInfoAsString = JSON.stringify(buildInfo);\n const funcFolder = resolve(\n join(oneOptionsRoot, `.vercel/output/functions/${path}.func`)\n );\n await fs.ensureDir(funcFolder);\n const outDir = buildInfo.outDir || \"dist\";\n const distServerFrom = resolve(join(oneOptionsRoot, outDir, \"server\"));\n const distServerTo = resolve(join(funcFolder, \"server\"));\n await fs.ensureDir(distServerTo);\n postBuildLogs.push(\n `[one.build][vercel.createSsrServerlessFunction] copy server dist files from ${distServerFrom} to ${distServerTo}`\n );\n await fs.copy(distServerFrom, distServerTo);\n postBuildLogs.push(\n `[one.build][vercel.createSsrServerlessFunction] writing buildInfo.json`\n );\n await fs.writeFile(\n join(funcFolder, \"buildInfo.js\"),\n `export default ${buildInfoAsString}`\n );\n await fs.ensureDir(join(funcFolder, \"entrypoint\"));\n const entrypointFilePath = resolve(join(funcFolder, \"entrypoint\", \"index.js\"));\n postBuildLogs.push(\n `[one.build][vercel.createSsrServerlessFunction] writing entrypoint to ${entrypointFilePath}`\n );\n await fs.writeFile(\n entrypointFilePath,\n `\n const buildInfoConfig = await import('../buildInfo.js');\n const entry = await import('../server/_virtual_one-entry.js');\n const routeFile = ${JSON.stringify(route.file)}\n\n const handler = async (req, res) => {\n // console.debug(\"req.url\", req.url);\n const url = new URL(req.url, \\`https://\\${process.env.VERCEL_URL}\\`);\n\n // Check if this is a loader request (routed here by config.json rewrite)\n const isLoaderRequest = url.searchParams.get('__loader') === '1';\n\n // Extract route params - from URL path match OR from query params (for loader requests)\n const routePattern = ${JSON.stringify(route.page)};\n const paramNames = [];\n const regexPattern = routePattern\n .replace(/\\\\[\\\\.\\\\.\\\\.(\\\\w+)\\\\]/g, (_, name) => { paramNames.push({ name, catch: true }); return '(.+)'; })\n .replace(/\\\\[(\\\\w+)\\\\]/g, (_, name) => { paramNames.push({ name, catch: false }); return '([^/]+)'; });\n\n const routeParams = {};\n\n // First try to get params from query string (set by Vercel rewrite rules)\n // This handles both loader requests and regular page requests that went through rewrites\n for (const param of paramNames) {\n const value = url.searchParams.get(param.name);\n if (value) {\n routeParams[param.name] = param.catch ? value.split('/') : value;\n }\n }\n\n // If no params found in query string, try extracting from URL path\n if (Object.keys(routeParams).length === 0) {\n const match = url.pathname.match(new RegExp(\\`^\\${regexPattern}$\\`));\n if (match) {\n paramNames.forEach((param, index) => {\n const value = match[index + 1];\n routeParams[param.name] = param.catch ? value.split('/') : value;\n });\n }\n }\n\n // Create a proper Request object for SSR loaders\n const request = new Request(url.toString(), {\n method: req.method || 'GET',\n headers: new Headers(req.headers || {}),\n });\n\n // Reconstruct the original path by replacing [param] placeholders with actual values\n // The pathname might be the rewritten path (e.g., /dynamic/[id] instead of /dynamic/123)\n let originalPath = url.pathname;\n for (const [key, value] of Object.entries(routeParams)) {\n originalPath = originalPath.replace(\n new RegExp(\\`(\\\\\\\\[|%5B)(\\\\\\\\.\\\\\\\\.\\\\\\\\.)?\\${key}(\\\\\\\\]|%5D)\\`, 'i'),\n () => (Array.isArray(value) ? value.join('/') : value)\n );\n }\n\n const host = url.hostname;\n let subdomain;\n if (host && host !== 'localhost' && !/^\\\\d+\\\\.\\\\d+\\\\.\\\\d+\\\\.\\\\d+$/.test(host)) {\n const parts = host.split('.');\n if (parts.length >= 3) subdomain = parts.slice(0, -2).join('.');\n }\n\n const loaderProps = {\n path: originalPath,\n params: routeParams,\n subdomain,\n request,\n }\n\n const postfix = url.pathname.endsWith('/') ? 'index.tsx' : '+ssr.tsx';\n // const routeFile = \\`.\\${url.pathname}\\${postfix}\\`;\n let route = buildInfoConfig.default.routeToBuildInfo[routeFile];\n\n // If we cannot find the route by direct match, try to find it by looking it up in the\n // pathToRoute mapping. Currently this handles cases such as \"(some-group)/index.tsx\",\n // \"index.web.tsx\".\n if (!route) {\n const routeName = buildInfoConfig.default.pathToRoute[url.pathname];\n route = buildInfoConfig.default.routeToBuildInfo[routeName];\n }\n\n const exported = await import(route.serverJsPath.replace('${outDir}/','../'))\n const loaderData = await exported.loader?.(loaderProps)\n\n // For loader requests, return the loader data as a JavaScript module\n if (isLoaderRequest) {\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8')\n res.setHeader('Cache-Control', 'no-store')\n res.end(\\`export function loader() { return \\${JSON.stringify(loaderData)} }\\`)\n return\n }\n\n // For page requests, render the full HTML\n const render = entry.default.render;\n const preloads = route.preloads\n const css = route.css || []\n const rendered = await render({\n mode: route.type,\n loaderData,\n loaderProps,\n path: loaderProps?.path || '/',\n preloads,\n css,\n })\n res.setHeader('Content-Type', 'text/html; charset=utf-8')\n // https://vercel.com/docs/deployments/skew-protection#supported-frameworks__\n if (process.env.VERCEL_SKEW_PROTECTION_ENABLED === '1') {\n res.setHeader('Set-Cookie', [\n \\`__vdpl=\\${process.env.VERCEL_DEPLOYMENT_ID}; HttpOnly\\`,\n ]);\n }\n res.end(rendered)\n }\n\n export default handler;\n `\n );\n const packageJsonFilePath = resolve(join(funcFolder, \"package.json\"));\n postBuildLogs.push(\n `[one.build][vercel.createSsrServerlessFunction] writing package.json to ${packageJsonFilePath}`\n );\n await fs.writeJSON(packageJsonFilePath, serverlessVercelPackageJson);\n const vcConfigFilePath = resolve(join(funcFolder, \".vc-config.json\"));\n postBuildLogs.push(\n `[one.build][vercel.createSsrServerlessFunction] writing .vc-config.json to ${vcConfigFilePath}`\n );\n return fs.writeJson(vcConfigFilePath, {\n ...serverlessVercelNodeJsConfig,\n handler: \"entrypoint/index.js\",\n environment: {\n ...serverlessVercelNodeJsConfig.environment,\n ONE_DEFAULT_RENDER_MODE: \"ssr\"\n }\n });\n } catch (e) {\n console.error(\n `[one.build][vercel.createSsrServerlessFunction] failed to generate func for ${route.file}`,\n e\n );\n }\n}\nexport {\n createSsrServerlessFunction\n};\n//# sourceMappingURL=createSsrServerlessFunction.js.map\n"],"mappings":";;;;;;;AAKA,eAAe,4BAA4B,OAAO,WAAW,gBAAgB,eAAe;CAC1F,IAAI;EACF,MAAM,OAAO,iBAAiB,OAAO,EAAE,cAAc,KAAK,CAAC;EAC3D,cAAc,KAAK,yDAAyD,MAAM;EAClF,MAAM,oBAAoB,KAAK,UAAU,SAAS;EAClD,MAAM,aAAa,QACjB,KAAK,gBAAgB,4BAA4B,KAAK,MAAM,CAC9D;EACA,MAAM,GAAG,UAAU,UAAU;EAC7B,MAAM,SAAS,UAAU,UAAU;EACnC,MAAM,iBAAiB,QAAQ,KAAK,gBAAgB,QAAQ,QAAQ,CAAC;EACrE,MAAM,eAAe,QAAQ,KAAK,YAAY,QAAQ,CAAC;EACvD,MAAM,GAAG,UAAU,YAAY;EAC/B,cAAc,KACZ,+EAA+E,eAAe,MAAM,cACtG;EACA,MAAM,GAAG,KAAK,gBAAgB,YAAY;EAC1C,cAAc,KACZ,wEACF;EACA,MAAM,GAAG,UACP,KAAK,YAAY,cAAc,GAC/B,kBAAkB,mBACpB;EACA,MAAM,GAAG,UAAU,KAAK,YAAY,YAAY,CAAC;EACjD,MAAM,qBAAqB,QAAQ,KAAK,YAAY,cAAc,UAAU,CAAC;EAC7E,cAAc,KACZ,yEAAyE,oBAC3E;EACA,MAAM,GAAG,UACP,oBACA;;;sBAGgB,KAAK,UAAU,MAAM,IAAI,EAAE;;;;;;;;;;2BAUtB,KAAK,UAAU,MAAM,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAsEU,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCnE;EACA,MAAM,sBAAsB,QAAQ,KAAK,YAAY,cAAc,CAAC;EACpE,cAAc,KACZ,2EAA2E,qBAC7E;EACA,MAAM,GAAG,UAAU,qBAAqB,2BAA2B;EACnE,MAAM,mBAAmB,QAAQ,KAAK,YAAY,iBAAiB,CAAC;EACpE,cAAc,KACZ,8EAA8E,kBAChF;EACA,OAAO,GAAG,UAAU,kBAAkB;GACpC,GAAG;GACH,SAAS;GACT,aAAa;IACX,GAAG,6BAA6B;IAChC,yBAAyB;GAC3B;EACF,CAAC;CACH,SAAS,GAAG;EACV,QAAQ,MACN,+EAA+E,MAAM,QACrF,CACF;CACF;AACF"}