npm package: @kpsoftec/vite-copy-plugin
Description: A Vite plugin to copy files with optional transformation and wildcard support
Author: KPSoftec
Latest version: 1.0.3

# @kpsoftec/vite-copy-plugin

A Vite plugin to copy files with optional transformation and wildcard support, similar to copy-webpack-plugin.

## Features

- ✅ Copy files with wildcard patterns
- ✅ Transform file content during copy
- ✅ Development server support with live serving
- ✅ Production build integration
- ✅ Multiple wildcard types: `*`, `?`, `[abc]`, `[a-z]`
- ✅ TypeScript support with type definitions
- ✅ Robust error handling for undefined URLs
- ✅ Force file watching in development mode

## Installation

```bash
npm install @kpsoftec/vite-copy-plugin
```

## Basic Usage

```js
import { defineConfig } from 'vite'
import { copyPlugin } from '@kpsoftec/vite-copy-plugin'

export default defineConfig(({ mode }) => ({
  plugins: [
    copyPlugin([
      {
        from: 'src/configs/app-config.json',
        to: 'configs/app-config.json',
        transform: (content) => {
          if (mode === 'production') return content
          const config = JSON.parse(content)
          return JSON.stringify({
            ...config,
            apiUrl: config.apiUrl.replace('prod', 'dev')
          }, null, 2)
        }
      }
    ])
  ]
}))
```

## TypeScript Support

The plugin includes TypeScript definitions out of the box:

```typescript
import { copyPlugin, CopyPattern } from '@kpsoftec/vite-copy-plugin'

const patterns: CopyPattern[] = [
  {
    from: 'src/config.json',
    to: 'config.json',
    transform: (content: string) => content.toUpperCase()
  }
]

export default defineConfig({
  plugins: [copyPlugin(patterns)]
})
```

## Error Handling

Version 1.0.1+ includes improved error handling:
- Handles undefined request URLs gracefully
- No more "Cannot read properties of undefined" errors
- Robust middleware implementation

## Wildcard Patterns

### Supported Wildcards

- **`*`** - Matches any characters (zero or more)
- **`?`** - Matches single character
- **`[abc]`** - Matches any character in brackets
- **`[a-z]`** - Matches character range

### Examples

```js
import { copyPlugin } from '@kpsoftec/vite-copy-plugin'

copyPlugin([
  // Copy single file
  {
    from: 'src/configs/app-config.json',
    to: 'configs/app-config.json'
  },
  
  // Copy all JSON files ending with -config
  {
    from: 'src/configs/*-config.json',
    to: 'configs/'  // trailing slash = directory
  },
  
  // Copy all JSON files
  {
    from: 'src/configs/*.json',
    to: 'configs/'
  },
  
  // Copy files with single character variation
  {
    from: 'src/data/file?.json',  // file1.json, fileA.json
    to: 'data/'
  },
  
  // Copy files matching character set
  {
    from: 'src/env/[123]-config.json',  // 1-config.json, 2-config.json, 3-config.json
    to: 'env/'
  },
  
  // Copy files matching character range
  {
    from: 'src/assets/[a-c]*.png',  // a-logo.png, b-icon.png, c-banner.png
    to: 'assets/'
  }
])
```

## Force Property

Use the `force` property to enable file watching in development mode for real-time updates:

```js
copyPlugin([
  {
    from: 'src/config.json',
    to: 'config.json',
    force: true,  // Enable file watching
    transform: (content) => {
      const config = JSON.parse(content)
      return JSON.stringify({ ...config, timestamp: Date.now() }, null, 2)
    }
  }
])
```

**When to use `force: true`:**
- Files that change frequently during development
- Configuration files that need live updates
- Files with dynamic content that should reflect immediately

**Performance note:** Only enable `force` for files that actually need watching to avoid unnecessary file system overhead.

## Transform Function

```js
{
  from: 'src/config.json',
  to: 'config.json',
  transform: (content) => {
    // Access to mode via closure or environment
    if (process.env.NODE_ENV === 'production') {
      return content  // No transformation in production
    }
    
    // Transform for development
    const config = JSON.parse(content)
    return JSON.stringify({
      ...config,
      debug: true,
      apiUrl: 'http://localhost:3000'
    }, null, 2)
  }
}
```

## Output Paths

```js
// Specific filename
{ from: 'src/file.json', to: 'output.json' }

// Directory (keeps original filenames)
{ from: 'src/*.json', to: 'configs/' }

// Nested directory
{ from: 'src/data/*.json', to: 'api/data/' }
```

## Development vs Production

- **Development**: Files are served dynamically via middleware
- **Production**: Files are copied to `dist` folder during build
- **Transform**: Applied in both modes (use mode check to skip in production)

## Real-world Example

```js
import { copyPlugin } from '@kpsoftec/vite-copy-plugin'

export default defineConfig(({ mode }) => ({
  plugins: [
    copyPlugin([
      // Main app config with environment-specific transforms
      {
        from: 'src/configs/app-config.json',
        to: 'configs/app-config.json',
        transform: (content) => {
          if (mode === 'production') return content
          
          const config = JSON.parse(content)
          return JSON.stringify({
            ...config,
            clientId: config.clientId.replace('#client_id#', 'dev-client'),
            env: config.env.replace('#client_env#', 'development'),
            apiUrl: config.apiUrl.replace('prod-api', 'dev-api')
          }, null, 2)
        }
      },
      
      // Copy all environment-specific configs
      {
        from: 'src/configs/*-configs.json',
        to: 'configs/'
      },
      
      // Copy locale files
      {
        from: 'src/locales/[a-z][a-z].json',  // en.json, fr.json, etc.
        to: 'locales/'
      }
    ])
  ]
}))
```

## API Reference

### copyPlugin(patterns)

- **patterns**: `Array<Pattern>` - Array of copy patterns

### Pattern

- **from**: `string` - Source file path (supports wildcards)
- **to**: `string` - Destination path (file or directory)
- **transform**: `(content: string) => string` - Optional transform function
- **force**: `boolean` - Enable file watching in development mode (default: false)

### Wildcard Support

| Pattern | Description | Example Matches |
|---------|-------------|----------------|
| `*.json` | Any JSON file | `config.json`, `data.json` |
| `*-config.json` | Files ending with -config | `app-config.json`, `db-config.json` |
| `file?.txt` | Single character variation | `file1.txt`, `fileA.txt` |
| `[123].json` | Character set | `1.json`, `2.json`, `3.json` |
| `[a-z]*.js` | Character range + wildcard | `a-script.js`, `b-module.js` |

## License

MIT