UNPKG

@reliverse/rse-sdk

Version:

@reliverse/rse-sdk allows you to create new plugins for @reliverse/rse CLI, interact with reliverse.org, and even extend your own CLI functionality (you may also try @reliverse/dler-sdk for this case).

275 lines (274 loc) 12 kB
import fs from "@reliverse/relifso"; import { relinka } from "@reliverse/relinka"; import path from "node:path"; export async function createReadme(projectDir, options) { const readmePath = path.join(projectDir, "README.md"); const content = generateReadmeContent(options); try { await fs.writeFile(readmePath, content); } catch (error) { relinka("error", "Failed to create README.md file:", error); } } function generateReadmeContent(options) { const { projectName, packageManager, database, auth, addons = [], orm = "drizzle", runtime = "bun", frontend = ["tanstack-router"], backend = "hono", api = "trpc" } = options; const isConvex = backend === "convex"; const hasReactRouter = frontend.includes("react-router"); const hasTanstackRouter = frontend.includes("tanstack-router"); const hasNative = frontend.includes("native-nativewind") || frontend.includes("native-unistyles"); const hasNext = frontend.includes("next"); const hasTanstackStart = frontend.includes("tanstack-start"); const hasSvelte = frontend.includes("svelte"); const hasSolid = frontend.includes("solid"); const hasNuxt = frontend.includes("nuxt"); const packageManagerRunCmd = packageManager === "npm" ? "npm run" : packageManager; let webPort = "3001"; if (hasReactRouter || hasSvelte) { webPort = "5173"; } return `# ${projectName} This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines ${hasTanstackRouter ? "React, TanStack Router" : hasReactRouter ? "React, React Router" : hasNext ? "Next.js" : hasTanstackStart ? "React, TanStack Start" : hasSvelte ? "SvelteKit" : hasNuxt ? "Nuxt" : hasSolid ? "SolidJS" : ""}, ${backend?.[0]?.toUpperCase() ?? ""}${backend?.slice(1) ?? ""}${isConvex ? "" : `, ${api.toUpperCase()}`}, and more. ## Features ${generateFeaturesList( database, auth, addons, orm, runtime, frontend, backend, api )} ## Getting Started First, install the dependencies: \`\`\`bash ${packageManager} install \`\`\` ${isConvex ? ` ## Convex Setup This project uses Convex as a backend. You'll need to set up Convex before running the app: \`\`\`bash ${packageManagerRunCmd} dev:setup \`\`\` Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm)} Then, run the development server: \`\`\`bash ${packageManagerRunCmd} dev \`\`\` ${hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart || hasSvelte || hasNuxt || hasSolid ? `Open [http://localhost:${webPort}](http://localhost:${webPort}) in your browser to see the web application.` : ""} ${hasNative ? "Use the Expo Go app to run the mobile application.\n" : ""} ${isConvex ? "Your app will connect to the Convex cloud backend automatically." : "The API is running at [http://localhost:3000](http://localhost:3000)."} ${addons.includes("pwa") && hasReactRouter ? "\n## PWA Support with React Router v7\n\nThere is a known compatibility issue between VitePWA and React Router v7.\nSee: https://github.com/vite-pwa/vite-plugin-pwa/issues/809\n" : ""} ## Project Structure \`\`\` ${projectName}/ \u251C\u2500\u2500 apps/ ${hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart || hasSvelte || hasNuxt || hasSolid ? `\u2502 \u251C\u2500\u2500 web/ # Frontend application (${hasTanstackRouter ? "React + TanStack Router" : hasReactRouter ? "React + React Router" : hasNext ? "Next.js" : hasTanstackStart ? "React + TanStack Start" : hasSvelte ? "SvelteKit" : hasNuxt ? "Nuxt" : hasSolid ? "SolidJS" : ""}) ` : ""}${hasNative ? "\u2502 \u251C\u2500\u2500 native/ # Mobile application (React Native, Expo)\n" : ""}${addons.includes("starlight") ? "\u2502 \u251C\u2500\u2500 docs/ # Documentation site (Astro Starlight)\n" : ""}${isConvex ? "\u251C\u2500\u2500 packages/\n\u2502 \u2514\u2500\u2500 backend/ # Convex backend functions and schema\n" : `\u2502 \u2514\u2500\u2500 server/ # Backend API (${backend?.[0]?.toUpperCase() ?? ""}, ${api.toUpperCase()})`} \`\`\` ## Available Scripts ${generateScriptsList( packageManagerRunCmd, database, orm, auth, hasNative, addons, backend )} `; } function generateFeaturesList(database, auth, addons, orm, runtime, frontend, backend, api) { const isConvex = backend === "convex"; const hasTanstackRouter = frontend.includes("tanstack-router"); const hasReactRouter = frontend.includes("react-router"); const hasNative = frontend.includes("native-nativewind") || frontend.includes("native-unistyles"); const hasNext = frontend.includes("next"); const hasTanstackStart = frontend.includes("tanstack-start"); const hasSvelte = frontend.includes("svelte"); const hasNuxt = frontend.includes("nuxt"); const hasSolid = frontend.includes("solid"); const addonsList = [ "- **TypeScript** - For type safety and improved developer experience" ]; if (hasTanstackRouter) { addonsList.push( "- **TanStack Router** - File-based routing with full type safety" ); } else if (hasReactRouter) { addonsList.push("- **React Router** - Declarative routing for React"); } else if (hasNext) { addonsList.push("- **Next.js** - Full-stack React framework"); } else if (hasTanstackStart) { addonsList.push( "- **TanStack Start** - SSR framework with TanStack Router" ); } else if (hasSvelte) { addonsList.push("- **SvelteKit** - Web framework for building Svelte apps"); } else if (hasNuxt) { addonsList.push("- **Nuxt** - The Intuitive Vue Framework"); } else if (hasSolid) { addonsList.push("- **SolidJS** - Simple and performant reactivity"); } if (hasNative) { addonsList.push("- **React Native** - Build mobile apps using React"); addonsList.push("- **Expo** - Tools for React Native development"); } addonsList.push( "- **TailwindCSS** - Utility-first CSS for rapid UI development", "- **shadcn/ui** - Reusable UI components" ); if (isConvex) { addonsList.push("- **Convex** - Reactive backend-as-a-service platform"); } else { if (backend === "hono") { addonsList.push("- **Hono** - Lightweight, performant server framework"); } else if (backend === "express") { addonsList.push("- **Express** - Fast, unopinionated web framework"); } else if (backend === "fastify") { addonsList.push("- **Fastify** - Fast, low-overhead web framework"); } else if (backend === "elysia") { addonsList.push("- **Elysia** - Type-safe, high-performance framework"); } else if (backend === "next") { addonsList.push("- **Next.js** - Full-stack React framework"); } if (api === "trpc") { addonsList.push("- **tRPC** - End-to-end type-safe APIs"); } else if (api === "orpc") { addonsList.push( "- **oRPC** - End-to-end type-safe APIs with OpenAPI integration" ); } addonsList.push( `- **${runtime === "bun" ? "Bun" : "Node.js"}** - Runtime environment` ); } if (database !== "none" && !isConvex) { addonsList.push( `- **${orm === "drizzle" ? "Drizzle" : orm === "prisma" ? "Prisma" : "Mongoose"}** - TypeScript-first ORM`, `- **${database === "sqlite" ? "SQLite/Turso" : database === "postgres" ? "PostgreSQL" : database === "mysql" ? "MySQL" : "MongoDB"}** - Database engine` ); } if (auth && !isConvex) { addonsList.push( "- **Authentication** - Email & password authentication with Better Auth" ); } for (const addon of addons) { if (addon === "pwa") { addonsList.push("- **PWA** - Progressive Web App support"); } else if (addon === "tauri") { addonsList.push("- **Tauri** - Build native desktop applications"); } else if (addon === "biome") { addonsList.push("- **Biome** - Linting and formatting"); } else if (addon === "husky") { addonsList.push("- **Husky** - Git hooks for code quality"); } else if (addon === "starlight") { addonsList.push("- **Starlight** - Documentation site with Astro"); } else if (addon === "turborepo") { addonsList.push("- **Turborepo** - Optimized monorepo build system"); } } return addonsList.join("\n"); } function generateDatabaseSetup(database, auth, packageManagerRunCmd, orm) { if (database === "none") { return ""; } let setup = "## Database Setup\n\n"; if (database === "sqlite") { setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}. 1. Start the local SQLite database: \`\`\`bash cd apps/server && ${packageManagerRunCmd} db:local \`\`\` 2. Update your \`.env\` file in the \`apps/server\` directory with the appropriate connection details if needed. `; } else if (database === "postgres") { setup += `This project uses PostgreSQL${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}. 1. Make sure you have a PostgreSQL database set up. 2. Update your \`apps/server/.env\` file with your PostgreSQL connection details. `; } else if (database === "mysql") { setup += `This project uses MySQL${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}. 1. Make sure you have a MySQL database set up. 2. Update your \`apps/server/.env\` file with your MySQL connection details. `; } else if (database === "mongodb") { setup += `This project uses MongoDB ${orm === "mongoose" ? "with Mongoose" : "with Prisma ORM"}. 1. Make sure you have MongoDB set up. 2. Update your \`apps/server/.env\` file with your MongoDB connection URI. `; } setup += ` ${auth ? "3" : "3"}. ${orm === "prisma" ? `Generate the Prisma client and push the schema: \`\`\`bash ${packageManagerRunCmd} db:push \`\`\`` : orm === "drizzle" ? `Apply the schema to your database: \`\`\`bash ${packageManagerRunCmd} db:push \`\`\`` : `Apply the schema to your database: \`\`\`bash ${packageManagerRunCmd} db:push \`\`\``} `; return setup; } function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNative, addons, backend) { const isConvex = backend === "convex"; let scripts = `- \`${packageManagerRunCmd} dev\`: Start all applications in development mode - \`${packageManagerRunCmd} build\`: Build all applications - \`${packageManagerRunCmd} dev:web\`: Start only the web application`; if (isConvex) { scripts += ` - \`${packageManagerRunCmd} dev:setup\`: Setup and configure your Convex project`; } else { scripts += ` - \`${packageManagerRunCmd} dev:server\`: Start only the server`; } scripts += ` - \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`; if (hasNative) { scripts += ` - \`${packageManagerRunCmd} dev:native\`: Start the React Native/Expo development server`; } if (database !== "none" && !isConvex) { scripts += ` - \`${packageManagerRunCmd} db:push\`: Push schema changes to database - \`${packageManagerRunCmd} db:studio\`: Open database studio UI`; if (database === "sqlite" && orm === "drizzle") { scripts += ` - \`cd apps/server && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`; } } if (addons.includes("biome")) { scripts += ` - \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`; } if (addons.includes("pwa")) { scripts += ` - \`cd apps/web && ${packageManagerRunCmd} generate-pwa-assets\`: Generate PWA assets`; } if (addons.includes("tauri")) { scripts += ` - \`cd apps/web && ${packageManagerRunCmd} desktop:dev\`: Start Tauri desktop app in development - \`cd apps/web && ${packageManagerRunCmd} desktop:build\`: Build Tauri desktop app`; } if (addons.includes("starlight")) { scripts += ` - \`cd apps/docs && ${packageManagerRunCmd} dev\`: Start documentation site - \`cd apps/docs && ${packageManagerRunCmd} build\`: Build documentation site`; } return scripts; }