From 243f170e094102b499d0b109c76a48e6758b04f1 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 06:45:34 +0100 Subject: [PATCH 1/8] feat(cli): Add validation for create plugin --- .github/workflows/build-lint-test.yml | 2 +- .github/workflows/bump_publish.yml | 4 +- apps/docs/content/docs/dev/plugins.mdx | 6 +- package.json | 4 +- packages/create-vitnode-app/README.md | 11 ++ .../helpers/get-package-manager-from-root.ts | 22 ++++ packages/create-vitnode-app/src/index.ts | 4 +- .../plugin/create/create-plugin-vitnode.ts | 68 ++++++++++ .../create-vitnode-app/src/plugin/index.ts | 18 ++- .../src/plugin/questions.ts | 26 ++++ .../src/plugin/validation.ts | 122 ++++++++++++++++++ .../modules/cron/helpers/process-cron-jobs.ts | 6 +- packages/vitnode/src/components/ui/button.tsx | 2 +- .../vitnode/src/components/ui/command.tsx | 2 +- .../src/components/ui/context-menu.tsx | 8 +- packages/vitnode/src/components/ui/dialog.tsx | 2 +- .../src/components/ui/dropdown-menu.tsx | 6 +- .../vitnode/src/components/ui/menubar.tsx | 6 +- .../src/components/ui/navigation-menu.tsx | 2 +- packages/vitnode/src/components/ui/select.tsx | 4 +- packages/vitnode/src/components/ui/tabs.tsx | 2 +- packages/vitnode/src/components/ui/toggle.tsx | 2 +- packages/vitnode/src/vitnode.config.ts | 5 +- scripts/{ => bump-version}/bump-version.ts | 2 +- scripts/{ => bump-version}/environment.ts | 0 .../files/file-copy-manager.ts | 0 .../{ => bump-version}/files/file-system.ts | 0 scripts/{ => bump-version}/version-manager.ts | 0 28 files changed, 299 insertions(+), 37 deletions(-) create mode 100644 packages/create-vitnode-app/src/helpers/get-package-manager-from-root.ts create mode 100644 packages/create-vitnode-app/src/plugin/create/create-plugin-vitnode.ts create mode 100644 packages/create-vitnode-app/src/plugin/questions.ts create mode 100644 packages/create-vitnode-app/src/plugin/validation.ts rename scripts/{ => bump-version}/bump-version.ts (97%) rename scripts/{ => bump-version}/environment.ts (100%) rename scripts/{ => bump-version}/files/file-copy-manager.ts (100%) rename scripts/{ => bump-version}/files/file-system.ts (100%) rename scripts/{ => bump-version}/version-manager.ts (100%) 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/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/package.json b/package.json index 3a088959b..9e2f1ed74 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", @@ -29,7 +29,7 @@ "engines": { "node": ">=22" }, - "packageManager": "pnpm@10.18.0", + "packageManager": "pnpm@10.18.3", "workspaces": [ "apps/*", "packages/*", 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/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..3940d495f 100644 --- a/packages/create-vitnode-app/src/plugin/index.ts +++ b/packages/create-vitnode-app/src/plugin/index.ts @@ -1,9 +1,19 @@ +import type { Command } from "commander"; + import { input } from "@inquirer/prompts"; import { basename, resolve } from "node:path"; import { validateNpmName } from "../helpers/validate-pkg.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 +23,12 @@ 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); }; 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..dd3f7f10d --- /dev/null +++ b/packages/create-vitnode-app/src/plugin/validation.ts @@ -0,0 +1,122 @@ +import { program } from "commander"; +import { existsSync, readFileSync } from "node:fs"; +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( + readFileSync(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); + } + + // 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/src/api/modules/cron/helpers/process-cron-jobs.ts b/packages/vitnode/src/api/modules/cron/helpers/process-cron-jobs.ts index 0a5ed6613..de25a9da3 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, PostgresJsDatabase } from "drizzle-orm/postgres-js"; import { eq, inArray } from "drizzle-orm"; import { validate } from "node-cron"; @@ -48,7 +48,7 @@ function getJobChanges( } export async function cleanupOutdatedCronJobs( - db: PostgresJsDatabase, + db: ReturnType, cronFromDb: CronJobFromDb[], currentCronJobs: CronJobConfig[], ) { @@ -113,7 +113,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/ui/button.tsx b/packages/vitnode/src/components/ui/button.tsx index 54c2ff5ee..a566638bc 100644 --- a/packages/vitnode/src/components/ui/button.tsx +++ b/packages/vitnode/src/components/ui/button.tsx @@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { ClientButton } from "./button-client"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer overflow-hidden active:scale-[0.98] select-none", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer overflow-hidden active:scale-[0.98] select-none", { variants: { variant: { diff --git a/packages/vitnode/src/components/ui/command.tsx b/packages/vitnode/src/components/ui/command.tsx index e48e11cdb..1b2eca8d5 100644 --- a/packages/vitnode/src/components/ui/command.tsx +++ b/packages/vitnode/src/components/ui/command.tsx @@ -147,7 +147,7 @@ function CommandItem({ return ( { if (isDirty) { diff --git a/packages/vitnode/src/components/ui/dropdown-menu.tsx b/packages/vitnode/src/components/ui/dropdown-menu.tsx index d389303cd..1ed2e5fce 100644 --- a/packages/vitnode/src/components/ui/dropdown-menu.tsx +++ b/packages/vitnode/src/components/ui/dropdown-menu.tsx @@ -72,7 +72,7 @@ function DropdownMenuItem({ return ( ; email?: { adapter?: EmailApiPlugin; logo?: DefaultTemplateEmailProps["templateProps"]["logo"]; diff --git a/scripts/bump-version.ts b/scripts/bump-version/bump-version.ts similarity index 97% rename from scripts/bump-version.ts rename to scripts/bump-version/bump-version.ts index 15c098613..d016328d0 100644 --- a/scripts/bump-version.ts +++ b/scripts/bump-version/bump-version.ts @@ -24,7 +24,7 @@ async function main(): Promise { console.log("✔ Process completed successfully! 🎉"); } -main().catch((error) => { +main().catch(error => { console.error("❌ Process failed:", error); process.exit(1); }); diff --git a/scripts/environment.ts b/scripts/bump-version/environment.ts similarity index 100% rename from scripts/environment.ts rename to scripts/bump-version/environment.ts diff --git a/scripts/files/file-copy-manager.ts b/scripts/bump-version/files/file-copy-manager.ts similarity index 100% rename from scripts/files/file-copy-manager.ts rename to scripts/bump-version/files/file-copy-manager.ts diff --git a/scripts/files/file-system.ts b/scripts/bump-version/files/file-system.ts similarity index 100% rename from scripts/files/file-system.ts rename to scripts/bump-version/files/file-system.ts diff --git a/scripts/version-manager.ts b/scripts/bump-version/version-manager.ts similarity index 100% rename from scripts/version-manager.ts rename to scripts/bump-version/version-manager.ts From acf38b0145b8c102beb211c76f2c0b3083663b22 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 05:49:52 +0000 Subject: [PATCH 2/8] ci: version bump to v1.2.0-canary.57 --- apps/api/package.json | 2 +- apps/docs/package.json | 2 +- packages/config/package.json | 2 +- packages/create-vitnode-app/package.json | 2 +- packages/vitnode/package.json | 2 +- plugins/blog/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/api/package.json b/apps/api/package.json index 51bfb03bf..62b809b87 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.57", "private": true, "type": "module", "scripts": { diff --git a/apps/docs/package.json b/apps/docs/package.json index b4448ff89..fe4a9629f 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,6 +1,6 @@ { "name": "docs", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.57", "type": "module", "private": true, "scripts": { diff --git a/packages/config/package.json b/packages/config/package.json index b0630cab5..bd3ce40fe 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.57", "description": "ESLint, Prettier, TypeScript (TSConfig) config for VitNode", "author": "VitNode Team", "license": "MIT", diff --git a/packages/create-vitnode-app/package.json b/packages/create-vitnode-app/package.json index 5a3edb92b..8c4f923df 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.57", "description": "Create a new VitNode app in seconds.", "author": "VitNode Team", "license": "MIT", diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index 1b7bb44a1..424111a39 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.57", "description": "Core package for VitNode, providing essential functionalities and configurations.", "author": "VitNode Team", "license": "MIT", diff --git a/plugins/blog/package.json b/plugins/blog/package.json index 6445a974e..832db6489 100644 --- a/plugins/blog/package.json +++ b/plugins/blog/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/blog", - "version": "1.2.0-canary.56", + "version": "1.2.0-canary.57", "description": "Blog plugin for VitNode, providing a blogging platform with Next.js and Hono.js.", "author": "VitNode Team", "license": "MIT", From f8c9de16825421ddb76f5d2e1cd27208edd6be1a Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 07:02:33 +0100 Subject: [PATCH 3/8] =?UTF-8?q?perf(cli=5Fplugin):=20=E2=9C=A8=20Enhance?= =?UTF-8?q?=20monorepo=20handling=20and=20improve=20validation=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../create-vitnode-app/src/create/create-vitnode.ts | 12 +++++++++++- packages/create-vitnode-app/src/plugin/validation.ts | 10 ++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/create-vitnode-app/src/create/create-vitnode.ts b/packages/create-vitnode-app/src/create/create-vitnode.ts index 75103353b..5a80f5cfa 100644 --- a/packages/create-vitnode-app/src/create/create-vitnode.ts +++ b/packages/create-vitnode-app/src/create/create-vitnode.ts @@ -125,10 +125,20 @@ 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) { diff --git a/packages/create-vitnode-app/src/plugin/validation.ts b/packages/create-vitnode-app/src/plugin/validation.ts index dd3f7f10d..479faa44f 100644 --- a/packages/create-vitnode-app/src/plugin/validation.ts +++ b/packages/create-vitnode-app/src/plugin/validation.ts @@ -1,5 +1,6 @@ import { program } from "commander"; -import { existsSync, readFileSync } from "node:fs"; +import { existsSync } from "node:fs"; +import { mkdir, readFile } from "node:fs/promises"; import { basename, join, resolve } from "node:path"; import color from "picocolors"; @@ -54,7 +55,7 @@ export const validationProjectForPlugin = async (projectPath: string) => { try { const packageJson: PackageJSON = JSON.parse( - readFileSync(packageJsonPath, "utf-8"), + await readFile(packageJsonPath, "utf-8"), ); if (!packageJson.packageManager) { @@ -107,6 +108,11 @@ export const validationProjectForPlugin = async (projectPath: string) => { 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( From 464fce01b0dc4c0e78c28d27fb00ee70d5fd901c Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 06:03:59 +0000 Subject: [PATCH 4/8] ci: version bump to v1.2.0-canary.58 --- apps/api/package.json | 2 +- apps/docs/package.json | 2 +- packages/config/package.json | 2 +- packages/create-vitnode-app/package.json | 2 +- packages/vitnode/package.json | 2 +- plugins/blog/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/api/package.json b/apps/api/package.json index 62b809b87..5b54eae75 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "api", - "version": "1.2.0-canary.57", + "version": "1.2.0-canary.58", "private": true, "type": "module", "scripts": { diff --git a/apps/docs/package.json b/apps/docs/package.json index fe4a9629f..b792f4947 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,6 +1,6 @@ { "name": "docs", - "version": "1.2.0-canary.57", + "version": "1.2.0-canary.58", "type": "module", "private": true, "scripts": { diff --git a/packages/config/package.json b/packages/config/package.json index bd3ce40fe..0cef525bc 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/config", - "version": "1.2.0-canary.57", + "version": "1.2.0-canary.58", "description": "ESLint, Prettier, TypeScript (TSConfig) config for VitNode", "author": "VitNode Team", "license": "MIT", diff --git a/packages/create-vitnode-app/package.json b/packages/create-vitnode-app/package.json index 8c4f923df..17c09f260 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.57", + "version": "1.2.0-canary.58", "description": "Create a new VitNode app in seconds.", "author": "VitNode Team", "license": "MIT", diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index 424111a39..eae49db76 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/core", - "version": "1.2.0-canary.57", + "version": "1.2.0-canary.58", "description": "Core package for VitNode, providing essential functionalities and configurations.", "author": "VitNode Team", "license": "MIT", diff --git a/plugins/blog/package.json b/plugins/blog/package.json index 832db6489..ec33993e8 100644 --- a/plugins/blog/package.json +++ b/plugins/blog/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/blog", - "version": "1.2.0-canary.57", + "version": "1.2.0-canary.58", "description": "Blog plugin for VitNode, providing a blogging platform with Next.js and Hono.js.", "author": "VitNode Team", "license": "MIT", From 5bd0026950dbe27a3a7506978c88ef8484794445 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 07:13:20 +0100 Subject: [PATCH 5/8] =?UTF-8?q?feat(create-plugin):=20=E2=9C=A8=20Improve?= =?UTF-8?q?=20ESLint=20support=20and=20improve=20plugin=20creation=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../create-vitnode-app/src/create/create-package-json.ts | 5 ++++- packages/create-vitnode-app/src/create/create-vitnode.ts | 4 +++- packages/create-vitnode-app/src/plugin/index.ts | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) 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..6079f1d5e 100644 --- a/packages/create-vitnode-app/src/create/create-package-json.ts +++ b/packages/create-vitnode-app/src/create/create-package-json.ts @@ -89,7 +89,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) }), }); diff --git a/packages/create-vitnode-app/src/create/create-vitnode.ts b/packages/create-vitnode-app/src/create/create-vitnode.ts index 5a80f5cfa..06612c1f5 100644 --- a/packages/create-vitnode-app/src/create/create-vitnode.ts +++ b/packages/create-vitnode-app/src/create/create-vitnode.ts @@ -143,7 +143,9 @@ export const createVitNode = async ({ 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/plugin/index.ts b/packages/create-vitnode-app/src/plugin/index.ts index 3940d495f..f5d8a2d2f 100644 --- a/packages/create-vitnode-app/src/plugin/index.ts +++ b/packages/create-vitnode-app/src/plugin/index.ts @@ -6,6 +6,7 @@ import { basename, resolve } from "node:path"; import { validateNpmName } from "../helpers/validate-pkg.js"; import { createPluginQuestionsCli } from "./questions.js"; import { validationProjectForPlugin } from "./validation.js"; +import { createPluginVitNode } from "./create/create-plugin-vitnode.js"; export const createPlugin = async ({ program, @@ -29,6 +30,11 @@ export const createPlugin = async ({ } const { pluginName, pluginPath } = await validationProjectForPlugin(name); - const options = await createPluginQuestionsCli(program); + await createPluginVitNode({ + pluginName, + pluginPath, + root: projectPath, + ...options, + }); }; From 14b9516783e37c298f553bdc3711023fc483f20b Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 26 Oct 2025 06:14:42 +0000 Subject: [PATCH 6/8] ci: version bump to v1.2.0-canary.59 --- apps/api/package.json | 2 +- apps/docs/package.json | 2 +- packages/config/package.json | 2 +- packages/create-vitnode-app/package.json | 2 +- packages/vitnode/package.json | 2 +- plugins/blog/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/api/package.json b/apps/api/package.json index 5b54eae75..7b9e78748 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "api", - "version": "1.2.0-canary.58", + "version": "1.2.0-canary.59", "private": true, "type": "module", "scripts": { diff --git a/apps/docs/package.json b/apps/docs/package.json index b792f4947..a4fa92b62 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,6 +1,6 @@ { "name": "docs", - "version": "1.2.0-canary.58", + "version": "1.2.0-canary.59", "type": "module", "private": true, "scripts": { diff --git a/packages/config/package.json b/packages/config/package.json index 0cef525bc..8b90d8368 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/config", - "version": "1.2.0-canary.58", + "version": "1.2.0-canary.59", "description": "ESLint, Prettier, TypeScript (TSConfig) config for VitNode", "author": "VitNode Team", "license": "MIT", diff --git a/packages/create-vitnode-app/package.json b/packages/create-vitnode-app/package.json index 17c09f260..2438365a4 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.58", + "version": "1.2.0-canary.59", "description": "Create a new VitNode app in seconds.", "author": "VitNode Team", "license": "MIT", diff --git a/packages/vitnode/package.json b/packages/vitnode/package.json index eae49db76..58cef773b 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/core", - "version": "1.2.0-canary.58", + "version": "1.2.0-canary.59", "description": "Core package for VitNode, providing essential functionalities and configurations.", "author": "VitNode Team", "license": "MIT", diff --git a/plugins/blog/package.json b/plugins/blog/package.json index ec33993e8..a33862985 100644 --- a/plugins/blog/package.json +++ b/plugins/blog/package.json @@ -1,6 +1,6 @@ { "name": "@vitnode/blog", - "version": "1.2.0-canary.58", + "version": "1.2.0-canary.59", "description": "Blog plugin for VitNode, providing a blogging platform with Next.js and Hono.js.", "author": "VitNode Team", "license": "MIT", From 624fbb05d64f267f2442a28da7484e1670619aca Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 9 Nov 2025 22:15:09 +0100 Subject: [PATCH 7/8] =?UTF-8?q?refactor(api):=20=E2=9C=A8=20Update=20Postg?= =?UTF-8?q?reSQL=20URL=20assignment=20to=20use=20nullish=20coalescing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/content/docs/dev/sso/index.mdx | 80 ++++++++++--------- .../api-single-app/src/vitnode.api.config.ts | 2 +- .../api/src/vitnode.api.config.ts | 2 +- .../create-vitnode-app/src/plugin/index.ts | 2 +- .../modules/cron/helpers/process-cron-jobs.ts | 2 +- .../src/views/auth/sign-in/form/use-form.ts | 2 +- packages/vitnode/src/vitnode.config.ts | 3 +- .../bump-version/files/file-copy-manager.ts | 10 +-- scripts/bump-version/files/file-system.ts | 7 +- 9 files changed, 57 insertions(+), 53 deletions(-) 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/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/src/plugin/index.ts b/packages/create-vitnode-app/src/plugin/index.ts index f5d8a2d2f..3651c606a 100644 --- a/packages/create-vitnode-app/src/plugin/index.ts +++ b/packages/create-vitnode-app/src/plugin/index.ts @@ -4,9 +4,9 @@ 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"; -import { createPluginVitNode } from "./create/create-plugin-vitnode.js"; export const createPlugin = async ({ program, 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 de25a9da3..75af1d55b 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 { drizzle, 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"; diff --git a/packages/vitnode/src/views/auth/sign-in/form/use-form.ts b/packages/vitnode/src/views/auth/sign-in/form/use-form.ts index eb9d24529..b24342b44 100644 --- a/packages/vitnode/src/views/auth/sign-in/form/use-form.ts +++ b/packages/vitnode/src/views/auth/sign-in/form/use-form.ts @@ -7,7 +7,7 @@ import type { AutoFormOnSubmit } from "@/components/form/auto-form"; import { mutationApi } from "./mutation-api"; -export const useFormSignIn = ({ isAdmin }: { isAdmin?: boolean }) => { +export const useFormSignIn = ({ isAdmin = false }: { isAdmin?: boolean }) => { const [error, setError] = React.useState<"" | "access_denied">(""); const t = useTranslations<"core.auth.sign_in">("core.auth.sign_in"); const tErrors = useTranslations("core.global.errors"); diff --git a/packages/vitnode/src/vitnode.config.ts b/packages/vitnode/src/vitnode.config.ts index fc32561e6..83e58cf4a 100644 --- a/packages/vitnode/src/vitnode.config.ts +++ b/packages/vitnode/src/vitnode.config.ts @@ -1,6 +1,5 @@ -import type { drizzle, PostgresJsDatabase } from "drizzle-orm/postgres-js"; +import type { drizzle } from "drizzle-orm/postgres-js"; import type { ThemeProvider } from "next-themes"; -import type postgres from "postgres"; import type { IRateLimiterOptions } from "rate-limiter-flexible"; import type { CronAdapter } from "./api/lib/cron"; diff --git a/scripts/bump-version/files/file-copy-manager.ts b/scripts/bump-version/files/file-copy-manager.ts index e94391ac9..b2da4ffe1 100644 --- a/scripts/bump-version/files/file-copy-manager.ts +++ b/scripts/bump-version/files/file-copy-manager.ts @@ -62,7 +62,7 @@ export class FileCopyManager { ]); } - copyFileOrDirectory( + async copyFileOrDirectory( sourcePath: string, destPath: string, relativePath: string, @@ -79,18 +79,18 @@ export class FileCopyManager { if (stats.isDirectory()) { copyDirectoryExcludingPlugins(from, to); } else { - copyFile(from, to); + await copyFile(from, to); } } - copyFiles(sourcePath: string, destPath: string, filesToCopy: string[]) { + async copyFiles(sourcePath: string, destPath: string, filesToCopy: string[]) { // Handle special files with different names const specialFiles = [ { source: ".gitignore", dest: ".gitignore_template" }, ]; for (const relativePath of filesToCopy) { - this.copyFileOrDirectory(sourcePath, destPath, relativePath); + await this.copyFileOrDirectory(sourcePath, destPath, relativePath); } // Handle special files with different destination names @@ -105,7 +105,7 @@ export class FileCopyManager { } if (stats.isFile()) { - copyFile(from, to); + await copyFile(from, to); } } } diff --git a/scripts/bump-version/files/file-system.ts b/scripts/bump-version/files/file-system.ts index 666970241..b2b7303bb 100644 --- a/scripts/bump-version/files/file-system.ts +++ b/scripts/bump-version/files/file-system.ts @@ -5,13 +5,14 @@ import { readdirSync, statSync, } from "node:fs"; +import { mkdir } from "node:fs/promises"; import { dirname, join } from "node:path"; -export function copyFile(from: string, to: string): void { +export const copyFile = async (from: string, to: string) => { try { const destinationDir = dirname(to); if (!existsSync(destinationDir)) { - mkdirSync(destinationDir, { recursive: true }); + await mkdir(destinationDir, { recursive: true }); } copyFileSync(from, to); } catch (error) { @@ -19,7 +20,7 @@ export function copyFile(from: string, to: string): void { `Failed to copy file: ${from} → ${to}: ${(error as Error).message}`, ); } -} +}; export function copyDirectoryExcludingPlugins(from: string, to: string): void { try { From 73c3a7062fa137d9f9c355a2241fc9e32b3619e4 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Sun, 9 Nov 2025 22:51:17 +0100 Subject: [PATCH 8/8] perf: Update packages --- apps/api/package.json | 30 +- apps/docs/docker-compose.yml | 4 +- apps/docs/next.config.ts | 7 +- apps/docs/package.json | 56 +- .../src/app/[locale]/(docs)/docs/layout.tsx | 2 +- .../src/app/[locale]/(main)/(home)/page.tsx | 4 +- .../(main)/(home)/sections/admin/admin.tsx | 4 +- .../(main)/(home)/sections/call-to-action.tsx | 4 +- .../powering-by/logos/tailwindcss.tsx | 2 +- .../sections/powering-by/powering-by.tsx | 4 +- apps/docs/src/app/[locale]/layout.tsx | 2 +- .../animated-beam/animated-beam.tsx | 3 +- apps/docs/src/examples/scroll-area.tsx | 2 +- apps/docs/src/examples/separator.tsx | 2 +- apps/docs/src/{middleware.ts => proxy.ts} | 0 package.json | 8 +- packages/config/package.json | 12 +- .../root/src/{middleware.ts => proxy.ts} | 0 packages/create-vitnode-app/package.json | 10 +- .../src/create/create-package-json.ts | 44 +- packages/vitnode/package.json | 74 +- .../src/api/middlewares/global.middleware.ts | 2 +- .../vitnode/src/components/form/auto-form.tsx | 2 +- .../src/components/form/fields/checkbox.tsx | 2 +- .../components/form/fields/radio-group.tsx | 2 +- .../switchers/themes/theme-switcher.tsx | 4 +- .../vitnode/src/components/table/content.tsx | 2 +- .../vitnode/src/components/ui/accordion.tsx | 4 +- .../src/components/ui/alert-dialog.tsx | 2 +- packages/vitnode/src/components/ui/card.tsx | 6 +- .../vitnode/src/components/ui/checkbox.tsx | 2 +- .../vitnode/src/components/ui/command.tsx | 8 +- .../src/components/ui/context-menu.tsx | 12 +- packages/vitnode/src/components/ui/dialog.tsx | 6 +- .../src/components/ui/dropdown-menu.tsx | 12 +- packages/vitnode/src/components/ui/editor.tsx | 2 +- .../vitnode/src/components/ui/hover-card.tsx | 2 +- .../vitnode/src/components/ui/input-otp.tsx | 4 +- packages/vitnode/src/components/ui/input.tsx | 2 +- packages/vitnode/src/components/ui/label.tsx | 2 +- .../vitnode/src/components/ui/menubar.tsx | 16 +- .../src/components/ui/navigation-menu.tsx | 8 +- .../vitnode/src/components/ui/popover.tsx | 2 +- .../vitnode/src/components/ui/radio-group.tsx | 4 +- .../vitnode/src/components/ui/scroll-area.tsx | 4 +- packages/vitnode/src/components/ui/select.tsx | 6 +- .../vitnode/src/components/ui/separator.tsx | 2 +- packages/vitnode/src/components/ui/sheet.tsx | 2 +- .../vitnode/src/components/ui/sidebar.tsx | 22 +- packages/vitnode/src/components/ui/slider.tsx | 6 +- packages/vitnode/src/components/ui/switch.tsx | 2 +- packages/vitnode/src/components/ui/table.tsx | 2 +- packages/vitnode/src/components/ui/tabs.tsx | 2 +- .../vitnode/src/components/ui/textarea.tsx | 2 +- .../src/components/ui/toggle-group.tsx | 2 +- .../vitnode/src/components/ui/tooltip.tsx | 2 +- .../vitnode/src/emails/reset-password.tsx | 2 +- packages/vitnode/src/emails/ui/card.tsx | 2 +- .../src/views/auth/sign-in/sign-in-view.tsx | 2 +- .../src/views/auth/sign-up/sign-up-view.tsx | 2 +- plugins/blog/package.json | 32 +- pnpm-lock.yaml | 7895 ++++++++--------- 62 files changed, 3991 insertions(+), 4380 deletions(-) rename apps/docs/src/{middleware.ts => proxy.ts} (100%) rename packages/create-vitnode-app/copy-of-vitnode-app/root/src/{middleware.ts => proxy.ts} (100%) diff --git a/apps/api/package.json b/apps/api/package.json index 7b9e78748..04723c5cd 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -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/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 a4fa92b62..d55ae0e2b 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -7,9 +7,9 @@ "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 9e2f1ed74..2735bbe21 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,14 @@ "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" diff --git a/packages/config/package.json b/packages/config/package.json index 8b90d8368..ded6eee12 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -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/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 2438365a4..6a8862627 100644 --- a/packages/create-vitnode-app/package.json +++ b/packages/create-vitnode-app/package.json @@ -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 6079f1d5e..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", }; @@ -128,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", @@ -139,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), @@ -183,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, @@ -252,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/vitnode/package.json b/packages/vitnode/package.json index 58cef773b..1d1462963 100644 --- a/packages/vitnode/package.json +++ b/packages/vitnode/package.json @@ -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/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 1ed2e5fce..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 (