@better-t-stack/template-generator 3.36.4 → 3.37.0

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,"file":"fs-writer.d.mts","names":[],"sources":["../src/fs-writer.ts"],"mappings":";;;;;cAM2F,mBAAA;;;;;;;;cAO9E,cAAA,SAAuB,mBAIhC;;;;AAJJ;iBAUsB,SAAA,CACpB,IAAA,EAAM,eAAA,EACN,OAAA,WACC,OAAA,CAAQ,MAAA,OAAa,cAAA;;;AATpB;AAMJ;iBAiDsB,aAAA,CACpB,IAAA,EAAM,eAAA,EACN,OAAA,UACA,MAAA,GAAS,QAAA,uBACR,OAAA,CAAQ,MAAA,WAAiB,cAAA"}
1
+ {"version":3,"file":"fs-writer.d.mts","names":[],"sources":["../src/fs-writer.ts"],"mappings":";;;;;cAO2F,mBAAA;;;;;;;;cAO9E,cAAA,SAAuB,mBAIhC;;;;AAJJ;iBAUsB,SAAA,CACpB,IAAA,EAAM,eAAA,EACN,OAAA,WACC,OAAA,CAAQ,MAAA,OAAa,cAAA;;;AATpB;AAMJ;iBAmDsB,aAAA,CACpB,IAAA,EAAM,eAAA,EACN,OAAA,UACA,MAAA,GAAS,QAAA,uBACR,OAAA,CAAQ,MAAA,WAAiB,cAAA"}
@@ -1,6 +1,7 @@
1
1
  import { t as getBinaryTemplatesRoot } from "./template-reader-DVuwwW6S.mjs";
2
2
  import { Result, TaggedError } from "better-result";
3
3
  import { dirname, join } from "pathe";
4
+ import path from "node:path";
4
5
  import * as fs from "node:fs/promises";
5
6
  //#region src/fs-writer.ts
6
7
  const BINARY_FILE_MARKER = "[Binary file]";
@@ -31,10 +32,12 @@ async function writeNodeInternal(node, baseDir, relativePath) {
31
32
  const nodePath = relativePath ? join(relativePath, node.name) : node.name;
32
33
  if (node.type === "file") {
33
34
  const fileNode = node;
35
+ await assertSafeWritePath(baseDir, fullPath);
34
36
  await fs.mkdir(dirname(fullPath), { recursive: true });
35
37
  if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) await copyBinaryFile(fileNode.sourcePath, fullPath);
36
38
  else if (fileNode.content !== BINARY_FILE_MARKER) await fs.writeFile(fullPath, fileNode.content, "utf-8");
37
39
  } else {
40
+ await assertSafeWritePath(baseDir, fullPath);
38
41
  await fs.mkdir(fullPath, { recursive: true });
39
42
  for (const child of node.children) await writeNodeInternal(child, baseDir, nodePath);
40
43
  }
@@ -64,6 +67,7 @@ async function writeSelectedNodeInternal(node, baseDir, relativePath, filter, wr
64
67
  if (node.type === "file") {
65
68
  if (filter(nodePath)) {
66
69
  const fileNode = node;
70
+ await assertSafeWritePath(baseDir, join(baseDir, nodePath));
67
71
  await fs.mkdir(dirname(join(baseDir, nodePath)), { recursive: true });
68
72
  if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) await copyBinaryFile(fileNode.sourcePath, join(baseDir, nodePath));
69
73
  else if (fileNode.content !== BINARY_FILE_MARKER) await fs.writeFile(join(baseDir, nodePath), fileNode.content, "utf-8");
@@ -75,6 +79,31 @@ async function copyBinaryFile(templatePath, destPath) {
75
79
  const sourcePath = join(getBinaryTemplatesRoot(), templatePath);
76
80
  await fs.copyFile(sourcePath, destPath);
77
81
  }
82
+ async function assertSafeWritePath(baseDir, destinationPath) {
83
+ const resolvedBase = path.resolve(baseDir);
84
+ const resolvedDestination = path.resolve(destinationPath);
85
+ const relativeDestination = path.relative(resolvedBase, resolvedDestination);
86
+ if (relativeDestination === ".." || relativeDestination.startsWith(`..${path.sep}`) || path.isAbsolute(relativeDestination)) throw new FileWriteError({
87
+ message: `Refusing to write outside project directory: ${resolvedDestination}`,
88
+ path: resolvedDestination
89
+ });
90
+ let currentPath = resolvedBase;
91
+ const pathSegments = relativeDestination.split(path.sep).filter(Boolean);
92
+ for (const segment of ["", ...pathSegments]) {
93
+ if (segment) currentPath = path.join(currentPath, segment);
94
+ let stats;
95
+ try {
96
+ stats = await fs.lstat(currentPath);
97
+ } catch (error) {
98
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return;
99
+ throw error;
100
+ }
101
+ if (stats.isSymbolicLink()) throw new FileWriteError({
102
+ message: `Refusing to write through symbolic link: ${currentPath}`,
103
+ path: currentPath
104
+ });
105
+ }
106
+ }
78
107
  //#endregion
79
108
  export { FileWriteError, writeSelected, writeTree };
80
109
 
@@ -1 +1 @@
1
- {"version":3,"file":"fs-writer.mjs","names":[],"sources":["../src/fs-writer.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\n\nimport { Result, TaggedError } from \"better-result\";\nimport { join, dirname } from \"pathe\";\n\nimport { getBinaryTemplatesRoot } from \"./core/template-reader\";\nimport type { VirtualFileTree, VirtualNode, VirtualFile, VirtualDirectory } from \"./types\";\n\nconst BINARY_FILE_MARKER = \"[Binary file]\";\n\n/**\n * Error class for filesystem write failures\n */\nexport class FileWriteError extends TaggedError(\"FileWriteError\")<{\n message: string;\n path?: string;\n cause?: unknown;\n}>() {}\n\n/**\n * Writes a virtual file tree to the filesystem.\n * Returns a Result type for type-safe error handling.\n */\nexport async function writeTree(\n tree: VirtualFileTree,\n destDir: string,\n): Promise<Result<void, FileWriteError>> {\n return Result.tryPromise({\n try: async () => {\n for (const child of tree.root.children) {\n await writeNodeInternal(child, destDir, \"\");\n }\n },\n catch: (e) => {\n if (FileWriteError.is(e)) return e;\n return new FileWriteError({\n message: e instanceof Error ? e.message : String(e),\n cause: e,\n });\n },\n });\n}\n\nasync function writeNodeInternal(\n node: VirtualNode,\n baseDir: string,\n relativePath: string,\n): Promise<void> {\n const fullPath = join(baseDir, relativePath, node.name);\n const nodePath = relativePath ? join(relativePath, node.name) : node.name;\n\n if (node.type === \"file\") {\n const fileNode = node as VirtualFile;\n await fs.mkdir(dirname(fullPath), { recursive: true });\n\n if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) {\n await copyBinaryFile(fileNode.sourcePath, fullPath);\n } else if (fileNode.content !== BINARY_FILE_MARKER) {\n await fs.writeFile(fullPath, fileNode.content, \"utf-8\");\n }\n } else {\n await fs.mkdir(fullPath, { recursive: true });\n for (const child of (node as VirtualDirectory).children) {\n await writeNodeInternal(child, baseDir, nodePath);\n }\n }\n}\n\n/**\n * Writes selected files from a virtual file tree to the filesystem.\n * Returns a Result with the list of written file paths.\n */\nexport async function writeSelected(\n tree: VirtualFileTree,\n destDir: string,\n filter: (filePath: string) => boolean,\n): Promise<Result<string[], FileWriteError>> {\n return Result.tryPromise({\n try: async () => {\n const writtenFiles: string[] = [];\n await writeSelectedNodeInternal(tree.root, destDir, \"\", filter, writtenFiles);\n return writtenFiles;\n },\n catch: (e) => {\n if (FileWriteError.is(e)) return e;\n return new FileWriteError({\n message: e instanceof Error ? e.message : String(e),\n cause: e,\n });\n },\n });\n}\n\nasync function writeSelectedNodeInternal(\n node: VirtualNode,\n baseDir: string,\n relativePath: string,\n filter: (filePath: string) => boolean,\n writtenFiles: string[],\n): Promise<void> {\n const nodePath = relativePath ? `${relativePath}/${node.name}` : node.name;\n\n if (node.type === \"file\") {\n if (filter(nodePath)) {\n const fileNode = node as VirtualFile;\n await fs.mkdir(dirname(join(baseDir, nodePath)), { recursive: true });\n\n if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) {\n await copyBinaryFile(fileNode.sourcePath, join(baseDir, nodePath));\n } else if (fileNode.content !== BINARY_FILE_MARKER) {\n await fs.writeFile(join(baseDir, nodePath), fileNode.content, \"utf-8\");\n }\n writtenFiles.push(nodePath);\n }\n } else {\n for (const child of (node as VirtualDirectory).children) {\n await writeSelectedNodeInternal(child, baseDir, nodePath, filter, writtenFiles);\n }\n }\n}\n\nasync function copyBinaryFile(templatePath: string, destPath: string): Promise<void> {\n const templatesRoot = getBinaryTemplatesRoot();\n const sourcePath = join(templatesRoot, templatePath);\n // Let errors propagate - they'll be caught by the Result wrapper\n await fs.copyFile(sourcePath, destPath);\n}\n"],"mappings":";;;;;AAQA,MAAM,qBAAqB;;;;AAK3B,IAAa,iBAAb,cAAoC,YAAY,gBAAgB,EAI7D,EAAE,CAAC;;;;;AAMN,eAAsB,UACpB,MACA,SACuC;CACvC,OAAO,OAAO,WAAW;EACvB,KAAK,YAAY;GACf,KAAK,MAAM,SAAS,KAAK,KAAK,UAC5B,MAAM,kBAAkB,OAAO,SAAS,EAAE;EAE9C;EACA,QAAQ,MAAM;GACZ,IAAI,eAAe,GAAG,CAAC,GAAG,OAAO;GACjC,OAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;IAClD,OAAO;GACT,CAAC;EACH;CACF,CAAC;AACH;AAEA,eAAe,kBACb,MACA,SACA,cACe;CACf,MAAM,WAAW,KAAK,SAAS,cAAc,KAAK,IAAI;CACtD,MAAM,WAAW,eAAe,KAAK,cAAc,KAAK,IAAI,IAAI,KAAK;CAErE,IAAI,KAAK,SAAS,QAAQ;EACxB,MAAM,WAAW;EACjB,MAAM,GAAG,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;EAErD,IAAI,SAAS,YAAY,sBAAsB,SAAS,YACtD,MAAM,eAAe,SAAS,YAAY,QAAQ;OAC7C,IAAI,SAAS,YAAY,oBAC9B,MAAM,GAAG,UAAU,UAAU,SAAS,SAAS,OAAO;CAE1D,OAAO;EACL,MAAM,GAAG,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;EAC5C,KAAK,MAAM,SAAU,KAA0B,UAC7C,MAAM,kBAAkB,OAAO,SAAS,QAAQ;CAEpD;AACF;;;;;AAMA,eAAsB,cACpB,MACA,SACA,QAC2C;CAC3C,OAAO,OAAO,WAAW;EACvB,KAAK,YAAY;GACf,MAAM,eAAyB,CAAC;GAChC,MAAM,0BAA0B,KAAK,MAAM,SAAS,IAAI,QAAQ,YAAY;GAC5E,OAAO;EACT;EACA,QAAQ,MAAM;GACZ,IAAI,eAAe,GAAG,CAAC,GAAG,OAAO;GACjC,OAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;IAClD,OAAO;GACT,CAAC;EACH;CACF,CAAC;AACH;AAEA,eAAe,0BACb,MACA,SACA,cACA,QACA,cACe;CACf,MAAM,WAAW,eAAe,GAAG,aAAa,GAAG,KAAK,SAAS,KAAK;CAEtE,IAAI,KAAK,SAAS;MACZ,OAAO,QAAQ,GAAG;GACpB,MAAM,WAAW;GACjB,MAAM,GAAG,MAAM,QAAQ,KAAK,SAAS,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;GAEpE,IAAI,SAAS,YAAY,sBAAsB,SAAS,YACtD,MAAM,eAAe,SAAS,YAAY,KAAK,SAAS,QAAQ,CAAC;QAC5D,IAAI,SAAS,YAAY,oBAC9B,MAAM,GAAG,UAAU,KAAK,SAAS,QAAQ,GAAG,SAAS,SAAS,OAAO;GAEvE,aAAa,KAAK,QAAQ;EAC5B;QAEA,KAAK,MAAM,SAAU,KAA0B,UAC7C,MAAM,0BAA0B,OAAO,SAAS,UAAU,QAAQ,YAAY;AAGpF;AAEA,eAAe,eAAe,cAAsB,UAAiC;CAEnF,MAAM,aAAa,KADG,uBACc,GAAG,YAAY;CAEnD,MAAM,GAAG,SAAS,YAAY,QAAQ;AACxC"}
1
+ {"version":3,"file":"fs-writer.mjs","names":[],"sources":["../src/fs-writer.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { Result, TaggedError } from \"better-result\";\nimport { join, dirname } from \"pathe\";\n\nimport { getBinaryTemplatesRoot } from \"./core/template-reader\";\nimport type { VirtualFileTree, VirtualNode, VirtualFile, VirtualDirectory } from \"./types\";\n\nconst BINARY_FILE_MARKER = \"[Binary file]\";\n\n/**\n * Error class for filesystem write failures\n */\nexport class FileWriteError extends TaggedError(\"FileWriteError\")<{\n message: string;\n path?: string;\n cause?: unknown;\n}>() {}\n\n/**\n * Writes a virtual file tree to the filesystem.\n * Returns a Result type for type-safe error handling.\n */\nexport async function writeTree(\n tree: VirtualFileTree,\n destDir: string,\n): Promise<Result<void, FileWriteError>> {\n return Result.tryPromise({\n try: async () => {\n for (const child of tree.root.children) {\n await writeNodeInternal(child, destDir, \"\");\n }\n },\n catch: (e) => {\n if (FileWriteError.is(e)) return e;\n return new FileWriteError({\n message: e instanceof Error ? e.message : String(e),\n cause: e,\n });\n },\n });\n}\n\nasync function writeNodeInternal(\n node: VirtualNode,\n baseDir: string,\n relativePath: string,\n): Promise<void> {\n const fullPath = join(baseDir, relativePath, node.name);\n const nodePath = relativePath ? join(relativePath, node.name) : node.name;\n\n if (node.type === \"file\") {\n const fileNode = node as VirtualFile;\n await assertSafeWritePath(baseDir, fullPath);\n await fs.mkdir(dirname(fullPath), { recursive: true });\n\n if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) {\n await copyBinaryFile(fileNode.sourcePath, fullPath);\n } else if (fileNode.content !== BINARY_FILE_MARKER) {\n await fs.writeFile(fullPath, fileNode.content, \"utf-8\");\n }\n } else {\n await assertSafeWritePath(baseDir, fullPath);\n await fs.mkdir(fullPath, { recursive: true });\n for (const child of (node as VirtualDirectory).children) {\n await writeNodeInternal(child, baseDir, nodePath);\n }\n }\n}\n\n/**\n * Writes selected files from a virtual file tree to the filesystem.\n * Returns a Result with the list of written file paths.\n */\nexport async function writeSelected(\n tree: VirtualFileTree,\n destDir: string,\n filter: (filePath: string) => boolean,\n): Promise<Result<string[], FileWriteError>> {\n return Result.tryPromise({\n try: async () => {\n const writtenFiles: string[] = [];\n await writeSelectedNodeInternal(tree.root, destDir, \"\", filter, writtenFiles);\n return writtenFiles;\n },\n catch: (e) => {\n if (FileWriteError.is(e)) return e;\n return new FileWriteError({\n message: e instanceof Error ? e.message : String(e),\n cause: e,\n });\n },\n });\n}\n\nasync function writeSelectedNodeInternal(\n node: VirtualNode,\n baseDir: string,\n relativePath: string,\n filter: (filePath: string) => boolean,\n writtenFiles: string[],\n): Promise<void> {\n const nodePath = relativePath ? `${relativePath}/${node.name}` : node.name;\n\n if (node.type === \"file\") {\n if (filter(nodePath)) {\n const fileNode = node as VirtualFile;\n await assertSafeWritePath(baseDir, join(baseDir, nodePath));\n await fs.mkdir(dirname(join(baseDir, nodePath)), { recursive: true });\n\n if (fileNode.content === BINARY_FILE_MARKER && fileNode.sourcePath) {\n await copyBinaryFile(fileNode.sourcePath, join(baseDir, nodePath));\n } else if (fileNode.content !== BINARY_FILE_MARKER) {\n await fs.writeFile(join(baseDir, nodePath), fileNode.content, \"utf-8\");\n }\n writtenFiles.push(nodePath);\n }\n } else {\n for (const child of (node as VirtualDirectory).children) {\n await writeSelectedNodeInternal(child, baseDir, nodePath, filter, writtenFiles);\n }\n }\n}\n\nasync function copyBinaryFile(templatePath: string, destPath: string): Promise<void> {\n const templatesRoot = getBinaryTemplatesRoot();\n const sourcePath = join(templatesRoot, templatePath);\n // Let errors propagate - they'll be caught by the Result wrapper\n await fs.copyFile(sourcePath, destPath);\n}\n\nasync function assertSafeWritePath(baseDir: string, destinationPath: string): Promise<void> {\n const resolvedBase = path.resolve(baseDir);\n const resolvedDestination = path.resolve(destinationPath);\n const relativeDestination = path.relative(resolvedBase, resolvedDestination);\n\n if (\n relativeDestination === \"..\" ||\n relativeDestination.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativeDestination)\n ) {\n throw new FileWriteError({\n message: `Refusing to write outside project directory: ${resolvedDestination}`,\n path: resolvedDestination,\n });\n }\n\n let currentPath = resolvedBase;\n const pathSegments = relativeDestination.split(path.sep).filter(Boolean);\n for (const segment of [\"\", ...pathSegments]) {\n if (segment) currentPath = path.join(currentPath, segment);\n\n let stats;\n try {\n stats = await fs.lstat(currentPath);\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return;\n }\n throw error;\n }\n\n if (stats.isSymbolicLink()) {\n throw new FileWriteError({\n message: `Refusing to write through symbolic link: ${currentPath}`,\n path: currentPath,\n });\n }\n }\n}\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -199,7 +199,7 @@ declare const dependencyVersionMap: {
199
199
  readonly "@tanstack/solid-query-devtools": "^5.101.2";
200
200
  readonly "@tanstack/solid-router-devtools": "^1.167.0";
201
201
  readonly wrangler: "^4.107.0";
202
- readonly "@cloudflare/vite-plugin": "^1.43.0";
202
+ readonly "@cloudflare/vite-plugin": "1.43.0";
203
203
  readonly "@opennextjs/cloudflare": "^1.20.1";
204
204
  readonly "nitro-cloudflare-dev": "^0.2.2";
205
205
  readonly "@sveltejs/adapter-cloudflare": "^7.2.9";
@@ -222,7 +222,7 @@ declare const dependencyVersionMap: {
222
222
  readonly "@polar-sh/sdk": "^0.47.1";
223
223
  readonly "@stripe/react-stripe-js": "^5.6.1";
224
224
  readonly "@stripe/stripe-js": "^8.11.0";
225
- readonly evlog: "^2.19.2";
225
+ readonly evlog: "^2.22.0";
226
226
  };
227
227
  type AvailableDependencies = keyof typeof dependencyVersionMap;
228
228
  //#endregion
package/dist/index.mjs CHANGED
@@ -272,16 +272,13 @@ function writeBtsConfigToVfs(vfs, projectConfig, version, reproducibleCommand) {
272
272
  serverDeploy: projectConfig.serverDeploy
273
273
  };
274
274
  const jsonContent = JSON.stringify(baseContent, null, 2);
275
- const finalContent = `// Better-T-Stack
275
+ const finalContent = `// Better-T-Stack project metadata
276
276
  //
277
- // Website: https://www.better-t-stack.dev/
278
- // Stack Builder: https://www.better-t-stack.dev/new
279
- // Analytics: https://www.better-t-stack.dev/analytics
280
- // Showcase: https://www.better-t-stack.dev/showcase
281
- // Sponsor: https://github.com/sponsors/AmanVarshney01
277
+ // Keep this file to use the \`add\` command.
278
+ // Add addons: ${projectConfig.packageManager === "npm" ? "npx create-better-t-stack@latest add" : projectConfig.packageManager === "pnpm" ? "pnpm dlx create-better-t-stack@latest add" : "bunx create-better-t-stack@latest add"}
282
279
  //
283
- // Add new addons with: ${projectConfig.packageManager === "npm" ? "npx create-better-t-stack add" : projectConfig.packageManager === "pnpm" ? "pnpm dlx create-better-t-stack add" : "bun create better-t-stack add"}
284
- // This file is safe to delete
280
+ // Docs: https://better-t-stack.dev/docs
281
+ // Stack Builder: https://better-t-stack.dev/new
285
282
 
286
283
  ${jsonContent}`;
287
284
  vfs.writeFile(BTS_CONFIG_FILE, finalContent);
@@ -515,7 +512,7 @@ const dependencyVersionMap = {
515
512
  "@tanstack/solid-query-devtools": "^5.101.2",
516
513
  "@tanstack/solid-router-devtools": "^1.167.0",
517
514
  wrangler: "^4.107.0",
518
- "@cloudflare/vite-plugin": "^1.43.0",
515
+ "@cloudflare/vite-plugin": "1.43.0",
519
516
  "@opennextjs/cloudflare": "^1.20.1",
520
517
  "nitro-cloudflare-dev": "^0.2.2",
521
518
  "@sveltejs/adapter-cloudflare": "^7.2.9",
@@ -538,7 +535,7 @@ const dependencyVersionMap = {
538
535
  "@polar-sh/sdk": "^0.47.1",
539
536
  "@stripe/react-stripe-js": "^5.6.1",
540
537
  "@stripe/stripe-js": "^8.11.0",
541
- evlog: "^2.19.2"
538
+ evlog: "^2.22.0"
542
539
  };
543
540
  /**
544
541
  * Add dependencies to a package.json file in the VFS
@@ -1227,7 +1224,7 @@ const hasAlchemyConfig = existsSync(alchemyConfigPath);`);
1227
1224
  }
1228
1225
  if (!sourceFile.getVariableDeclaration("cloudflareWorkersAlias")) {
1229
1226
  const firstExport = sourceFile.getStatements().findIndex((statement) => Node.isExportAssignment(statement));
1230
- sourceFile.insertStatements(firstExport === -1 ? sourceFile.getStatements().length : firstExport, `const cloudflareWorkersAlias = shouldUseAlchemy
1227
+ sourceFile.insertStatements(firstExport === -1 ? sourceFile.getStatements().length : firstExport, `const cloudflareWorkersAlias: Record<string, string> = shouldUseAlchemy
1231
1228
  ? {}
1232
1229
  : {
1233
1230
  "cloudflare:workers": cloudflareWorkersShimPath,
@@ -18916,7 +18913,7 @@ const apiHandler = new OpenAPIHandler(appRouter, {
18916
18913
  });
18917
18914
  {{/if}}
18918
18915
 
18919
- const app = {{#if (eq runtime "node")}}new Elysia({ adapter: node() }){{else}}new Elysia(){{/if}}
18916
+ {{#if (eq serverDeploy "vercel")}}const app = {{/if}}{{#if (eq runtime "node")}}new Elysia({ adapter: node() }){{else}}new Elysia(){{/if}}
18920
18917
  .use(
18921
18918
  cors({
18922
18919
  origin: env.CORS_ORIGIN,
@@ -24417,7 +24414,7 @@ async function handleSubmit(e: Event) {
24417
24414
  class="ms-auto"
24418
24415
  :status="status"
24419
24416
  @stop="stop"
24420
- @reload="regenerate"
24417
+ @reload="() => regenerate()"
24421
24418
  />
24422
24419
  </UChatPrompt>
24423
24420