From d82ad80ac4000a7398cbb19a2e59bedc84437393 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Sat, 19 Apr 2025 18:59:02 +0530 Subject: [PATCH] fix native scaffolding --- .changeset/light-bars-relax.md | 5 ++ apps/cli/src/helpers/api-setup.ts | 30 ++++++---- apps/cli/src/helpers/auth-setup.ts | 44 +++++++------- apps/cli/src/helpers/examples-setup.ts | 14 +++-- apps/cli/src/helpers/template-manager.ts | 57 ++++++++++++------- .../templates/frontend/native/app/_layout.tsx | 2 +- bun.lock | 2 +- 7 files changed, 96 insertions(+), 58 deletions(-) create mode 100644 .changeset/light-bars-relax.md diff --git a/.changeset/light-bars-relax.md b/.changeset/light-bars-relax.md new file mode 100644 index 0000000..3a95bad --- /dev/null +++ b/.changeset/light-bars-relax.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": patch +--- + +fix native scaffolding diff --git a/apps/cli/src/helpers/api-setup.ts b/apps/cli/src/helpers/api-setup.ts index debbeda..7328a81 100644 --- a/apps/cli/src/helpers/api-setup.ts +++ b/apps/cli/src/helpers/api-setup.ts @@ -1,4 +1,5 @@ import * as path from "node:path"; +import fs from "fs-extra"; import type { ProjectConfig } from "../types"; import { addPackageDependency } from "../utils/add-package-deps"; @@ -7,12 +8,15 @@ export async function setupApi(config: ProjectConfig): Promise { const projectDir = path.resolve(process.cwd(), projectName); const webDir = path.join(projectDir, "apps/web"); const serverDir = path.join(projectDir, "apps/server"); + const webDirExists = await fs.pathExists(webDir); if (api === "orpc") { - await addPackageDependency({ - dependencies: ["@orpc/react-query", "@orpc/server", "@orpc/client"], - projectDir: webDir, - }); + if (webDirExists) { + await addPackageDependency({ + dependencies: ["@orpc/react-query", "@orpc/server", "@orpc/client"], + projectDir: webDir, + }); + } await addPackageDependency({ dependencies: ["@orpc/server", "@orpc/client"], projectDir: serverDir, @@ -20,14 +24,16 @@ export async function setupApi(config: ProjectConfig): Promise { } if (api === "trpc") { - await addPackageDependency({ - dependencies: [ - "@trpc/tanstack-react-query", - "@trpc/server", - "@trpc/client", - ], - projectDir: webDir, - }); + if (webDirExists) { + await addPackageDependency({ + dependencies: [ + "@trpc/tanstack-react-query", + "@trpc/server", + "@trpc/client", + ], + projectDir: webDir, + }); + } await addPackageDependency({ dependencies: ["@trpc/server", "@trpc/client"], projectDir: serverDir, diff --git a/apps/cli/src/helpers/auth-setup.ts b/apps/cli/src/helpers/auth-setup.ts index a68383a..b43b184 100644 --- a/apps/cli/src/helpers/auth-setup.ts +++ b/apps/cli/src/helpers/auth-setup.ts @@ -1,20 +1,9 @@ import path from "node:path"; import consola from "consola"; +import fs from "fs-extra"; import pc from "picocolors"; -import { addPackageDependency } from "../utils/add-package-deps"; - -export function generateAuthSecret(length = 32): string { - const characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let result = ""; - const charactersLength = characters.length; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -} - import type { ProjectConfig } from "../types"; +import { addPackageDependency } from "../utils/add-package-deps"; export async function setupAuth(config: ProjectConfig): Promise { const { projectName, auth, frontend } = config; @@ -27,22 +16,29 @@ export async function setupAuth(config: ProjectConfig): Promise { const clientDir = path.join(projectDir, "apps/web"); const nativeDir = path.join(projectDir, "apps/native"); + const clientDirExists = await fs.pathExists(clientDir); + const nativeDirExists = await fs.pathExists(nativeDir); + try { await addPackageDependency({ dependencies: ["better-auth"], projectDir: serverDir, }); - if ( + + const hasWebFrontend = frontend.includes("react-router") || frontend.includes("tanstack-router") || - frontend.includes("tanstack-start") - ) { + frontend.includes("tanstack-start") || + frontend.includes("next"); + + if (hasWebFrontend && clientDirExists) { await addPackageDependency({ dependencies: ["better-auth"], projectDir: clientDir, }); } - if (frontend.includes("native")) { + + if (frontend.includes("native") && nativeDirExists) { await addPackageDependency({ dependencies: ["better-auth", "@better-auth/expo"], projectDir: nativeDir, @@ -53,10 +49,20 @@ export async function setupAuth(config: ProjectConfig): Promise { }); } } catch (error) { - consola.error(pc.red("Failed to configure authentication")); + consola.error(pc.red("Failed to configure authentication dependencies")); if (error instanceof Error) { consola.error(pc.red(error.message)); } - throw error; } } + +export function generateAuthSecret(length = 32): string { + const characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} diff --git a/apps/cli/src/helpers/examples-setup.ts b/apps/cli/src/helpers/examples-setup.ts index ef0182d..031d8bc 100644 --- a/apps/cli/src/helpers/examples-setup.ts +++ b/apps/cli/src/helpers/examples-setup.ts @@ -1,4 +1,5 @@ import path from "node:path"; +import fs from "fs-extra"; import type { ProjectConfig } from "../types"; import { addPackageDependency } from "../utils/add-package-deps"; @@ -8,11 +9,16 @@ export async function setupExamples(config: ProjectConfig): Promise { if (examples.includes("ai")) { const clientDir = path.join(projectDir, "apps/web"); - await addPackageDependency({ - dependencies: ["ai"], - projectDir: clientDir, - }); const serverDir = path.join(projectDir, "apps/server"); + const clientDirExists = await fs.pathExists(clientDir); + + if (clientDirExists) { + await addPackageDependency({ + dependencies: ["ai"], + projectDir: clientDir, + }); + } + await addPackageDependency({ dependencies: ["ai", "@ai-sdk/google"], projectDir: serverDir, diff --git a/apps/cli/src/helpers/template-manager.ts b/apps/cli/src/helpers/template-manager.ts index c51f9e9..e1696e8 100644 --- a/apps/cli/src/helpers/template-manager.ts +++ b/apps/cli/src/helpers/template-manager.ts @@ -217,6 +217,11 @@ export async function setupAuthTemplate( const serverAppDir = path.join(projectDir, "apps/server"); const webAppDir = path.join(projectDir, "apps/web"); const nativeAppDir = path.join(projectDir, "apps/native"); + + const serverAppDirExists = await fs.pathExists(serverAppDir); + const webAppDirExists = await fs.pathExists(webAppDir); + const nativeAppDirExists = await fs.pathExists(nativeAppDir); + const webFrontends = context.frontend.filter( (f) => f === "tanstack-router" || @@ -226,7 +231,7 @@ export async function setupAuthTemplate( ); const hasNative = context.frontend.includes("native"); - if (await fs.pathExists(serverAppDir)) { + if (serverAppDirExists) { const authServerBaseSrc = path.join(PKG_ROOT, "templates/auth/server/base"); if (await fs.pathExists(authServerBaseSrc)) { await processAndCopyFiles( @@ -243,20 +248,25 @@ export async function setupAuthTemplate( ); } - const authServerNextSrc = path.join(PKG_ROOT, "templates/auth/server/next"); - if (await fs.pathExists(authServerNextSrc)) { - await processAndCopyFiles( - "**/*", - authServerNextSrc, - serverAppDir, - context, - ); - } else { - consola.warn( - pc.yellow( - `Warning: Next auth server template not found at ${authServerNextSrc}`, - ), + if (context.backend === "next") { + const authServerNextSrc = path.join( + PKG_ROOT, + "templates/auth/server/next", ); + if (await fs.pathExists(authServerNextSrc)) { + await processAndCopyFiles( + "**/*", + authServerNextSrc, + serverAppDir, + context, + ); + } else { + consola.warn( + pc.yellow( + `Warning: Next auth server template not found at ${authServerNextSrc}`, + ), + ); + } } if (context.orm !== "none" && context.database !== "none") { @@ -287,12 +297,12 @@ export async function setupAuthTemplate( } else { consola.warn( pc.yellow( - "Warning: apps/server directory does not exist, skipping server-side auth setup.", + "Warning: apps/server directory does not exist, skipping server-side auth template setup.", ), ); } - if (webFrontends.length > 0 && (await fs.pathExists(webAppDir))) { + if (webFrontends.length > 0 && webAppDirExists) { const authWebBaseSrc = path.join(PKG_ROOT, "templates/auth/web/base"); if (await fs.pathExists(authWebBaseSrc)) { await processAndCopyFiles("**/*", authWebBaseSrc, webAppDir, context); @@ -326,7 +336,7 @@ export async function setupAuthTemplate( } } - if (hasNative && (await fs.pathExists(nativeAppDir))) { + if (hasNative && nativeAppDirExists) { const authNativeSrc = path.join(PKG_ROOT, "templates/auth/native"); if (await fs.pathExists(authNativeSrc)) { await processAndCopyFiles("**/*", authNativeSrc, nativeAppDir, context); @@ -374,13 +384,15 @@ export async function setupAddonsTemplate( if (context.addons.includes("pwa")) { const pwaSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web"); const webAppDir = path.join(projectDir, "apps/web"); + const webAppDirExists = await fs.pathExists(webAppDir); + if (await fs.pathExists(pwaSrcDir)) { - if (await fs.pathExists(webAppDir)) { + if (webAppDirExists) { await processAndCopyFiles("**/*", pwaSrcDir, webAppDir, context); } else { consola.warn( pc.yellow( - "Warning: apps/web directory not found, cannot setup PWA addon.", + "Warning: apps/web directory not found, cannot setup PWA addon template.", ), ); } @@ -399,10 +411,13 @@ export async function setupExamplesTemplate( const serverAppDir = path.join(projectDir, "apps/server"); const webAppDir = path.join(projectDir, "apps/web"); + const serverAppDirExists = await fs.pathExists(serverAppDir); + const webAppDirExists = await fs.pathExists(webAppDir); + for (const example of context.examples) { const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`); - if (await fs.pathExists(serverAppDir)) { + if (serverAppDirExists) { const exampleServerSrc = path.join(exampleBaseDir, "server"); if (await fs.pathExists(exampleServerSrc)) { if (context.orm !== "none") { @@ -441,7 +456,7 @@ export async function setupExamplesTemplate( } } - if (await fs.pathExists(webAppDir)) { + if (webAppDirExists) { const exampleWebSrc = path.join(exampleBaseDir, "web"); if (await fs.pathExists(exampleWebSrc)) { const webFrameworks = context.frontend.filter((f) => diff --git a/apps/cli/templates/frontend/native/app/_layout.tsx b/apps/cli/templates/frontend/native/app/_layout.tsx index 16a98df..d8a17b0 100644 --- a/apps/cli/templates/frontend/native/app/_layout.tsx +++ b/apps/cli/templates/frontend/native/app/_layout.tsx @@ -3,7 +3,7 @@ import { Stack } from "expo-router"; import { DarkTheme, DefaultTheme, - Theme, + type Theme, ThemeProvider, } from "@react-navigation/native"; import { StatusBar } from "expo-status-bar"; diff --git a/bun.lock b/bun.lock index ae33360..cf3c363 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ }, "apps/cli": { "name": "create-better-t-stack", - "version": "2.0.6-beta.0", + "version": "2.0.6", "bin": { "create-better-t-stack": "dist/index.js", },