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 🙏

© 2025 – Pkg Stats / Ryan Hefner

vite-plugin-proto-global

v2.0.0

Published

Auto-import pure functions from utils folder and extend JavaScript prototypes globally in your Vite project

Readme

vite-plugin-proto-global

Transform your JavaScript development by auto-importing pure utility functions and extending native prototypes globally in your Vite project.

npm version License

✨ Features

  • 🚀 Auto-import from utils folder - Point to a directory and automatically extend prototypes
  • 📁 Folder-based organization - Structure your utilities by type (utils/array/, utils/string/)
  • 🎯 Pure functions - Keep your utilities testable and reusable
  • 🔧 Manual configuration - Full control when you need it
  • 📦 Zero runtime overhead - Extensions are injected at build time
  • 🎨 TypeScript support - Full type definitions included
  • Vite 7 compatible - Works with the latest Vite

📦 Installation

npm i vite-plugin-proto-global -D
# or
yarn add vite-plugin-proto-global -D
# or
pnpm add vite-plugin-proto-global -D

🚀 Quick Start

Auto-Import Mode (Recommended)

1. Create your utils folder structure:

utils/
├── array/
│   ├── sum.js
│   ├── average.js
│   └── unique.js
├── string/
│   ├── capitalize.js
│   ├── truncate.js
│   └── reverse.js
└── number/
    ├── square.js
    └── clamp.js

2. Write pure utility functions:

// utils/array/sum.js
export default function sum() {
  return this.reduce((acc, val) => acc + val, 0);
}

// utils/string/capitalize.js
export default function capitalize() {
  return this.charAt(0).toUpperCase() + this.slice(1);
}

// utils/number/clamp.js
export default function clamp(min, max) {
  return Math.min(Math.max(this, min), max);
}

3. Configure the plugin:

// vite.config.js
import { defineConfig } from 'vite';
import { protoGlobalPlugin } from 'vite-plugin-proto-global';

export default defineConfig({
  plugins: [
    protoGlobalPlugin({
      utilsDir: './utils',
      namingConvention: 'folder', // Use folder name to determine prototype
    }),
  ],
});

4. Use anywhere in your project:

// No imports needed! Methods are available globally
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // 15
console.log(numbers.average()); // 3

const text = 'hello world';
console.log(text.capitalize()); // "Hello world"

const value = 150;
console.log(value.clamp(0, 100)); // 100

📖 Configuration Options

Auto-Import Configuration

interface AutoImportConfig {
  /**
   * Path to the utilities directory (relative to project root)
   * @example './utils'
   */
  utilsDir: string;

  /**
   * Include only files matching these patterns
   * @example ['sum', 'average']
   */
  include?: string[];

  /**
   * Exclude files matching these patterns
   * @example ['test', 'spec']
   */
  exclude?: string[];

  /**
   * Naming convention for determining which prototype to extend
   * - 'folder': Use folder name (e.g., utils/array/sum.js -> Array.prototype.sum)
   * - 'prefix': Use file prefix (e.g., array_sum.js -> Array.prototype.sum)
   * - 'auto': Try folder first, then prefix (default)
   * @default 'auto'
   */
  namingConvention?: 'folder' | 'prefix' | 'auto';
}

Manual Configuration

For full control, you can still use the manual configuration:

// vite.config.js
import { defineConfig } from 'vite';
import { protoGlobalPlugin } from 'vite-plugin-proto-global';

export default defineConfig({
  plugins: [
    protoGlobalPlugin([
      {
        className: 'Array',
        methods: {
          sum: function () {
            return this.reduce((acc, val) => acc + val, 0);
          },
          average: function () {
            return this.length > 0 ? this.sum() / this.length : 0;
          },
        },
      },
      {
        className: 'String',
        methods: {
          capitalize: function () {
            return this.charAt(0).toUpperCase() + this.slice(1);
          },
        },
      },
    ]),
  ],
});

🎯 Use Cases

1. Project-Wide Utilities

Keep your codebase DRY by defining utilities once and using them everywhere:

// utils/array/chunk.js
export default function chunk(size) {
  const chunks = [];
  for (let i = 0; i < this.length; i += size) {
    chunks.push(this.slice(i, i + size));
  }
  return chunks;
}

// Use anywhere
const items = [1, 2, 3, 4, 5, 6];
console.log(items.chunk(2)); // [[1, 2], [3, 4], [5, 6]]

2. Domain-Specific Extensions

Add business logic helpers:

// utils/number/toCurrency.js
export default function toCurrency(currency = 'USD') {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
  }).format(this);
}

// Use in your app
const price = 1234.56;
console.log(price.toCurrency()); // "$1,234.56"

3. Shareable Utility Packages

Create and share utility collections across projects:

npm install my-company-utils
// vite.config.js
protoGlobalPlugin({
  utilsDir: './node_modules/my-company-utils/dist',
});

🏗️ Project Structure Examples

Folder-Based (Recommended)

utils/
├── array/
│   ├── sum.js
│   ├── average.js
│   ├── unique.js
│   └── chunk.js
├── string/
│   ├── capitalize.js
│   ├── truncate.js
│   ├── slugify.js
│   └── reverse.js
└── number/
    ├── square.js
    ├── clamp.js
    └── toCurrency.js

Prefix-Based

utils/
├── array_sum.js
├── array_average.js
├── string_capitalize.js
├── string_truncate.js
├── number_square.js
└── number_clamp.js

💡 Best Practices

1. Keep Functions Pure

Your utility functions should be pure and only operate on this:

// ✅ Good - Pure function
export default function double() {
  return this.map(x => x * 2);
}

// ❌ Bad - Side effects
export default function double() {
  this.forEach((x, i) => (this[i] = x * 2)); // Mutates original
  return this;
}

2. Use Descriptive Names

Function names become method names, so make them clear:

// ✅ Good
export default function removeWhitespace() {
  return this.replace(/\s+/g, '');
}

// ❌ Bad
export default function rw() {
  return this.replace(/\s+/g, '');
}

3. Document Your Functions

Add JSDoc comments for better IDE support:

/**
 * Truncate a string to a specified length
 * @param {number} length - Maximum length
 * @param {string} suffix - Suffix to add (default: '...')
 * @returns {string} The truncated string
 */
export default function truncate(length, suffix = '...') {
  if (this.length <= length) return this.toString();
  return this.substring(0, length) + suffix;
}

4. Organize by Prototype

Keep related utilities together:

utils/
├── array/          # Array.prototype extensions
├── string/         # String.prototype extensions
├── number/         # Number.prototype extensions
├── object/         # Object.prototype extensions
└── date/           # Date.prototype extensions

🧪 Testing Your Utilities

Since utilities are pure functions, they're easy to test:

// utils/array/sum.test.js
import sum from './sum.js';

describe('Array.sum', () => {
  it('should sum array elements', () => {
    const arr = [1, 2, 3, 4, 5];
    expect(sum.call(arr)).toBe(15);
  });

  it('should return 0 for empty array', () => {
    const arr = [];
    expect(sum.call(arr)).toBe(0);
  });
});

⚠️ Important Considerations

Prototype Pollution

Extending native prototypes can be controversial. Consider these points:

  • Use in applications where you control the entire codebase
  • Great for internal tools and company-wide utilities
  • ⚠️ Be cautious in libraries that others will consume
  • ⚠️ Avoid name conflicts with existing or future native methods

Performance

  • Extensions are injected at build time, not runtime
  • Zero overhead compared to importing utilities
  • Functions are not tree-shakeable (all are included in bundle)

TypeScript Support

For TypeScript projects, you'll need to declare the extended prototypes:

// types/global.d.ts
interface Array<T> {
  sum(): number;
  average(): number;
  unique(): T[];
}

interface String {
  capitalize(): string;
  truncate(length: number, suffix?: string): string;
}

interface Number {
  square(): number;
  clamp(min: number, max: number): number;
}

🔧 Advanced Usage

Filtering Utilities

Include or exclude specific utilities:

protoGlobalPlugin({
  utilsDir: './utils',
  include: ['sum', 'average'], // Only include these
  exclude: ['deprecated'], // Exclude these
});

Multiple Prototype Types

The plugin supports extending any JavaScript prototype:

// utils/date/addDays.js
export default function addDays(days) {
  const result = new Date(this);
  result.setDate(result.getDate() + days);
  return result;
}

// Usage
const tomorrow = new Date().addDays(1);

Combining Manual and Auto-Import

You can't mix both in a single plugin instance, but you can use multiple instances:

export default defineConfig({
  plugins: [
    // Auto-import from utils
    protoGlobalPlugin({
      utilsDir: './utils',
    }),
    // Manual critical extensions
    protoGlobalPlugin([
      {
        className: 'Array',
        methods: {
          customMethod: function () {
            /* ... */
          },
        },
      },
    ]),
  ],
});

📊 Examples

Check out the demo folder for a complete working example with:

  • ✅ Array utilities (sum, average, unique, reverseNumbers)
  • ✅ String utilities (capitalize, reverse, truncate)
  • ✅ Number utilities (square, isEven, clamp)
  • ✅ Live demo page with tests

Run the demo:

cd demo
yarn install
yarn dev

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

Apache License 2.0 - see LICENSE file for details.

🙏 Support

If you find this plugin helpful:

  • ⭐ Star the repository
  • 🐛 Report bugs via GitHub Issues
  • 💡 Suggest features
  • 📖 Improve documentation

🔗 Links


Made with ❤️ by Vitaly Kuprin