From 3632b6cd0682e05399ddedcd0dde06a32b7ebc6c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 3 Jun 2025 18:39:01 +0200 Subject: [PATCH 1/2] added CLAUDE --- CLAUDE.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e8ab566 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Common Commands + +```bash +# Run all tests +npm run test + +# Run linter +npm run lint + +# Run linter with autofix +npm run lint:fix + +# Run a specific test file +npx tsx node_modules/mocha/bin/mocha "tests/index.test.ts" +``` + +## Code Architecture + +This is a Vite plugin for Nette framework that facilitates integration between Vite development server and Nette applications. The plugin is written in TypeScript and built as an ES module. + +### Key Components + +- **Main Plugin** (`src/index.ts`): The core plugin that exports the default function `vitePluginNette()` +- **Configuration Management**: Sets up default Vite configuration for Nette projects including asset output directory (`www/assets`), CORS settings, and manifest generation +- **Dev Server Integration**: Generates a JSON info file containing the dev server URL for Nette to consume +- **TypeScript Support**: Full TypeScript implementation with peer dependency on Vite ^6.0.0 + +### Plugin Features + +- Automatically configures `www/assets` as the default output directory +- Generates `.vite/nette.json` with dev server information during development +- Sets up CORS configuration for local development +- Enables manifest generation for production builds +- Configures asset directory structure for Nette applications + +### Development Setup + +- Uses ESLint with `@nette/eslint-plugin` for TypeScript linting +- Mocha for testing with comprehensive test suite +- Entry point is `src/index.ts` (native TypeScript support via Vite) + +### Windows Testing Notes + +Tests create temporary directories for isolation. On Windows, you may encounter EPERM errors during cleanup due to file system locking. The tests include retry logic with delays to handle this, but occasional cleanup warnings are normal and don't affect plugin functionality. From 23882b916ef0ec09d19a8b6dfcef9f1a04b25aef Mon Sep 17 00:00:00 2001 From: kapka Date: Fri, 4 Jul 2025 07:18:13 +0200 Subject: [PATCH 2/2] feat: log after plugin init, default HTML Nette-like --- package-lock.json | 4 +- package.json | 4 +- src/dev-server-index.html | 93 +++++++++++++++++++++++++++++++++++++++ src/index.ts | 46 ++++++++++++++++++- 4 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 src/dev-server-index.html diff --git a/package-lock.json b/package-lock.json index 517f27a..b0de486 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@nette/vite-plugin", - "version": "0.1", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@nette/vite-plugin", - "version": "0.1", + "version": "1.0.2", "license": "MIT", "devDependencies": { "@nette/eslint-plugin": "^0.1.2", diff --git a/package.json b/package.json index 6fdbb77..a88ac50 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "typescript-eslint": "^8.32.1" }, "scripts": { - "build": "tsc", - "prepare": "npm run build", + "build": "tsc && cp src/dev-server-index.html dist/", + "prepare": "npm run build && cp src/dev-server-index.html dist/", "test": "npx tsx node_modules/mocha/bin/mocha \"tests/**/*.ts\"", "lint": "eslint --cache", "lint:fix": "eslint --cache --fix" diff --git a/src/dev-server-index.html b/src/dev-server-index.html new file mode 100644 index 0000000..bdd1214 --- /dev/null +++ b/src/dev-server-index.html @@ -0,0 +1,93 @@ + + + + + + + Nette Vite + + + +
+

This is the Vite development server that provides Hot Module Replacement for your Nette application.

+

+ If you are exploring Nette for the first time, you should read the + Quick Start, documentation, + blog and forum.

+ +

We hope you enjoy Nette!

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + diff --git a/src/index.ts b/src/index.ts index 773b3b7..380cd93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,10 @@ +// Portions adapted from Laravel (https://laravel.com), MIT licensed. + import path from 'path'; import fs from 'fs'; -import { defaultAllowedOrigins, HttpServer, type PluginOption, ResolvedConfig, type ViteDevServer } from 'vite'; +import { fileURLToPath } from 'url'; +import colors from 'picocolors'; +import {defaultAllowedOrigins, HttpServer, type PluginOption, ResolvedConfig, type ViteDevServer} from 'vite'; interface PluginConfig { infoFile?: string; @@ -38,10 +42,16 @@ function generateInfoFile(httpServer: HttpServer): void { let port = (httpServer.address() as any).port; let devServerUrl = `${protocol}://${host}:${port}`; + + writeJson(infoFilePath, { devServer: devServerUrl }); // Update Vite server's origin field so other parts of Vite or downstream tools can pick it up resolvedConfig.server.origin = devServerUrl; + + setTimeout(() => { + console.log(`\n ${colors.blue(`${colors.bold('Nette')} ${netteVersion()}`)} ${colors.dim('plugin')} ${colors.bold(`v${nettepluginVersion()}`)}`) + }, 200) }); httpServer.on('close', () => { @@ -119,6 +129,40 @@ export default function vitePluginNette(config: PluginConfig = {}): PluginOption if (resolvedConfig.command === 'serve' && devServer.httpServer) { generateInfoFile(devServer.httpServer); } + + return () => devServer.middlewares.use((req, res, next) => { + if (req.url === '/index.html') { + res.statusCode = 404 + + res.end( + fs.readFileSync(path.join(dirname(), 'dev-server-index.html')).toString() + ) + } + + next() + }) }, }; } + +function netteVersion(): string { + try { + const composer = JSON.parse(fs.readFileSync('composer.lock').toString()) + + return composer.packages?.find((composerPackage: {name: string}) => composerPackage.name === 'nette/application')?.version ?? '' + } catch { + return '' + } +} + +function nettepluginVersion(): string { + try { + return JSON.parse(fs.readFileSync(path.join(dirname(), '../package.json')).toString())?.version + } catch { + return '' + } +} + +function dirname(): string { + return fileURLToPath(new URL('.', import.meta.url)) +}