diff --git a/.env.example b/.env.example index 1d34646f3..8cd02f224 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,7 @@ POSTGRES_URL=postgresql://root:root@localhost:5432/vitnode -NEXT_PUBLIC_BACKEND_URL=http://localhost:3000 -NEXT_PUBLIC_BACKEND_CLIENT_URL=http://localhost:3000 -NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000 +NEXT_PUBLIC_API_URL=http://localhost:3000 +NEXT_PUBLIC_WEB_URL=http://localhost:3000 # === Docker Database Postgres === POSTGRES_USER=root diff --git a/apps/api/drizzle.config.ts b/apps/api/drizzle.config.ts new file mode 100644 index 000000000..0d630172b --- /dev/null +++ b/apps/api/drizzle.config.ts @@ -0,0 +1,12 @@ +import { defineVitNodeDrizzleConfig } from '@vitnode/core/drizzle.config'; + +import { POSTGRES_URL, vitNodeApiConfig } from './src/vitnode.api.config'; + +export default defineVitNodeDrizzleConfig({ + vitNodeApiConfig, + out: './migrations/', + dialect: 'postgresql', + dbCredentials: { + url: POSTGRES_URL, + }, +}); diff --git a/apps/api/eslint.config.mjs b/apps/api/eslint.config.mjs new file mode 100644 index 000000000..dd3efc12a --- /dev/null +++ b/apps/api/eslint.config.mjs @@ -0,0 +1,8 @@ +import eslintVitNode from '@vitnode/eslint-config/eslint'; + +export default [ + ...eslintVitNode, + { + ignores: ['drizzle.config.ts'], + }, +]; diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 000000000..efcd03033 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,42 @@ +{ + "name": "api", + "version": "1.2.0-canary.31", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx watch src/index.ts", + "build": "tsc && tsc-alias -p tsconfig.json", + "start": "node dist/index.js", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "drizzle-kit": "drizzle-kit" + }, + "dependencies": { + "@hono/zod-openapi": "^0.19.8", + "@hono/zod-validator": "^0.7.0", + "@react-email/components": "^0.1.1", + "@vitnode/core": "workspace:*", + "drizzle-kit": "^0.31.3", + "drizzle-orm": "^0.44.2", + "hono": "^4.8.3", + "next-intl": "^4.3.1", + "react": "^19.1", + "react-dom": "^19.1", + "zod": "^3.25.67" + }, + "devDependencies": { + "@hono/node-server": "^1.15.0", + "@types/node": "^24", + "@types/react": "^19.1", + "@types/react-dom": "^19.1", + "@vitnode/eslint-config": "workspace:*", + "dotenv": "^17.1.0", + "eslint": "^9.29.0", + "prettier": "^3.6.1", + "prettier-plugin-tailwindcss": "^0.6.12", + "react-email": "^4.0.17", + "tsc-alias": "^1.8.16", + "tsx": "^4.20.3", + "typescript": "^5.8.3" + } +} diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts new file mode 100644 index 000000000..98369de4f --- /dev/null +++ b/apps/api/src/index.ts @@ -0,0 +1,29 @@ +import { serve } from '@hono/node-server'; +import { OpenAPIHono } from '@hono/zod-openapi'; +import { VitNodeAPI } from '@vitnode/core/api/config'; + +import { vitNodeApiConfig } from './vitnode.api.config.js'; +import { vitNodeConfig } from './vitnode.config.js'; + +const app = new OpenAPIHono().basePath('/api'); + +VitNodeAPI({ + app, + vitNodeApiConfig, + vitNodeConfig, +}); + +serve( + { + fetch: app.fetch, + port: 8080, + }, + info => { + const initMessage = '\x1b[34m[VitNode]\x1b[0m'; + + // eslint-disable-next-line no-console + console.log( + `${initMessage} API server is running on http://localhost:${info.port}`, + ); + }, +); diff --git a/apps/api/src/vitnode.api.config.ts b/apps/api/src/vitnode.api.config.ts new file mode 100644 index 000000000..5111961a1 --- /dev/null +++ b/apps/api/src/vitnode.api.config.ts @@ -0,0 +1,17 @@ +import { buildApiConfig } from '@vitnode/core/vitnode.config'; +import * as dotenv from 'dotenv'; +import { drizzle } from 'drizzle-orm/postgres-js'; + +dotenv.config(); + +export const POSTGRES_URL = + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + process.env.POSTGRES_URL || 'postgresql://root:root@localhost:5432/vitnode'; + +export const vitNodeApiConfig = buildApiConfig({ + plugins: [], + dbProvider: drizzle({ + connection: POSTGRES_URL, + casing: 'camelCase', + }), +}); diff --git a/apps/api/src/vitnode.config.ts b/apps/api/src/vitnode.config.ts new file mode 100644 index 000000000..4f20e8a11 --- /dev/null +++ b/apps/api/src/vitnode.config.ts @@ -0,0 +1,32 @@ +import { buildConfig, handleRequestConfig } from '@vitnode/core/vitnode.config'; +import { getRequestConfig } from 'next-intl/server'; + +export const vitNodeConfig = buildConfig({ + metadata: { + title: 'VitNode', + shortTitle: 'VitNode', + }, + plugins: [], + i18n: { + locales: [ + { + code: 'en', + name: 'English', + }, + ], + defaultLocale: 'en', + }, + theme: { + defaultTheme: 'light', + }, +}); + +// This is the request config for the app. It will be used in the app router. +export default getRequestConfig( + async ({ requestLocale }) => + await handleRequestConfig({ + requestLocale, + vitNodeConfig, + pathToMessages: async path => await import(`./locales/${path}`), + }), +); diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 000000000..9498a3d91 --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vitnode/eslint-config/tsconfig", + "compilerOptions": { + "target": "ESNext", + "module": "NodeNext", + "baseUrl": ".", + "outDir": "./dist", + "types": ["node"], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore index 55a12ae71..c3a96f073 100644 --- a/apps/docs/.gitignore +++ b/apps/docs/.gitignore @@ -1,5 +1,6 @@ # deps /node_modules +.turbo # generated content .contentlayer diff --git a/apps/docs/.prettierrc.mjs b/apps/docs/.prettierrc.mjs deleted file mode 100644 index 92fe83d4d..000000000 --- a/apps/docs/.prettierrc.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import vitnodePrettier from '@vitnode/eslint-config/prettierrc'; - -/** - * @see https://prettier.io/docs/en/configuration.html - * @type {import("prettier").Config} - */ -const config = { - ...vitnodePrettier, -}; - -export default config; diff --git a/apps/docs/content/docs/dev/deployments/cloud/vercel.mdx b/apps/docs/content/docs/dev/deployments/cloud/vercel.mdx index 750605896..a2015a5ea 100644 --- a/apps/docs/content/docs/dev/deployments/cloud/vercel.mdx +++ b/apps/docs/content/docs/dev/deployments/cloud/vercel.mdx @@ -7,6 +7,13 @@ description: How to deploy your Vitnode app on Vercel. We're working hard to bring you the best documentation experience. +## Limitations + +Some features of Vitnode are not supported on Vercel due to its serverless architecture. These include: + +- Self-hosted static files +- WebSockets + ## Requirements - A Vercel account diff --git a/apps/docs/package.json b/apps/docs/package.json index 7b7caa85e..c90a6aa74 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -35,29 +35,28 @@ "motion": "^12.23.0", "next": "^15.3.5", "next-intl": "^4.3.4", - "react": "^19.1.0", - "react-dom": "^19.1.0", + "react": "^19.1", + "react-dom": "^19.1", "react-hook-form": "^7.60.0", "react-use": "^17.6.0", - "sonner": "^2.0.6", - "zod": "^3.25.74" + "sonner": "^2.0.6" }, "devDependencies": { "@playwright/test": "^1.53.2", "@tailwindcss/postcss": "^4.1.11", "@types/mdx": "^2.0.13", "@types/node": "^24.0.10", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", + "@types/react": "^19.1", + "@types/react-dom": "^19.1", "@vitnode/eslint-config": "workspace:*", "class-variance-authority": "^0.7.1", - "dotenv": "^17.0.1", "eslint": "^9.30.1", "postcss": "^8.5.6", "react-email": "^4.0.17", "shiki": "^3.7.0", "tailwindcss": "^4.1.11", "tw-animate-css": "^1.3.5", - "typescript": "^5.8.3" + "typescript": "^5.8.3", + "zod": "^3.25.74" } } diff --git a/apps/docs/src/app/[locale]/(docs)/docs/[[...slug]]/page.tsx b/apps/docs/src/app/[locale]/(docs)/docs/[[...slug]]/page.tsx index 5c62704cf..627049e0e 100644 --- a/apps/docs/src/app/[locale]/(docs)/docs/[[...slug]]/page.tsx +++ b/apps/docs/src/app/[locale]/(docs)/docs/[[...slug]]/page.tsx @@ -36,7 +36,7 @@ export default async function Page(props: {
{page.data.description}
-+
Simplifies development with a powerful Plugin System, Admin Control Panel and extensible architecture.
diff --git a/apps/docs/src/app/[locale]/(main)/(home)/sections/admin/admin.tsx b/apps/docs/src/app/[locale]/(main)/(home)/sections/admin/admin.tsx index 34eb36d6b..9dfc71db9 100644 --- a/apps/docs/src/app/[locale]/(main)/(home)/sections/admin/admin.tsx +++ b/apps/docs/src/app/[locale]/(main)/(home)/sections/admin/admin.tsx @@ -13,8 +13,8 @@ export const AdminSection = () => {+
Everything you need for modern web apps, zero config.
diff --git a/apps/docs/src/app/[locale]/(main)/(home)/sections/powering-by/logos/tailwindcss.tsx b/apps/docs/src/app/[locale]/(main)/(home)/sections/powering-by/logos/tailwindcss.tsx index 82cd065f9..0dee1a73b 100644 --- a/apps/docs/src/app/[locale]/(main)/(home)/sections/powering-by/logos/tailwindcss.tsx +++ b/apps/docs/src/app/[locale]/(main)/(home)/sections/powering-by/logos/tailwindcss.tsx @@ -2,7 +2,7 @@ export const TailwindCSSLogo = () => { return (An open-source UI component library.
diff --git a/apps/docs/src/vitnode.api.config.ts b/apps/docs/src/vitnode.api.config.ts index 45f3d6fd5..ed34849c9 100644 --- a/apps/docs/src/vitnode.api.config.ts +++ b/apps/docs/src/vitnode.api.config.ts @@ -4,13 +4,7 @@ import { DiscordSSOApiPlugin } from '@vitnode/core/api/adapters/sso/discord'; import { FacebookSSOApiPlugin } from '@vitnode/core/api/adapters/sso/facebook'; import { GoogleSSOApiPlugin } from '@vitnode/core/api/adapters/sso/google'; import { buildApiConfig } from '@vitnode/core/vitnode.config'; -import * as dotenv from 'dotenv'; import { drizzle } from 'drizzle-orm/postgres-js'; -import { join } from 'path'; - -dotenv.config({ - path: join(process.cwd(), '..', '..', '.env'), -}); export const POSTGRES_URL = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing diff --git a/package.json b/package.json index 8447b5c19..b836265b6 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,10 @@ "test:e2e": "turbo test:e2e" }, "devDependencies": { - "@types/node": "^24.0.10", + "@types/node": "^24", "@vitnode/eslint-config": "workspace:*", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.13", - "tsx": "^4.20.3", "turbo": "^2.5.4", "typescript": "^5.8.3", "zod": "^3.25.74" diff --git a/packages/create-vitnode-app/README.md b/packages/create-vitnode-app/README.md index f80887a89..91a9fcb0c 100644 --- a/packages/create-vitnode-app/README.md +++ b/packages/create-vitnode-app/README.md @@ -37,8 +37,9 @@ bun create vitnode-app@latest ## Options -| Option | Description | -| ------------------- | ---------------------------------------------------------- | -| `--package-manager` | Specify the package manager to use. Support `npm`, `pnpm`. | -| `--eslint` | Initialize with eslint config. | -| `--skip-install` | Skip installing packages after initializing the project. | +| Option | Description | +| ------------------- | --------------------------------------------------------------------------------- | +| `--package-manager` | Specify the package manager to use. Support `npm`, `pnpm`. | +| `--eslint` | Initialize with eslint config. | +| `--skip-install` | Skip installing packages after initializing the project. | +| `--mode` | Specify the type of app to create. Support `singleApp`, `apiMonorepo`, `onlyApi`. | diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/root/.env.example b/packages/create-vitnode-app/copy-of-vitnode-app/root/.env.example index 1d34646f3..8cd02f224 100644 --- a/packages/create-vitnode-app/copy-of-vitnode-app/root/.env.example +++ b/packages/create-vitnode-app/copy-of-vitnode-app/root/.env.example @@ -1,8 +1,7 @@ POSTGRES_URL=postgresql://root:root@localhost:5432/vitnode -NEXT_PUBLIC_BACKEND_URL=http://localhost:3000 -NEXT_PUBLIC_BACKEND_CLIENT_URL=http://localhost:3000 -NEXT_PUBLIC_FRONTEND_URL=http://localhost:3000 +NEXT_PUBLIC_API_URL=http://localhost:3000 +NEXT_PUBLIC_WEB_URL=http://localhost:3000 # === Docker Database Postgres === POSTGRES_USER=root diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/root/tsconfig.json b/packages/create-vitnode-app/copy-of-vitnode-app/root/tsconfig.json new file mode 100644 index 000000000..13dc93961 --- /dev/null +++ b/packages/create-vitnode-app/copy-of-vitnode-app/root/tsconfig.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vitnode/eslint-config/tsconfig", + "compilerOptions": { + "target": "ESNext", + "module": "esnext", + "moduleResolution": "bundler", + "noEmit": true, + "baseUrl": ".", + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/create-vitnode-app/src/create/create-package-json.ts b/packages/create-vitnode-app/src/create/create-package-json.ts index 588eac634..51e5c7946 100644 --- a/packages/create-vitnode-app/src/create/create-package-json.ts +++ b/packages/create-vitnode-app/src/create/create-package-json.ts @@ -3,6 +3,7 @@ import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; import type { PackageJSON } from '../helpers/packages-json.js'; +import type { CreateCliReturn } from '../questions.js'; import { getAvailablePackageManagers } from '../helpers/get-available-package-managers.js'; @@ -15,10 +16,12 @@ export const createPackageJSON = async ({ root, eslint, docker, + mode, }: { appName: string; docker?: boolean; eslint: boolean; + mode: CreateCliReturn['mode']; packageManager: string; root: string; }) => { @@ -27,24 +30,22 @@ export const createPackageJSON = async ({ await readFile(join(__dirname, '..', '..', '..', 'package.json'), 'utf-8'), ); - const packageJson: PackageJSON = { - name: appName, + const apiPackageJson: PackageJSON = { + name: mode === 'apiMonorepo' ? 'api' : appName, version: '0.1.0', private: true, type: 'module', scripts: { - 'db:push': 'vitnode push', - 'db:migrate': 'vitnode migrate', - dev: 'vitnode init && next dev --turbopack', - build: 'next build --turbopack', - start: 'next start', + dev: 'tsx watch src/index.ts', + build: 'tsc && tsc-alias -p tsconfig.json', + start: 'node dist/index.js', ...(eslint ? { lint: 'eslint .', 'lint:fix': 'eslint . --fix', } : {}), - ...(docker + ...(docker && mode === 'onlyApi' ? { 'docker:dev': `docker compose -f ./docker-compose.yml -p ${appName}-vitnode-dev up -d`, } @@ -52,47 +53,207 @@ export const createPackageJSON = async ({ 'drizzle-kit': 'drizzle-kit', }, dependencies: { - '@hono/zod-openapi': '^0.19.9', + '@hono/zod-openapi': '^0.19.8', '@hono/zod-validator': '^0.7.0', - '@hookform/resolvers': '^5.1.1', '@react-email/components': '^0.1.1', '@vitnode/core': `^${pkg.version}`, - 'babel-plugin-react-compiler': '19.1.0-rc.2', - 'drizzle-kit': '^0.31.4', + 'drizzle-kit': '^0.31.3', 'drizzle-orm': '^0.44.2', - hono: '^4.8.4', - 'lucide-react': '^0.525.0', - next: '^15.3.5', - 'next-intl': '^4.3.4', - react: '^19.1.0', - 'react-dom': '^19.1.0', - 'react-hook-form': '^7.60.0', - sonner: '^2.0.6', - zod: '^3.25.74', + hono: '^4.8.3', + 'next-intl': '^4.3.1', + react: '^19.1', + 'react-dom': '^19.1', + zod: '^3.25.67', }, devDependencies: { - '@tailwindcss/postcss': '^4.1.11', + '@hono/node-server': '^1.15.0', '@types/node': '^24', '@types/react': '^19.1', '@types/react-dom': '^19.1', + '@vitnode/eslint-config': `^${pkg.version}`, + dotenv: '^17.1.0', ...(eslint ? { eslint: '^9.30.1', - '@vitnode/eslint-config': `^${pkg.version}`, - 'prettier-plugin-tailwindcss': '^0.6.12', - prettier: '^3.6.2', + ...(mode === 'onlyApi' + ? { + 'prettier-plugin-tailwindcss': '^0.6.12', + prettier: '^3.6.2', + } + : {}), } : {}), 'react-email': '^4.0.17', - tailwindcss: '^4.1.11', - 'tw-animate-css': '^1.3.5', + 'tsc-alias': '^1.8.16', + tsx: '^4.20.3', typescript: '^5.8.3', }, - packageManager: `${packageManager}@${availablePackageManagers[packageManager]}`, }; - await writeFile( - join(root, 'package.json'), - JSON.stringify(packageJson, null, 2), - ); + if (mode === 'singleApp') { + const packageJson: PackageJSON = { + name: appName, + version: '0.1.0', + private: true, + type: 'module', + scripts: { + 'db:push': 'vitnode push', + 'db:migrate': 'vitnode migrate', + dev: 'vitnode init && next dev --turbopack', + build: 'next build --turbopack', + start: 'next start', + ...(eslint + ? { + lint: 'eslint .', + 'lint:fix': 'eslint . --fix', + } + : {}), + ...(docker + ? { + 'docker:dev': `docker compose -f ./docker-compose.yml -p ${appName}-vitnode-dev up -d`, + } + : {}), + 'drizzle-kit': 'drizzle-kit', + }, + dependencies: { + '@hono/zod-openapi': '^0.19.9', + '@hono/zod-validator': '^0.7.0', + '@hookform/resolvers': '^5.1.1', + '@react-email/components': '^0.1.1', + '@vitnode/core': `^${pkg.version}`, + 'babel-plugin-react-compiler': '19.1.0-rc.2', + 'drizzle-kit': '^0.31.4', + 'drizzle-orm': '^0.44.2', + hono: '^4.8.4', + 'lucide-react': '^0.525.0', + next: '^15.3.5', + 'next-intl': '^4.3.4', + react: '^19.1', + 'react-dom': '^19.1', + 'react-hook-form': '^7.60.0', + sonner: '^2.0.6', + zod: '^3.25.74', + }, + devDependencies: { + '@tailwindcss/postcss': '^4.1.11', + '@types/node': '^24', + '@types/react': '^19.1', + '@types/react-dom': '^19.1', + '@vitnode/eslint-config': `^${pkg.version}`, + ...(eslint + ? { + eslint: '^9.30.1', + 'prettier-plugin-tailwindcss': '^0.6.12', + prettier: '^3.6.2', + } + : {}), + 'react-email': '^4.0.17', + turbo: '^2.5.4', + tailwindcss: '^4.1.11', + 'tw-animate-css': '^1.3.5', + typescript: '^5.8.3', + }, + packageManager: `${packageManager}@${availablePackageManagers[packageManager]}`, + }; + + await writeFile( + join(root, 'package.json'), + JSON.stringify(packageJson, null, 2), + ); + } else if (mode === 'apiMonorepo') { + const rootPackageJson: PackageJSON = { + name: appName, + private: true, + scripts: { + 'db:migrate': 'turbo db:migrate', + 'db:push': 'turbo db:push', + build: 'turbo build', + start: 'turbo start', + dev: ' turbo dev', + lint: 'turbo lint', + 'lint:fix': 'turbo lint:fix', + }, + devDependencies: { + '@types/node': '^24', + '@vitnode/eslint-config': `^${pkg.version}`, + ...(eslint + ? { + 'prettier-plugin-tailwindcss': '^0.6.12', + prettier: '^3.6.2', + } + : {}), + turbo: '^2.5.4', + typescript: '^5.8.3', + zod: '^3.25.74', + }, + packageManager: `${packageManager}@${availablePackageManagers[packageManager]}`, + workspaces: ['apps/*', 'plugins/*'], + }; + + await writeFile( + join(root, 'package.json'), + JSON.stringify(rootPackageJson, null, 2), + ); + + await writeFile( + join(root, 'apps', 'api', 'package.json'), + JSON.stringify(apiPackageJson, null, 2), + ); + + const webPackageJson: PackageJSON = { + name: 'web', + version: '0.1.0', + private: true, + type: 'module', + scripts: { + dev: 'vitnode init && next dev --turbopack', + build: 'next build --turbopack', + start: 'next start', + lint: 'eslint .', + 'lint:fix': 'eslint . --fix', + }, + dependencies: { + '@vitnode/core': `^${pkg.version}`, + 'babel-plugin-react-compiler': '19.1.0-rc.2', + 'lucide-react': '^0.525.0', + next: '^15.3.5', + 'next-intl': '^4.3.4', + react: '^19.1', + 'react-dom': '^19.1', + 'react-hook-form': '^7.60.0', + sonner: '^2.0.6', + }, + devDependencies: { + '@playwright/test': '^1.53.2', + '@tailwindcss/postcss': '^4.1.11', + '@types/mdx': '^2.0.13', + '@types/node': '^24.0.10', + '@types/react': '^19.1', + '@types/react-dom': '^19.1', + '@vitnode/eslint-config': `^${pkg.version}`, + 'class-variance-authority': '^0.7.1', + ...(eslint + ? { + eslint: '^9.30.1', + } + : {}), + postcss: '^8.5.6', + 'react-email': '^4.0.17', + tailwindcss: '^4.1.11', + 'tw-animate-css': '^1.3.5', + typescript: '^5.8.3', + zod: '^3.25.74', + }, + }; + + await writeFile( + join(root, 'apps', 'web', 'package.json'), + JSON.stringify(webPackageJson, null, 2), + ); + } else if (mode === 'onlyApi') { + await writeFile( + join(root, 'package.json'), + JSON.stringify(apiPackageJson, null, 2), + ); + } }; diff --git a/packages/create-vitnode-app/src/create/create-vitnode.ts b/packages/create-vitnode-app/src/create/create-vitnode.ts index a25729d2f..a56972a7a 100644 --- a/packages/create-vitnode-app/src/create/create-vitnode.ts +++ b/packages/create-vitnode-app/src/create/create-vitnode.ts @@ -22,6 +22,7 @@ export const createVitNode = async ({ eslint, install, docker, + mode, }: CreateCliReturn & { appName: string; root: string; @@ -45,11 +46,44 @@ export const createVitNode = async ({ if (!isFolderEmpty(root, appName)) { process.exit(1); } + const monorepoStructure = { + api: join(root, 'apps', 'api'), + web: join(root, 'apps', 'web'), + }; + + if (mode === 'apiMonorepo') { + spinner.text = 'Preparing monorepo structure...'; + // Create api, web folders + await Promise.all([ + mkdir(monorepoStructure.api, { recursive: true }), + mkdir(monorepoStructure.web, { recursive: true }), + ]); + } spinner.text = 'Copying files...'; - await cp(join(templatePath, 'root'), root, { - recursive: true, - }); + if (mode === 'singleApp') { + await Promise.all([ + cp(join(templatePath, 'root'), root, { + recursive: true, + }), + cp(join(templatePath, 'api-single-app'), root, { + recursive: true, + }), + ]); + } else if (mode === 'apiMonorepo') { + await Promise.all([ + cp(join(templatePath, 'root'), monorepoStructure.web, { + recursive: true, + }), + cp(join(templatePath, 'api'), monorepoStructure.api, { + recursive: true, + }), + ]); + } else if (mode === 'onlyApi') { + await cp(join(templatePath, 'api'), root, { + recursive: true, + }); + } if (eslint) { spinner.text = 'Copying eslint files...'; @@ -58,7 +92,6 @@ export const createVitNode = async ({ }); } - // Rename special files spinner.text = 'Renaming special files...'; await rename(join(root, '.gitignore_template'), join(root, '.gitignore')); @@ -69,6 +102,7 @@ export const createVitNode = async ({ packageManager, eslint, docker, + mode, }); if (docker) { diff --git a/packages/create-vitnode-app/src/helpers/packages-json.ts b/packages/create-vitnode-app/src/helpers/packages-json.ts index 240b6954e..90febe98f 100644 --- a/packages/create-vitnode-app/src/helpers/packages-json.ts +++ b/packages/create-vitnode-app/src/helpers/packages-json.ts @@ -9,6 +9,6 @@ export interface PackageJSON { private: boolean; scripts?: Record