@blinkk/root 1.0.6 → 1.0.7
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.
- package/dist/{chunk-MLPPFGKW.js → chunk-BMKSXG4B.js} +2 -2
- package/dist/{chunk-MLPPFGKW.js.map → chunk-BMKSXG4B.js.map} +1 -1
- package/dist/{chunk-YKQ4SVXX.js → chunk-G5ALYSEQ.js} +2 -2
- package/dist/{chunk-7Z2GR6V5.js → chunk-GNRN2XDJ.js} +144 -63
- package/dist/chunk-GNRN2XDJ.js.map +1 -0
- package/dist/{chunk-6JZGMQBR.js → chunk-WICFYADD.js} +1 -1
- package/dist/chunk-WICFYADD.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -4
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/functions.js +4 -4
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/render.d.ts +1 -1
- package/dist/render.js +9 -0
- package/dist/render.js.map +1 -1
- package/dist/{types-yoz1mf3y.d.ts → types-E50PeqBX.d.ts} +11 -1
- package/package.json +1 -1
- package/dist/chunk-6JZGMQBR.js.map +0 -1
- package/dist/chunk-7Z2GR6V5.js.map +0 -1
- /package/dist/{chunk-YKQ4SVXX.js.map → chunk-G5ALYSEQ.js.map} +0 -0
|
@@ -143,7 +143,7 @@ function sessionMiddleware(options) {
|
|
|
143
143
|
sameSite
|
|
144
144
|
});
|
|
145
145
|
};
|
|
146
|
-
req.hooks.add("
|
|
146
|
+
req.hooks.add("preRender", () => {
|
|
147
147
|
res.saveSession();
|
|
148
148
|
});
|
|
149
149
|
next();
|
|
@@ -200,4 +200,4 @@ export {
|
|
|
200
200
|
sessionMiddleware,
|
|
201
201
|
Session
|
|
202
202
|
};
|
|
203
|
-
//# sourceMappingURL=chunk-
|
|
203
|
+
//# sourceMappingURL=chunk-BMKSXG4B.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware/common.ts","../src/middleware/multipart.ts","../src/middleware/session.ts"],"sourcesContent":["import path from 'node:path';\nimport micromatch from 'micromatch';\nimport {RootConfig} from '../core/config.js';\nimport {Request, Response, NextFunction} from '../core/types.js';\n\n/**\n * Middleware that injects the root.js project config into the request context.\n */\nexport function rootProjectMiddleware(options: {rootConfig: RootConfig}) {\n return (req: Request, _: Response, next: NextFunction) => {\n req.rootConfig = options.rootConfig;\n next();\n };\n}\n\n/**\n * Middleware that injects HTTP headers from the `server.headers` config in\n * root.config.ts.\n */\nexport function headersMiddleware(options: {rootConfig: RootConfig}) {\n const headersUserConfig = options.rootConfig.server?.headers || [];\n // Filter header config values that are invalid.\n const headersConfig = headersUserConfig.filter((headerConfig) => {\n return (\n headerConfig.source &&\n headerConfig.headers &&\n headerConfig.headers.length > 0\n );\n });\n return (req: Request, res: Response, next: NextFunction) => {\n headersConfig.forEach((headerConfig) => {\n if (micromatch.isMatch(req.path, headerConfig.source)) {\n headerConfig.headers.forEach((header) => {\n if (header.key) {\n res.setHeader(String(header.key), String(header.value));\n }\n });\n }\n });\n next();\n };\n}\n\n/**\n * Trailing slash middleware. Handles trailing slash redirects (preserving any\n * query params) using the `server.trailingSlash` config in root.config.ts.\n */\nexport function trailingSlashMiddleware(options: {rootConfig: RootConfig}) {\n const trailingSlash = options.rootConfig.server?.trailingSlash;\n\n return (req: Request, res: Response, next: NextFunction) => {\n // If `trailingSlash: false`, force a trailing slash in the URL.\n if (\n trailingSlash === true &&\n !path.extname(req.path) &&\n !req.path.endsWith('/')\n ) {\n const redirectPath = `${req.path}/`;\n redirectWithQuery(req, res, 301, redirectPath);\n return;\n }\n\n // If `trailingSlash: false`, remove any trailing slash from the URL.\n if (\n trailingSlash === false &&\n !path.extname(req.path) &&\n req.path !== '/' &&\n req.path.endsWith('/')\n ) {\n const redirectPath = removeTrailingSlashes(req.path);\n redirectWithQuery(req, res, 301, redirectPath);\n return;\n }\n\n next();\n };\n}\n\n/**\n * Issues an HTTP redirect, preserving any query params from the original req.\n */\nfunction redirectWithQuery(\n req: Request,\n res: Response,\n redirectCode: number,\n redirectPath: string\n) {\n const queryStr = getQueryStr(req);\n const redirectUrl = queryStr ? `${redirectPath}?${queryStr}` : redirectPath;\n res.redirect(redirectCode, redirectUrl);\n}\n\n/**\n * Returns the query string for a request, or empty string if no query.\n */\nfunction getQueryStr(req: Request): string {\n const qIndex = req.originalUrl.indexOf('?');\n if (qIndex === -1) {\n return '';\n }\n return req.originalUrl.slice(qIndex + 1);\n}\n\n/**\n * Removes trailing slashes from a URL path.\n * Note: A path with only slashes (e.g. `///`) returns `/`.\n */\nfunction removeTrailingSlashes(urlPath: string) {\n while (urlPath.endsWith('/') && urlPath !== '/') {\n urlPath = urlPath.slice(0, -1);\n }\n return urlPath;\n}\n","import busboy from 'busboy';\nimport {RequestHandler} from 'express';\nimport {Request, Response, NextFunction, MultipartFile} from '../core/types.js';\n\nconst DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\n\n/**\n * Middleware for parsing multipart file uploads that's compatible with the dev\n * server and Firebase Functions.\n *\n * Context:\n * https://stackoverflow.com/questions/47242340/how-to-perform-an-http-file-upload-using-express-on-cloud-functions-for-firebase\n */\nexport function multipartMiddleware(options?: {\n maxFileSize?: number;\n}): RequestHandler {\n const maxFileSize = options?.maxFileSize || DEFAULT_MAX_FILE_SIZE;\n const handler: any = (req: Request, res: Response, next: NextFunction) => {\n const contentType = String(req.headers['content-type'] || '');\n if (\n req.method === 'POST' &&\n contentType.startsWith('multipart/form-data')\n ) {\n const parser = busboy({headers: req.headers});\n\n // Data storage for fields and files\n const fields: {[fieldname: string]: string} = {};\n const files: {[name: string]: MultipartFile} = {};\n\n // Handle field data.\n parser.on('field', (fieldname: string, val: any) => {\n fields[fieldname] = val;\n });\n\n // Handle file data. Files are saved to an in-memory buffer.\n parser.on(\n 'file',\n (\n fieldname: string,\n file: any,\n meta: {\n filename: string;\n encoding: string;\n mimeType: string;\n }\n ) => {\n const {filename, encoding, mimeType: mimetype} = meta;\n const fileChunks: Uint8Array[] = [];\n let totalBytesRead = 0;\n\n file.on('data', (chunk: Uint8Array) => {\n totalBytesRead += chunk.length;\n\n if (totalBytesRead > maxFileSize) {\n // File size exceeds the limit, stop reading.\n console.error(`File size exceeds the limit: ${fieldname}.`);\n file.removeAllListeners('data');\n // Consume and discard remaining data.\n file.resume();\n } else {\n fileChunks.push(chunk);\n }\n });\n\n file.on('end', () => {\n if (totalBytesRead <= maxFileSize) {\n const buffer = Buffer.concat(fileChunks);\n\n files[fieldname] = {\n fieldname,\n buffer,\n originalName: filename,\n encoding,\n mimetype,\n };\n }\n });\n }\n );\n\n // Update `req.body` and `req.files`.\n parser.on('finish', () => {\n req.body = fields;\n req.files = files;\n next();\n });\n\n // Pipe the request to Busboy. On Firebase Functions, `rawBody` contains\n // the multipart request. Otherwise the express request can be piped to\n // the Busboy parser.\n if (req.rawBody) {\n parser.end(req.rawBody);\n } else {\n req.pipe(parser);\n }\n } else {\n next();\n }\n };\n return handler;\n}\n","import {NextFunction, Request, Response} from '../core/types.js';\n\nexport const SESSION_COOKIE = '__session';\n\n// 5 days.\nconst DEFAULT_MAX_AGE = 60 * 60 * 24 * 5 * 1000;\n\nexport interface SessionMiddlewareOptions {\n maxAge?: number;\n}\n\nexport interface SaveSessionOptions {\n sameSite?: 'strict' | 'lax' | 'none';\n}\n\n/**\n * Middleware for storing session data stored in an http cookie called\n * `__session`. This cookie is compatible with Firebase Hosting:\n * https://firebase.google.com/docs/hosting/manage-cache#using_cookies\n */\nexport function sessionMiddleware(options?: SessionMiddlewareOptions) {\n const maxAge = options?.maxAge || DEFAULT_MAX_AGE;\n return (req: Request, res: Response, next: NextFunction) => {\n const cookieValue = String(req.signedCookies[SESSION_COOKIE] || '');\n const session = Session.fromCookieValue(cookieValue);\n req.session = session;\n res.session = session;\n res.saveSession = (saveSessionOptions?: SaveSessionOptions) => {\n // \"secure\" cookies require https, so disable \"secure\" when in development.\n const secureCookie = Boolean(process.env.NODE_ENV !== 'development');\n const cookieValue = session.toString();\n const sameSite = saveSessionOptions?.sameSite || 'strict';\n res.cookie(SESSION_COOKIE, cookieValue, {\n maxAge: maxAge,\n httpOnly: true,\n secure: secureCookie,\n signed: true,\n sameSite: sameSite,\n });\n };\n req.hooks.add('beforeRender', () => {\n res.saveSession();\n });\n next();\n };\n}\n\nexport class Session {\n private data: Record<string, string> = {};\n\n constructor(data?: Record<string, string>) {\n this.data = data || {};\n }\n\n static fromCookieValue(cookieValue: string) {\n const data: Record<string, string> = {};\n if (cookieValue.startsWith('b64:')) {\n try {\n const encodedStr = cookieValue.slice(4);\n const params = new URLSearchParams(base64Decode(encodedStr));\n for (const [key, value] of params.entries()) {\n data[key] = value;\n }\n } catch (err) {\n console.warn('failed to parse session cookie:', err);\n return new Session();\n }\n }\n return new Session(data);\n }\n\n getItem(key: string): string | null {\n return this.data[key] ?? null;\n }\n\n setItem(key: string, value: string) {\n this.data[key] = value;\n }\n\n removeItem(key: string) {\n delete this.data[key];\n }\n\n toString(): string {\n const params = new URLSearchParams(this.data);\n return `b64:${base64Encode(params.toString())}`;\n }\n}\n\nfunction base64Encode(str: string): string {\n return Buffer.from(str, 'utf-8').toString('base64');\n}\n\nfunction base64Decode(str: string): string {\n return Buffer.from(str, 'base64').toString('utf-8');\n}\n"],"mappings":"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","names":["cookieValue"]}
|
|
1
|
+
{"version":3,"sources":["../src/middleware/common.ts","../src/middleware/multipart.ts","../src/middleware/session.ts"],"sourcesContent":["import path from 'node:path';\nimport micromatch from 'micromatch';\nimport {RootConfig} from '../core/config.js';\nimport {Request, Response, NextFunction} from '../core/types.js';\n\n/**\n * Middleware that injects the root.js project config into the request context.\n */\nexport function rootProjectMiddleware(options: {rootConfig: RootConfig}) {\n return (req: Request, _: Response, next: NextFunction) => {\n req.rootConfig = options.rootConfig;\n next();\n };\n}\n\n/**\n * Middleware that injects HTTP headers from the `server.headers` config in\n * root.config.ts.\n */\nexport function headersMiddleware(options: {rootConfig: RootConfig}) {\n const headersUserConfig = options.rootConfig.server?.headers || [];\n // Filter header config values that are invalid.\n const headersConfig = headersUserConfig.filter((headerConfig) => {\n return (\n headerConfig.source &&\n headerConfig.headers &&\n headerConfig.headers.length > 0\n );\n });\n return (req: Request, res: Response, next: NextFunction) => {\n headersConfig.forEach((headerConfig) => {\n if (micromatch.isMatch(req.path, headerConfig.source)) {\n headerConfig.headers.forEach((header) => {\n if (header.key) {\n res.setHeader(String(header.key), String(header.value));\n }\n });\n }\n });\n next();\n };\n}\n\n/**\n * Trailing slash middleware. Handles trailing slash redirects (preserving any\n * query params) using the `server.trailingSlash` config in root.config.ts.\n */\nexport function trailingSlashMiddleware(options: {rootConfig: RootConfig}) {\n const trailingSlash = options.rootConfig.server?.trailingSlash;\n\n return (req: Request, res: Response, next: NextFunction) => {\n // If `trailingSlash: false`, force a trailing slash in the URL.\n if (\n trailingSlash === true &&\n !path.extname(req.path) &&\n !req.path.endsWith('/')\n ) {\n const redirectPath = `${req.path}/`;\n redirectWithQuery(req, res, 301, redirectPath);\n return;\n }\n\n // If `trailingSlash: false`, remove any trailing slash from the URL.\n if (\n trailingSlash === false &&\n !path.extname(req.path) &&\n req.path !== '/' &&\n req.path.endsWith('/')\n ) {\n const redirectPath = removeTrailingSlashes(req.path);\n redirectWithQuery(req, res, 301, redirectPath);\n return;\n }\n\n next();\n };\n}\n\n/**\n * Issues an HTTP redirect, preserving any query params from the original req.\n */\nfunction redirectWithQuery(\n req: Request,\n res: Response,\n redirectCode: number,\n redirectPath: string\n) {\n const queryStr = getQueryStr(req);\n const redirectUrl = queryStr ? `${redirectPath}?${queryStr}` : redirectPath;\n res.redirect(redirectCode, redirectUrl);\n}\n\n/**\n * Returns the query string for a request, or empty string if no query.\n */\nfunction getQueryStr(req: Request): string {\n const qIndex = req.originalUrl.indexOf('?');\n if (qIndex === -1) {\n return '';\n }\n return req.originalUrl.slice(qIndex + 1);\n}\n\n/**\n * Removes trailing slashes from a URL path.\n * Note: A path with only slashes (e.g. `///`) returns `/`.\n */\nfunction removeTrailingSlashes(urlPath: string) {\n while (urlPath.endsWith('/') && urlPath !== '/') {\n urlPath = urlPath.slice(0, -1);\n }\n return urlPath;\n}\n","import busboy from 'busboy';\nimport {RequestHandler} from 'express';\nimport {Request, Response, NextFunction, MultipartFile} from '../core/types.js';\n\nconst DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\n\n/**\n * Middleware for parsing multipart file uploads that's compatible with the dev\n * server and Firebase Functions.\n *\n * Context:\n * https://stackoverflow.com/questions/47242340/how-to-perform-an-http-file-upload-using-express-on-cloud-functions-for-firebase\n */\nexport function multipartMiddleware(options?: {\n maxFileSize?: number;\n}): RequestHandler {\n const maxFileSize = options?.maxFileSize || DEFAULT_MAX_FILE_SIZE;\n const handler: any = (req: Request, res: Response, next: NextFunction) => {\n const contentType = String(req.headers['content-type'] || '');\n if (\n req.method === 'POST' &&\n contentType.startsWith('multipart/form-data')\n ) {\n const parser = busboy({headers: req.headers});\n\n // Data storage for fields and files\n const fields: {[fieldname: string]: string} = {};\n const files: {[name: string]: MultipartFile} = {};\n\n // Handle field data.\n parser.on('field', (fieldname: string, val: any) => {\n fields[fieldname] = val;\n });\n\n // Handle file data. Files are saved to an in-memory buffer.\n parser.on(\n 'file',\n (\n fieldname: string,\n file: any,\n meta: {\n filename: string;\n encoding: string;\n mimeType: string;\n }\n ) => {\n const {filename, encoding, mimeType: mimetype} = meta;\n const fileChunks: Uint8Array[] = [];\n let totalBytesRead = 0;\n\n file.on('data', (chunk: Uint8Array) => {\n totalBytesRead += chunk.length;\n\n if (totalBytesRead > maxFileSize) {\n // File size exceeds the limit, stop reading.\n console.error(`File size exceeds the limit: ${fieldname}.`);\n file.removeAllListeners('data');\n // Consume and discard remaining data.\n file.resume();\n } else {\n fileChunks.push(chunk);\n }\n });\n\n file.on('end', () => {\n if (totalBytesRead <= maxFileSize) {\n const buffer = Buffer.concat(fileChunks);\n\n files[fieldname] = {\n fieldname,\n buffer,\n originalName: filename,\n encoding,\n mimetype,\n };\n }\n });\n }\n );\n\n // Update `req.body` and `req.files`.\n parser.on('finish', () => {\n req.body = fields;\n req.files = files;\n next();\n });\n\n // Pipe the request to Busboy. On Firebase Functions, `rawBody` contains\n // the multipart request. Otherwise the express request can be piped to\n // the Busboy parser.\n if (req.rawBody) {\n parser.end(req.rawBody);\n } else {\n req.pipe(parser);\n }\n } else {\n next();\n }\n };\n return handler;\n}\n","import {NextFunction, Request, Response} from '../core/types.js';\n\nexport const SESSION_COOKIE = '__session';\n\n// 5 days.\nconst DEFAULT_MAX_AGE = 60 * 60 * 24 * 5 * 1000;\n\nexport interface SessionMiddlewareOptions {\n maxAge?: number;\n}\n\nexport interface SaveSessionOptions {\n sameSite?: 'strict' | 'lax' | 'none';\n}\n\n/**\n * Middleware for storing session data stored in an http cookie called\n * `__session`. This cookie is compatible with Firebase Hosting:\n * https://firebase.google.com/docs/hosting/manage-cache#using_cookies\n */\nexport function sessionMiddleware(options?: SessionMiddlewareOptions) {\n const maxAge = options?.maxAge || DEFAULT_MAX_AGE;\n return (req: Request, res: Response, next: NextFunction) => {\n const cookieValue = String(req.signedCookies[SESSION_COOKIE] || '');\n const session = Session.fromCookieValue(cookieValue);\n req.session = session;\n res.session = session;\n res.saveSession = (saveSessionOptions?: SaveSessionOptions) => {\n // \"secure\" cookies require https, so disable \"secure\" when in development.\n const secureCookie = Boolean(process.env.NODE_ENV !== 'development');\n const cookieValue = session.toString();\n const sameSite = saveSessionOptions?.sameSite || 'strict';\n res.cookie(SESSION_COOKIE, cookieValue, {\n maxAge: maxAge,\n httpOnly: true,\n secure: secureCookie,\n signed: true,\n sameSite: sameSite,\n });\n };\n req.hooks.add('preRender', () => {\n res.saveSession();\n });\n next();\n };\n}\n\nexport class Session {\n private data: Record<string, string> = {};\n\n constructor(data?: Record<string, string>) {\n this.data = data || {};\n }\n\n static fromCookieValue(cookieValue: string) {\n const data: Record<string, string> = {};\n if (cookieValue.startsWith('b64:')) {\n try {\n const encodedStr = cookieValue.slice(4);\n const params = new URLSearchParams(base64Decode(encodedStr));\n for (const [key, value] of params.entries()) {\n data[key] = value;\n }\n } catch (err) {\n console.warn('failed to parse session cookie:', err);\n return new Session();\n }\n }\n return new Session(data);\n }\n\n getItem(key: string): string | null {\n return this.data[key] ?? null;\n }\n\n setItem(key: string, value: string) {\n this.data[key] = value;\n }\n\n removeItem(key: string) {\n delete this.data[key];\n }\n\n toString(): string {\n const params = new URLSearchParams(this.data);\n return `b64:${base64Encode(params.toString())}`;\n }\n}\n\nfunction base64Encode(str: string): string {\n return Buffer.from(str, 'utf-8').toString('base64');\n}\n\nfunction base64Decode(str: string): string {\n return Buffer.from(str, 'base64').toString('utf-8');\n}\n"],"mappings":"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","names":["cookieValue"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getVitePlugins
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WICFYADD.js";
|
|
4
4
|
|
|
5
5
|
// src/node/load-config.ts
|
|
6
6
|
import path2 from "node:path";
|
|
@@ -264,4 +264,4 @@ export {
|
|
|
264
264
|
createViteServer,
|
|
265
265
|
viteSsrLoadModule
|
|
266
266
|
};
|
|
267
|
-
//# sourceMappingURL=chunk-
|
|
267
|
+
//# sourceMappingURL=chunk-G5ALYSEQ.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
rootProjectMiddleware,
|
|
4
4
|
sessionMiddleware,
|
|
5
5
|
trailingSlashMiddleware
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BMKSXG4B.js";
|
|
7
7
|
import {
|
|
8
8
|
bundleRootConfig,
|
|
9
9
|
copyDir,
|
|
@@ -21,11 +21,11 @@ import {
|
|
|
21
21
|
rmDir,
|
|
22
22
|
writeFile,
|
|
23
23
|
writeJson
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-G5ALYSEQ.js";
|
|
25
25
|
import {
|
|
26
26
|
configureServerPlugins,
|
|
27
27
|
getVitePlugins
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-WICFYADD.js";
|
|
29
29
|
import {
|
|
30
30
|
RouteTrie,
|
|
31
31
|
htmlMinify,
|
|
@@ -687,24 +687,104 @@ function formatParams(params) {
|
|
|
687
687
|
}).join("\n");
|
|
688
688
|
}
|
|
689
689
|
|
|
690
|
-
// src/cli/
|
|
690
|
+
// src/cli/codegen.ts
|
|
691
691
|
import { promises as fs3 } from "node:fs";
|
|
692
692
|
import path4 from "node:path";
|
|
693
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
694
|
+
import glob3 from "tiny-glob";
|
|
695
|
+
var __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
696
|
+
async function codegen(type, name, options) {
|
|
697
|
+
const rootDir = path4.resolve(process.cwd());
|
|
698
|
+
const project = new Project(rootDir);
|
|
699
|
+
await project.generateCode(type, name, options);
|
|
700
|
+
}
|
|
701
|
+
var Project = class {
|
|
702
|
+
rootDir;
|
|
703
|
+
tplDirs;
|
|
704
|
+
constructor(rootDir) {
|
|
705
|
+
this.rootDir = rootDir;
|
|
706
|
+
this.tplDirs = [
|
|
707
|
+
path4.join(rootDir, "codegen"),
|
|
708
|
+
path4.join(__dirname2, "../codegen")
|
|
709
|
+
];
|
|
710
|
+
}
|
|
711
|
+
async generateCode(type, name, options) {
|
|
712
|
+
const files = await this.loadFiles(type);
|
|
713
|
+
if (Object.keys(files).length === 0) {
|
|
714
|
+
console.log(`no files in codegen/${type}/*.tpl`);
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const outname = options?.out || `${type}s`;
|
|
718
|
+
const outdir = path4.join(this.rootDir, outname, name);
|
|
719
|
+
if (await dirExists(outdir)) {
|
|
720
|
+
await rmDir(outdir);
|
|
721
|
+
}
|
|
722
|
+
await makeDir(outdir);
|
|
723
|
+
for (const tplName in files) {
|
|
724
|
+
const tpl = await files[tplName].read();
|
|
725
|
+
const content = tpl.replaceAll("[[name]]", name).replaceAll("[[name:camel_upper]]", toCamelCaseUpper(name));
|
|
726
|
+
const filename = tplName.replace("[name]", name);
|
|
727
|
+
const filepath = path4.join(outdir, filename);
|
|
728
|
+
await writeFile(filepath, content);
|
|
729
|
+
console.log(`saved ${filepath}`);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Searches the project's "codegen" dir (or fallsback to root's "codegen" dir)
|
|
734
|
+
* and returns a `TemplateMap` for all files in `codgen/<type>/*.tpl`.
|
|
735
|
+
*/
|
|
736
|
+
async loadFiles(type) {
|
|
737
|
+
for (const tplDir of this.tplDirs) {
|
|
738
|
+
const typeDir = path4.join(tplDir, type);
|
|
739
|
+
if (await dirExists(typeDir)) {
|
|
740
|
+
return this.loadTplFiles(typeDir);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return {};
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Reads files matching `*.tpl` in a given directory.
|
|
747
|
+
*/
|
|
748
|
+
async loadTplFiles(dirpath) {
|
|
749
|
+
const tplFiles = {};
|
|
750
|
+
const files = await glob3("*.tpl", { cwd: dirpath });
|
|
751
|
+
for (const filename of files) {
|
|
752
|
+
const filepath = path4.join(dirpath, filename);
|
|
753
|
+
const name = filename.slice(0, -4);
|
|
754
|
+
tplFiles[name] = {
|
|
755
|
+
read: () => fs3.readFile(filepath, "utf-8")
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
return tplFiles;
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
function toCamelCaseUpper(str) {
|
|
762
|
+
const segments = str.split("-");
|
|
763
|
+
return segments.map((part) => toTitleCase(part)).join("");
|
|
764
|
+
}
|
|
765
|
+
function toTitleCase(str) {
|
|
766
|
+
const ch = String(str).charAt(0).toUpperCase();
|
|
767
|
+
return `${ch}${str.slice(1)}`;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// src/cli/create-package.ts
|
|
771
|
+
import { promises as fs4 } from "node:fs";
|
|
772
|
+
import path5 from "node:path";
|
|
693
773
|
import { build as esbuild } from "esbuild";
|
|
694
774
|
async function createPackage(rootProjectDir, options) {
|
|
695
775
|
const mode = options?.mode || "production";
|
|
696
776
|
process.env.NODE_ENV = mode;
|
|
697
|
-
const rootDir =
|
|
698
|
-
const distDir =
|
|
777
|
+
const rootDir = path5.resolve(rootProjectDir || process.cwd());
|
|
778
|
+
const distDir = path5.join(rootDir, "dist");
|
|
699
779
|
const target = options?.target || await getDefaultTarget(rootDir);
|
|
700
|
-
const outDir =
|
|
780
|
+
const outDir = path5.resolve(options?.out || target || "out");
|
|
701
781
|
await build(rootProjectDir, { ssrOnly: true, mode });
|
|
702
782
|
await rmDir(outDir);
|
|
703
783
|
await makeDir(outDir);
|
|
704
|
-
await copyDir(distDir,
|
|
705
|
-
const collectionsDir =
|
|
784
|
+
await copyDir(distDir, path5.resolve(outDir, "dist"));
|
|
785
|
+
const collectionsDir = path5.resolve(rootDir, "collections");
|
|
706
786
|
if (await dirExists(collectionsDir)) {
|
|
707
|
-
await copyDir(collectionsDir,
|
|
787
|
+
await copyDir(collectionsDir, path5.join(outDir, "collections"));
|
|
708
788
|
}
|
|
709
789
|
const packageJson = await generatePackageJson(rootDir);
|
|
710
790
|
if (options?.version && packageJson.dependencies) {
|
|
@@ -723,16 +803,16 @@ async function createPackage(rootProjectDir, options) {
|
|
|
723
803
|
} else if (target === "firebase") {
|
|
724
804
|
await onFirebase({ rootDir, packageJson, outDir });
|
|
725
805
|
}
|
|
726
|
-
await writeJson(
|
|
806
|
+
await writeJson(path5.resolve(outDir, "package.json"), packageJson);
|
|
727
807
|
console.log("done!");
|
|
728
808
|
console.log(`saved package to ${outDir}`);
|
|
729
809
|
}
|
|
730
810
|
async function getDefaultTarget(rootDir) {
|
|
731
|
-
const firebaseConfigPath =
|
|
811
|
+
const firebaseConfigPath = path5.resolve(rootDir, "firebase.json");
|
|
732
812
|
if (await fileExists(firebaseConfigPath)) {
|
|
733
813
|
return "firebase";
|
|
734
814
|
}
|
|
735
|
-
const appEngineConfigPath =
|
|
815
|
+
const appEngineConfigPath = path5.resolve(rootDir, "app.yaml");
|
|
736
816
|
if (await fileExists(appEngineConfigPath)) {
|
|
737
817
|
return "appengine";
|
|
738
818
|
}
|
|
@@ -740,7 +820,7 @@ async function getDefaultTarget(rootDir) {
|
|
|
740
820
|
}
|
|
741
821
|
async function generatePackageJson(rootDir) {
|
|
742
822
|
const packageJson = await loadJson(
|
|
743
|
-
|
|
823
|
+
path5.resolve(rootDir, "package.json")
|
|
744
824
|
);
|
|
745
825
|
if (packageJson.peerDependencies) {
|
|
746
826
|
await updatePeerDepsFromWorkspace(rootDir, packageJson);
|
|
@@ -756,7 +836,7 @@ async function updatePeerDepsFromWorkspace(rootDir, packageJson) {
|
|
|
756
836
|
if (!workspaceRoot) {
|
|
757
837
|
return;
|
|
758
838
|
}
|
|
759
|
-
const workspacePackageJsonPath =
|
|
839
|
+
const workspacePackageJsonPath = path5.resolve(workspaceRoot, "package.json");
|
|
760
840
|
const workspacePackageJson = await loadJson(
|
|
761
841
|
workspacePackageJsonPath
|
|
762
842
|
);
|
|
@@ -779,15 +859,15 @@ async function updatePeerDepsFromWorkspace(rootDir, packageJson) {
|
|
|
779
859
|
}
|
|
780
860
|
}
|
|
781
861
|
async function findWorkspaceRoot(rootDir) {
|
|
782
|
-
const parentDir =
|
|
862
|
+
const parentDir = path5.dirname(rootDir);
|
|
783
863
|
if (parentDir === "/") {
|
|
784
864
|
return null;
|
|
785
865
|
}
|
|
786
|
-
const pnpmWorkspaceFile =
|
|
866
|
+
const pnpmWorkspaceFile = path5.resolve(parentDir, "pnpm-workspace.yaml");
|
|
787
867
|
if (await fileExists(pnpmWorkspaceFile)) {
|
|
788
868
|
return parentDir;
|
|
789
869
|
}
|
|
790
|
-
const packageJsonPath =
|
|
870
|
+
const packageJsonPath = path5.resolve(parentDir, "package.json");
|
|
791
871
|
if (await fileExists(packageJsonPath)) {
|
|
792
872
|
const parentPackageJson = await loadJson(packageJsonPath);
|
|
793
873
|
if (parentPackageJson && parentPackageJson.workspaces) {
|
|
@@ -810,9 +890,9 @@ function getRequiredPeerDeps(packageJson) {
|
|
|
810
890
|
}
|
|
811
891
|
async function onAppEngine(options) {
|
|
812
892
|
const { rootDir, outDir, packageJson } = options;
|
|
813
|
-
const configPath =
|
|
893
|
+
const configPath = path5.resolve(rootDir, "app.yaml");
|
|
814
894
|
if (await fileExists(configPath)) {
|
|
815
|
-
await
|
|
895
|
+
await fs4.copyFile(configPath, path5.resolve(outDir, "app.yaml"));
|
|
816
896
|
}
|
|
817
897
|
if (packageJson.scripts?.start) {
|
|
818
898
|
packageJson.scripts = { start: packageJson.scripts.start };
|
|
@@ -822,11 +902,11 @@ async function onAppEngine(options) {
|
|
|
822
902
|
}
|
|
823
903
|
async function onFirebase(options) {
|
|
824
904
|
const { rootDir, outDir, packageJson } = options;
|
|
825
|
-
const outBasename =
|
|
905
|
+
const outBasename = path5.basename(outDir);
|
|
826
906
|
if (outBasename === "functions") {
|
|
827
|
-
const indexTsFile =
|
|
907
|
+
const indexTsFile = path5.resolve(rootDir, "index.ts");
|
|
828
908
|
if (await fileExists(indexTsFile)) {
|
|
829
|
-
await bundleTsFile(indexTsFile,
|
|
909
|
+
await bundleTsFile(indexTsFile, path5.resolve(outDir, "index.js"));
|
|
830
910
|
}
|
|
831
911
|
}
|
|
832
912
|
if (packageJson.scripts?.start) {
|
|
@@ -851,7 +931,7 @@ async function bundleTsFile(srcPath, outPath) {
|
|
|
851
931
|
setup(build2) {
|
|
852
932
|
build2.onResolve({ filter: /.*/ }, (args) => {
|
|
853
933
|
const id = args.path;
|
|
854
|
-
if (id[0] !== "." && !
|
|
934
|
+
if (id[0] !== "." && !path5.isAbsolute(id)) {
|
|
855
935
|
return {
|
|
856
936
|
external: true
|
|
857
937
|
};
|
|
@@ -865,13 +945,13 @@ async function bundleTsFile(srcPath, outPath) {
|
|
|
865
945
|
}
|
|
866
946
|
|
|
867
947
|
// src/cli/dev.ts
|
|
868
|
-
import
|
|
869
|
-
import { fileURLToPath as
|
|
948
|
+
import path7 from "node:path";
|
|
949
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
870
950
|
import cookieParser from "cookie-parser";
|
|
871
951
|
import { default as express } from "express";
|
|
872
952
|
import { dim as dim2 } from "kleur/colors";
|
|
873
953
|
import sirv from "sirv";
|
|
874
|
-
import
|
|
954
|
+
import glob4 from "tiny-glob";
|
|
875
955
|
|
|
876
956
|
// src/middleware/hooks.ts
|
|
877
957
|
function hooksMiddleware() {
|
|
@@ -940,7 +1020,7 @@ function replaceParams(urlPathFormat, params) {
|
|
|
940
1020
|
}
|
|
941
1021
|
|
|
942
1022
|
// src/render/asset-map/dev-asset-map.ts
|
|
943
|
-
import
|
|
1023
|
+
import path6 from "node:path";
|
|
944
1024
|
import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
|
|
945
1025
|
var DevServerAssetMap = class {
|
|
946
1026
|
rootConfig;
|
|
@@ -950,7 +1030,7 @@ var DevServerAssetMap = class {
|
|
|
950
1030
|
this.moduleGraph = moduleGraph;
|
|
951
1031
|
}
|
|
952
1032
|
async get(src) {
|
|
953
|
-
const file =
|
|
1033
|
+
const file = path6.resolve(this.rootConfig.rootDir, src);
|
|
954
1034
|
const viteModules = this.moduleGraph.getModulesByFile(file);
|
|
955
1035
|
if (viteModules && viteModules.size > 0) {
|
|
956
1036
|
const [viteModule] = viteModules;
|
|
@@ -982,7 +1062,7 @@ var DevServerAssetMap = class {
|
|
|
982
1062
|
return null;
|
|
983
1063
|
}
|
|
984
1064
|
filePathToSrc(file) {
|
|
985
|
-
return
|
|
1065
|
+
return path6.relative(this.rootConfig.rootDir, file);
|
|
986
1066
|
}
|
|
987
1067
|
};
|
|
988
1068
|
var DevServerAsset = class _DevServerAsset {
|
|
@@ -1024,7 +1104,7 @@ var DevServerAsset = class _DevServerAsset {
|
|
|
1024
1104
|
return;
|
|
1025
1105
|
}
|
|
1026
1106
|
visited.add(asset.moduleId);
|
|
1027
|
-
const parts =
|
|
1107
|
+
const parts = path6.parse(asset.assetUrl);
|
|
1028
1108
|
if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
|
|
1029
1109
|
urls.add(asset.assetUrl);
|
|
1030
1110
|
}
|
|
@@ -1051,7 +1131,7 @@ var DevServerAsset = class _DevServerAsset {
|
|
|
1051
1131
|
}
|
|
1052
1132
|
visited.add(asset.assetUrl);
|
|
1053
1133
|
if (asset.src.endsWith(".scss")) {
|
|
1054
|
-
const parts =
|
|
1134
|
+
const parts = path6.parse(asset.src);
|
|
1055
1135
|
if (!parts.name.startsWith("_")) {
|
|
1056
1136
|
urls.add(asset.assetUrl);
|
|
1057
1137
|
}
|
|
@@ -1118,10 +1198,10 @@ function randString(len) {
|
|
|
1118
1198
|
}
|
|
1119
1199
|
|
|
1120
1200
|
// src/cli/dev.ts
|
|
1121
|
-
var
|
|
1201
|
+
var __dirname3 = path7.dirname(fileURLToPath3(import.meta.url));
|
|
1122
1202
|
async function dev(rootProjectDir, options) {
|
|
1123
1203
|
process.env.NODE_ENV = "development";
|
|
1124
|
-
const rootDir =
|
|
1204
|
+
const rootDir = path7.resolve(rootProjectDir || process.cwd());
|
|
1125
1205
|
const defaultPort = parseInt(process.env.PORT || "4007");
|
|
1126
1206
|
const host = options?.host || "localhost";
|
|
1127
1207
|
const port = await findOpenPort(defaultPort, defaultPort + 10);
|
|
@@ -1139,7 +1219,7 @@ async function dev(rootProjectDir, options) {
|
|
|
1139
1219
|
server.listen(port, host);
|
|
1140
1220
|
}
|
|
1141
1221
|
async function createDevServer(options) {
|
|
1142
|
-
const rootDir =
|
|
1222
|
+
const rootDir = path7.resolve(options?.rootDir || process.cwd());
|
|
1143
1223
|
const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
|
|
1144
1224
|
const port = options?.port;
|
|
1145
1225
|
const server = express();
|
|
@@ -1172,7 +1252,7 @@ async function createDevServer(options) {
|
|
|
1172
1252
|
if (rootConfig.server?.headers) {
|
|
1173
1253
|
server.use(headersMiddleware({ rootConfig }));
|
|
1174
1254
|
}
|
|
1175
|
-
const publicDir =
|
|
1255
|
+
const publicDir = path7.join(rootDir, "public");
|
|
1176
1256
|
if (await dirExists(publicDir)) {
|
|
1177
1257
|
server.use(rootPublicDirMiddleware({ publicDir, viteServer }));
|
|
1178
1258
|
}
|
|
@@ -1194,10 +1274,10 @@ async function createViteMiddleware(options) {
|
|
|
1194
1274
|
return sourceFile.relPath;
|
|
1195
1275
|
});
|
|
1196
1276
|
const bundleScripts = [];
|
|
1197
|
-
if (await isDirectory(
|
|
1198
|
-
const bundleFiles = await
|
|
1277
|
+
if (await isDirectory(path7.join(rootDir, "bundles"))) {
|
|
1278
|
+
const bundleFiles = await glob4("bundles/*", { cwd: rootDir });
|
|
1199
1279
|
bundleFiles.forEach((file) => {
|
|
1200
|
-
const parts =
|
|
1280
|
+
const parts = path7.parse(file);
|
|
1201
1281
|
if (isJsFile(parts.base)) {
|
|
1202
1282
|
bundleScripts.push(file);
|
|
1203
1283
|
}
|
|
@@ -1209,7 +1289,7 @@ async function createViteMiddleware(options) {
|
|
|
1209
1289
|
optimizeDeps
|
|
1210
1290
|
});
|
|
1211
1291
|
function isInElementsDir(changedFilePath) {
|
|
1212
|
-
const filePath =
|
|
1292
|
+
const filePath = path7.resolve(changedFilePath);
|
|
1213
1293
|
const elementsDirs = getElementsDirs(rootConfig);
|
|
1214
1294
|
return elementsDirs.some((dirPath) => filePath.startsWith(dirPath));
|
|
1215
1295
|
}
|
|
@@ -1228,7 +1308,7 @@ async function createViteMiddleware(options) {
|
|
|
1228
1308
|
const viteMiddleware = async (req, res, next) => {
|
|
1229
1309
|
try {
|
|
1230
1310
|
req.viteServer = viteServer;
|
|
1231
|
-
const renderModulePath =
|
|
1311
|
+
const renderModulePath = path7.resolve(__dirname3, "./render.js");
|
|
1232
1312
|
const render = await viteServer.ssrLoadModule(
|
|
1233
1313
|
renderModulePath
|
|
1234
1314
|
);
|
|
@@ -1252,7 +1332,7 @@ function rootPublicDirMiddleware(options) {
|
|
|
1252
1332
|
handler = sirv(publicDir, sirvOptions);
|
|
1253
1333
|
}, 1e3);
|
|
1254
1334
|
function isInPublicDir(changedFilePath) {
|
|
1255
|
-
const filePath =
|
|
1335
|
+
const filePath = path7.resolve(changedFilePath);
|
|
1256
1336
|
return filePath.startsWith(publicDir);
|
|
1257
1337
|
}
|
|
1258
1338
|
const watcher = options.viteServer.watcher;
|
|
@@ -1282,7 +1362,7 @@ function rootDevServer404Middleware() {
|
|
|
1282
1362
|
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
1283
1363
|
if (req.renderer) {
|
|
1284
1364
|
const url = req.path;
|
|
1285
|
-
const ext =
|
|
1365
|
+
const ext = path7.extname(url);
|
|
1286
1366
|
if (!ext) {
|
|
1287
1367
|
const renderer = req.renderer;
|
|
1288
1368
|
const data = await renderer.renderDevServer404(req);
|
|
@@ -1300,7 +1380,7 @@ function rootDevServer500Middleware() {
|
|
|
1300
1380
|
console.error(String(err.stack || err));
|
|
1301
1381
|
if (req.renderer) {
|
|
1302
1382
|
const url = req.path;
|
|
1303
|
-
const ext =
|
|
1383
|
+
const ext = path7.extname(url);
|
|
1304
1384
|
if (!ext) {
|
|
1305
1385
|
const renderer = req.renderer;
|
|
1306
1386
|
const data = await renderer.renderDevServer500(req, err);
|
|
@@ -1325,7 +1405,7 @@ function debounce(fn, timeout) {
|
|
|
1325
1405
|
}
|
|
1326
1406
|
|
|
1327
1407
|
// src/cli/preview.ts
|
|
1328
|
-
import
|
|
1408
|
+
import path8 from "node:path";
|
|
1329
1409
|
import compression from "compression";
|
|
1330
1410
|
import cookieParser2 from "cookie-parser";
|
|
1331
1411
|
import { default as express2 } from "express";
|
|
@@ -1333,7 +1413,7 @@ import { dim as dim3 } from "kleur/colors";
|
|
|
1333
1413
|
import sirv2 from "sirv";
|
|
1334
1414
|
async function preview(rootProjectDir, options) {
|
|
1335
1415
|
process.env.NODE_ENV = "development";
|
|
1336
|
-
const rootDir =
|
|
1416
|
+
const rootDir = path8.resolve(rootProjectDir || process.cwd());
|
|
1337
1417
|
const server = await createPreviewServer({ rootDir });
|
|
1338
1418
|
const port = parseInt(process.env.PORT || "4007");
|
|
1339
1419
|
const host = options?.host || "localhost";
|
|
@@ -1347,7 +1427,7 @@ async function preview(rootProjectDir, options) {
|
|
|
1347
1427
|
async function createPreviewServer(options) {
|
|
1348
1428
|
const rootDir = options.rootDir;
|
|
1349
1429
|
const rootConfig = await loadBundledConfig(rootDir, { command: "preview" });
|
|
1350
|
-
const distDir =
|
|
1430
|
+
const distDir = path8.join(rootDir, "dist");
|
|
1351
1431
|
const server = express2();
|
|
1352
1432
|
server.disable("x-powered-by");
|
|
1353
1433
|
server.use(compression());
|
|
@@ -1373,7 +1453,7 @@ async function createPreviewServer(options) {
|
|
|
1373
1453
|
if (rootConfig.server?.headers) {
|
|
1374
1454
|
server.use(headersMiddleware({ rootConfig }));
|
|
1375
1455
|
}
|
|
1376
|
-
const publicDir =
|
|
1456
|
+
const publicDir = path8.join(distDir, "html");
|
|
1377
1457
|
server.use(sirv2(publicDir, { dev: false }));
|
|
1378
1458
|
server.use(trailingSlashMiddleware({ rootConfig }));
|
|
1379
1459
|
server.use(rootPreviewServerMiddleware());
|
|
@@ -1387,14 +1467,14 @@ async function createPreviewServer(options) {
|
|
|
1387
1467
|
}
|
|
1388
1468
|
async function rootPreviewRendererMiddleware(options) {
|
|
1389
1469
|
const { distDir, rootConfig } = options;
|
|
1390
|
-
const render = await import(
|
|
1391
|
-
const manifestPath =
|
|
1470
|
+
const render = await import(path8.join(distDir, "server/render.js"));
|
|
1471
|
+
const manifestPath = path8.join(distDir, ".root/manifest.json");
|
|
1392
1472
|
if (!await fileExists(manifestPath)) {
|
|
1393
1473
|
throw new Error(
|
|
1394
1474
|
`could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
|
|
1395
1475
|
);
|
|
1396
1476
|
}
|
|
1397
|
-
const elementGraphJsonPath =
|
|
1477
|
+
const elementGraphJsonPath = path8.join(distDir, ".root/elements.json");
|
|
1398
1478
|
if (!await fileExists(elementGraphJsonPath)) {
|
|
1399
1479
|
throw new Error(
|
|
1400
1480
|
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root preview\`.`
|
|
@@ -1434,7 +1514,7 @@ function rootPreviewServer404Middleware() {
|
|
|
1434
1514
|
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
1435
1515
|
if (req.renderer) {
|
|
1436
1516
|
const url = req.path;
|
|
1437
|
-
const ext =
|
|
1517
|
+
const ext = path8.extname(url);
|
|
1438
1518
|
if (!ext) {
|
|
1439
1519
|
const renderer = req.renderer;
|
|
1440
1520
|
const data = await renderer.render404({ currentPath: url });
|
|
@@ -1452,7 +1532,7 @@ function rootPreviewServer500Middleware() {
|
|
|
1452
1532
|
console.error(String(err.stack || err));
|
|
1453
1533
|
if (req.renderer) {
|
|
1454
1534
|
const url = req.path;
|
|
1455
|
-
const ext =
|
|
1535
|
+
const ext = path8.extname(url);
|
|
1456
1536
|
if (!ext) {
|
|
1457
1537
|
const renderer = req.renderer;
|
|
1458
1538
|
const data = await renderer.renderDevServer500(req, err);
|
|
@@ -1466,7 +1546,7 @@ function rootPreviewServer500Middleware() {
|
|
|
1466
1546
|
}
|
|
1467
1547
|
|
|
1468
1548
|
// src/cli/start.ts
|
|
1469
|
-
import
|
|
1549
|
+
import path9 from "node:path";
|
|
1470
1550
|
import compression2 from "compression";
|
|
1471
1551
|
import cookieParser3 from "cookie-parser";
|
|
1472
1552
|
import { default as express3 } from "express";
|
|
@@ -1474,7 +1554,7 @@ import { dim as dim4 } from "kleur/colors";
|
|
|
1474
1554
|
import sirv3 from "sirv";
|
|
1475
1555
|
async function start(rootProjectDir, options) {
|
|
1476
1556
|
process.env.NODE_ENV = "production";
|
|
1477
|
-
const rootDir =
|
|
1557
|
+
const rootDir = path9.resolve(rootProjectDir || process.cwd());
|
|
1478
1558
|
const server = await createProdServer({ rootDir });
|
|
1479
1559
|
const port = parseInt(process.env.PORT || "4007");
|
|
1480
1560
|
const host = options?.host || "localhost";
|
|
@@ -1488,7 +1568,7 @@ async function start(rootProjectDir, options) {
|
|
|
1488
1568
|
async function createProdServer(options) {
|
|
1489
1569
|
const rootDir = options.rootDir;
|
|
1490
1570
|
const rootConfig = await loadBundledConfig(rootDir, { command: "start" });
|
|
1491
|
-
const distDir =
|
|
1571
|
+
const distDir = path9.join(rootDir, "dist");
|
|
1492
1572
|
const server = express3();
|
|
1493
1573
|
server.disable("x-powered-by");
|
|
1494
1574
|
server.use(compression2());
|
|
@@ -1514,7 +1594,7 @@ async function createProdServer(options) {
|
|
|
1514
1594
|
if (rootConfig.server?.headers) {
|
|
1515
1595
|
server.use(headersMiddleware({ rootConfig }));
|
|
1516
1596
|
}
|
|
1517
|
-
const publicDir =
|
|
1597
|
+
const publicDir = path9.join(distDir, "html");
|
|
1518
1598
|
server.use(sirv3(publicDir, { dev: false }));
|
|
1519
1599
|
server.use(trailingSlashMiddleware({ rootConfig }));
|
|
1520
1600
|
server.use(rootProdServerMiddleware());
|
|
@@ -1528,14 +1608,14 @@ async function createProdServer(options) {
|
|
|
1528
1608
|
}
|
|
1529
1609
|
async function rootProdRendererMiddleware(options) {
|
|
1530
1610
|
const { distDir, rootConfig } = options;
|
|
1531
|
-
const render = await import(
|
|
1532
|
-
const manifestPath =
|
|
1611
|
+
const render = await import(path9.join(distDir, "server/render.js"));
|
|
1612
|
+
const manifestPath = path9.join(distDir, ".root/manifest.json");
|
|
1533
1613
|
if (!await fileExists(manifestPath)) {
|
|
1534
1614
|
throw new Error(
|
|
1535
1615
|
`could not find ${manifestPath}. run \`root build\` before \`root start\`.`
|
|
1536
1616
|
);
|
|
1537
1617
|
}
|
|
1538
|
-
const elementGraphJsonPath =
|
|
1618
|
+
const elementGraphJsonPath = path9.join(distDir, ".root/elements.json");
|
|
1539
1619
|
if (!await fileExists(elementGraphJsonPath)) {
|
|
1540
1620
|
throw new Error(
|
|
1541
1621
|
`could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
|
|
@@ -1575,7 +1655,7 @@ function rootProdServer404Middleware() {
|
|
|
1575
1655
|
console.error(`\u2753 404 ${req.originalUrl}`);
|
|
1576
1656
|
if (req.renderer) {
|
|
1577
1657
|
const url = req.path;
|
|
1578
|
-
const ext =
|
|
1658
|
+
const ext = path9.extname(url);
|
|
1579
1659
|
if (!ext) {
|
|
1580
1660
|
const renderer = req.renderer;
|
|
1581
1661
|
const data = await renderer.render404({ currentPath: url });
|
|
@@ -1593,7 +1673,7 @@ function rootProdServer500Middleware() {
|
|
|
1593
1673
|
console.error(String(err.stack || err));
|
|
1594
1674
|
if (req.renderer) {
|
|
1595
1675
|
const url = req.path;
|
|
1596
|
-
const ext =
|
|
1676
|
+
const ext = path9.extname(url);
|
|
1597
1677
|
if (!ext) {
|
|
1598
1678
|
const renderer = req.renderer;
|
|
1599
1679
|
const data = await renderer.renderError(err);
|
|
@@ -1635,6 +1715,7 @@ var CliRunner = class {
|
|
|
1635
1715
|
"number of files to build concurrently",
|
|
1636
1716
|
"10"
|
|
1637
1717
|
).action(build);
|
|
1718
|
+
program.command("codegen [type] [name]").description("generates boilerplate code").option("--out <outdir>", "output dir").action(codegen);
|
|
1638
1719
|
program.command("create-package [path]").alias("package").description(
|
|
1639
1720
|
"creates a standalone npm package for deployment to various hosting services"
|
|
1640
1721
|
).option("--target <target>", "hosting target, i.e. appengine or firebase").option("--out <outdir>", "output dir").option("--mode <mode>", "deployment mode, i.e. production or preview").action((rootPackageDir, options) => {
|
|
@@ -1668,4 +1749,4 @@ export {
|
|
|
1668
1749
|
createProdServer,
|
|
1669
1750
|
CliRunner
|
|
1670
1751
|
};
|
|
1671
|
-
//# sourceMappingURL=chunk-
|
|
1752
|
+
//# sourceMappingURL=chunk-GNRN2XDJ.js.map
|