@better-t-stack/template-generator 3.23.0 → 3.24.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":"template-reader.d.mts","names":[],"sources":["../../src/core/template-reader.ts"],"sourcesContent":[],"mappings":";;;iBASgB,gBAAA,CAAA;iBAcA,sBAAA,CAAA;AAdA,iBA4BM,aAAA,CA5BU,MAAA,CAAA,EAAA,MAAA,CAAA,EA4BsB,OA5BtB,CA4B8B,GA5B9B,CAAA,MAAA,EAAA,MAAA,CAAA,CAAA;AAchB,iBAyCA,YAAA,CAzCsB,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AAchB,iBAkCA,aAAA,CAlCgC,MAAO,CAAA,EAAA,MAAA,CAAA,EAkCP,OAlCO,CAAA,MAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"template-reader.d.mts","names":[],"sources":["../../src/core/template-reader.ts"],"sourcesContent":[],"mappings":";;;iBAUgB,gBAAA,CAAA;iBAcA,sBAAA,CAAA;AAdA,iBA4BM,aAAA,CA5BU,MAAA,CAAA,EAAA,MAAA,CAAA,EA4BsB,OA5BtB,CA4B8B,GA5B9B,CAAA,MAAA,EAAA,MAAA,CAAA,CAAA;AAchB,iBAyCA,YAAA,CAzCsB,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AAchB,iBAkCA,aAAA,CAlCgC,MAAO,CAAA,EAAA,MAAA,CAAA,EAkCP,OAlCO,CAAA,MAAA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs-writer.d.mts","names":[],"sources":["../src/fs-writer.ts"],"sourcesContent":[],"mappings":";;;;;cAI2F,qBAAA,cAAA,CAAA;;;EAAA,KAAA,CAAA,EAAA,OAAA;AAS3F,CAAA,CAAA;AAUA;;;AAGW,cAbE,cAAA,SAAuB,mBAAA,CAazB;;AA8CX;;;AAIW,iBArDW,SAAA,CAqDX,IAAA,EApDH,eAoDG,EAAA,OAAA,EAAA,MAAA,CAAA,EAlDR,OAkDQ,CAlDA,MAkDA,CAAA,IAAA,EAlDa,cAkDb,CAAA,CAAA;;;;;iBAJW,aAAA,OACd,0EAGL,QAAQ,iBAAiB"}
1
+ {"version":3,"file":"fs-writer.d.mts","names":[],"sources":["../src/fs-writer.ts"],"sourcesContent":[],"mappings":";;;;;cAM2F,qBAAA,cAAA,CAAA;;;EAAA,KAAA,CAAA,EAAA,OAAA;AAO3F,CAAA,CAAA;AAUA;;;AAGW,cAbE,cAAA,SAAuB,mBAAA,CAazB;;AA8CX;;;AAIW,iBArDW,SAAA,CAqDX,IAAA,EApDH,eAoDG,EAAA,OAAA,EAAA,MAAA,CAAA,EAlDR,OAkDQ,CAlDA,MAkDA,CAAA,IAAA,EAlDa,cAkDb,CAAA,CAAA;;;;;iBAJW,aAAA,OACd,0EAGL,QAAQ,iBAAiB"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs-writer.mjs","names":["writtenFiles: string[]"],"sources":["../src/fs-writer.ts"],"sourcesContent":["import { Result, TaggedError } from \"better-result\";\nimport * as fs from \"node:fs/promises\";\nimport { join, dirname } from \"pathe\";\n\nimport type { VirtualFileTree, VirtualNode, VirtualFile, VirtualDirectory } from \"./types\";\n\nimport { getBinaryTemplatesRoot } from \"./core/template-reader\";\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,iBAAiB,EAI7D,CAAC;;;;;AAML,eAAsB,UACpB,MACA,SACuC;AACvC,QAAO,OAAO,WAAW;EACvB,KAAK,YAAY;AACf,QAAK,MAAM,SAAS,KAAK,KAAK,SAC5B,OAAM,kBAAkB,OAAO,SAAS,GAAG;;EAG/C,QAAQ,MAAM;AACZ,OAAI,eAAe,GAAG,EAAE,CAAE,QAAO;AACjC,UAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IACnD,OAAO;IACR,CAAC;;EAEL,CAAC;;AAGJ,eAAe,kBACb,MACA,SACA,cACe;CACf,MAAM,WAAW,KAAK,SAAS,cAAc,KAAK,KAAK;CACvD,MAAM,WAAW,eAAe,KAAK,cAAc,KAAK,KAAK,GAAG,KAAK;AAErE,KAAI,KAAK,SAAS,QAAQ;EACxB,MAAM,WAAW;AACjB,QAAM,GAAG,MAAM,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AAEtD,MAAI,SAAS,YAAY,sBAAsB,SAAS,WACtD,OAAM,eAAe,SAAS,YAAY,SAAS;WAC1C,SAAS,YAAY,mBAC9B,OAAM,GAAG,UAAU,UAAU,SAAS,SAAS,QAAQ;QAEpD;AACL,QAAM,GAAG,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;AAC7C,OAAK,MAAM,SAAU,KAA0B,SAC7C,OAAM,kBAAkB,OAAO,SAAS,SAAS;;;;;;;AASvD,eAAsB,cACpB,MACA,SACA,QAC2C;AAC3C,QAAO,OAAO,WAAW;EACvB,KAAK,YAAY;GACf,MAAMA,eAAyB,EAAE;AACjC,SAAM,0BAA0B,KAAK,MAAM,SAAS,IAAI,QAAQ,aAAa;AAC7E,UAAO;;EAET,QAAQ,MAAM;AACZ,OAAI,eAAe,GAAG,EAAE,CAAE,QAAO;AACjC,UAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IACnD,OAAO;IACR,CAAC;;EAEL,CAAC;;AAGJ,eAAe,0BACb,MACA,SACA,cACA,QACA,cACe;CACf,MAAM,WAAW,eAAe,GAAG,aAAa,GAAG,KAAK,SAAS,KAAK;AAEtE,KAAI,KAAK,SAAS,QAChB;MAAI,OAAO,SAAS,EAAE;GACpB,MAAM,WAAW;AACjB,SAAM,GAAG,MAAM,QAAQ,KAAK,SAAS,SAAS,CAAC,EAAE,EAAE,WAAW,MAAM,CAAC;AAErE,OAAI,SAAS,YAAY,sBAAsB,SAAS,WACtD,OAAM,eAAe,SAAS,YAAY,KAAK,SAAS,SAAS,CAAC;YACzD,SAAS,YAAY,mBAC9B,OAAM,GAAG,UAAU,KAAK,SAAS,SAAS,EAAE,SAAS,SAAS,QAAQ;AAExE,gBAAa,KAAK,SAAS;;OAG7B,MAAK,MAAM,SAAU,KAA0B,SAC7C,OAAM,0BAA0B,OAAO,SAAS,UAAU,QAAQ,aAAa;;AAKrF,eAAe,eAAe,cAAsB,UAAiC;CAEnF,MAAM,aAAa,KADG,wBAAwB,EACP,aAAa;AAEpD,OAAM,GAAG,SAAS,YAAY,SAAS"}
1
+ {"version":3,"file":"fs-writer.mjs","names":["writtenFiles: string[]"],"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,iBAAiB,EAI7D,CAAC;;;;;AAML,eAAsB,UACpB,MACA,SACuC;AACvC,QAAO,OAAO,WAAW;EACvB,KAAK,YAAY;AACf,QAAK,MAAM,SAAS,KAAK,KAAK,SAC5B,OAAM,kBAAkB,OAAO,SAAS,GAAG;;EAG/C,QAAQ,MAAM;AACZ,OAAI,eAAe,GAAG,EAAE,CAAE,QAAO;AACjC,UAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IACnD,OAAO;IACR,CAAC;;EAEL,CAAC;;AAGJ,eAAe,kBACb,MACA,SACA,cACe;CACf,MAAM,WAAW,KAAK,SAAS,cAAc,KAAK,KAAK;CACvD,MAAM,WAAW,eAAe,KAAK,cAAc,KAAK,KAAK,GAAG,KAAK;AAErE,KAAI,KAAK,SAAS,QAAQ;EACxB,MAAM,WAAW;AACjB,QAAM,GAAG,MAAM,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AAEtD,MAAI,SAAS,YAAY,sBAAsB,SAAS,WACtD,OAAM,eAAe,SAAS,YAAY,SAAS;WAC1C,SAAS,YAAY,mBAC9B,OAAM,GAAG,UAAU,UAAU,SAAS,SAAS,QAAQ;QAEpD;AACL,QAAM,GAAG,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;AAC7C,OAAK,MAAM,SAAU,KAA0B,SAC7C,OAAM,kBAAkB,OAAO,SAAS,SAAS;;;;;;;AASvD,eAAsB,cACpB,MACA,SACA,QAC2C;AAC3C,QAAO,OAAO,WAAW;EACvB,KAAK,YAAY;GACf,MAAMA,eAAyB,EAAE;AACjC,SAAM,0BAA0B,KAAK,MAAM,SAAS,IAAI,QAAQ,aAAa;AAC7E,UAAO;;EAET,QAAQ,MAAM;AACZ,OAAI,eAAe,GAAG,EAAE,CAAE,QAAO;AACjC,UAAO,IAAI,eAAe;IACxB,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IACnD,OAAO;IACR,CAAC;;EAEL,CAAC;;AAGJ,eAAe,0BACb,MACA,SACA,cACA,QACA,cACe;CACf,MAAM,WAAW,eAAe,GAAG,aAAa,GAAG,KAAK,SAAS,KAAK;AAEtE,KAAI,KAAK,SAAS,QAChB;MAAI,OAAO,SAAS,EAAE;GACpB,MAAM,WAAW;AACjB,SAAM,GAAG,MAAM,QAAQ,KAAK,SAAS,SAAS,CAAC,EAAE,EAAE,WAAW,MAAM,CAAC;AAErE,OAAI,SAAS,YAAY,sBAAsB,SAAS,WACtD,OAAM,eAAe,SAAS,YAAY,KAAK,SAAS,SAAS,CAAC;YACzD,SAAS,YAAY,mBAC9B,OAAM,GAAG,UAAU,KAAK,SAAS,SAAS,EAAE,SAAS,SAAS,QAAQ;AAExE,gBAAa,KAAK,SAAS;;OAG7B,MAAK,MAAM,SAAU,KAA0B,SAC7C,OAAM,0BAA0B,OAAO,SAAS,UAAU,QAAQ,aAAa;;AAKrF,eAAe,eAAe,cAAsB,UAAiC;CAEnF,MAAM,aAAa,KADG,wBAAwB,EACP,aAAa;AAEpD,OAAM,GAAG,SAAS,YAAY,SAAS"}
package/dist/index.d.mts CHANGED
@@ -74,7 +74,7 @@ declare function writeBtsConfigToVfs(vfs: VirtualFileSystem, projectConfig: Proj
74
74
  //#endregion
75
75
  //#region src/templates.generated.d.ts
76
76
  declare const EMBEDDED_TEMPLATES: Map<string, string>;
77
- declare const TEMPLATE_COUNT = 441;
77
+ declare const TEMPLATE_COUNT = 444;
78
78
  //#endregion
79
79
  //#region src/utils/add-deps.d.ts
80
80
  declare const dependencyVersionMap: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/virtual-fs.ts","../src/core/template-processor.ts","../src/template-handlers/utils.ts","../src/template-handlers/addons.ts","../src/generator.ts","../src/processors/addons-deps.ts","../src/bts-config.ts","../src/templates.generated.ts","../src/utils/add-deps.ts","../src/utils/reproducible-command.ts"],"sourcesContent":[],"mappings":";;;;;;;cAOa,iBAAA;;;;;;EAAA,QAAA,CAAA,QAAA,EAAA,MAAiB,CAAA,EAAA,MAAA,GAAA,SAAA;EA6Ea,MAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAkCX,UAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAAgB,eAcrC,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAAA,KAGJ,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA,UAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;2CAnDoC;;ECzE3B,WAAA,CAAA,CAAA,EAAA,MAAA,EAAA;EAIA,iBAAY,CAAA,CAAA,EAAA,MAAA,EAAA;EAIZ,YAAA,CAAA,CAAA,EAAA,MAAiB;EAUjB,iBAAA,CAAA,CAAA,EAAkB,MAAA;6BDyFF;;eAAgB,MAAA,CAcrC;EE9HC,KAAA,CAAA,CAAA,EF8HD,MAAA,CAGJ,GEjIoB;;;;ECAL,QAAA,aAAA;;;;iBFKN,qBAAA,2BAAgD;iBAIhD,YAAA;iBAIA,iBAAA;iBAUA,kBAAA,6CAGL;;;KC1BC,YAAA,GAAe;;;iBCAL,qBAAA,MACf,8BACM,sBACH,gBACP;;;;;AHHH;;;;;;;;;ACIA;AAIA;AAIgB,iBG+BM,QAAA,CH/BW,OAAA,EGgCtB,gBHhCsB,CAAA,EGiC9B,OHjC8B,CGiCtB,MHjCsB,CGiCf,eHjCe,EGiCE,cHjCF,CAAA,CAAA;;;iBIJjB,iBAAA,MAAuB,2BAA2B;;;;;;;iBCLlD,mBAAA,MACT,kCACU;;;cCTJ,oBAAoB;cAsp0BpB,cAAA;;;cC5o0BA;;;ERNA,SAAA,mBAAiB,EAAA,OAAA;EA6Ea,SAAA,eAAA,EAAA,SAAA;EAkCX,SAAA,oBAAA,EAAA,SAAA;EAAgB,SAcrC,6BAAA,EAAA,SAAA;EAAA,SAGJ,mBAAA,EAAA,UAAA;EAAA,SAAA,aAAA,EAAA,SAAA;;;;EC5HS,SAAA,MAAA,EAAA,QAAqB;EAIrB,SAAA,0BAAY,EAAA,QAAA;EAIZ,SAAA,EAAA,EAAA,SAAiB;EAUjB,SAAA,WAAA,EAAkB,SAAA;;;;ECvBtB,SAAA,gBAAY,EAAG,QAAG;;;;ECAR,SAAA,yBAAqB,EAAA,QAAA;EACpC,SAAA,wBAAA,EAAA,QAAA;EACM,SAAA,gCAAA,EAAA,QAAA;EACH,SAAA,oBAAA,EAAA,QAAA;EACP,SAAA,6BAAA,EAAA,QAAA;EAAO,SAAA,QAAA,EAAA,SAAA;;;;ECwCY,SAAA,gBAAQ,EAAA,QAAA;EACnB,SAAA,MAAA,EAAA,SAAA;EACO,SAAA,KAAA,EAAA,SAAA;EAAiB,SAAA,KAAA,EAAA,QAAA;EAAxB,SAAA,QAAA,EAAA,SAAA;EAAR,SAAA,aAAA,EAAA,SAAA;EAAO,SAAA,GAAA,EAAA,SAAA;;;;ECrCM,SAAA,gBAAiB,EAAA,QAAM;;;;ECLvB,SAAA,mBAAmB,EAAA,QAC5B;;;;ECRM,SAAA,gBAop0BX,EAAA,QApp0B+B;EAsp0BpB,SAAA,aAAc,EAAA,SAAA;;;;EC5o0Bd,SAAA,EAAA,EAAA,SAAA;EAiJD,SAAA,EAAA,EAAA,QAAA;;;;ECnII,SAAA,eAAA,EAAA,QAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KDmI/B,qBAAA,gBAAqC;;;iBCnIjC,2BAAA,SAAoC"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/virtual-fs.ts","../src/core/template-processor.ts","../src/template-handlers/utils.ts","../src/template-handlers/addons.ts","../src/generator.ts","../src/processors/addons-deps.ts","../src/bts-config.ts","../src/templates.generated.ts","../src/utils/add-deps.ts","../src/utils/reproducible-command.ts"],"sourcesContent":[],"mappings":";;;;;;;cAOa,iBAAA;;;;;;EAAA,QAAA,CAAA,QAAA,EAAA,MAAiB,CAAA,EAAA,MAAA,GAAA,SAAA;EA6Ea,MAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAkCX,UAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAAgB,eAcrC,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAAA,KAGJ,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA,UAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;2CAnDoC;;EC1E3B,WAAA,CAAA,CAAA,EAAA,MAAA,EAAA;EAIA,iBAAY,CAAA,CAAA,EAAA,MAAA,EAAA;EAIZ,YAAA,CAAA,CAAA,EAAA,MAAiB;EAUjB,iBAAA,CAAA,CAAA,EAAkB,MAAA;6BD0FF;;eAAgB,MAAA,CAcrC;EE/HC,KAAA,CAAA,CAAA,EF+HD,MAAA,CAGJ,GElIoB;;;;ECAL,QAAA,aAAA;;;;iBFKN,qBAAA,2BAAgD;iBAIhD,YAAA;iBAIA,iBAAA;iBAUA,kBAAA,6CAGL;;;KC1BC,YAAA,GAAe;;;iBCAL,qBAAA,MACf,8BACM,sBACH,gBACP;;;;;AHFH;;;;;;;;;ACGA;AAIA;AAIgB,iBG+BM,QAAA,CH/BW,OAAA,EGgCtB,gBHhCsB,CAAA,EGiC9B,OHjC8B,CGiCtB,MHjCsB,CGiCf,eHjCe,EGiCE,cHjCF,CAAA,CAAA;;;iBIJjB,iBAAA,MAAuB,2BAA2B;;;;;;;iBCJlD,mBAAA,MACT,kCACU;;;cCTJ,oBAAoB;cAwn0BpB,cAAA;;;cC9m0BA;;;ERNA,SAAA,mBAAiB,EAAA,OAAA;EA6Ea,SAAA,eAAA,EAAA,SAAA;EAkCX,SAAA,oBAAA,EAAA,SAAA;EAAgB,SAcrC,6BAAA,EAAA,SAAA;EAAA,SAGJ,mBAAA,EAAA,UAAA;EAAA,SAAA,aAAA,EAAA,SAAA;;;;EC7HS,SAAA,MAAA,EAAA,QAAqB;EAIrB,SAAA,0BAAY,EAAA,QAAA;EAIZ,SAAA,EAAA,EAAA,SAAiB;EAUjB,SAAA,WAAA,EAAkB,SAAA;;;;ECvBtB,SAAA,gBAAY,EAAG,QAAG;;;;ECAR,SAAA,yBAAqB,EAAA,QAAA;EACpC,SAAA,wBAAA,EAAA,QAAA;EACM,SAAA,gCAAA,EAAA,QAAA;EACH,SAAA,oBAAA,EAAA,QAAA;EACP,SAAA,6BAAA,EAAA,QAAA;EAAO,SAAA,QAAA,EAAA,SAAA;;;;ECwCY,SAAA,gBAAQ,EAAA,QAAA;EACnB,SAAA,MAAA,EAAA,SAAA;EACO,SAAA,KAAA,EAAA,SAAA;EAAiB,SAAA,KAAA,EAAA,QAAA;EAAxB,SAAA,QAAA,EAAA,SAAA;EAAR,SAAA,aAAA,EAAA,SAAA;EAAO,SAAA,GAAA,EAAA,SAAA;;;;ECrCM,SAAA,gBAAiB,EAAA,QAAM;;;;ECJvB,SAAA,mBAAmB,EAAA,QAC5B;;;;ECRM,SAAA,gBAsn0BX,EAAA,QAtn0B+B;EAwn0BpB,SAAA,aAAc,EAAA,SAAA;;;;EC9m0Bd,SAAA,EAAA,EAAA,SAAA;EAiJD,SAAA,EAAA,EAAA,QAAA;;;;ECnII,SAAA,eAAA,EAAA,QAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KDmI/B,qBAAA,gBAAqC;;;iBCnIjC,2BAAA,SAAoC"}
package/dist/index.mjs CHANGED
@@ -4,6 +4,7 @@ import { memfs } from "memfs";
4
4
  import { dirname, extname, join, normalize } from "pathe";
5
5
  import Handlebars from "handlebars";
6
6
  import yaml from "yaml";
7
+ import { desktopWebFrontends } from "@better-t-stack/types";
7
8
  import { IndentationText, Node, Project, QuoteKind, SyntaxKind } from "ts-morph";
8
9
 
9
10
  //#region src/types.ts
@@ -267,6 +268,7 @@ const PACKAGE_PATHS = [
267
268
  "apps/server",
268
269
  "apps/web",
269
270
  "apps/native",
271
+ "apps/desktop",
270
272
  "apps/fumadocs",
271
273
  "apps/docs",
272
274
  "packages/api",
@@ -408,6 +410,10 @@ function getDbScriptSupport(config) {
408
410
  //#endregion
409
411
  //#region src/post-process/package-configs.ts
410
412
  /**
413
+ * Package.json configuration post-processor
414
+ * Updates package names, scripts, and workspaces after template generation
415
+ */
416
+ /**
411
417
  * Update all package.json files with proper names, scripts, and workspaces
412
418
  */
413
419
  function processPackageConfigs(vfs, config) {
@@ -416,6 +422,7 @@ function processPackageConfigs(vfs, config) {
416
422
  updateEnvPackageJson(vfs, config);
417
423
  updateUiPackageJson(vfs, config);
418
424
  updateInfraPackageJson(vfs, config);
425
+ updateDesktopPackageJson(vfs, config);
419
426
  renameDevScriptsForAlchemy(vfs, config);
420
427
  if (config.backend === "convex") updateConvexPackageJson(vfs, config);
421
428
  else if (config.backend !== "none") {
@@ -434,7 +441,13 @@ function updateRootPackageJson(vfs, config) {
434
441
  else if (pkgJson.workspaces && typeof pkgJson.workspaces === "object" && pkgJson.workspaces.packages) workspaces = pkgJson.workspaces.packages;
435
442
  pkgJson.workspaces = workspaces;
436
443
  const scripts = pkgJson.scripts;
437
- const { projectName, packageManager, backend, database, orm, dbSetup, addons } = config;
444
+ const { projectName, packageManager, backend, database, orm, dbSetup, addons, frontend } = config;
445
+ const hasWebApp = frontend.some((item) => desktopWebFrontends.includes(item));
446
+ const hasNativeApp = frontend.some((item) => [
447
+ "native-bare",
448
+ "native-uniwind",
449
+ "native-unistyles"
450
+ ].includes(item));
438
451
  const backendPackageName = backend === "convex" ? `@${projectName}/backend` : "server";
439
452
  const dbPackageName = `@${projectName}/db`;
440
453
  const hasTurborepo = addons.includes("turborepo");
@@ -449,8 +462,13 @@ function updateRootPackageJson(vfs, config) {
449
462
  scripts.dev = pmConfig.dev;
450
463
  scripts.build = pmConfig.build;
451
464
  scripts["check-types"] = pmConfig.checkTypes;
452
- scripts["dev:native"] = pmConfig.filter("native", "dev");
453
- scripts["dev:web"] = pmConfig.filter("web", "dev");
465
+ if (hasNativeApp) scripts["dev:native"] = pmConfig.filter("native", "dev");
466
+ if (hasWebApp) scripts["dev:web"] = pmConfig.filter("web", "dev");
467
+ if (addons.includes("electrobun")) {
468
+ scripts["dev:desktop"] = pmConfig.filter("desktop", "dev:hmr");
469
+ scripts["build:desktop"] = pmConfig.filter("desktop", "build:stable");
470
+ scripts["build:desktop:canary"] = pmConfig.filter("desktop", "build:canary");
471
+ }
454
472
  if (addons.includes("opentui")) scripts["dev:tui"] = pmConfig.filter("tui", "dev");
455
473
  if (backend !== "self" && backend !== "none") scripts["dev:server"] = pmConfig.filter(backendPackageName, "dev");
456
474
  if (backend === "convex") scripts["dev:setup"] = pmConfig.filter(backendPackageName, "dev:setup");
@@ -522,6 +540,53 @@ function getPackageManagerConfig(packageManager, options) {
522
540
  };
523
541
  }
524
542
  }
543
+ function updateDesktopPackageJson(vfs, config) {
544
+ const pkgJson = vfs.readJson("apps/desktop/package.json");
545
+ if (!pkgJson) return;
546
+ const { packageManager, addons, frontend } = config;
547
+ const hasTurborepo = addons.includes("turborepo");
548
+ const hasNx = addons.includes("nx");
549
+ const desktopBuildScript = frontend.includes("nuxt") ? "generate" : "build";
550
+ const webBuildCommand = getDesktopWebCommand(packageManager, {
551
+ hasTurborepo,
552
+ hasNx
553
+ }, desktopBuildScript);
554
+ const webDevCommand = getDesktopWebCommand(packageManager, {
555
+ hasTurborepo,
556
+ hasNx
557
+ }, "dev");
558
+ const localRunCommand = getLocalRunCommand(packageManager);
559
+ pkgJson.scripts = {
560
+ ...pkgJson.scripts,
561
+ start: `${webBuildCommand} && electrobun dev`,
562
+ dev: "electrobun dev --watch",
563
+ "dev:hmr": `concurrently "${localRunCommand} hmr" "${localRunCommand} start"`,
564
+ hmr: webDevCommand,
565
+ build: `${webBuildCommand} && electrobun build`,
566
+ "build:stable": `${webBuildCommand} && electrobun build --env=stable`,
567
+ "build:canary": `${webBuildCommand} && electrobun build --env=canary`,
568
+ "check-types": "tsc --noEmit"
569
+ };
570
+ vfs.writeJson("apps/desktop/package.json", pkgJson);
571
+ }
572
+ function getDesktopWebCommand(packageManager, options, script) {
573
+ if (options.hasTurborepo) return `turbo -F web ${script}`;
574
+ if (options.hasNx) return `nx run-many -t ${script} --projects=web`;
575
+ switch (packageManager) {
576
+ case "npm": return `npm run ${script} --workspace web`;
577
+ case "pnpm": return `pnpm -w --filter web ${script}`;
578
+ case "bun":
579
+ default: return `bun run --filter web ${script}`;
580
+ }
581
+ }
582
+ function getLocalRunCommand(packageManager) {
583
+ switch (packageManager) {
584
+ case "npm": return "npm run";
585
+ case "pnpm": return "pnpm run";
586
+ case "bun":
587
+ default: return "bun run";
588
+ }
589
+ }
525
590
  function updateDbPackageJson(vfs, config) {
526
591
  const pkgJson = vfs.readJson("packages/db/package.json");
527
592
  if (!pkgJson) return;
@@ -576,15 +641,7 @@ function updateEnvPackageJson(vfs, config) {
576
641
  const pkgJson = vfs.readJson("packages/env/package.json");
577
642
  if (!pkgJson) return;
578
643
  pkgJson.name = `@${config.projectName}/env`;
579
- const hasWebFrontend = config.frontend.some((f) => [
580
- "tanstack-router",
581
- "react-router",
582
- "tanstack-start",
583
- "next",
584
- "nuxt",
585
- "svelte",
586
- "solid"
587
- ].includes(f));
644
+ const hasWebFrontend = config.frontend.some((f) => desktopWebFrontends.includes(f));
588
645
  const hasNative = config.frontend.some((f) => [
589
646
  "native-bare",
590
647
  "native-uniwind",
@@ -2359,6 +2416,18 @@ function processPwaPlugins(vfs, config) {
2359
2416
 
2360
2417
  //#endregion
2361
2418
  //#region src/processors/readme-generator.ts
2419
+ function getDesktopStaticBuildNote(frontend) {
2420
+ const staticBuildFrontends = new Map([
2421
+ ["tanstack-start", "TanStack Start"],
2422
+ ["next", "Next.js"],
2423
+ ["nuxt", "Nuxt"],
2424
+ ["svelte", "SvelteKit"],
2425
+ ["astro", "Astro"]
2426
+ ]);
2427
+ const staticBuildFrontend = frontend.find((value) => staticBuildFrontends.has(value));
2428
+ if (!staticBuildFrontend) return "";
2429
+ return `Desktop builds package static web assets. ${staticBuildFrontends.get(staticBuildFrontend)} needs a static/export build configuration before desktop packaging will work.`;
2430
+ }
2362
2431
  function processReadme(vfs, config) {
2363
2432
  const content = generateReadmeContent(config);
2364
2433
  vfs.writeFile("README.md", content);
@@ -2623,6 +2692,7 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
2623
2692
  const addonFeatures = {
2624
2693
  pwa: "- **PWA** - Progressive Web App support",
2625
2694
  tauri: "- **Tauri** - Build native desktop applications",
2695
+ electrobun: "- **Electrobun** - Lightweight desktop shell for web frontends",
2626
2696
  biome: "- **Biome** - Linting and formatting",
2627
2697
  oxlint: "- **Oxlint** - Oxlint + Oxfmt (linting & formatting)",
2628
2698
  husky: "- **Husky** - Git hooks for code quality",
@@ -2679,13 +2749,23 @@ ${packageManagerRunCmd} db:push
2679
2749
  return setup;
2680
2750
  }
2681
2751
  function generateScriptsList(packageManagerRunCmd, config, hasNative) {
2682
- const { database, addons, backend, dbSetup } = config;
2752
+ const { database, addons, backend, dbSetup, frontend } = config;
2683
2753
  const isConvex = backend === "convex";
2684
2754
  const isBackendSelf = backend === "self";
2755
+ const hasWeb = frontend.some((f) => [
2756
+ "tanstack-router",
2757
+ "react-router",
2758
+ "tanstack-start",
2759
+ "next",
2760
+ "nuxt",
2761
+ "svelte",
2762
+ "solid",
2763
+ "astro"
2764
+ ].includes(f));
2685
2765
  const dbSupport = getDbScriptSupport(config);
2686
2766
  let scripts = `- \`${packageManagerRunCmd} dev\`: Start all applications in development mode
2687
2767
  - \`${packageManagerRunCmd} build\`: Build all applications`;
2688
- if (!isBackendSelf) scripts += `\n- \`${packageManagerRunCmd} dev:web\`: Start only the web application`;
2768
+ if (hasWeb) scripts += `\n- \`${packageManagerRunCmd} dev:web\`: Start only the web application`;
2689
2769
  if (isConvex) scripts += `\n- \`${packageManagerRunCmd} dev:setup\`: Setup and configure your Convex project`;
2690
2770
  else if (backend !== "none" && !isBackendSelf) scripts += `\n- \`${packageManagerRunCmd} dev:server\`: Start only the server`;
2691
2771
  scripts += `\n- \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`;
@@ -2700,8 +2780,19 @@ function generateScriptsList(packageManagerRunCmd, config, hasNative) {
2700
2780
  if (addons.includes("biome")) scripts += `\n- \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`;
2701
2781
  if (addons.includes("oxlint")) scripts += `\n- \`${packageManagerRunCmd} check\`: Run Oxlint and Oxfmt`;
2702
2782
  if (addons.includes("pwa")) scripts += `\n- \`cd apps/web && ${packageManagerRunCmd} generate-pwa-assets\`: Generate PWA assets`;
2703
- if (addons.includes("tauri")) scripts += `\n- \`cd apps/web && ${packageManagerRunCmd} desktop:dev\`: Start Tauri desktop app in development
2783
+ if (addons.includes("tauri")) {
2784
+ scripts += `\n- \`cd apps/web && ${packageManagerRunCmd} desktop:dev\`: Start Tauri desktop app in development
2704
2785
  - \`cd apps/web && ${packageManagerRunCmd} desktop:build\`: Build Tauri desktop app`;
2786
+ const staticBuildNote = getDesktopStaticBuildNote(frontend);
2787
+ if (staticBuildNote) scripts += `\n- Note: ${staticBuildNote}`;
2788
+ }
2789
+ if (addons.includes("electrobun")) {
2790
+ scripts += `\n- \`${packageManagerRunCmd} dev:desktop\`: Start the Electrobun desktop app with HMR
2791
+ - \`${packageManagerRunCmd} build:desktop\`: Build the stable Electrobun desktop app
2792
+ - \`${packageManagerRunCmd} build:desktop:canary\`: Build the canary Electrobun desktop app`;
2793
+ const staticBuildNote = getDesktopStaticBuildNote(frontend);
2794
+ if (staticBuildNote) scripts += `\n- Note: ${staticBuildNote}`;
2795
+ }
2705
2796
  if (addons.includes("starlight")) scripts += `\n- \`cd apps/docs && ${packageManagerRunCmd} dev\`: Start documentation site
2706
2797
  - \`cd apps/docs && ${packageManagerRunCmd} build\`: Build documentation site`;
2707
2798
  return scripts;
@@ -3648,6 +3739,114 @@ const EMBEDDED_TEMPLATES = new Map([
3648
3739
  ]
3649
3740
  {{/if}}
3650
3741
  }
3742
+ `],
3743
+ ["addons/electrobun/apps/desktop/.gitignore", `artifacts
3744
+ `],
3745
+ ["addons/electrobun/apps/desktop/electrobun.config.ts.hbs", `import type { ElectrobunConfig } from "electrobun";
3746
+
3747
+ const webBuildDir =
3748
+ "{{#if (includes frontend "react-router")}}../web/build/client{{else if (includes frontend "tanstack-start")}}../web/dist/client{{else if (includes frontend "next")}}../web/out{{else if (includes frontend "nuxt")}}../web/.output/public{{else if (includes frontend "svelte")}}../web/build{{else}}../web/dist{{/if}}";
3749
+
3750
+ export default {
3751
+ app: {
3752
+ name: "{{projectName}}",
3753
+ identifier: "dev.bettertstack.{{projectName}}.desktop",
3754
+ version: "0.0.1",
3755
+ },
3756
+ runtime: {
3757
+ exitOnLastWindowClosed: true,
3758
+ },
3759
+ build: {
3760
+ bun: {
3761
+ entrypoint: "src/bun/index.ts",
3762
+ },
3763
+ copy: {
3764
+ [webBuildDir]: "views/mainview",
3765
+ },
3766
+ watchIgnore: [\`\${webBuildDir}/**\`],
3767
+ mac: {
3768
+ bundleCEF: true,
3769
+ defaultRenderer: "cef",
3770
+ },
3771
+ linux: {
3772
+ bundleCEF: true,
3773
+ defaultRenderer: "cef",
3774
+ },
3775
+ win: {
3776
+ bundleCEF: true,
3777
+ defaultRenderer: "cef",
3778
+ },
3779
+ },
3780
+ } satisfies ElectrobunConfig;
3781
+ `],
3782
+ ["addons/electrobun/apps/desktop/package.json.hbs", `{
3783
+ "name": "desktop",
3784
+ "private": true,
3785
+ "type": "module",
3786
+ "scripts": {},
3787
+ "dependencies": {
3788
+ "electrobun": "^1.15.1"
3789
+ },
3790
+ "devDependencies": {
3791
+ "@types/bun": "^1.3.4",
3792
+ "concurrently": "^9.1.0",
3793
+ "typescript": "^5"
3794
+ }
3795
+ }
3796
+ `],
3797
+ ["addons/electrobun/apps/desktop/src/bun/index.ts.hbs", `import { BrowserWindow, Updater } from "electrobun/bun";
3798
+
3799
+ const DEV_SERVER_PORT = {{#if (or (includes frontend "react-router") (includes frontend "svelte"))}}5173{{else if (includes frontend "astro")}}4321{{else}}3001{{/if}};
3800
+ const DEV_SERVER_URL = \`http://localhost:\${DEV_SERVER_PORT}\`;
3801
+
3802
+ // Check if the web dev server is running for HMR
3803
+ async function getMainViewUrl(): Promise<string> {
3804
+ const channel = await Updater.localInfo.channel();
3805
+ if (channel === "dev") {
3806
+ try {
3807
+ await fetch(DEV_SERVER_URL, { method: "HEAD" });
3808
+ console.log(\`HMR enabled: Using web dev server at \${DEV_SERVER_URL}\`);
3809
+ return DEV_SERVER_URL;
3810
+ } catch {
3811
+ console.log(
3812
+ 'Web dev server not running. Run "{{packageManager}} run dev:hmr" for HMR support.',
3813
+ );
3814
+ }
3815
+ }
3816
+
3817
+ return "views://mainview/index.html";
3818
+ }
3819
+
3820
+ const url = await getMainViewUrl();
3821
+
3822
+ new BrowserWindow({
3823
+ title: "{{projectName}}",
3824
+ url,
3825
+ frame: {
3826
+ width: 1280,
3827
+ height: 820,
3828
+ x: 120,
3829
+ y: 120,
3830
+ },
3831
+ });
3832
+
3833
+ console.log("Electrobun desktop shell started.");
3834
+ `],
3835
+ ["addons/electrobun/apps/desktop/tsconfig.json.hbs", `{
3836
+ "extends": "../../packages/config/tsconfig.base.json",
3837
+ "compilerOptions": {
3838
+ "lib": ["ESNext", "DOM"],
3839
+ "target": "ESNext",
3840
+ "module": "ESNext",
3841
+ "moduleResolution": "bundler",
3842
+ "noEmit": true,
3843
+ "baseUrl": ".",
3844
+ "paths": {
3845
+ "@/*": ["./src/*"]
3846
+ }
3847
+ },
3848
+ "include": ["src/**/*.ts", "electrobun.config.ts"]
3849
+ }
3651
3850
  `],
3652
3851
  ["addons/husky/.husky/pre-commit", `lint-staged
3653
3852
  `],
@@ -3748,142 +3947,6 @@ export default defineConfig({
3748
3947
  preset,
3749
3948
  images: ["public/logo.png"],
3750
3949
  });
3751
- `],
3752
- ["addons/ruler/.ruler/bts.md.hbs", `# Better-T-Stack Project Rules
3753
-
3754
- This is a {{projectName}} project created with Better-T-Stack CLI.
3755
-
3756
- ## Project Structure
3757
-
3758
- This is a monorepo with the following structure:
3759
-
3760
- {{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
3761
- (includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
3762
- - **\`apps/web/\`** - {{#if (eq backend "self")}}Fullstack application{{else}}Frontend application{{/if}}{{#if (includes frontend "tanstack-router")}} (React with TanStack Router){{else if (includes frontend "react-router")}} (React with React Router){{else if (includes frontend "tanstack-start")}} (TanStack Start){{else if (includes frontend "next")}} (Next.js){{else if (includes frontend "nuxt")}} (Nuxt.js){{else if (includes frontend "svelte")}} (SvelteKit){{else if (includes frontend "solid")}} (SolidStart){{/if}}
3763
- {{/if}}
3764
-
3765
- {{#if (ne backend "convex")}}
3766
- {{#if (and (ne backend "none") (ne backend "self"))}}
3767
- - **\`apps/server/\`** - Backend server{{#if (eq backend "hono")}} (Hono){{else if (eq backend "express")}} (Express){{else if (eq backend "fastify")}} (Fastify){{else if (eq backend "elysia")}} (Elysia){{/if}}
3768
- {{/if}}
3769
- {{else}}
3770
- - **\`packages/backend/\`** - Convex backend functions
3771
- {{/if}}
3772
-
3773
- {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
3774
- - **\`apps/native/\`** - React Native mobile app{{#if (includes frontend "native-uniwind")}} (with NativeWind){{else if (includes frontend "native-unistyles")}} (with Unistyles){{else if (includes frontend "native-bare")}} (bare styling){{/if}}
3775
- {{/if}}
3776
-
3777
- {{#if (ne backend "convex")}}
3778
- {{#if (ne api "none")}}
3779
- - **\`packages/api/\`** - Shared API logic and types
3780
- {{/if}}
3781
- {{#if (and (ne auth "none") (ne backend "convex"))}}
3782
- - **\`packages/auth/\`** - Authentication logic and utilities
3783
- {{/if}}
3784
- {{#if (and (ne database "none") (ne orm "none"))}}
3785
- - **\`packages/db/\`** - Database schema and utilities
3786
- {{/if}}
3787
- - **\`packages/env/\`** - Shared environment variables and validation
3788
- - **\`packages/config/\`** - Shared TypeScript configuration
3789
- {{#if (or (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare"))}}
3790
- - **\`packages/infra/\`** - Infrastructure as code (Alchemy for Cloudflare)
3791
- {{/if}}
3792
- {{/if}}
3793
-
3794
- ## Available Scripts
3795
-
3796
- - \`{{packageManager}} run dev\` - Start all apps in development mode
3797
- {{#if (and (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
3798
- (includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid")) (ne backend "self"))}}
3799
- - \`{{packageManager}} run dev:web\` - Start only the web app
3800
- {{/if}}
3801
- {{#if (and (ne backend "none") (ne backend "convex") (ne backend "self"))}}
3802
- - \`{{packageManager}} run dev:server\` - Start only the server
3803
- {{/if}}
3804
- {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
3805
- - \`{{packageManager}} run dev:native\` - Start only the native app
3806
- {{/if}}
3807
- - \`{{packageManager}} run build\` - Build all apps
3808
- - \`{{packageManager}} run lint\` - Lint all packages
3809
- - \`{{packageManager}} run typecheck\` - Type check all packages
3810
-
3811
- {{#if (and (ne database "none") (ne orm "none") (ne backend "convex"))}}
3812
- ## Database Commands
3813
-
3814
- All database operations should be run from the {{#if (eq backend "self")}}web{{else}}server{{/if}} workspace:
3815
-
3816
- - \`{{packageManager}} run db:push\` - Push schema changes to database
3817
- - \`{{packageManager}} run db:studio\` - Open database studio
3818
- - \`{{packageManager}} run db:generate\` - Generate {{#if (eq orm "drizzle")}}Drizzle{{else if (eq orm "prisma")}}Prisma{{else}}{{orm}}{{/if}} files
3819
- - \`{{packageManager}} run db:migrate\` - Run database migrations
3820
-
3821
- {{#if (eq orm "drizzle")}}
3822
- Database schema files are located in {{#if (eq backend "self")}}\`apps/web/src/db/schema/\`{{else}}\`packages/db/src/schema/\`{{/if}}
3823
- {{else if (eq orm "prisma")}}
3824
- Database schema is located in {{#if (eq backend "self")}}\`apps/web/prisma/schema.prisma\`{{else}}\`packages/db/prisma/schema.prisma\`{{/if}}
3825
- {{else if (eq orm "mongoose")}}
3826
- Database models are located in {{#if (eq backend "self")}}\`apps/web/src/db/models/\`{{else}}\`packages/db/src/models/\`{{/if}}
3827
- {{/if}}
3828
- {{/if}}
3829
-
3830
- {{#if (ne api "none")}}
3831
- ## API Structure
3832
-
3833
- {{#if (eq api "trpc")}}
3834
- - tRPC routers are in \`packages/api/src/routers/\`
3835
- - Client-side tRPC utils are in \`apps/web/src/utils/trpc.ts\`
3836
- {{else if (eq api "orpc")}}
3837
- - oRPC contracts and routers are in \`packages/api/src/\`
3838
- - Client-side oRPC client is in \`apps/web/src/utils/orpc.ts\`
3839
- {{/if}}
3840
- {{/if}}
3841
-
3842
- {{#if (eq auth "better-auth")}}
3843
- ## Authentication
3844
-
3845
- Authentication is powered by Better Auth:
3846
- - Auth configuration is in \`packages/auth/src/\`
3847
- {{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
3848
- (includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
3849
- - Web app auth client is in \`apps/web/src/lib/auth-client.ts\`
3850
- {{/if}}
3851
- {{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
3852
- - Native app auth client is in \`apps/native/src/lib/auth-client.ts\`
3853
- {{/if}}
3854
- {{/if}}
3855
-
3856
- ## Project Configuration
3857
-
3858
- This project includes a \`bts.jsonc\` configuration file that stores your Better-T-Stack settings:
3859
-
3860
- - Contains your selected stack configuration (database, ORM, backend, frontend, etc.)
3861
- - Used by the CLI to understand your project structure
3862
- - Safe to delete if not needed
3863
-
3864
- ## Key Points
3865
-
3866
- - This is a {{#if (includes addons "turborepo")}}Turborepo {{/if}}monorepo using {{packageManager}} workspaces
3867
- - Each app has its own \`package.json\` and dependencies
3868
- - Run commands from the root to execute across all workspaces
3869
- - Run workspace-specific commands with \`{{packageManager}} run command-name\`
3870
- {{#if (includes addons "turborepo")}}
3871
- - Turborepo handles build caching and parallel execution
3872
- {{/if}}
3873
- {{#if (or (includes addons "husky") (includes addons "lefthook"))}}
3874
- - Git hooks are configured with {{#if (includes addons "husky")}}Husky{{else}}Lefthook{{/if}} for pre-commit checks
3875
- {{/if}}
3876
- `],
3877
- ["addons/ruler/.ruler/ruler.toml.hbs", `# Ruler Configuration File
3878
- # See https://okigu.com/ruler for documentation.
3879
-
3880
- # Default agents to run when --agents is not specified
3881
- default_agents = []
3882
-
3883
- # --- Global .gitignore Configuration ---
3884
- [gitignore]
3885
- # Enable/disable automatic .gitignore updates (default: true)
3886
- enabled = true
3887
3950
  `],
3888
3951
  ["api/orpc/fullstack/astro/src/pages/rpc/[...rest].ts.hbs", `import type { APIRoute } from "astro";
3889
3952
  import { RPCHandler } from "@orpc/server/fetch";
@@ -4147,24 +4210,23 @@ export const queryClient = new QueryClient({
4147
4210
 
4148
4211
  export const link = new RPCLink({
4149
4212
  {{#if (eq backend "self")}}
4150
- {{#unless (includes frontend "astro")}}
4213
+ {{#if (or (includes frontend "next") (includes frontend "tanstack-start"))}}
4151
4214
  url: \`\${env.EXPO_PUBLIC_SERVER_URL}/api/rpc\`,
4152
4215
  {{else}}
4153
4216
  url: \`\${env.EXPO_PUBLIC_SERVER_URL}/rpc\`,
4154
- {{/unless}}
4217
+ {{/if}}
4155
4218
  {{else}}
4156
4219
  url: \`\${env.EXPO_PUBLIC_SERVER_URL}/rpc\`,
4157
4220
  {{/if}}
4158
4221
  {{#if (eq auth "better-auth")}}
4159
4222
  fetch:
4160
- Platform.OS !== "web"
4161
- ? undefined
4162
- : function (url, options) {
4163
- return fetch(url, {
4164
- ...options,
4165
- credentials: "include",
4166
- });
4167
- },
4223
+ function (url, options) {
4224
+ return fetch(url, {
4225
+ ...options,
4226
+ // Better Auth Expo forwards the session cookie manually on native.
4227
+ credentials: Platform.OS === "web" ? "include" : "omit",
4228
+ });
4229
+ },
4168
4230
  headers() {
4169
4231
  if (Platform.OS === "web") {
4170
4232
  return {};
@@ -4852,14 +4914,13 @@ const trpcClient = createTRPCClient<AppRouter>({
4852
4914
  {{/if}}
4853
4915
  {{#if (eq auth "better-auth")}}
4854
4916
  fetch:
4855
- Platform.OS !== "web"
4856
- ? undefined
4857
- : function (url, options) {
4858
- return fetch(url, {
4859
- ...options,
4860
- credentials: "include",
4861
- });
4862
- },
4917
+ function (url, options) {
4918
+ return fetch(url, {
4919
+ ...options,
4920
+ // Better Auth Expo forwards the session cookie manually on native.
4921
+ credentials: Platform.OS === "web" ? "include" : "omit",
4922
+ });
4923
+ },
4863
4924
  headers() {
4864
4925
  if (Platform.OS === "web") {
4865
4926
  return {};
@@ -30323,7 +30384,7 @@ function SuccessPage() {
30323
30384
  </div>
30324
30385
  `]
30325
30386
  ]);
30326
- const TEMPLATE_COUNT = 441;
30387
+ const TEMPLATE_COUNT = 444;
30327
30388
 
30328
30389
  //#endregion
30329
30390
  export { EMBEDDED_TEMPLATES, GeneratorError, Handlebars, TEMPLATE_COUNT, VirtualFileSystem, dependencyVersionMap, generate, generateReproducibleCommand, isBinaryFile, processAddonTemplates, processAddonsDeps, processFileContent, processTemplateString, transformFilename, writeBtsConfigToVfs };