esbuild-plugin-scriptable
An ESBuild plugin for developing Scriptable iOS app scripts with modern JavaScript tooling.
Requirements
- Node.js 14 or later
- esbuild 0.24 or later
- Scriptable iOS app with iCloud Drive sync enabled
Features
- Automatically adds Scriptable metadata banner to output files
- Supports manifest files for script configuration
- Uses manifest name as output filename (if specified)
- Handles deployment to iCloud Drive with auto-detection
- Full TypeScript support with type definitions
- File filtering with glob pattern matching
- Custom manifest path mapping
- Configurable warning behaviors
- Continues building even when deployment fails (configurable)
Installation
npm install esbuild-plugin-scriptable --save-dev
pnpm add esbuild-plugin-scriptable --save-dev
yarn add esbuild-plugin-scriptable --dev
Basic Usage
import {build} from 'esbuild';
import {scriptableBanner, scriptableDeploy} from 'esbuild-plugin-scriptable';
await build({
entryPoints: ['src/widget.ts'],
outfile: 'dist/widget.js',
bundle: true,
plugins: [
scriptableBanner({
warnOnMissingManifest: true,
patterns: '**/*.widget.ts',
}),
scriptableDeploy({
verbose: true,
patterns: '**/*.widget.ts',
}),
],
});
Configuration
Banner Plugin Options
manifestExtensions
: Custom manifest file extensions (default: ['.manifest.json', '.manifest', '.json'])warnOnMissingManifest
: Show warning when manifest file is missing (default: true)warnOnInvalidManifest
: Show warning when manifest file is invalid (default: true)warnOnMissingEntry
: Show warning when no matching entry point is found (default: true)getManifestPath
: Custom manifest file path mapping functionpatterns
: Source file patterns to match entry points (default: ['**/*.{ts,tsx,js,jsx}'])
- Can be a string or array of strings
- Supports glob patterns with negation (! prefix)
- Examples:
'**/*.widget.ts'
- only process widget source files['**/*.ts', '!**/*.test.ts']
- exclude test files
Deploy Plugin Options
verbose
: Show detailed logs during deployment (default: false)continueOnError
: Continue building when deployment fails (default: true)scriptableDir
: Custom Scriptable directory path (default: auto-detect in iCloud Drive)patterns
: Source file patterns to match entry points (default: ['**/*.{ts,tsx,js,jsx}'])
- Can be a string or array of strings
- Supports glob patterns with negation (! prefix)
- Examples:
'**/*.widget.ts'
- only deploy widget source files['**/*.ts', '!**/*.test.ts']
- exclude test files
addBanner
: Whether to add Scriptable banner from manifest (default: true)manifestExtensions
: Custom manifest file extensions (default: ['.manifest.json', '.manifest', '.json'])
Manifest Configuration
The manifest file can be used to configure both the script metadata and the output filename:
{
"name": "weather-widget",
"alwaysRunInApp": true,
"shareSheetInputs": ["file-url", "url"],
"iconColor": "blue",
"iconGlyph": "cloud"
}
When a manifest includes a name
property:
- The deploy plugin will use this name for the output file (e.g.,
weather-widget.js
) - If no name is specified, the original filename will be used
- The banner plugin will still use all manifest properties to generate the script metadata
Advanced Usage
import {build} from 'esbuild';
import {scriptableBanner, scriptableDeploy} from 'esbuild-plugin-scriptable';
await build({
entryPoints: ['src/widget.ts'],
outfile: 'dist/widget.js',
bundle: true,
plugins: [
scriptableBanner({
warnOnMissingManifest: true,
patterns: ['**/*.ts', '!**/*.test.ts'],
getManifestPath: entryPath => {
return entryPath.replace(/\.ts$/, '.manifest.json');
},
}),
scriptableDeploy({
verbose: true,
addBanner: true,
patterns: ['**/*.ts', '!**/*.test.ts'],
scriptableDir: '/custom/path/to/Scriptable',
}),
],
});
License
Apache-2.0