fix native scaffolding

This commit is contained in:
Aman Varshney
2025-04-19 18:59:02 +05:30
parent b8c3fd40ab
commit d82ad80ac4
7 changed files with 96 additions and 58 deletions

View File

@@ -0,0 +1,5 @@
---
"create-better-t-stack": patch
---
fix native scaffolding

View File

@@ -1,4 +1,5 @@
import * as path from "node:path"; import * as path from "node:path";
import fs from "fs-extra";
import type { ProjectConfig } from "../types"; import type { ProjectConfig } from "../types";
import { addPackageDependency } from "../utils/add-package-deps"; import { addPackageDependency } from "../utils/add-package-deps";
@@ -7,12 +8,15 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
const projectDir = path.resolve(process.cwd(), projectName); const projectDir = path.resolve(process.cwd(), projectName);
const webDir = path.join(projectDir, "apps/web"); const webDir = path.join(projectDir, "apps/web");
const serverDir = path.join(projectDir, "apps/server"); const serverDir = path.join(projectDir, "apps/server");
const webDirExists = await fs.pathExists(webDir);
if (api === "orpc") { if (api === "orpc") {
if (webDirExists) {
await addPackageDependency({ await addPackageDependency({
dependencies: ["@orpc/react-query", "@orpc/server", "@orpc/client"], dependencies: ["@orpc/react-query", "@orpc/server", "@orpc/client"],
projectDir: webDir, projectDir: webDir,
}); });
}
await addPackageDependency({ await addPackageDependency({
dependencies: ["@orpc/server", "@orpc/client"], dependencies: ["@orpc/server", "@orpc/client"],
projectDir: serverDir, projectDir: serverDir,
@@ -20,6 +24,7 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
} }
if (api === "trpc") { if (api === "trpc") {
if (webDirExists) {
await addPackageDependency({ await addPackageDependency({
dependencies: [ dependencies: [
"@trpc/tanstack-react-query", "@trpc/tanstack-react-query",
@@ -28,6 +33,7 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
], ],
projectDir: webDir, projectDir: webDir,
}); });
}
await addPackageDependency({ await addPackageDependency({
dependencies: ["@trpc/server", "@trpc/client"], dependencies: ["@trpc/server", "@trpc/client"],
projectDir: serverDir, projectDir: serverDir,

View File

@@ -1,20 +1,9 @@
import path from "node:path"; import path from "node:path";
import consola from "consola"; import consola from "consola";
import fs from "fs-extra";
import pc from "picocolors"; 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 type { ProjectConfig } from "../types";
import { addPackageDependency } from "../utils/add-package-deps";
export async function setupAuth(config: ProjectConfig): Promise<void> { export async function setupAuth(config: ProjectConfig): Promise<void> {
const { projectName, auth, frontend } = config; const { projectName, auth, frontend } = config;
@@ -27,22 +16,29 @@ export async function setupAuth(config: ProjectConfig): Promise<void> {
const clientDir = path.join(projectDir, "apps/web"); const clientDir = path.join(projectDir, "apps/web");
const nativeDir = path.join(projectDir, "apps/native"); const nativeDir = path.join(projectDir, "apps/native");
const clientDirExists = await fs.pathExists(clientDir);
const nativeDirExists = await fs.pathExists(nativeDir);
try { try {
await addPackageDependency({ await addPackageDependency({
dependencies: ["better-auth"], dependencies: ["better-auth"],
projectDir: serverDir, projectDir: serverDir,
}); });
if (
const hasWebFrontend =
frontend.includes("react-router") || frontend.includes("react-router") ||
frontend.includes("tanstack-router") || frontend.includes("tanstack-router") ||
frontend.includes("tanstack-start") frontend.includes("tanstack-start") ||
) { frontend.includes("next");
if (hasWebFrontend && clientDirExists) {
await addPackageDependency({ await addPackageDependency({
dependencies: ["better-auth"], dependencies: ["better-auth"],
projectDir: clientDir, projectDir: clientDir,
}); });
} }
if (frontend.includes("native")) {
if (frontend.includes("native") && nativeDirExists) {
await addPackageDependency({ await addPackageDependency({
dependencies: ["better-auth", "@better-auth/expo"], dependencies: ["better-auth", "@better-auth/expo"],
projectDir: nativeDir, projectDir: nativeDir,
@@ -53,10 +49,20 @@ export async function setupAuth(config: ProjectConfig): Promise<void> {
}); });
} }
} catch (error) { } catch (error) {
consola.error(pc.red("Failed to configure authentication")); consola.error(pc.red("Failed to configure authentication dependencies"));
if (error instanceof Error) { if (error instanceof Error) {
consola.error(pc.red(error.message)); 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;
}

View File

@@ -1,4 +1,5 @@
import path from "node:path"; import path from "node:path";
import fs from "fs-extra";
import type { ProjectConfig } from "../types"; import type { ProjectConfig } from "../types";
import { addPackageDependency } from "../utils/add-package-deps"; import { addPackageDependency } from "../utils/add-package-deps";
@@ -8,11 +9,16 @@ export async function setupExamples(config: ProjectConfig): Promise<void> {
if (examples.includes("ai")) { if (examples.includes("ai")) {
const clientDir = path.join(projectDir, "apps/web"); const clientDir = path.join(projectDir, "apps/web");
const serverDir = path.join(projectDir, "apps/server");
const clientDirExists = await fs.pathExists(clientDir);
if (clientDirExists) {
await addPackageDependency({ await addPackageDependency({
dependencies: ["ai"], dependencies: ["ai"],
projectDir: clientDir, projectDir: clientDir,
}); });
const serverDir = path.join(projectDir, "apps/server"); }
await addPackageDependency({ await addPackageDependency({
dependencies: ["ai", "@ai-sdk/google"], dependencies: ["ai", "@ai-sdk/google"],
projectDir: serverDir, projectDir: serverDir,

View File

@@ -217,6 +217,11 @@ export async function setupAuthTemplate(
const serverAppDir = path.join(projectDir, "apps/server"); const serverAppDir = path.join(projectDir, "apps/server");
const webAppDir = path.join(projectDir, "apps/web"); const webAppDir = path.join(projectDir, "apps/web");
const nativeAppDir = path.join(projectDir, "apps/native"); 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( const webFrontends = context.frontend.filter(
(f) => (f) =>
f === "tanstack-router" || f === "tanstack-router" ||
@@ -226,7 +231,7 @@ export async function setupAuthTemplate(
); );
const hasNative = context.frontend.includes("native"); const hasNative = context.frontend.includes("native");
if (await fs.pathExists(serverAppDir)) { if (serverAppDirExists) {
const authServerBaseSrc = path.join(PKG_ROOT, "templates/auth/server/base"); const authServerBaseSrc = path.join(PKG_ROOT, "templates/auth/server/base");
if (await fs.pathExists(authServerBaseSrc)) { if (await fs.pathExists(authServerBaseSrc)) {
await processAndCopyFiles( await processAndCopyFiles(
@@ -243,7 +248,11 @@ export async function setupAuthTemplate(
); );
} }
const authServerNextSrc = path.join(PKG_ROOT, "templates/auth/server/next"); if (context.backend === "next") {
const authServerNextSrc = path.join(
PKG_ROOT,
"templates/auth/server/next",
);
if (await fs.pathExists(authServerNextSrc)) { if (await fs.pathExists(authServerNextSrc)) {
await processAndCopyFiles( await processAndCopyFiles(
"**/*", "**/*",
@@ -258,6 +267,7 @@ export async function setupAuthTemplate(
), ),
); );
} }
}
if (context.orm !== "none" && context.database !== "none") { if (context.orm !== "none" && context.database !== "none") {
const orm = context.orm; const orm = context.orm;
@@ -287,12 +297,12 @@ export async function setupAuthTemplate(
} else { } else {
consola.warn( consola.warn(
pc.yellow( 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"); const authWebBaseSrc = path.join(PKG_ROOT, "templates/auth/web/base");
if (await fs.pathExists(authWebBaseSrc)) { if (await fs.pathExists(authWebBaseSrc)) {
await processAndCopyFiles("**/*", authWebBaseSrc, webAppDir, context); 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"); const authNativeSrc = path.join(PKG_ROOT, "templates/auth/native");
if (await fs.pathExists(authNativeSrc)) { if (await fs.pathExists(authNativeSrc)) {
await processAndCopyFiles("**/*", authNativeSrc, nativeAppDir, context); await processAndCopyFiles("**/*", authNativeSrc, nativeAppDir, context);
@@ -374,13 +384,15 @@ export async function setupAddonsTemplate(
if (context.addons.includes("pwa")) { if (context.addons.includes("pwa")) {
const pwaSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web"); const pwaSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web");
const webAppDir = path.join(projectDir, "apps/web"); const webAppDir = path.join(projectDir, "apps/web");
const webAppDirExists = await fs.pathExists(webAppDir);
if (await fs.pathExists(pwaSrcDir)) { if (await fs.pathExists(pwaSrcDir)) {
if (await fs.pathExists(webAppDir)) { if (webAppDirExists) {
await processAndCopyFiles("**/*", pwaSrcDir, webAppDir, context); await processAndCopyFiles("**/*", pwaSrcDir, webAppDir, context);
} else { } else {
consola.warn( consola.warn(
pc.yellow( 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 serverAppDir = path.join(projectDir, "apps/server");
const webAppDir = path.join(projectDir, "apps/web"); 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) { for (const example of context.examples) {
const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`); const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`);
if (await fs.pathExists(serverAppDir)) { if (serverAppDirExists) {
const exampleServerSrc = path.join(exampleBaseDir, "server"); const exampleServerSrc = path.join(exampleBaseDir, "server");
if (await fs.pathExists(exampleServerSrc)) { if (await fs.pathExists(exampleServerSrc)) {
if (context.orm !== "none") { 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"); const exampleWebSrc = path.join(exampleBaseDir, "web");
if (await fs.pathExists(exampleWebSrc)) { if (await fs.pathExists(exampleWebSrc)) {
const webFrameworks = context.frontend.filter((f) => const webFrameworks = context.frontend.filter((f) =>

View File

@@ -3,7 +3,7 @@ import { Stack } from "expo-router";
import { import {
DarkTheme, DarkTheme,
DefaultTheme, DefaultTheme,
Theme, type Theme,
ThemeProvider, ThemeProvider,
} from "@react-navigation/native"; } from "@react-navigation/native";
import { StatusBar } from "expo-status-bar"; import { StatusBar } from "expo-status-bar";

View File

@@ -14,7 +14,7 @@
}, },
"apps/cli": { "apps/cli": {
"name": "create-better-t-stack", "name": "create-better-t-stack",
"version": "2.0.6-beta.0", "version": "2.0.6",
"bin": { "bin": {
"create-better-t-stack": "dist/index.js", "create-better-t-stack": "dist/index.js",
}, },