npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@asaidimu/vite-autoload

v8.0.0

Published

Autoloader for vite

Readme

@asaidimu/vite-autoload

npm version License Build Status

@asaidimu/vite-autoload is an enhanced Vite plugin for automatic route and module loading, designed to streamline development workflows by dynamically generating and managing application components and data based on your file system.

Table of Contents


Overview & Features

@asaidimu/vite-autoload is a powerful Vite plugin designed to automate the discovery, generation, and management of application assets such as routes, components, and data structures. It addresses the common challenge of manual import management and boilerplate code in modern web development by dynamically generating application code based on your file system or custom data sources.

This plugin streamlines development workflows by:

  • Eliminating Manual Imports and Boilerplate: Automates the often tedious and error-prone process of defining and updating imports for routes, components, and other modules. This significantly reduces repetitive coding, allowing developers to focus on core application logic.
  • Enhancing Developer Productivity: By automating asset management, it accelerates development cycles and iteration speeds, leading to a more efficient and productive coding experience.
  • Ensuring Type Safety for Dynamic Assets: Automatically generates TypeScript declaration files (.d.ts) for all generated modules. This provides robust type safety for dynamically loaded assets, improving code reliability and developer experience by catching potential errors at compile time.
  • Improving Project Maintainability: As applications scale, manually maintaining large routing tables or component registries becomes challenging. The plugin's automatic generation capabilities ensure consistency and reduce long-term maintenance overhead by keeping configurations synchronized with your source files.
  • Simplifying SEO and PWA Integration: Integrates the generation of essential web artifacts like sitemap.xml for search engine optimization and manifest.webmanifest for Progressive Web App (PWA) capabilities directly into the build pipeline, simplifying crucial setup steps.
  • Enabling Metadata-Driven Development: Provides a robust utility for extracting structured metadata from your source files using TypeScript AST analysis and Zod schema validation. This allows for dynamic UI rendering, routing, and application logic based on declarative metadata embedded directly in your code.

By providing these capabilities, @asaidimu/vite-autoload facilitates more efficient development paradigms, such as:

  • File-System Driven Routing and Component Discovery: Leverage your existing file and directory structure to automatically define routes or expose component collections, creating a natural and intuitive organization for your application.
  • Automated Data Layer Generation: Transform file-based content (e.g., Markdown for blog posts) or programmatic data into type-safe generated modules, providing a unified and easily consumable data layer for your application.
  • Integrated Build Artifacts: Ensure that critical SEO and PWA files are always up-to-date and correctly generated as part of your standard build process, without requiring separate tooling or manual updates.

This plugin is designed to be a fundamental tool for developers building scalable and maintainable applications with Vite, providing a robust foundation for automated asset management.

⚠️ Beta Notice: Rapid & Breaking Changes This project is currently in its early stages of development and should be considered beta software. The API and configuration options are subject to frequent and potentially breaking changes without prior notice as the project evolves (as seen in recent v3.0.0 and v4.0.0 breaking changes). While it is feature-rich, it has not yet been battle-tested in a wide range of production environments. Please use with caution, and be sure to pin a specific version in your package.json to avoid unexpected disruptions from new releases.

We highly encourage feedback and contributions, but please be prepared for a rapidly changing codebase.

Key Features

  • 🚀 Automatic Route & Module Generation: Dynamically discover and expose application routes (e.g., pages) and other reusable modules (e.g., components, hooks) from specified directories based on flexible glob patterns, or from custom data sources. This means less manual import management and more focus on your code's core logic.
  • 📦 Disk-Based Generated Modules: All processed data is written as real .ts files to a configurable output directory (default: src/generated/), allowing direct and type-safe imports into your application code. No virtual module magic — just standard file imports.
  • 🔄 Hot Module Replacement (HMR): Provides seamless HMR for changes in watched files. When files tracked by the plugin are added, modified, or removed, the generated disk files are updated and Vite's native file watcher triggers HMR automatically — no custom invalidation logic needed.
  • 🗺️ Sitemap Generation: Automatically generates a sitemap.xml during the build process, configured with your base URL and exclusion patterns, to enhance SEO and improve discoverability of your application.
  • 🌐 PWA Manifest Generation: Integrates with Vite's build pipeline to generate a manifest.webmanifest file, enabling your application to function as a Progressive Web App (PWA) with configurable icons, display modes, and more, all with minimal effort.
  • 📄 Type Definition Generation: Automatically generates TypeScript declaration files (.d.ts) alongside your generated modules. This ensures strong type safety and significantly improves developer experience when consuming the generated modules, leading to fewer runtime errors.
  • 🔑 Metadata Extraction: A powerful feature that allows extracting structured metadata directly from your source files (e.g., page titles, authentication requirements) using TypeScript AST analysis and validation against Zod schemas. This metadata can then be included in the generated modules, empowering dynamic content and routing decisions.
  • 🛠️ Highly Configurable: Offers extensive options for defining file matching rules, transforming discovered file or data, customizing output formats, and fine-tuning build-time and development-time behaviors. The plugin introduces a unified components model for defining module groups, replacing previous routes and modules root properties, offering unparalleled flexibility to adapt to your project's unique needs.
  • 🔧 Deterministic Build Output: Generated modules are written to dist/generated/ after build with stable filenames, enabling server-side module swapping and predictable import paths.

Installation & Setup

Prerequisites

  • Node.js: LTS version (e.g., 18.x or 20.x)
  • Vite: Version 7.0.0 or higher (as per package.json)
  • Package Manager: Bun (recommended as per package.json scripts), npm, Yarn, or pnpm
  • TypeScript: ~5.8.3 or higher (as per package.json)

Installation Steps

Install the plugin using your preferred package manager:

# Using bun (recommended)
bun add @asaidimu/vite-autoload

# Using npm
npm install @asaidimu/vite-autoload

# Using yarn
yarn add @asaidimu/vite-autoload

# Using pnpm
pnpm add @asaidimu/vite-autoload

For the full capabilities, especially metadata extraction using Zod schemas, you will also need to install these development dependencies:

# Using bun
bun add @babel/parser @babel/traverse zod --development

# Using npm
npm install --save-dev @babel/parser @babel/traverse zod

Configuration

To integrate @asaidimu/vite-autoload into your Vite project, update your vite.config.ts file:

// vite.config.ts
import { defineConfig } from "vite";
import { createAutoloadPlugin, extract } from "@asaidimu/vite-autoload"; // Import `extract` utility
import createAutoloadConfig from "./example.config"; // Your custom autoload config file

export default defineConfig({
  plugins: [
    // Pass the `extract` utility to your config function, as it's required by TransformConfig
    createAutoloadPlugin(createAutoloadConfig({ extract })),
  ],
});

Next, create an example.config.ts (or autoload.config.ts) file in your project root. This file defines how the plugin will discover, process, and expose your application's components and data. The configuration is an object adhering to the PluginOptions type.

// example.config.ts
import { z } from "zod";
import type {
  PluginOptions,
  ComponentConfig,
  TransformConfig,
  ResolvedFile,
  ExtractFunction,
} from "@asaidimu/vite-autoload"; // Adjust import paths based on your setup

interface ConfigOptions {
  readonly extract: ExtractFunction;
}

export default function createAutoloadConfig({
  extract,
}: ConfigOptions): PluginOptions {
  // Example demonstrating file-system driven routing with metadata extraction
  const viewsTransformConfig: TransformConfig<ResolvedFile, any, any> = {
    name: "views", // This name will be used for the generated file: `src/generated/views.ts`
    description: "Transforms UI view files into routable data.",
    input: {
      directory: "ui", // Base directory to scan, e.g., `src/ui/pages`
      match: ["**/*.ts", "**/*.tsx"], // Glob patterns to match files
      ignore: ["**/__tests__/**", "*.d.ts"], // Optional: ignore patterns for tests or type declarations
      prefix: "/_views/", // Optional: prefix for URIs in the generated output, useful for lazy loading
    },
    output: {
      // Defines the structure of the generated module, e.g., `export const views = [{ route: '/', ... }, ...];`
      template: "export const views = {{ data }};",
      // Generates a TypeScript type like `type ViewKeys = '/home' | '/about';` for type-safe route keys.
      types: { name: "ViewKeys", property: "route" },
    },
    transform: async (item: ResolvedFile) => {
      // Custom transformation logic for each discovered file.
      // This example constructs a clean route path from the file's relative path.
      const route = item.path
        .replace(/^ui/, "") // Adjust based on your `directory` path
        .replace(/\\/g, "/") // Normalize path separators for cross-OS compatibility
        .replace(/\.tsx?$/, "") // Remove file extensions
        .replace(/\/index$/, ""); // Remove /index for root routes, e.g., `ui/home/index.tsx` becomes `/home`

      // This demonstrates the "Metadata Extraction" feature.
      // It statically analyzes `item.file` (the source file) to find an exported `metadata` constant
      // and validates it against the provided Zod schema.
      const metadata = await extract({
        filePath: item.file,
        schema: z.object({
          title: z.string().describe("Page title for display."),
          description: z
            .string()
            .optional()
            .describe("Optional page description for SEO."),
          authRequired: z
            .boolean()
            .optional()
            .describe(
              "Indicates if authentication is required for this route.",
            ),
        }),
        name: "metadata", // Looks for `export const metadata = {...}` or `export default {...}`
      });

      return {
        route: route || "/", // Ensure '/' for root path if the transformed route is empty
        path: item.uri, // The full URI for the module, useful for dynamic imports
        metadata: metadata, // The extracted and validated metadata
      };
    },
    // aggregate: (items) => { /* Optional: Custom aggregation for all transformed 'views' items */ },
  };

  // Example demonstrating "Automated Data Layer Generation" from a programmatic source.
  const dataTransformConfig: TransformConfig<Array<number>, any, any> = {
    name: "data", // This will be exposed as `src/generated/data.ts`
    description: "Generates arbitrary numeric data from a programmatic source.",
    // The `input` function can fetch data from an API, database, or generate it on the fly.
    input: () =>
      Promise.resolve(Array.from(new Array(20)).map((_, i) => i + 1)),
    output: {
      template: "export const data = {{ data }};",
    },
    transform: async (item) => {
      return item as any; // Simple passthrough for numeric data
    },
  };

  // Defines a higher-level "component" that groups related transformation configurations.
  // This helps in organizing and applying global strategies (like sitemap generation) to multiple data sources.
  const routes: ComponentConfig = {
    name: "routes", // A logical name for this high-level component category (e.g., 'routes', 'ui-modules')
    description:
      "Defines the routing structure and data for application views and pages.",
    strategy: {
      // "Sitemap Generation": Uses the `route` property from the aggregated `views` data to build sitemap entries.
      sitemap: {
        property: "route", // Property from transformed data to use for sitemap entries
      },
      // "Type Definition Generation": Creates a union type of all `route` strings found in this component's data.
      types: {
        name: "AppRouteData", // Name for the generated TypeScript type (e.g., ApplicationRoute)
        property: "route", // Property to use for type generation (e.g., 'route' will create a union type of all route strings)
      },
    },
    groups: [viewsTransformConfig, dataTransformConfig], // Includes our defined transformation groups
  };

  return {
    settings: {
      rootDir: process.cwd(), // Base directory for resolving relative paths in plugin options
      outputDir: "src/generated", // Directory where generated modules are written to disk
      export: {
        // "Type Definition Generation": Specifies the output path for the auto-generated TypeScript types.
        types: "src/generated/autogen.d.ts",
        routeLimit: 1000, // Limits the number of entries in generated union types, preventing excessively large types.
      },
      // "Sitemap Generation": Comprehensive configuration for the `sitemap.xml` file.
      sitemap: {
        output: "sitemap.xml", // Output filename for the sitemap (placed in Vite's build output)
        baseUrl: "[https://example.com](https://example.com)", // Base URL for sitemap entries (essential for absolute URLs)
        exclude: ["/admin/*", "/private/*"], // Glob patterns to exclude specific routes from the sitemap
      },
      // "PWA Manifest Generation": Comprehensive configuration for the `manifest.webmanifest` file.
      manifest: {
        name: "My PWA App",
        shortName: "PWA App",
        description:
          "A Progressive Web Application demonstrating vite-autoload.",
        theme_color: "#4a90e2",
        background_color: "#ffffff",
        display: "standalone",
        start_url: "/",
        icons: [
          {
            src: "/icons/icon-192x192.png",
            sizes: "192x192",
            type: "image/png",
          },
          {
            src: "/icons/icon-512x512.png",
            sizes: "512x512",
            type: "image/png",
          },
        ],
        output: "manifest.webmanifest",
      },
      logLevel: "info", // 'debug', 'info', 'warn', 'error' for plugin's console output
      chunkSize: 100, // Number of items processed in a single batch for memory optimization during large scans
      watch: {
        // "Hot Module Replacement (HMR)": Debounce settings for file watcher to ensure stability and efficiency.
        debounceTime: 1000, // Debounce time for file changes (ms)
        stabilityThreshold: 300, // Time to wait for file system write stability (ms)
      },
      extract: extract, // The required metadata extraction utility
    },

    // Define different component categories and their groups
    components: [routes], // Add your defined components here
  };
}

Verification

After configuring the plugin, run your Vite development server:

bun run dev

You should see log messages prefixed with [vite-autoload] in your console, indicating that the file watcher has started and modules/types are being generated. Check for any errors or warnings. Generated modules are written to the outputDir directory (default: src/generated/). During a production build (bun run build), the plugin will also write generated modules to dist/generated/ with deterministic filenames, along with sitemap.xml and manifest.webmanifest. You should also find your autogen.d.ts file generated at the configured path, containing types like:

// src/generated/autogen.d.ts (example content)
export type ViewKeys = "/" | "/home" | "/about" | "/products/[id]" | "/blog/post";
export type AppRouteData = ViewKeys;

The generated module files look like:

// src/generated/views.ts (example content)
export const views = [
  {
    route: '/dashboard',
    path: '/_views/dashboard.js',
    metadata: { title: 'Dashboard', authRequired: true }
  },
  {
    route: '/settings',
    path: '/_views/settings.js',
    metadata: { title: 'User Settings' }
  }
];
export default views;

Usage Documentation

Integrating with Vite

The createAutoloadPlugin function is the main entry point to integrate the plugin into your Vite configuration. It accepts a PluginOptions object that dictates how files are matched, transformed, and written to disk as generated modules.

// vite.config.ts
import { defineConfig } from "vite";
import { createAutoloadPlugin, extract } from "@asaidimu/vite-autoload";
import createAutoloadConfig from "./example.config";

export default defineConfig({
  plugins: [createAutoloadPlugin(createAutoloadConfig({ extract }))],
});

Configuration Options

The PluginOptions object, which defines the comprehensive configuration for the plugin, is structured around settings (global options) and components (defining content categories and their transformation groups).

interface PluginOptions {
  settings: {
    rootDir?: string;
    outputDir?: string; // Directory for generated modules (default: "src/generated")
    export?: {
      types?: string;
      routeLimit?: number;
    };
    sitemap?: SitemapConfig;
    manifest?: ManifestConfig;
    logLevel?: LogLevel;
    extract?: ExtractFunction;
    chunkSize?: number;
    watch?: WatchOptions;
  };
  components: Array<ComponentConfig>;
}

type ComponentConfig = {
  name: string;
  description?: string;
  metadata?: Record<string, unknown>;
  strategy: {
    sitemap?: { property: string };
    types?: { name: string; property: string };
  };
  groups: Array<TransformConfig<any, any, any>>;
};

interface TransformConfig<InputData, TransformedOutput, AggregatedOutput> {
  name: string;
  description?: string;
  metadata?: Record<string, unknown>;
  input: FileMatchConfig | (() => Promise<Array<InputData>> | Array<InputData>);
  output?: {
    template?: string;
    types?: { name: string; property: string };
  };
  transform?: (
    item: ResolvedFile | InputData,
    context: TransformContext,
  ) => TransformedOutput | Promise<TransformedOutput>;
  aggregate?: (
    items: Array<TransformedOutput | Promise<TransformedOutput>>,
  ) => AggregatedOutput | Promise<AggregatedOutput>;
}

// Full type definitions for `SitemapConfig`, `ManifestConfig`, `FileMatchConfig`,
// `ResolvedFile`, `TransformContext`, `ExtractFunction`, `LogLevel`, `WatchOptions`
// are available in the plugin's `src/types/` directory.

Let's break down the key options:

settings

A top-level object containing global configurations for the plugin.

  • rootDir: string (Optional, Default: process.cwd()) The base directory from which all relative paths (e.g., for export.types) are resolved.
  • outputDir: string (Optional, Default: 'src/generated') The directory where generated module files are written to disk (relative to rootDir). During development, Vite watches this directory for native HMR. During production builds, generated modules are written to {build.outDir}/generated/ with deterministic filenames.
  • export: object (Optional) Configuration for generating supplementary output files like TypeScript types, directly supporting the "Type Definition Generation" feature.
    • types: string (Optional) The file path (relative to rootDir) where the TypeScript declaration file (.d.ts) should be generated (e.g., 'src/generated/autogen.d.ts'). This file will contain union types for module keys based on your configuration, ensuring type safety when consuming generated modules.
    • routeLimit: number (Optional, Default: 1000) Limits the number of entries (e.g., routes) included in a generated TypeScript union type. Useful for very large projects to prevent excessively large type declarations that could impact editor performance.
  • sitemap: SitemapConfig (Optional) Configuration for sitemap.xml generation, directly supporting the "Sitemap Generation" feature.
    • output: string - The output filename for the generated sitemap XML file (e.g., 'sitemap.xml'). This file will be placed in your Vite build output directory.
    • baseUrl: string - The base URL of your website (e.g., 'https://example.com'). Used to construct absolute URLs in the sitemap.
    • exclude: ReadonlyArray<string> (Optional) - An array of glob patterns or regex strings to exclude specific routes from the sitemap (e.g., ['/admin/*', '/private/*']).
  • manifest: ManifestConfig (Optional) Configuration for PWA Web App Manifest (manifest.webmanifest) generation, directly supporting the "PWA Manifest Generation" feature. This object directly maps to standard Web App Manifest properties. See src/types/manifest.ts for full details.
    • name: string - Full name of the application.
    • shortName: string (Optional) - Short name, used when space is limited.
    • description: string (Optional) - Description of the application.
    • theme_color: string (Optional) - Default theme color.
    • background_color: string (Optional) - Background color.
    • display: "fullscreen" | "standalone" | "minimal-ui" | "browser" (Optional, Default: 'standalone') - Preferred display mode.
    • orientation: "any" | "natural" | "landscape" | "portrait" (Optional) - Preferred orientation.
    • scope: string (Optional, Default: '/') - Navigation scope.
    • start_url: string (Optional, Default: '/') - URL that loads when the user launches the app.
    • icons: Array<{ src: string; sizes: string; type?: string; purpose?: "any" | "maskable" | "monochrome"; }> (Optional) - Array of icon objects.
    • output: string (Optional, Default: 'manifest.webmanifest') - Output filename for the manifest.
  • extract: (options: { filePath: string; schema: z.ZodType; name: string }) => Promise<Record<string, unknown> | null> (Required) A function that provides the logic for extracting metadata from source files, a core component of the "Metadata Extraction" feature. The extract utility exported from @asaidimu/vite-autoload (re-exporting from src/utils/metadata.ts) is specifically designed for this purpose, leveraging TypeScript's AST for static analysis and Zod for validation.
    • filePath: The absolute path to the file to extract metadata from.
    • schema: A Zod schema to validate the extracted metadata against.
    • name: The name of the exported constant (e.g., export const metadata = {...} or export default {...}) to extract. Use 'default' for default exports.
  • logLevel: LogLevel ('debug' | 'info' | 'warn' | 'error') (Optional, Default: 'info') Controls the verbosity of the plugin's console output. Set to 'debug' for detailed internal logs, useful for troubleshooting.
  • chunkSize: number (Optional, Default: 100) Controls the number of routes/modules processed in a single batch during the data generation phase. Adjusting this can help manage memory usage, especially for applications with a very large number of files.
  • watch: WatchOptions (Optional) Configuration for the underlying chokidar file watcher, essential for "Hot Module Replacement (HMR)" during development.
    • debounceTime: number (Optional, Default: 1000) - The time in milliseconds to wait before triggering an update after a file change.
    • stabilityThreshold: number (Optional, Default: 300) - The time in milliseconds to wait for write operations to finish before processing a file change.

components

This is the core of the plugin's configuration. It is an Array<ComponentConfig>, where each ComponentConfig defines a logical category of content (e.g., "routes", "ui-modules") and how its associated groups of files or data sources should be processed. This section demonstrates the "Highly Configurable" nature of the plugin.

ComponentConfig Properties
  • name: string (Required) A unique logical name for this high-level component category (e.g., 'routes', 'ui-modules', 'blog-posts'). This name is primarily for internal organization and helps categorize groups.
  • description: string (Optional) A brief description for this component category.
  • metadata: Record<string, unknown> (Optional) Optional arbitrary metadata associated with this component category.
  • strategy: object (Required) Defines the global strategy for how the groups within this component category contribute to features like sitemap or type generation.
    • sitemap: object (Optional) Sitemap generation output settings for this component's groups. The property specified here is used to find the URL for sitemap entries within the transformed data from its groups.
      • property: string - The property name from the transformed data (returned by transform or aggregate) to use for sitemap entries (e.g., 'route' or 'url').
    • types: object (Optional) Type generation output settings for this component's groups.
      • name: string - The name of the generated TypeScript type for this component (e.g., 'ApplicationRoute', 'ComponentKey').
      • property: string - The property to extract from the transformed/aggregated data for type generation (e.g., 'route' will create a union type of all route strings found in this component's data).
  • groups: Array<TransformConfig<any, any, any>> (Required) An array of individual transformation configurations (groups) that belong to this component category. Each TransformConfig defines how specific input data is transformed and aggregated, directly substantiating the "Automatic Route & Module Generation" and "Automated Data Layer Generation" claims.
    • name: string (Required) A unique name for this specific group (e.g., 'views', 'pages', 'components'). This name corresponds to the generated file (e.g., src/generated/<group-name>.ts).
    • description: string (Optional) An optional description for the transformation pipeline.
    • metadata: Record<string, unknown> (Optional) Optional arbitrary metadata associated with this transformation pipeline.
    • input: FileMatchConfig | (() => Promise<Array<InputData>> | Array<InputData>) (Required) Configuration for matching input files, or a function providing direct data. This flexibility is key to "File-System Driven Routing" and "Automated Data Layer Generation".
      • If FileMatchConfig (for file-based sources):
        • directory: string - The base directory to scan for files (e.g., 'src/pages').
        • match: Array<string> | string - Glob patterns (e.g., '*.tsx', '*/index.tsx') to match files within the directory.
        • ignore: Array<string> | string (Optional) - Glob patterns to exclude files from matching.
        • prefix: string (Optional) - A string prefix to add to the uri of resolved files (e.g., /_assets/). Useful for organizing dynamically imported modules.
        • data: Record<string, unknown> (Optional) - Additional static data to inject into each transformed item.
      • If () => Promise<Array<InputData>> | Array<InputData> (for programmatic data sources):
        • A function that returns an array of input data directly, allowing for non-file-system based data. This function can be async (e.g., fetching data from a headless CMS API at build time).
    • output: object (Optional) Controls the output format of the generated module, directly supporting "Disk-Based Generated Modules".
      • template: string - A template string for the generated module code. Use {{ data }} as a placeholder for the processed JSON stringified data. Example: 'export const {{ name }} = {{ data }};'.
      • types: object (Optional) - Configuration for generating TypeScript types specific to this group, further ensuring "Type Definition Generation".
        • name: string - The name of the TypeScript type to generate (e.g., 'DashboardViewData').
        • property: string - The property name from the transformed item (from the transform function's return value) to use for constructing the union type.
    • transform: (item: ResolvedFile | InputData, context: TransformContext) => TransformedOutput | Promise<TransformedOutput> (Optional) A powerful function to transform each individual ResolvedFile or InputData object into a desired custom data structure. This is where you can extract metadata (with the extract utility), construct routes, or format data, directly underpinning the "Metadata Extraction" and flexible "Automatic Route & Module Generation". This function can be async as well.
      • item: The ResolvedFile object (for file inputs) or InputData object (for programmatic inputs).
      • context: Provides data (from previous transformations), environment (e.g., 'build', 'dev').
    • aggregate: (items: Array<TransformedOutput | Promise<TransformedOutput>>) => AggregatedOutput | Promise<AggregatedOutput> (Optional) A function to perform aggregation on all transformed items for a given group, combining them into a single data structure (e.g., converting an array of objects into a map keyed by a specific property). This was introduced in v1.1.0. This function can also be async.

Consuming Generated Modules

The plugin writes your configured groups as real .ts files to the outputDir directory (default: src/generated/). You can import them directly in your application code using standard relative imports. This provides type-safe and direct access to your processed assets with no virtual module magic.

// For a group named 'views' (configured as above, likely from `src/ui/pages`):
// The 'views' object will contain the data structure returned by your 'transform' and 'aggregate' functions.
import { views } from "./generated/views";

console.log("Available Views:", views);
/*
Example output in your console (after transformation based on your files):
[
  {
    route: '/dashboard',
    path: '/_views/dashboard.js', // Path for dynamic import
    metadata: { title: 'Dashboard', authRequired: true }
  },
  {
    route: '/settings',
    path: '/_views/settings.js',
    metadata: { title: 'User Settings', description: 'Configure application preferences' }
  }
  // ... more views from your 'ui' directory
]
*/

// For a group named 'data' (from the programmatic source example defined in example.config.ts):
import { data } from "./generated/data";
console.log("Generated Data:", data);
/*
Example output:
[1, 2, 3, ..., 20]
*/

// Or import everything from the barrel export:
import { views, data } from "./generated";

// Example of dynamically importing a view component based on the generated data:
// (Requires a routing library like React Router, Vue Router, etc.)
// In a routing setup, you might map the `route` to the actual component file:
async function loadViewComponent(routePath: ViewKeys) {
  // `ViewKeys` is type-safe due to `output.types`
  // Find the corresponding entry in the generated 'views' data
  const viewEntry = views.find((v) => v.route === routePath);
  if (!viewEntry) {
    console.error(`View for route ${routePath} not found.`);
    return null;
  }
  // Dynamically import the component using the `path` provided by the transform function
  const componentModule = await import(/* @vite-ignore */ viewEntry.path);
  return componentModule.default; // Assuming components are default exports
}

// Usage in a framework, e.g., React:
// const MyDynamicComponent = React.lazy(() => loadViewComponent('/dashboard'));

Project Architecture

@asaidimu/vite-autoload is structured around a core Vite plugin that orchestrates file watching, module generation, and integrates with specialized generators for sitemaps, PWA manifests, and powerful metadata extraction. This section provides insights into how the plugin achieves its advertised features internally, demonstrating its robust design.

Core Components

  • createAutoloadPlugin: The central orchestrator of the plugin. It initializes collection generators, sets up the file watcher, registers Vite hooks, and coordinates the generation of sitemaps and PWA manifests. It manages writing generated modules to disk and Hot Module Replacement (HMR).
  • createCollectionGenerator: Responsible for discovering files based on FileMatchConfig or resolving data from a DataSource function. It applies transform functions to each item's data, optionally applies aggregate functions to the collection, and ultimately prepares the data for code generation. It maintains an internal cache of resolved data.
  • createFileResolver: Manages the initial discovery and ongoing tracking of files that match configured glob patterns within specified directories. It efficiently resolves paths and maintains an internal cache of ResolvedFile objects.
  • createDataResolver: Handles the resolution of data from programmatic DataSource functions, caching their results.
  • createDataProcessor: Handles the transformation and aggregation pipeline for the data associated with discovered files or resolved data sources. It applies the transform function to individual entries and the aggregate function to the collection of transformed data, preparing it for code generation.
  • createCodeGenerator: Generates the final JavaScript code string that constitutes the generated module, based on the processed data and an optional output template.
  • generateToDisk: Writes the generated code for each group as a separate .ts file to the configured output directory, along with a barrel index.ts. Only writes files when content has changed.
  • createFileWatcher: Utilizes the chokidar library to efficiently monitor specified directories for file additions, changes, and deletions. When changes are detected, it debounces and triggers an update callback that regenerates the affected disk files.
  • createMetadataExtractor: A sophisticated utility that performs static code analysis on TypeScript files using the typescript AST parser. It can extract the values of specific export const or export default object literals, handling various literal types, array literals, object literals, and even transforming imported modules into dynamic import functions. Extracted data is validated against provided Zod schemas.
  • NameIndex: A utility for ensuring uniqueness of component and group names within the plugin's configuration, preventing naming conflicts.

Data Flow

  1. Initialization:
    • During Vite's configResolved hook, the plugin stores the Vite configuration.
    • On configureServer (development) or buildStart (production), createAutoloadPlugin initializes createCollectionGenerator instances for all configured components and their groups. Each generator uses an internal FileResolver to perform an initial file scan and DataResolver for programmatic data, building its cache of matched files/data.
  2. File Watching & HMR (Development):
    • On dev server start, generated modules are written to the outputDir directory as real .ts files.
    • The output directory is registered with Vite's watcher, enabling native HMR when generated files change.
    • createFileWatcher monitors the source directories specified in your PluginOptions.components[].groups[].input.
    • When a source file is added, changed, or removed, the watcher triggers a debounced callback.
    • The callback updates the generators (add/remove/touch files) and calls generateToDisk to rewrite the affected generated files.
    • Vite detects the changes to the generated .ts files and triggers HMR automatically — no custom module graph invalidation needed.
  3. Disk File Generation:
    • The generateToDisk function iterates all generators, resolves data for each group, and writes one .ts file per group (e.g., views.ts, data.ts) plus a barrel index.ts.
    • Each generated file contains the module's data as JSON, a default export, and any custom template content.
    • Files are only rewritten when content changes, avoiding unnecessary disk I/O.
  4. Production Build:
    • During closeBundle, generated modules are written to {build.outDir}/generated/ with deterministic filenames.
    • This provides stable import paths for server-side code that needs to reference generated modules.

Extension Points

  • transform Function: This is the primary way to customize the data payload for each discovered file or data item. It allows you to define how a ResolvedFile object or InputData is processed into the desired structure, enabling custom route generation, metadata enrichment, and more. This function can be asynchronous.
  • aggregate Function: Provides a powerful hook to combine all transformed items for a given group into a single, aggregated data structure. This is ideal for converting arrays of items into objects/maps keyed by a specific property, optimizing data access in your application. This function can also be asynchronous.
  • extract Function: A crucial extension point for performing custom static analysis on your source files. By providing an implementation (like the one from src/utils/metadata.ts), you can read and validate specific exported metadata from your components or pages, making it available in the generated modules. This function is asynchronous.

Development & Contributing

Development Setup

To set up the @asaidimu/vite-autoload project for local development:

  1. Clone the repository:

    git clone [https://github.com/asaidimu/vite-autoload.git](https://github.com/asaidimu/vite-autoload.git)
    cd vite-autoload
  2. Install dependencies: The project uses Bun as the preferred package manager, but npm/yarn will also work.

    # Using bun (recommended)
    bun install
    
    # Or using npm
    npm install

Scripts

The package.json defines several useful scripts for development and building:

  • bun ci: Installs project dependencies. Used in CI environments.
  • bun dev: Starts the Vite development server with the plugin active, allowing you to test changes locally. This runs vite from the root, utilizing vite.config.ts.
  • bun clean: Removes the dist output directory.
  • bun prebuild: Cleans the dist directory and runs an internal synchronization script (.sync-package.ts) before building.
  • bun build: Compiles the TypeScript source files (src/) into JavaScript and TypeScript declaration files (.d.ts) in the dist directory.
  • bun postbuild: Copies essential files (README.md, LICENSE.md, dist.package.json, example.config.ts) into the dist directory, preparing the package for publishing.

Testing

Currently, explicit unit or integration test files (.test.ts, .spec.ts) are not present in the provided codebase snapshot. For thorough testing of a plugin like this, you would typically include:

  • Unit Tests: For utilities (e.g., debounce, hash, checkers, logger, uri) and smaller components (e.g., metadata extractor logic, sitemap generation).
    • Integration Tests: To verify the plugin's behavior within a Vite environment, ensuring generated modules load correctly, HMR works, and assets are generated as expected during build.

If tests were available, you would typically run them with a command like:

# Placeholder for running tests (if tests were present)
bun test
# or
npm test

Contributing Guidelines

Contributions are highly welcome! If you're interested in contributing to @asaidimu/vite-autoload, please follow these guidelines:

  1. Fork the Repository: Start by forking the repository on GitHub.
  2. Clone Your Fork: Clone your forked repository to your local development machine.
    git clone [https://github.com/YOUR_USERNAME/vite-autoload.git](https://github.com/YOUR_USERNAME/vite-autoload.git)
    cd vite-autoload
  3. Create a New Branch: Always create a new branch for your feature or bug fix. Use descriptive names like feature/add-new-config-option or fix/hmr-issue.
    git checkout -b feature/your-feature-name
  4. Make Your Changes: Implement your changes, ensuring they align with the existing code style and architecture.
  5. Write Tests (if applicable): If you're adding new features or fixing bugs, please consider adding relevant tests to ensure correctness and prevent regressions.
  6. Commit Messages: Write clear, concise, and descriptive commit messages. Follow Conventional Commits guidelines (e.g., feat: Add new configuration option, fix: Resolve HMR issue). The package.json release configuration uses @semantic-release/commit-analyzer, indicating strict adherence to these.
  7. Push to Your Fork: Push your changes to your fork on GitHub.
    git push origin feature/your-feature-name
  8. Open a Pull Request: Go to the original @asaidimu/vite-autoload repository on GitHub and open a Pull Request from your new branch. Provide a detailed description of your changes.

Issue Reporting

If you encounter any bugs, have feature requests, or need assistance, please open an issue on our GitHub Issues page. When reporting bugs, please provide:

  • A clear and concise description of the issue.
  • Steps to reproduce the behavior.
  • Expected behavior.
  • Actual behavior.
  • Screenshots or code snippets if helpful.
  • Your environment details (Node.js version, Vite version, OS).

Additional Information

Troubleshooting & Performance Optimization

This plugin is designed with performance and developer experience in mind. Here are some guidelines and troubleshooting tips to help you get the most out of it:

  1. Memory Usage Guidelines:
    • Limit Watched Directories: Configure input.directory and input.ignore precisely to only watch files and directories that are directly relevant to your generated modules. Avoid watching unnecessary large directories like node_modules or extensive test folders.
      // In example.config.ts
      components: [
        {
          name: "routes",
          groups: [
            {
              name: "views",
              input: {
                directory: "src/app/views",
                match: ["**/*.vue", "**/*.tsx"],
                ignore: ["**/node_modules/**", "**/__tests__/**"],
              },
            },
          ],
        },
      ];
    • Module Processing Chunking: For very large applications with thousands of routes or modules, adjusting the chunkSize option in PluginOptions.settings can help manage memory usage by processing files in smaller batches. A smaller chunkSize (e.g., 50) reduces peak memory consumption, though it might slightly increase overall processing time.
      // In example.config.ts
      settings: {
        // ...
        chunkSize: 50, // Process 50 items at a time within a group
      },
    • Type Generation Limit: The export.routeLimit option (in PluginOptions.settings.export) helps prevent generating excessively large TypeScript union types for applications with a very high route count. Large type definitions can sometimes impact editor responsiveness and type-checking performance.
      // In example.config.ts
      settings: {
        export: {
          types: 'src/types/autogen.d.ts',
          routeLimit: 500 // Limit generated route type to 500 entries
        },
        // ...
      },
  2. File Watching Stability: The watch options (debounceTime, stabilityThreshold) can be fine-tuned to improve the file watcher's responsiveness and stability, especially in environments with slow I/O or network drives, or when dealing with applications that generate many temporary files.
    • debounceTime: Increase this value if rapid successive file saves lead to multiple, redundant rebuilds or HMR updates.
    • stabilityThreshold: Increase this value if you notice that file changes are sometimes processed before the files are fully written to disk, leading to partial or empty content being read.
  3. HMR Not Triggering Correctly:
    • Generated Module Imports: Ensure that your application imports the generated modules from the correct path (e.g., import { views } from './generated/views';). Vite watches the generated files and triggers HMR automatically when they change.
    • logLevel Debugging: Set logLevel: 'debug' in your PluginOptions.settings to get detailed console output about file changes, module invalidations, and HMR events. This can help you diagnose why HMR might not be triggering as expected.
  4. Metadata Extraction Errors:
    • Schema Mismatch: If your extract function is failing or returning unexpected results, carefully review the schema (Zod type) you are providing. It must accurately match the structure of the metadata object you are attempting to extract from your source files.
    • Syntax Errors: Ensure the source files from which you are extracting metadata have valid TypeScript/JavaScript syntax. Parsing errors in the source file can prevent metadata extraction.
    • Static Analysis Limitations: The extract utility performs static analysis of your code. It can successfully extract values from literal expressions (strings, numbers, booleans, arrays, objects) and identifiers that resolve to such literals or imported modules. It cannot evaluate complex runtime logic, function calls, or dynamic computations within the metadata object.

Changelog

For a detailed history of changes, new features, and bug fixes, please refer to the CHANGELOG.md file. Note the significant breaking changes introduced in versions 3.0.0 and 4.0.0 related to plugin configuration structure.

License

This project is licensed under the MIT License.

Acknowledgments

This project is developed and maintained by Saidimu. It leverages several excellent open-source libraries and tools, including Vite, Chokidar, Zod, es-module-lexer, Babel, and Playwright (for dev environment), for which we are immensely grateful.