Delete SigProRouterPlugin directory
This commit is contained in:
@@ -1,139 +0,0 @@
|
|||||||
# SigPro Router Plugin for Vite
|
|
||||||
|
|
||||||
A Vite plugin that automatically generates routes from your file structure in `src/pages/`, similar to Next.js file-based routing but for any JavaScript project.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- 📁 **File-based routing**: Automatically creates routes from your `src/pages` directory
|
|
||||||
- 🔗 **Dynamic routes**: Supports parameterized routes using `[param]` syntax
|
|
||||||
- 🧭 **Path-to-regexp conversion**: Dynamic routes are converted to RegExp with named capture groups
|
|
||||||
- 📊 **Route map generation**: Console output shows all detected routes at build time
|
|
||||||
- 🎯 **Virtual module**: Access your routes via `virtual:sigpro-routes`
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Save the plugin code in your project, for example as `plugins/sigpro-router.js`
|
|
||||||
|
|
||||||
2. Add it to your Vite configuration:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// vite.config.js
|
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import sigproRouter from './plugins/sigpro-router';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [sigproRouter()]
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### 1. Create Pages
|
|
||||||
|
|
||||||
Create `.js` files in your `src/pages` directory. Each file becomes a route:
|
|
||||||
|
|
||||||
```
|
|
||||||
src/pages/
|
|
||||||
├── index.js -> /
|
|
||||||
├── about.js -> /about
|
|
||||||
├── blog/
|
|
||||||
│ ├── index.js -> /blog
|
|
||||||
│ └── [id].js -> /blog/:id (dynamic)
|
|
||||||
└── users/
|
|
||||||
└── [userId].js -> /users/:userId (dynamic)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Access Routes in Your Application
|
|
||||||
|
|
||||||
The plugin exposes a virtual module `virtual:sigpro-routes` that exports a `routes` array:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// In your router or main application file
|
|
||||||
import { routes } from 'virtual:sigpro-routes';
|
|
||||||
|
|
||||||
// The routes array structure:
|
|
||||||
// [
|
|
||||||
// { path: '/', component: PageComponent, isDynamic: false, paramName: null },
|
|
||||||
// { path: /^\/blog\/(?<id>[^/]+)$/, component: PageComponent, isDynamic: true, paramName: 'id' },
|
|
||||||
// { path: /^\/users\/(?<userId>[^/]+)$/, component: PageComponent, isDynamic: true, paramName: 'userId' },
|
|
||||||
// ]
|
|
||||||
|
|
||||||
// Example usage with a simple router
|
|
||||||
function renderRoute(path) {
|
|
||||||
for (const route of routes) {
|
|
||||||
if (!route.isDynamic && route.path === path) {
|
|
||||||
return route.component();
|
|
||||||
} else if (route.isDynamic) {
|
|
||||||
const match = path.match(route.path);
|
|
||||||
if (match) {
|
|
||||||
// Access params via match.groups
|
|
||||||
const params = match.groups;
|
|
||||||
return route.component(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '<h1>404 Not Found</h1>';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Build Time Output
|
|
||||||
|
|
||||||
When you run your Vite dev server or build, you'll see a route map in the console:
|
|
||||||
|
|
||||||
```
|
|
||||||
🚀 [SigPro Router] Mapa de rutas generado:
|
|
||||||
📄 / -> index.js
|
|
||||||
📄 /about -> about.js
|
|
||||||
📄 /blog -> blog/index.js
|
|
||||||
🔗 /blog/[id] -> blog/[id].js
|
|
||||||
🔗 /users/[userId] -> users/[userId].js
|
|
||||||
```
|
|
||||||
|
|
||||||
## Route Priority
|
|
||||||
|
|
||||||
Routes are automatically prioritized:
|
|
||||||
|
|
||||||
1. Static routes (non-dynamic) are matched before dynamic routes
|
|
||||||
2. Routes are sorted by path length (shorter paths first)
|
|
||||||
|
|
||||||
## Route Object Properties
|
|
||||||
|
|
||||||
Each route in the `routes` array contains:
|
|
||||||
|
|
||||||
| Property | Type | Description |
|
|
||||||
|----------|------|-------------|
|
|
||||||
| `path` | `string \| RegExp` | Static path string or RegExp for dynamic routes |
|
|
||||||
| `component` | `Function` | The imported page component/module |
|
|
||||||
| `isDynamic` | `boolean` | Whether the route has parameters |
|
|
||||||
| `paramName` | `string \| null` | The parameter name for dynamic routes |
|
|
||||||
|
|
||||||
## Dynamic Route Parameters
|
|
||||||
|
|
||||||
For dynamic routes like `blog/[id].js`:
|
|
||||||
|
|
||||||
- The route path becomes: `new RegExp("^\\/blog\\/(?<id>[^/]+)$")`
|
|
||||||
- Parameters can be accessed via `match.groups` when matching the route
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```javascript
|
|
||||||
const match = '/blog/123'.match(/^\/blog\/(?<id>[^/]+)$/);
|
|
||||||
console.log(match.groups.id); // '123'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
- Only scans `.js` files (no JSX/TS support by default - modify the plugin if needed)
|
|
||||||
- Requires a `src/pages` directory in your project root
|
|
||||||
- Dynamic parameters are matched as single path segments (no catch-all routes)
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
You can modify the plugin to:
|
|
||||||
- Support other file extensions (.jsx, .ts, .tsx)
|
|
||||||
- Change the pages directory location
|
|
||||||
- Add custom route sorting logic
|
|
||||||
- Implement nested dynamic routes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Built for SigPro applications with Vite.
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SigPro Router Plugin for Vite
|
|
||||||
*
|
|
||||||
* This plugin generates routes automatically based on the file structure in src/pages/
|
|
||||||
* It creates a virtual module 'virtual:sigpro-routes' that exports a routes array
|
|
||||||
* with all the detected pages and their corresponding components.
|
|
||||||
*
|
|
||||||
* @returns {import('vite').Plugin} Vite plugin object
|
|
||||||
*/
|
|
||||||
export default function sigproRouter() {
|
|
||||||
// Virtual module identifiers
|
|
||||||
const VIRTUAL_MODULE_ID = 'virtual:sigpro-routes';
|
|
||||||
const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively retrieves all JavaScript files from a directory
|
|
||||||
*
|
|
||||||
* @param {string} directoryPath - The path to scan for files
|
|
||||||
* @returns {string[]} Array of absolute paths to all .js files found
|
|
||||||
*/
|
|
||||||
function getAllJavaScriptFiles(directoryPath) {
|
|
||||||
let filesFound = [];
|
|
||||||
|
|
||||||
// Return empty array if directory doesn't exist
|
|
||||||
if (!fs.existsSync(directoryPath)) return filesFound;
|
|
||||||
|
|
||||||
const directoryContents = fs.readdirSync(directoryPath);
|
|
||||||
|
|
||||||
directoryContents.forEach(item => {
|
|
||||||
const fullItemPath = path.resolve(directoryPath, item);
|
|
||||||
const itemStats = fs.statSync(fullItemPath);
|
|
||||||
|
|
||||||
if (itemStats && itemStats.isDirectory()) {
|
|
||||||
// Recursively scan subdirectories
|
|
||||||
filesFound = filesFound.concat(getAllJavaScriptFiles(fullItemPath));
|
|
||||||
} else if (item.endsWith('.js')) {
|
|
||||||
// Add JavaScript files to results
|
|
||||||
filesFound.push(fullItemPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return filesFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: 'sigpro-router',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves the virtual module ID to our internal ID
|
|
||||||
*
|
|
||||||
* @param {string} importeeId - The module ID being imported
|
|
||||||
* @returns {string|null} The resolved virtual module ID or null
|
|
||||||
*/
|
|
||||||
resolveId(importeeId) {
|
|
||||||
if (importeeId === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the virtual module content with route definitions
|
|
||||||
*
|
|
||||||
* @param {string} moduleId - The resolved module ID being loaded
|
|
||||||
* @returns {string|null} Generated module code or null
|
|
||||||
*/
|
|
||||||
load(moduleId) {
|
|
||||||
if (moduleId === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
||||||
const PAGES_DIRECTORY = path.resolve(process.cwd(), 'src/pages');
|
|
||||||
let pageFiles = getAllJavaScriptFiles(PAGES_DIRECTORY);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort files to prioritize routes:
|
|
||||||
* 1. Static routes come before dynamic routes
|
|
||||||
* 2. Shorter paths come first (more specific routes)
|
|
||||||
*/
|
|
||||||
pageFiles = pageFiles.sort((fileA, fileB) => {
|
|
||||||
const fileAHasDynamicParam = fileA.includes('[');
|
|
||||||
const fileBHasDynamicParam = fileB.includes('[');
|
|
||||||
|
|
||||||
if (fileAHasDynamicParam !== fileBHasDynamicParam) {
|
|
||||||
return fileAHasDynamicParam ? 1 : -1;
|
|
||||||
}
|
|
||||||
return fileA.length - fileB.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
let importStatements = '';
|
|
||||||
let routeDefinitions = 'export const routes = [\n';
|
|
||||||
|
|
||||||
console.log('\n🚀 [SigPro Router] Generated route map:');
|
|
||||||
|
|
||||||
pageFiles.forEach((fullFilePath, index) => {
|
|
||||||
// Calculate relative path from pages directory
|
|
||||||
const relativeFilePath = path.relative(PAGES_DIRECTORY, fullFilePath).replace(/\\/g, '/');
|
|
||||||
const fileNameWithoutExtension = relativeFilePath.replace('.js', '');
|
|
||||||
const componentVariableName = `Page_${index}`;
|
|
||||||
|
|
||||||
// Convert file path to URL path
|
|
||||||
let urlPath = '/' + fileNameWithoutExtension.toLowerCase();
|
|
||||||
if (urlPath.endsWith('/index')) urlPath = urlPath.replace('/index', '') || '/';
|
|
||||||
|
|
||||||
// Detect if this is a dynamic route (contains [param])
|
|
||||||
const isDynamicRoute = urlPath.includes('[') && urlPath.includes(']');
|
|
||||||
let finalPathValue = `'${urlPath}'`;
|
|
||||||
let parameterName = null;
|
|
||||||
|
|
||||||
if (isDynamicRoute) {
|
|
||||||
// Extract parameter name from brackets (e.g., from [id] extract 'id')
|
|
||||||
const parameterMatch = urlPath.match(/\[([^\]]+)\]/);
|
|
||||||
parameterName = parameterMatch ? parameterMatch[1] : 'id';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert dynamic route to RegExp with named capture groups
|
|
||||||
* Example: /blog/[id] becomes new RegExp("^\\/blog\\/(?<id>[^/]+)$")
|
|
||||||
* This allows accessing parameters via match.groups.parameterName
|
|
||||||
*/
|
|
||||||
const regexPattern = urlPath
|
|
||||||
.replace(/\//g, '\\/')
|
|
||||||
.replace(/\[([^\]]+)\]/, '(?<$1>[^/]+)'); // Replace [id] with (?<id>[^/]+)
|
|
||||||
|
|
||||||
finalPathValue = `new RegExp("^${regexPattern}$")`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log route information to console
|
|
||||||
console.log(` ${isDynamicRoute ? '🔗' : '📄'} ${urlPath.padEnd(20)} -> ${relativeFilePath}`);
|
|
||||||
|
|
||||||
// Generate import statement for this page component
|
|
||||||
importStatements += `import ${componentVariableName} from './src/pages/${relativeFilePath}';\n`;
|
|
||||||
|
|
||||||
// Generate route definition object
|
|
||||||
routeDefinitions += ` { path: ${finalPathValue}, component: ${componentVariableName}, isDynamic: ${isDynamicRoute}, paramName: ${parameterName ? `'${parameterName}'` : 'null'} },\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
routeDefinitions += '];';
|
|
||||||
|
|
||||||
// Return complete module code
|
|
||||||
return `${importStatements}\n${routeDefinitions}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user