Package Exports
- vite-plugin-gas
Readme
vite-plugin-gas
A Vite plugin for Google Apps Script development with TypeScript support.
Features
- ๐ Built-in TypeScript Support - Uses Vite's native esbuild for TypeScript compilation (no external TypeScript plugin required)
- ๐ Module Statement Removal - Automatically removes import/export statements unsupported by GAS
- ๐ก๏ธ GAS Function Protection - Preserves special GAS functions (onEdit, onOpen, etc.) from optimization
- โก Zero Configuration - Works out-of-the-box with minimal setup
- ๐ฏ ES2017 Compatibility - Optimized for Google Apps Script runtime
- ๐ Auto-Detection - Automatically detects TypeScript files in specified directories
- ๐งน Smart File Filtering - Automatically filters out empty files and comment-only files
- ๐ console.log Transform - Optionally transforms console.log to Logger.log for GAS compatibility
- ๐ appsscript.json Copy - Automatically copies appsscript.json to output directory for deployment
Installation
npm install vite-plugin-gas --save-dev
# or
pnpm add vite-plugin-gas -D
# or
yarn add vite-plugin-gas --devQuick Start
โจ Simple Setup (Recommended)
No need for additional TypeScript plugins! This plugin leverages Vite's built-in TypeScript support:
// vite.config.ts
import { defineConfig } from 'vite'
import gas from 'vite-plugin-gas'
export default defineConfig({
plugins: [
gas() // That's it! No additional TypeScript plugin needed
]
})
### ๐ฏ Advanced Configuration
```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import gas from 'vite-plugin-gas'
export default defineConfig({
plugins: [
gas({
autoDetect: true,
include: ['src', 'lib'],
exclude: ['**/*.test.ts', '**/*.spec.ts'],
outDir: 'dist',
transformLogger: true,
copyAppsscriptJson: true
})
]
})โ What NOT to do
Before (with this plugin, you no longer need this):
// DON'T DO THIS - No longer needed!
import typescript from '@rollup/plugin-typescript'
import { defineConfig } from 'vite'
import gas from 'vite-plugin-gas'
export default defineConfig({
plugins: [
typescript(), // โ Not needed - vite-plugin-gas handles TypeScript
gas(),
],
})After (correct usage):
// โ
Simple and clean
import { defineConfig } from 'vite'
import gas from 'vite-plugin-gas'
export default defineConfig({
plugins: [
gas(), // โ
Handles TypeScript automatically
],
})Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
autoDetect |
boolean |
true |
Enable automatic TypeScript file detection |
include |
string[] |
['src'] |
Directories to include when scanning for files |
exclude |
string[] |
['**/*.test.ts', '**/*.spec.ts'] |
File patterns to exclude |
outDir |
string |
'dist' |
Output directory for compiled files |
transformLogger |
boolean |
true |
Replace console.log with Logger.log for GAS |
copyAppsscriptJson |
boolean |
true |
Automatically copy appsscript.json to output directory |
enablePathAliases |
boolean |
true |
Enable automatic path aliases configuration |
pathAliases |
Record<string, string> |
{ '@': './src', '~': './src' } |
Custom path aliases for module resolution |
How It Works
TypeScript Compilation Process
- Vite's esbuild compiles TypeScript to JavaScript
- vite-plugin-gas processes the JavaScript output:
- Removes import/export statements
- Transforms console.log to Logger.log (optional)
- Preserves GAS special functions
- Bundles dependencies
Example Transformation
Input (TypeScript):
// src/main.ts
import { helper } from './utils/helper'
export function onEdit(e: GoogleAppsScript.Events.SheetsOnEdit) {
console.log('Edit detected')
helper.processEdit(e)
}
export function doGet(): GoogleAppsScript.HTML.HtmlOutput {
console.log('GET request received')
return HtmlService.createHtmlOutput('<h1>Hello GAS!</h1>')
}Output (JavaScript for GAS):
// dist/main.js
/* @preserve onEdit */ function onEdit(e) {
Logger.log('Edit detected')
helper.processEdit(e)
}
/* @preserve doGet */ function doGet() {
Logger.log('GET request received')
return HtmlService.createHtmlOutput('<h1>Hello GAS!</h1>')
}
// helper functions are bundled here...Troubleshooting
Common Issues
Error: "X is not exported by Y"
โ Before: You needed @rollup/plugin-typescript to resolve this
โ
After: This plugin now handles TypeScript compilation automatically
Path alias resolution errors (e.g., @/module not found)
โ
Solution: The plugin automatically configures common path aliases (@ and ~ pointing to ./src)
// Automatically supported imports
import { helper } from '@/utils/helper'
import { config } from '~/config'Custom path aliases
โ Solution: Configure custom aliases via plugin options
gas({
pathAliases: {
'@': './src',
'@lib': './lib',
'@utils': './src/utils'
}
})Missing imports after build
โ Solution: The plugin automatically bundles all dependencies into each output file
GAS functions not working
โ
Solution: Special GAS functions (onEdit, onOpen, etc.) are automatically preserved with @preserve comments
Advanced Usage
Manual Entry Configuration
If you prefer manual control over entry points:
// vite.config.ts
export default defineConfig({
plugins: [
gas({
autoDetect: false // Disable auto-detection
})
],
build: {
rollupOptions: {
input: {
main: 'src/main.ts',
triggers: 'src/triggers.ts',
'utils/helper': 'src/utils/helper.ts'
}
}
}
})Path Aliases Configuration
The plugin automatically configures path aliases for cleaner imports:
// Default configuration
gas({
enablePathAliases: true, // Enable automatic path aliases
pathAliases: {
'@': './src', // @/utils/helper -> src/utils/helper
'~': './src' // ~/config -> src/config
}
})Custom aliases for complex projects:
gas({
pathAliases: {
'@': './src',
'@lib': './lib',
'@utils': './src/utils',
'@models': './src/models',
'@config': './config'
}
})Usage in TypeScript files:
// src/main.ts
import { processData } from '@utils/processor'
import { UserModel } from '@models/user'
import { API_CONFIG } from '@config/api'
function onEdit(e: GoogleAppsScript.Events.SheetsOnEdit) {
const userData = processData(e.range.getValue())
const user = new UserModel(userData)
// ... rest of your code
}Working with Clasp
This plugin works seamlessly with clasp for GAS deployment:
// .clasp.json
{
"scriptId": "your-script-id",
"rootDir": "./dist"
}# Build and deploy
npm run build
clasp pushappsscript.json Management
The plugin automatically copies your appsscript.json file to the output directory for seamless deployment:
// vite.config.ts
export default defineConfig({
plugins: [
gas({
copyAppsscriptJson: true // Default: true
})
]
})Project Structure:
project/
โโโ src/
โ โโโ main.ts
โ โโโ utils.ts
โโโ appsscript.json # Source manifest
โโโ dist/ # Build output
โโโ main.js
โโโ utils.js
โโโ appsscript.json # Automatically copiedBenefits:
- Ensures manifest file is always included in deployments
- Maintains consistency between source and build directories
- Works seamlessly with clasp deployment workflow
- Can be disabled if you prefer manual manifest management
Handling Empty Files
The plugin gracefully handles various file states:
- โ Empty files (0 bytes)
- โ Whitespace-only files
- โ Comment-only files
- โ Files with only type definitions โ โโโ utils/ โ โโโ helpers.ts # Utility functions
โโโ dist/ # Build output (individual files) โ โโโ main.js โ โโโ triggers.js โ โโโ helpers.js โโโ vite.config.ts โโโ package.json
### Example Code
#### Input (TypeScript)
```typescript
// src/main.ts
import { logMessage } from './utils/helpers'
function main() {
logMessage('Hello, GAS!')
}
// src/triggers.ts
function onOpen() {
main()
## Example
### Input (TypeScript)
```typescript
// src/main.ts
import { helper } from './utils/helper'
export function main() {
console.log('Hello, GAS!')
helper()
}
// src/utils/helper.ts
export function helper() {
console.log('Helper function called')
}
// src/triggers.ts
function onOpen() {
main()
}
function onEdit(e: GoogleAppsScript.Events.SheetsOnEdit) {
console.log('Cell edited:', e.range.getA1Notation())
}Output (JavaScript)
// dist/main.js
function helper() {
Logger.log('Helper function called');
}
function main() {
Logger.log('Hello, GAS!');
helper();
}
// dist/utils/helper.js
function helper() {
Logger.log('Helper function called');
}
// dist/triggers.js
function onOpen() {
main();
}
function onEdit(e) {
Logger.log('Cell edited:', e.range.getA1Notation());
}GAS Special Functions
The plugin automatically preserves these Google Apps Script special functions:
onOpen()- Triggered when a spreadsheet/document is openedonEdit(e)- Triggered when a spreadsheet is editedonSelectionChange(e)- Triggered when selection changesonFormSubmit(e)- Triggered when a form is submitteddoGet(e)- HTTP GET request handlerdoPost(e)- HTTP POST request handleronInstall(e)- Triggered when an add-on is installed
Scripts
{
"scripts": {
"build": "vite build",
"dev": "vite build --watch",
"deploy": "npm run build && clasp push"
}
}Requirements
- Node.js 18.0.0 or higher
- Vite 5.0.0 or higher
Quality Assurance
This project maintains high quality standards:
Development Standards
- Test Coverage: >90% maintained across all modules
- camelCase Convention: Consistent file naming throughout the project
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT ยฉ 11gather11
Changelog
See CHANGELOG.md for details about changes in each version.
- Test Coverage: Minimum 90% test coverage required (currently achieving 94.94%)
- Error Handling: Comprehensive error handling with proper runtime type checking
File Naming Convention
- camelCase: All source files use camelCase naming convention
- Examples:
gasConfigProcessor.ts(notgas-config-processor.ts)fileDetector.ts(notfile-detector.ts)viteConfig.ts(notvite-config.ts)
Testing Standards
- All new features must include comprehensive tests
- Tests must cover both success and error cases
- Mock external dependencies appropriately
- Maintain high test coverage (90%+ required)
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.