diff --git a/.github/workflows/build-lint-test.yml b/.github/workflows/build-lint-test.yml index fde016a7e..9665a27ac 100644 --- a/.github/workflows/build-lint-test.yml +++ b/.github/workflows/build-lint-test.yml @@ -22,7 +22,7 @@ jobs: - uses: pnpm/action-setup@v4 name: Install pnpm with: - version: 10.18.0 + version: 10.18.3 - name: Install Node.js uses: actions/setup-node@v4 diff --git a/.github/workflows/bump_publish.yml b/.github/workflows/bump_publish.yml index ba1891e9d..c8e5c0255 100644 --- a/.github/workflows/bump_publish.yml +++ b/.github/workflows/bump_publish.yml @@ -9,8 +9,8 @@ on: type: choice options: - canary - - stable - release-candidate + - stable type: description: "Type of package to publish" required: true @@ -52,7 +52,7 @@ jobs: - uses: pnpm/action-setup@v4 name: Install pnpm with: - version: 10.18.0 + version: 10.18.3 - name: Install Node.js uses: actions/setup-node@v4 diff --git a/apps/api/package.json b/apps/api/package.json index 51bfb03bf..04723c5cd 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "api", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.59", "private": true, "type": "module", "scripts": { @@ -14,28 +14,28 @@ "lint:fix": "eslint . --fix" }, "dependencies": { - "@hono/zod-openapi": "^1.1.3", - "@hono/zod-validator": "^0.7.3", + "@hono/zod-openapi": "^1.1.4", + "@hono/zod-validator": "^0.7.4", "@vitnode/core": "workspace:*", - "drizzle-kit": "^0.31.5", - "drizzle-orm": "^0.44.6", - "hono": "^4.9.9", - "next-intl": "^4.3.9", + "drizzle-kit": "^0.31.6", + "drizzle-orm": "^0.44.7", + "hono": "^4.10.4", + "next-intl": "^4.5.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "use-intl": "^4.3.9", - "zod": "^4.1.11" + "use-intl": "^4.5.0", + "zod": "^4.1.12" }, "devDependencies": { - "@hono/node-server": "^1.19.5", - "@react-email/components": "^0.5.5", - "@types/node": "^24.6.2", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", + "@hono/node-server": "^1.19.6", + "@react-email/components": "^1.0.0", + "@types/node": "^24.10.0", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", "@vitnode/config": "workspace:*", "dotenv": "^17.2.3", - "eslint": "^9.36.0", - "react-email": "^4.2.12", + "eslint": "^9.39.1", + "react-email": "^5.0.1", "tsc-alias": "^1.8.16", "tsx": "^4.20.6", "typescript": "^5.9.3" diff --git a/apps/docs/content/docs/dev/plugins.mdx b/apps/docs/content/docs/dev/plugins.mdx index 10ccac544..0fbeff08a 100644 --- a/apps/docs/content/docs/dev/plugins.mdx +++ b/apps/docs/content/docs/dev/plugins.mdx @@ -22,13 +22,13 @@ By creating a plugin, you can extend the functionality like: ## Prerequisites - - To create a plugin, you need to have a TurboRepo setup. + + To create a plugin, you need to have a Turborepo setup. ## Create a Plugin -import { Tab, Tabs } from 'fumadocs-ui/components/tabs'; +import { Tab, Tabs } from "fumadocs-ui/components/tabs"; diff --git a/apps/docs/content/docs/dev/sso/index.mdx b/apps/docs/content/docs/dev/sso/index.mdx index b4e324621..4c2fa1875 100644 --- a/apps/docs/content/docs/dev/sso/index.mdx +++ b/apps/docs/content/docs/dev/sso/index.mdx @@ -40,7 +40,7 @@ import { SSOApiPlugin, getRedirectUri } from "@vitnode/core/api/models/sso"; export const DiscordSSOApiPlugin = ({ clientId, - clientSecret + clientSecret, }: { clientId: string; clientSecret: string; @@ -66,7 +66,7 @@ import { SSOApiPlugin, getRedirectUri } from "@vitnode/core/api/models/sso"; export const DiscordSSOApiPlugin = ({ clientId, - clientSecret + clientSecret, }: { clientId: string; clientSecret: string; @@ -94,14 +94,14 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] return url.toString(); // [!code ++] - } + }, }; }; ``` - Always include the `state` parameter - it's your security guard against CSRF attacks. Don't worry, - VitNode handles this automatically! + Always include the `state` parameter - it's your security guard against CSRF + attacks. Don't worry, VitNode handles this automatically! @@ -120,12 +120,12 @@ import { z } from "zod"; const tokenSchema = z.object({ access_token: z.string(), - token_type: z.string() + token_type: z.string(), }); export const DiscordSSOApiPlugin = ({ clientId, - clientSecret + clientSecret, }: { clientId: string; clientSecret: string; @@ -137,7 +137,7 @@ export const DiscordSSOApiPlugin = ({ id, name: "Discord", // [!code ++] - fetchToken: async (code) => { + fetchToken: async code => { // [!code ++] const res = await fetch("https://discord.com/api/oauth2/token", { // [!code ++] @@ -147,7 +147,7 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] "Content-Type": "application/x-www-form-urlencoded", // [!code ++] - Accept: "application/json" + Accept: "application/json", // [!code ++] }, // [!code ++] @@ -161,9 +161,9 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] client_id: clientId, // [!code ++] - client_secret: clientSecret + client_secret: clientSecret, // [!code ++] - }) + }), // [!code ++] }); @@ -176,9 +176,9 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] { // [!code ++] - message: "Internal error requesting token" + message: "Internal error requesting token", // [!code ++] - } + }, // [!code ++] ); // [!code ++] @@ -187,11 +187,11 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] const { data, error } = tokenSchema.safeParse(await res.json()); // [!code ++] - if (error || !data) { + if (error ?? !data) { // [!code ++] throw new HTTPException(400, { // [!code ++] - message: "Invalid token response" + message: "Invalid token response", // [!code ++] }); // [!code ++] @@ -210,7 +210,7 @@ export const DiscordSSOApiPlugin = ({ url.searchParams.set("state", state); return url.toString(); - } + }, }; }; ``` @@ -232,12 +232,12 @@ import { z } from "zod"; const userSchema = z.object({ id: z.number(), email: z.string(), - username: z.string() + username: z.string(), }); export const DiscordSSOApiPlugin = ({ clientId, - clientSecret + clientSecret, }: { clientId: string; clientSecret: string; @@ -255,20 +255,20 @@ export const DiscordSSOApiPlugin = ({ // [!code ++] headers: { // [!code ++] - Authorization: `${token_type} ${access_token}` + Authorization: `${token_type} ${access_token}`, // [!code ++] - } + }, // [!code ++] }); // [!code ++] const { data, error } = userSchema.safeParse(await res.json()); // [!code ++] - if (error || !data) { + if (error ?? !data) { // [!code ++] throw new HTTPException(400, { // [!code ++] - message: "Invalid user response" + message: "Invalid user response", // [!code ++] }); // [!code ++] @@ -278,32 +278,35 @@ export const DiscordSSOApiPlugin = ({ return data; // [!code ++] }, - fetchToken: async (code) => { + fetchToken: async code => { const res = await fetch("https://discord.com/api/oauth2/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json" + Accept: "application/json", }, body: new URLSearchParams({ code, redirect_uri: redirectUri, grant_type: "authorization_code", client_id: clientId, - client_secret: clientSecret - }) + client_secret: clientSecret, + }), }); if (!res.ok) { - throw new HTTPException(+res.status.toString() as ContentfulStatusCode, { - message: "Internal error requesting token" - }); + throw new HTTPException( + +res.status.toString() as ContentfulStatusCode, + { + message: "Internal error requesting token", + }, + ); } const { data, error } = tokenSchema.safeParse(await res.json()); - if (error || !data) { + if (error ?? !data) { throw new HTTPException(400, { - message: "Invalid token response" + message: "Invalid token response", }); } @@ -318,14 +321,15 @@ export const DiscordSSOApiPlugin = ({ url.searchParams.set("state", state); return url.toString(); - } + }, }; }; ``` - Pro tip: Some OAuth providers might return unverified email addresses. If your provider gives you - an email verification status, add it to your validation to keep things secure! + Pro tip: Some OAuth providers might return unverified email addresses. If your + provider gives you an email verification status, add it to your validation to + keep things secure! @@ -354,11 +358,11 @@ VitNodeAPI({ // [!code ++] clientId: process.env.DISCORD_CLIENT_ID, // [!code ++] - clientSecret: process.env.DISCORD_CLIENT_SECRET + clientSecret: process.env.DISCORD_CLIENT_SECRET, // [!code ++] - }) + }), // [!code ++] - ] - } + ], + }, }); ``` diff --git a/apps/docs/docker-compose.yml b/apps/docs/docker-compose.yml index 7b59f0e56..ee9e7a7e1 100644 --- a/apps/docs/docker-compose.yml +++ b/apps/docs/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: "3.8" services: database: @@ -12,7 +12,7 @@ services: volumes: - ../../docker/dev:/var/lib/postgresql/data ports: - - '5432:5432' + - "5432:5432" networks: - vitnode_dev diff --git a/apps/docs/next.config.ts b/apps/docs/next.config.ts index ff1e2c44c..a7954fecc 100644 --- a/apps/docs/next.config.ts +++ b/apps/docs/next.config.ts @@ -9,11 +9,6 @@ const withBundleAnalyzer = nextAnalyzer({ enabled: process.env.ANALYZE === "true", }); -const nextConfig: NextConfig = { - experimental: { - inlineCss: true, - ppr: "incremental", - }, -}; +const nextConfig: NextConfig = {}; export default withBundleAnalyzer(withMDX(vitNodeNextConfig(nextConfig))); diff --git a/apps/docs/package.json b/apps/docs/package.json index b4448ff89..d55ae0e2b 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,15 +1,15 @@ { "name": "docs", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.59", "type": "module", "private": true, "scripts": { "db:migrate": "vitnode migrate", "docker:dev": "docker compose -f ./docker-compose.yml -p vitnode-dev-dun up -d", "init": "vitnode init", - "dev": "vitnode init && next dev --turbopack", + "dev": "vitnode init && next dev", "dev:email": "email dev --dir src/emails", - "build": "next build --turbopack", + "build": "next build", "build:analyze": "ANALYZE=true next build", "start": "next start", "test:e2e": "playwright test", @@ -22,46 +22,46 @@ "lint:fix": "eslint . --fix" }, "dependencies": { - "@hono/zod-openapi": "^1.1.3", - "@hono/zod-validator": "^0.7.3", + "@hono/zod-openapi": "^1.1.4", + "@hono/zod-validator": "^0.7.4", "@vitnode/blog": "workspace:*", "@vitnode/core": "workspace:*", - "drizzle-kit": "^0.31.5", - "drizzle-orm": "^0.44.6", - "fumadocs-core": "^15.8.3", - "fumadocs-mdx": "^12.0.2", - "fumadocs-ui": "^15.8.3", - "hono": "^4.9.9", - "lucide-react": "^0.544.0", - "motion": "^12.23.22", - "next": "15.6.0-canary.41", - "next-intl": "^4.3.9", + "drizzle-kit": "^0.31.6", + "drizzle-orm": "^0.44.7", + "fumadocs-core": "^16.0.8", + "fumadocs-mdx": "^13.0.5", + "fumadocs-ui": "^16.0.8", + "hono": "^4.10.4", + "lucide-react": "^0.553.0", + "motion": "^12.23.24", + "next": "^16.0.1", + "next-intl": "^4.5.0", "node-cron": "^4.2.1", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-hook-form": "^7.63.0", + "react-hook-form": "^7.66.0", "react-use": "^17.6.0", "sonner": "^2.0.7" }, "devDependencies": { - "@next/bundle-analyzer": "^15.5.4", - "@playwright/test": "^1.55.1", - "@react-email/components": "^0.5.5", - "@tailwindcss/postcss": "^4.1.14", + "@next/bundle-analyzer": "^16.0.1", + "@playwright/test": "^1.56.1", + "@react-email/components": "^1.0.0", + "@tailwindcss/postcss": "^4.1.17", "@types/mdx": "^2.0.13", - "@types/node": "^24.6.2", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", + "@types/node": "^24.10.0", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", "@vitnode/config": "workspace:*", "class-variance-authority": "^0.7.1", - "eslint": "^9.36.0", + "eslint": "^9.39.1", "postcss": "^8.5.6", - "react-email": "^4.2.12", - "shiki": "^3.13.0", - "tailwindcss": "^4.1.14", + "react-email": "^5.0.1", + "shiki": "^3.15.0", + "tailwindcss": "^4.1.17", "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", - "use-intl": "^4.3.9", - "zod": "^4.1.11" + "use-intl": "^4.5.0", + "zod": "^4.1.12" } } diff --git a/apps/docs/src/app/[locale]/(docs)/docs/layout.tsx b/apps/docs/src/app/[locale]/(docs)/docs/layout.tsx index e8a4384d0..0e82841ab 100644 --- a/apps/docs/src/app/[locale]/(docs)/docs/layout.tsx +++ b/apps/docs/src/app/[locale]/(docs)/docs/layout.tsx @@ -22,7 +22,7 @@ export default function Layout({ children }: { children: ReactNode }) { ...option, icon: (
-

+

Extendable Framework for Building Apps

-

+

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 1a3d46b0c..604c17f34 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 = () => {
-
-
+
+
payments illustration dark { return (
-

+

Start Building

-

+

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 bcd565d7e..8fe70187b 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 ( { -
-
+
+
diff --git a/apps/docs/src/app/[locale]/layout.tsx b/apps/docs/src/app/[locale]/layout.tsx index bf39489a9..c7de97abc 100644 --- a/apps/docs/src/app/[locale]/layout.tsx +++ b/apps/docs/src/app/[locale]/layout.tsx @@ -5,7 +5,7 @@ import { generateMetadataRootLayout, RootLayout, } from "@vitnode/core/views/layouts/root-layout"; -import { RootProvider } from "fumadocs-ui/provider"; +import { RootProvider } from "fumadocs-ui/provider/next"; import { Geist, Geist_Mono } from "next/font/google"; import { vitNodeConfig } from "@/vitnode.config"; diff --git a/apps/docs/src/components/animated-beam/animated-beam.tsx b/apps/docs/src/components/animated-beam/animated-beam.tsx index 0c0923880..44ec99aa5 100644 --- a/apps/docs/src/components/animated-beam/animated-beam.tsx +++ b/apps/docs/src/components/animated-beam/animated-beam.tsx @@ -104,6 +104,7 @@ export const AnimatedBeam = ({ } // Call the updatePath initially to set the initial path + // eslint-disable-next-line react-you-might-not-need-an-effect/no-adjust-state-on-prop-change updatePath(); // Clean up the observer on component unmount @@ -124,7 +125,7 @@ export const AnimatedBeam = ({ return (
-

Tags

+

Tags

{tags.map(tag => (
{tag}
diff --git a/apps/docs/src/examples/separator.tsx b/apps/docs/src/examples/separator.tsx index 7e5459e82..f5221bc5c 100644 --- a/apps/docs/src/examples/separator.tsx +++ b/apps/docs/src/examples/separator.tsx @@ -4,7 +4,7 @@ export default function ProgressDemo() { return (
-

Radix Primitives

+

Radix Primitives

An open-source UI component library.

diff --git a/apps/docs/src/middleware.ts b/apps/docs/src/proxy.ts similarity index 100% rename from apps/docs/src/middleware.ts rename to apps/docs/src/proxy.ts diff --git a/package.json b/package.json index 3a088959b..2735bbe21 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vitnode", "private": true, "scripts": { - "release": "tsx ./scripts/bump-version.ts", + "release": "tsx ./scripts/bump-version/bump-version.ts", "db:migrate": "turbo db:migrate", "docker:dev": "turbo docker:dev", "build:scripts": "turbo build:scripts && pnpm i", @@ -17,19 +17,19 @@ "test:e2e": "turbo test:e2e" }, "devDependencies": { - "@types/node": "^24.6.2", + "@types/node": "^24.10.0", "@vitnode/config": "workspace:*", "prettier": "^3.6.2", - "prettier-plugin-tailwindcss": "^0.6.14", + "prettier-plugin-tailwindcss": "^0.7.1", "tsx": "^4.20.6", - "turbo": "^2.5.8", + "turbo": "^2.6.0", "typescript": "^5.9.3", - "zod": "^4.1.11" + "zod": "^4.1.12" }, "engines": { "node": ">=22" }, - "packageManager": "pnpm@10.18.0", + "packageManager": "pnpm@10.18.3", "workspaces": [ "apps/*", "packages/*", diff --git a/packages/config/package.json b/packages/config/package.json index b0630cab5..ded6eee12 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/config", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.59", "description": "ESLint, Prettier, TypeScript (TSConfig) config for VitNode", "author": "VitNode Team", "license": "MIT", @@ -41,16 +41,16 @@ "typescript": "^5.9.3" }, "dependencies": { - "@eslint-react/eslint-plugin": "^2.0.6", - "@eslint/js": "^9.36.0", + "@eslint-react/eslint-plugin": "^2.3.1", + "@eslint/js": "^9.39.1", "eslint-config-prettier": "^10.1.8", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-perfectionist": "^4.15.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-you-might-not-need-an-effect": "^0.5.5", - "prettier-plugin-tailwindcss": "^0.6.14", - "typescript-eslint": "^8.45.0" + "eslint-plugin-react-you-might-not-need-an-effect": "^0.7.0", + "prettier-plugin-tailwindcss": "^0.7.1", + "typescript-eslint": "^8.46.3" } } diff --git a/packages/create-vitnode-app/README.md b/packages/create-vitnode-app/README.md index 0dd11c7a2..1cfb09022 100644 --- a/packages/create-vitnode-app/README.md +++ b/packages/create-vitnode-app/README.md @@ -45,3 +45,14 @@ bun create vitnode-app@latest | `--mode` | Specify the type of app to create. Support `singleApp`, `apiMonorepo`, `onlyApi`. | | `--monorepo` | Create project with monorepo structure. | | `--docker` | Initialize with Docker support. | +| `--plugin` | Create a VitNode plugin project. | + +## Create Plugin + +Use the `--plugin` flag to create a VitNode plugin project. + +### Options + +| Option | Description | +| ---------------- | -------------------------------------------------------- | +| `--skip-install` | Skip installing packages after initializing the project. | diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts b/packages/create-vitnode-app/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts index 316a9eb9c..0db2a1773 100644 --- a/packages/create-vitnode-app/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts +++ b/packages/create-vitnode-app/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts @@ -2,7 +2,7 @@ import { buildApiConfig } from "@vitnode/core/vitnode.config"; import { drizzle } from "drizzle-orm/postgres-js"; export const POSTGRES_URL = - process.env.POSTGRES_URL || "postgresql://root:root@localhost:5432/vitnode"; + process.env.POSTGRES_URL ?? "postgresql://root:root@localhost:5432/vitnode"; export const vitNodeApiConfig = buildApiConfig({ pathToMessages: async path => await import(`./locales/${path}`), diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/api/src/vitnode.api.config.ts b/packages/create-vitnode-app/copy-of-vitnode-app/api/src/vitnode.api.config.ts index 7cc1e1355..c546f72eb 100644 --- a/packages/create-vitnode-app/copy-of-vitnode-app/api/src/vitnode.api.config.ts +++ b/packages/create-vitnode-app/copy-of-vitnode-app/api/src/vitnode.api.config.ts @@ -7,7 +7,7 @@ config({ }); export const POSTGRES_URL = - process.env.POSTGRES_URL || "postgresql://root:root@localhost:5432/vitnode"; + process.env.POSTGRES_URL ?? "postgresql://root:root@localhost:5432/vitnode"; export const vitNodeApiConfig = buildApiConfig({ plugins: [], diff --git a/packages/create-vitnode-app/copy-of-vitnode-app/root/src/middleware.ts b/packages/create-vitnode-app/copy-of-vitnode-app/root/src/proxy.ts similarity index 100% rename from packages/create-vitnode-app/copy-of-vitnode-app/root/src/middleware.ts rename to packages/create-vitnode-app/copy-of-vitnode-app/root/src/proxy.ts diff --git a/packages/create-vitnode-app/package.json b/packages/create-vitnode-app/package.json index 5a3edb92b..6a8862627 100644 --- a/packages/create-vitnode-app/package.json +++ b/packages/create-vitnode-app/package.json @@ -1,6 +1,6 @@ { "name": "create-vitnode-app", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.59", "description": "Create a new VitNode app in seconds.", "author": "VitNode Team", "license": "MIT", @@ -28,18 +28,18 @@ "typescript" ], "dependencies": { - "@inquirer/prompts": "^7.8.6", - "commander": "^14.0.1", + "@inquirer/prompts": "^7.10.0", + "commander": "^14.0.2", "ora": "^9.0.0", "picocolors": "^1.1.1", - "validate-npm-package-name": "^6.0.2" + "validate-npm-package-name": "^7.0.0" }, "devDependencies": { - "@types/node": "^24.6.2", + "@types/node": "^24.10.0", "@types/prompts": "^2.4.9", "@types/validate-npm-package-name": "^4.0.2", "@vitnode/config": "workspace:*", - "eslint": "^9.36.0", + "eslint": "^9.39.1", "typescript": "^5.9.3" } } 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 0b6ec84b8..32d3097f3 100644 --- a/packages/create-vitnode-app/src/create/create-package-json.ts +++ b/packages/create-vitnode-app/src/create/create-package-json.ts @@ -28,42 +28,41 @@ const versions = { typesNode: "^24", typesReact: "^19.2", typesReactDom: "^19.2", - typesMdx: "^2.0.13", typesBun: "latest", - turbo: "^2.5.8", - typescript: "^5.9.3", + turbo: "^2.5", + typescript: "^5.9", tsx: "^4.20.6", tscAlias: "^1.8.16", - eslint: "^9.33.0", + eslint: "^9.39.1", prettier: "^3.6.2", prettierTailwind: "^0.6.14", - tailwind: "^4.1.14", - tailwindPostcss: "^4.1.14", + tailwind: "^4.1.17", + tailwindPostcss: "^4.1.17", postcss: "^8.5.6", twAnimateCss: "^1.4.0", react: "^19.2", reactDom: "^19.2", - nextSingle: "15.6.0-canary.41", + nextSingle: "^16.0.1", nextWebInMonorepo: "^15.4.6", - nextIntl: "^4.3.9", - useIntl: "^4.3.9", - rhf: "^7.63.0", + nextIntl: "^4.5.0", + useIntl: "^4.5.0", + rhf: "^7.66.0", rhfResolvers: "^5.1.1", - lucide: "^0.544.0", + lucide: "^0.553.0", sonner: "^2.0.7", dotenv: "^17.2.2", - drizzleKit: "^0.31.5", - drizzleOrm: "^0.44.6", + drizzleKit: "^0.31.6", + drizzleOrm: "^0.44.7", - hono: "^4.9.9", - honoZodOpenapi: "^1.1.3", - honoZodValidator: "^0.7.3", - reactEmail: "^4.2.12", - reactEmailComponents: "^0.5.5", - zod: "^4.1.11", + hono: "^4.10.4", + honoZodOpenapi: "^1.1.4", + honoZodValidator: "^0.7.4", + reactEmail: "^5.0.1", + reactEmailComponents: "^1.0.0", + zod: "^4.1.12", cva: "^0.7.1", }; @@ -89,7 +88,10 @@ const rootScripts = ( dev: "turbo dev", build: "turbo build", start: "turbo start", - ...withIf(enableEslint, eslintScripts), + ...withIf(enableEslint, { + lint: "turbo lint", + "lint:fix": "turbo lint:fix", + }), ...withIf(enableDocker, { "docker:dev": dockerDevScript(appName) }), }); @@ -125,7 +127,7 @@ const singleAppScripts = ( ) => ({ "db:migrate": "vitnode migrate", init: "vitnode init", - dev: "vitnode init && next dev --turbopack", + dev: "vitnode init && next dev", "dev:email": "email dev --dir src/emails", build: "next build", start: "next start", @@ -136,7 +138,7 @@ const singleAppScripts = ( const webScripts = (eslint: boolean) => ({ init: "vitnode init --web", - dev: "vitnode init --web && next dev --turbopack", + dev: "vitnode init --web && next dev", build: "next build", start: "next start", ...withIf(eslint, eslintScripts), @@ -180,7 +182,7 @@ const apiDeps = { }; const apiDevDeps = (pm: string, eslint: boolean) => ({ - "@hono/node-server": "^1.19.5", + "@hono/node-server": "^1.19", ...(pm === "bun" ? { "@types/bun": versions.typesBun } : {}), "@types/node": versions.typesNode, "@types/react": versions.typesReact, @@ -249,7 +251,6 @@ const webDeps = { const webDevDeps = (eslint: boolean) => ({ "@hookform/resolvers": versions.rhfResolvers, "@tailwindcss/postcss": versions.tailwindPostcss, - "@types/mdx": versions.typesMdx, "@types/node": versions.typesNode, "@types/react": versions.typesReact, "@types/react-dom": versions.typesReactDom, diff --git a/packages/create-vitnode-app/src/create/create-vitnode.ts b/packages/create-vitnode-app/src/create/create-vitnode.ts index 75103353b..06612c1f5 100644 --- a/packages/create-vitnode-app/src/create/create-vitnode.ts +++ b/packages/create-vitnode-app/src/create/create-vitnode.ts @@ -125,15 +125,27 @@ export const createVitNode = async ({ } } - if (mode === "apiMonorepo" || monorepo) { + if (mode === "apiMonorepo" || (monorepo && mode !== "singleApp")) { await cp(join(templatePath, "monorepo"), root, { recursive: true, }); + } else if (monorepo && mode === "singleApp") { + // Copy only the necessary monorepo files, excluding the api folder + await copyFile( + join(templatePath, "monorepo", "turbo.json"), + join(root, "turbo.json"), + ); + await copyFile( + join(templatePath, "monorepo", ".gitignore_template"), + join(root, ".gitignore_template"), + ); } if (eslint) { spinner.text = "Copying ESLint & Prettier files..."; - await cp(join(templatePath, "eslint"), root, { + const eslintTarget = + monorepo && mode === "singleApp" ? monorepoStructure.web : root; + await cp(join(templatePath, "eslint"), eslintTarget, { recursive: true, }); } diff --git a/packages/create-vitnode-app/src/helpers/get-package-manager-from-root.ts b/packages/create-vitnode-app/src/helpers/get-package-manager-from-root.ts new file mode 100644 index 000000000..172ec87ae --- /dev/null +++ b/packages/create-vitnode-app/src/helpers/get-package-manager-from-root.ts @@ -0,0 +1,22 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +import type { PackageJSON } from "./packages-json.js"; + +export const getPackageManagerFromRoot = (rootPath: string): string => { + try { + const packageJsonPath = join(rootPath, "package.json"); + const packageJson: PackageJSON = JSON.parse( + readFileSync(packageJsonPath, "utf-8"), + ); + + if (packageJson.packageManager) { + // Extract package manager name from "pnpm@10.18.3" -> "pnpm" + return packageJson.packageManager.split("@")[0]; + } + + return "npm"; + } catch { + return "npm"; + } +}; diff --git a/packages/create-vitnode-app/src/index.ts b/packages/create-vitnode-app/src/index.ts index f710ab19e..2e49b5a74 100644 --- a/packages/create-vitnode-app/src/index.ts +++ b/packages/create-vitnode-app/src/index.ts @@ -54,7 +54,6 @@ const init = async () => { "--skip-install", "Skip installing packages after initializing the project.", ); - program.option("--plugin", "Enable plugin mode."); program.addOption( new Option( "--mode ", @@ -63,12 +62,13 @@ const init = async () => { ); program.option("--monorepo", "Create project with monorepo structure."); program.option("--docker", "Initialize with Docker support."); + program.option("--plugin", "Create a plugin."); program.parse(process.argv); const opts = program.opts(); if (opts.plugin) { - await createPlugin(projectPath); + await createPlugin({ projectPath, program }); return; } diff --git a/packages/create-vitnode-app/src/plugin/create/create-plugin-vitnode.ts b/packages/create-vitnode-app/src/plugin/create/create-plugin-vitnode.ts new file mode 100644 index 000000000..89dc3f3b5 --- /dev/null +++ b/packages/create-vitnode-app/src/plugin/create/create-plugin-vitnode.ts @@ -0,0 +1,68 @@ +import { existsSync } from "fs"; +import { mkdir } from "fs/promises"; +import ora from "ora"; +import { dirname, join } from "path"; +import color from "picocolors"; +import { fileURLToPath } from "url"; + +import type { CreatePluginCliReturn } from "../questions.js"; + +import { getPackageManagerFromRoot } from "../../helpers/get-package-manager-from-root.js"; +import { installDependencies } from "../../helpers/install-dependencies.js"; +import { isFolderEmpty } from "../../helpers/is-folder-empty.js"; + +export const createPluginVitNode = async ({ + pluginPath, + pluginName, + install, + root, +}: CreatePluginCliReturn & { + pluginName: string; + pluginPath: string; + root: string; +}) => { + const packageManager = getPackageManagerFromRoot(process.cwd()); + + const spinner = ora( + `Creating a new VitNode plugin in ${color.green(pluginPath)}. Using ${color.green(packageManager)}...`, + ).start(); + + const __filename = fileURLToPath(import.meta.url); + const __dirname = dirname(__filename); + const templatePath = join( + __dirname, + "..", + "..", + "..", + "copy-of-vitnode-plugin", + ); + if (!existsSync(templatePath)) { + spinner.fail( + `\n${color.red("Error!")} Template path ${color.cyan(templatePath)} does not exist.`, + ); + process.exit(1); + } + + // Create the folder for the plugin + await mkdir(pluginPath, { recursive: true }); + if (!isFolderEmpty(pluginPath, pluginName)) { + process.exit(1); + } + + spinner.text = "Preparing the plugin structure..."; + + spinner.text = "Creating package.json..."; + // Create package.json for the plugin + + if (install) { + spinner.text = "Installing dependencies..."; + await installDependencies({ + packageManager, + cwd: root, + }); + } + + spinner.succeed( + `${color.green("Success!")} Created ${color.cyan(pluginName)} at ${color.cyan(pluginPath)}`, + ); +}; diff --git a/packages/create-vitnode-app/src/plugin/index.ts b/packages/create-vitnode-app/src/plugin/index.ts index 952c5ed74..3651c606a 100644 --- a/packages/create-vitnode-app/src/plugin/index.ts +++ b/packages/create-vitnode-app/src/plugin/index.ts @@ -1,9 +1,20 @@ +import type { Command } from "commander"; + import { input } from "@inquirer/prompts"; import { basename, resolve } from "node:path"; import { validateNpmName } from "../helpers/validate-pkg.js"; +import { createPluginVitNode } from "./create/create-plugin-vitnode.js"; +import { createPluginQuestionsCli } from "./questions.js"; +import { validationProjectForPlugin } from "./validation.js"; -export const createPlugin = async (projectPath: string) => { +export const createPlugin = async ({ + program, + projectPath, +}: { + program: Command; + projectPath: string; +}) => { let name = projectPath; if (!name) { name = await input({ @@ -13,10 +24,17 @@ export const createPlugin = async (projectPath: string) => { const validation = validateNpmName({ name: basename(resolve(name)) }); if (validation.valid) return true; - console.log(validation.problems); - return `Invalid plugin name: ${validation.problems[0]}`; }, }); } + + const { pluginName, pluginPath } = await validationProjectForPlugin(name); + const options = await createPluginQuestionsCli(program); + await createPluginVitNode({ + pluginName, + pluginPath, + root: projectPath, + ...options, + }); }; diff --git a/packages/create-vitnode-app/src/plugin/questions.ts b/packages/create-vitnode-app/src/plugin/questions.ts new file mode 100644 index 000000000..9865a289d --- /dev/null +++ b/packages/create-vitnode-app/src/plugin/questions.ts @@ -0,0 +1,26 @@ +import type { Command } from "commander"; + +import { confirm } from "@inquirer/prompts"; +import color from "picocolors"; + +export interface CreatePluginCliReturn { + install: boolean; +} + +export const createPluginQuestionsCli = async ( + program: Command, +): Promise => { + const optionsFromProgram = program.opts(); + + const options: CreatePluginCliReturn = { + install: !optionsFromProgram.skipInstall, + }; + + if (optionsFromProgram.skipInstall === undefined) { + options.install = await confirm({ + message: `Would you like to ${color.blue("Install dependencies")}?`, + }); + } + + return options; +}; diff --git a/packages/create-vitnode-app/src/plugin/validation.ts b/packages/create-vitnode-app/src/plugin/validation.ts new file mode 100644 index 000000000..479faa44f --- /dev/null +++ b/packages/create-vitnode-app/src/plugin/validation.ts @@ -0,0 +1,128 @@ +import { program } from "commander"; +import { existsSync } from "node:fs"; +import { mkdir, readFile } from "node:fs/promises"; +import { basename, join, resolve } from "node:path"; +import color from "picocolors"; + +import type { PackageJSON } from "../helpers/packages-json.js"; + +import { isFolderEmpty } from "../helpers/is-folder-empty.js"; +import { isWriteable } from "../helpers/is-writeable.js"; +import { validateNpmName } from "../helpers/validate-pkg.js"; + +export const validationProjectForPlugin = async (projectPath: string) => { + // Verify the project path is provided + if (!projectPath) { + console.log( + "\nPlease specify the plugin directory:\n" + + ` ${color.cyan(program.name())} ${color.green("")}\n` + + "For example:\n" + + ` ${color.cyan(program.name())} ${color.green("my-vitnode-plugin")}\n\n` + + `Run ${color.cyan(`${program.name()} --help`)} to see all options.`, + ); + process.exit(1); + } + + // Verify we're in a monorepo with turbo.json and package.json + const cwd = process.cwd(); + const turboJsonPath = join(cwd, "turbo.json"); + const packageJsonPath = join(cwd, "package.json"); + + // Check if turbo.json exists + if (!existsSync(turboJsonPath)) { + console.error( + `${color.red("Error:")} Could not find ${color.cyan("turbo.json")} in the current directory.`, + ); + console.error( + `Plugins must be created inside a VitNode monorepo structure.`, + ); + console.error( + `\nPlease run this command from the root of your VitNode monorepo project.`, + ); + process.exit(1); + } + + // Check if package.json exists and has packageManager defined + if (!existsSync(packageJsonPath)) { + console.error( + `${color.red("Error:")} Could not find ${color.cyan("package.json")} in the current directory.`, + ); + console.error( + `\nPlease run this command from the root of your VitNode monorepo project.`, + ); + process.exit(1); + } + + try { + const packageJson: PackageJSON = JSON.parse( + await readFile(packageJsonPath, "utf-8"), + ); + + if (!packageJson.packageManager) { + console.error( + `${color.red("Error:")} The ${color.cyan("packageManager")} field is not defined in ${color.cyan("package.json")}.`, + ); + console.error( + `\nPlease add a ${color.cyan('"packageManager"')} field to your ${color.cyan("package.json")} file.`, + ); + console.error( + `Example: ${color.green('"packageManager": "pnpm@10.18.3"')}`, + ); + process.exit(1); + } + } catch (error) { + console.error( + `${color.red("Error:")} Failed to read or parse ${color.cyan("package.json")}.`, + ); + console.error(error); + process.exit(1); + } + + // Verify the project name is valid + const projectName = basename(resolve(projectPath)); + const validation = validateNpmName({ name: projectName }); + if (!validation.valid) { + console.error( + `Could not create a plugin called ${color.red( + `"${projectName}"`, + )} because of npm naming restrictions:`, + ); + + validation.problems.forEach(p => { + console.error(`${color.red(color.bold("*"))} ${p}`); + }); + process.exit(1); + } + + // Create plugin path inside plugins folder + const pluginsDir = join(cwd, "plugins"); + const pluginPath = join(pluginsDir, projectName); + const pluginName = basename(pluginPath); + + // Verify the plugin dir is empty or doesn't exist + const folderExists = existsSync(pluginPath); + if (folderExists && !isFolderEmpty(pluginPath, pluginName)) { + console.error( + `The directory ${color.cyan(`plugins/${pluginName}`)} is not empty.`, + ); + process.exit(1); + } + + // Check that plugins directory exists + if (!existsSync(pluginsDir)) { + await mkdir(pluginsDir, { recursive: true }); + } + + // Verify the plugins dir is writeable + if (!(await isWriteable(pluginsDir))) { + console.error( + `The plugins directory is not writable, please check folder permissions and try again.`, + ); + console.error( + `It is likely you do not have write permissions for this folder.`, + ); + process.exit(1); + } + + return { pluginName, pluginPath }; +}; diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index 1b7bb44a1..1d1462963 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/core", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.59", "description": "Core package for VitNode, providing essential functionalities and configurations.", "author": "VitNode Team", "license": "MIT", @@ -28,56 +28,56 @@ "drizzle-orm": "^0.44.x", "hono": "^4.9.x", "motion": "^12.x.x", - "next": "^15.5.x", + "next": "^16.0.x", "next-intl": "^4.x.x", - "react": "^19.1.x", - "react-dom": "^19.1.x", + "react": "^19.2.x", + "react-dom": "^19.2.x", "react-hook-form": "^7.x.x", "typescript": "^5.9.x", "zod": "^4.x.x" }, "devDependencies": { - "@hono/zod-openapi": "^1.1.3", - "@hono/zod-validator": "^0.7.3", + "@hono/zod-openapi": "^1.1.4", + "@hono/zod-validator": "^0.7.4", "@hookform/resolvers": "^5.2.2", - "@react-email/components": "^0.5.5", + "@react-email/components": "^1.0.0", "@swc/cli": "0.6.0", "@swc/core": "^1.13.5", "@testing-library/dom": "^10.4.1", "@testing-library/react": "^16.3.0", - "@types/node": "^24.6.2", - "@types/nodemailer": "^7.0.2", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^5.0.4", - "@vitest/coverage-v8": "^3.2.4", + "@types/node": "^24.10.0", + "@types/nodemailer": "^7.0.3", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@vitejs/plugin-react": "^5.1.0", + "@vitest/coverage-v8": "^4.0.8", "@vitnode/config": "workspace:*", "chokidar": "^4.0.3", "concurrently": "^9.2.1", "dotenv": "^17.2.3", - "drizzle-kit": "^0.31.5", - "drizzle-orm": "^0.44.6", - "eslint": "^9.36.0", - "hono": "^4.9.9", - "jsdom": "^26.1.0", - "lucide-react": "^0.544.0", - "next": "15.6.0-canary.41", - "next-intl": "^4.3.9", + "drizzle-kit": "^0.31.6", + "drizzle-orm": "^0.44.7", + "eslint": "^9.39.1", + "hono": "^4.10.4", + "jsdom": "^27.1.0", + "lucide-react": "^0.553.0", + "next": "^16.0.1", + "next-intl": "^4.5.0", "node-cron": "^4.2.1", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-email": "^4.2.12", - "react-hook-form": "^7.63.0", + "react-email": "^5.0.1", + "react-hook-form": "^7.66.0", "sonner": "^2.0.7", - "tailwindcss": "^4.1.14", + "tailwindcss": "^4.1.17", "tsc-alias": "^1.8.16", "tsup": "^8.5.0", "tsx": "^4.20.6", "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.2.4", - "zod": "^4.1.11" + "vitest": "^4.0.8", + "zod": "^4.1.12" }, "bin": { "vitnode": "./dist/scripts/scripts.js" @@ -113,28 +113,28 @@ "dependencies": { "@dnd-kit/core": "^6.3.1", "@hono/swagger-ui": "^0.5.2", - "@react-email/preview-server": "^4.2.12", - "@tanstack/react-query": "^5.90.2", - "@tiptap/extension-text-align": "^3.6.5", - "@tiptap/pm": "^3.6.5", - "@tiptap/react": "^3.6.5", - "@tiptap/starter-kit": "^3.6.5", + "@react-email/preview-server": "^5.0.1", + "@tanstack/react-query": "^5.90.7", + "@tiptap/extension-text-align": "^3.10.4", + "@tiptap/pm": "^3.10.4", + "@tiptap/react": "^3.10.4", + "@tiptap/starter-kit": "^3.10.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "cron-parser": "^5.4.0", "input-otp": "^1.4.2", - "motion": "^12.23.22", + "motion": "^12.23.24", "next-themes": "^0.4.6", - "nodemailer": "^7.0.6", + "nodemailer": "^7.0.10", "postgres": "^3.4.7", "radix-ui": "^1.4.3", - "rate-limiter-flexible": "^8.0.1", + "rate-limiter-flexible": "^8.2.0", "react-scan": "^0.4.3", - "resend": "^6.1.2", - "tailwind-merge": "^3.3.1", + "resend": "^6.4.2", + "tailwind-merge": "^3.4.0", "use-debounce": "^10.0.6", - "use-intl": "^4.3.9", + "use-intl": "^4.5.0", "vaul": "^1.1.2" } } diff --git a/packages/vitnode/src/api/middlewares/global.middleware.ts b/packages/vitnode/src/api/middlewares/global.middleware.ts index 0c9748b6f..981300229 100644 --- a/packages/vitnode/src/api/middlewares/global.middleware.ts +++ b/packages/vitnode/src/api/middlewares/global.middleware.ts @@ -146,7 +146,7 @@ export const globalMiddleware = ({ ipAddress = c.req.header(key); if (ipAddress) break; - ipAddress = c.req.raw.headers.get(key); + ipAddress = c.req.raw.headers.get(key) ?? undefined; if (ipAddress) break; } diff --git a/packages/vitnode/src/api/modules/cron/helpers/process-cron-jobs.ts b/packages/vitnode/src/api/modules/cron/helpers/process-cron-jobs.ts index ff19a8796..6d2ef8ffd 100644 --- a/packages/vitnode/src/api/modules/cron/helpers/process-cron-jobs.ts +++ b/packages/vitnode/src/api/modules/cron/helpers/process-cron-jobs.ts @@ -1,4 +1,4 @@ -import type { PostgresJsDatabase } from "drizzle-orm/postgres-js"; +import type { drizzle } from "drizzle-orm/postgres-js"; import { eq, inArray } from "drizzle-orm"; import { validate } from "node-cron"; @@ -36,7 +36,7 @@ function getJobChanges( } export async function cleanupOutdatedCronJobs( - db: PostgresJsDatabase, + db: ReturnType, cronFromDb: CronJobFromDb[], currentCronJobs: CronJobConfig[], ) { @@ -111,7 +111,7 @@ export function processCronJobs( } export async function updateCronJobs( - db: PostgresJsDatabase, + db: ReturnType, jobsToUpdate: { changes: { description?: boolean; schedule?: boolean }; existingJob: CronJobFromDb; diff --git a/packages/vitnode/src/components/form/auto-form.tsx b/packages/vitnode/src/components/form/auto-form.tsx index feef41a60..06bd2c57b 100644 --- a/packages/vitnode/src/components/form/auto-form.tsx +++ b/packages/vitnode/src/components/form/auto-form.tsx @@ -142,7 +142,7 @@ export function AutoForm< return (
{item.label && ( - + {item.label} )} diff --git a/packages/vitnode/src/components/form/fields/checkbox.tsx b/packages/vitnode/src/components/form/fields/checkbox.tsx index 3d0a1c7f2..0c96090dd 100644 --- a/packages/vitnode/src/components/form/fields/checkbox.tsx +++ b/packages/vitnode/src/components/form/fields/checkbox.tsx @@ -15,7 +15,7 @@ export const AutoFormCheckbox = ({ }: ItemAutoFormComponentProps & Omit, "checked">) => { return ( - + {values.map(({ value, label }) => ( diff --git a/packages/vitnode/src/components/switchers/themes/theme-switcher.tsx b/packages/vitnode/src/components/switchers/themes/theme-switcher.tsx index 5c5429445..ffcc4140c 100644 --- a/packages/vitnode/src/components/switchers/themes/theme-switcher.tsx +++ b/packages/vitnode/src/components/switchers/themes/theme-switcher.tsx @@ -21,8 +21,8 @@ export const ThemeSwitcher = () => { size="icon" variant="ghost" > - - + + ); }; diff --git a/packages/vitnode/src/components/table/content.tsx b/packages/vitnode/src/components/table/content.tsx index b5464fa67..8deed95cb 100644 --- a/packages/vitnode/src/components/table/content.tsx +++ b/packages/vitnode/src/components/table/content.tsx @@ -77,7 +77,7 @@ export function ContentDataTable({ ) : ( {customNotFoundComponent ?? ( diff --git a/packages/vitnode/src/components/ui/accordion.tsx b/packages/vitnode/src/components/ui/accordion.tsx index 0fe9d3dcd..87172e9d7 100644 --- a/packages/vitnode/src/components/ui/accordion.tsx +++ b/packages/vitnode/src/components/ui/accordion.tsx @@ -35,7 +35,7 @@ function AccordionTrigger({ svg]:rotate-180", + "focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180", className, )} data-slot="accordion-trigger" @@ -59,7 +59,7 @@ function AccordionContent({ data-slot="accordion-content" {...props} > -
{children}
+
{children}
); } diff --git a/packages/vitnode/src/components/ui/alert-dialog.tsx b/packages/vitnode/src/components/ui/alert-dialog.tsx index cc0109eb2..29f58ff92 100644 --- a/packages/vitnode/src/components/ui/alert-dialog.tsx +++ b/packages/vitnode/src/components/ui/alert-dialog.tsx @@ -85,7 +85,7 @@ function AlertDialogContent({ ) { return (
) { function CardTitle({ className, ...props }: React.ComponentProps<"div">) { return (
@@ -74,7 +74,7 @@ function CardContent({ className, ...props }: React.ComponentProps<"div">) { function CardFooter({ className, ...props }: React.ComponentProps<"div">) { return (
diff --git a/packages/vitnode/src/components/ui/checkbox.tsx b/packages/vitnode/src/components/ui/checkbox.tsx index e30a700ae..e57fb25a4 100644 --- a/packages/vitnode/src/components/ui/checkbox.tsx +++ b/packages/vitnode/src/components/ui/checkbox.tsx @@ -14,7 +14,7 @@ function Checkbox({ return ( - + {children} @@ -73,7 +73,7 @@ function CommandInput({ { if (isDirty) { @@ -240,7 +240,7 @@ function DialogTitle({ }: React.ComponentProps) { return ( diff --git a/packages/vitnode/src/components/ui/dropdown-menu.tsx b/packages/vitnode/src/components/ui/dropdown-menu.tsx index d389303cd..78b8e7705 100644 --- a/packages/vitnode/src/components/ui/dropdown-menu.tsx +++ b/packages/vitnode/src/components/ui/dropdown-menu.tsx @@ -41,7 +41,7 @@ function DropdownMenuContent({ ) { return ( - + ); diff --git a/packages/vitnode/src/components/ui/scroll-area.tsx b/packages/vitnode/src/components/ui/scroll-area.tsx index 97a2b01b8..952f12aea 100644 --- a/packages/vitnode/src/components/ui/scroll-area.tsx +++ b/packages/vitnode/src/components/ui/scroll-area.tsx @@ -18,7 +18,7 @@ function ScrollArea({ {...props} > {children} @@ -37,7 +37,7 @@ function ScrollBar({ return ( {children} - + Close diff --git a/packages/vitnode/src/components/ui/sidebar.tsx b/packages/vitnode/src/components/ui/sidebar.tsx index 71cceebd4..f35d9e21f 100644 --- a/packages/vitnode/src/components/ui/sidebar.tsx +++ b/packages/vitnode/src/components/ui/sidebar.tsx @@ -172,7 +172,7 @@ function Sidebar({ return (