Initial commit
This commit is contained in:
252
skills/gluegun-patterns/examples/plugin-system/README.md
Normal file
252
skills/gluegun-patterns/examples/plugin-system/README.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# Gluegun Plugin System Example
|
||||
|
||||
Demonstrates how to build an extensible CLI with plugin architecture.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
plugin-system/
|
||||
├── src/
|
||||
│ ├── cli.ts # CLI with plugin loading
|
||||
│ ├── commands/
|
||||
│ │ └── plugin.ts # Plugin management command
|
||||
│ └── plugins/
|
||||
│ ├── custom-plugin.ts # Example plugin
|
||||
│ └── validator-plugin.ts # Validation plugin
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Plugin discovery and loading
|
||||
- Custom toolbox extensions via plugins
|
||||
- Plugin-provided commands
|
||||
- Plugin configuration management
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Load Plugins
|
||||
|
||||
```bash
|
||||
# CLI automatically loads plugins from:
|
||||
# - ./plugins/
|
||||
# - ./node_modules/mycli-*
|
||||
```
|
||||
|
||||
### Use Plugin Commands
|
||||
|
||||
```bash
|
||||
# Commands added by plugins
|
||||
./bin/cli validate
|
||||
./bin/cli custom-action
|
||||
```
|
||||
|
||||
### Use Plugin Extensions
|
||||
|
||||
```typescript
|
||||
// In any command
|
||||
const { myPlugin } = toolbox
|
||||
myPlugin.doSomething()
|
||||
```
|
||||
|
||||
## Creating a Plugin
|
||||
|
||||
### Basic Plugin Structure
|
||||
|
||||
```typescript
|
||||
module.exports = (toolbox) => {
|
||||
const { print } = toolbox
|
||||
|
||||
// Add to toolbox
|
||||
toolbox.myPlugin = {
|
||||
version: '1.0.0',
|
||||
doSomething: () => {
|
||||
print.info('Plugin action executed')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin with Commands
|
||||
|
||||
```typescript
|
||||
module.exports = (toolbox) => {
|
||||
const { runtime } = toolbox
|
||||
|
||||
runtime.addPlugin({
|
||||
name: 'my-plugin',
|
||||
commands: [
|
||||
{
|
||||
name: 'my-command',
|
||||
run: async (toolbox) => {
|
||||
// Command implementation
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Discovery
|
||||
|
||||
The CLI looks for plugins in:
|
||||
|
||||
1. **Local plugins directory**: `./plugins/*.js`
|
||||
2. **Node modules**: `./node_modules/mycli-*`
|
||||
3. **Scoped packages**: `@scope/mycli-*`
|
||||
|
||||
## Plugin Naming Convention
|
||||
|
||||
- Local plugins: Any `.js` or `.ts` file in `plugins/`
|
||||
- NPM plugins: Must match pattern `mycli-*`
|
||||
- Example: `mycli-validator`, `@myorg/mycli-helper`
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### 1. Load Plugins from Directory
|
||||
|
||||
```typescript
|
||||
cli.plugins('./plugins', { matching: '*.js' })
|
||||
```
|
||||
|
||||
### 2. Load NPM Plugins
|
||||
|
||||
```typescript
|
||||
cli.plugins('./node_modules', {
|
||||
matching: 'mycli-*',
|
||||
hidden: true
|
||||
})
|
||||
```
|
||||
|
||||
### 3. Add Toolbox Extension
|
||||
|
||||
```typescript
|
||||
toolbox.validator = {
|
||||
validate: (data) => { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Register Commands
|
||||
|
||||
```typescript
|
||||
runtime.addPlugin({
|
||||
name: 'my-plugin',
|
||||
commands: [/* commands */]
|
||||
})
|
||||
```
|
||||
|
||||
## Example Plugins
|
||||
|
||||
### custom-plugin.ts
|
||||
|
||||
Adds custom utilities to toolbox.
|
||||
|
||||
```typescript
|
||||
toolbox.custom = {
|
||||
formatDate: (date) => { /* ... */ },
|
||||
parseConfig: (file) => { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
### validator-plugin.ts
|
||||
|
||||
Adds validation command and utilities.
|
||||
|
||||
```typescript
|
||||
toolbox.validator = {
|
||||
validateFile: (path) => { /* ... */ },
|
||||
validateSchema: (data) => { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
## Publishing Plugins
|
||||
|
||||
### 1. Create NPM Package
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "mycli-myplugin",
|
||||
"main": "dist/index.js",
|
||||
"keywords": ["mycli", "plugin"]
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Export Plugin
|
||||
|
||||
```typescript
|
||||
module.exports = (toolbox) => {
|
||||
// Plugin implementation
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Publish
|
||||
|
||||
```bash
|
||||
npm publish
|
||||
```
|
||||
|
||||
### 4. Install and Use
|
||||
|
||||
```bash
|
||||
npm install mycli-myplugin
|
||||
# Automatically loaded by CLI
|
||||
```
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Conditional Plugin Loading
|
||||
|
||||
```typescript
|
||||
if (config.enablePlugin) {
|
||||
cli.plugins('./plugins/optional')
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin Configuration
|
||||
|
||||
```typescript
|
||||
toolbox.myPlugin = {
|
||||
config: await filesystem.read('.mypluginrc', 'json'),
|
||||
// Plugin methods
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin Dependencies
|
||||
|
||||
```typescript
|
||||
module.exports = (toolbox) => {
|
||||
// Check for required plugins
|
||||
if (!toolbox.otherPlugin) {
|
||||
throw new Error('Requires other-plugin')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Namespace Extensions**: Use unique names for toolbox extensions
|
||||
2. **Document APIs**: Provide clear documentation for plugin methods
|
||||
3. **Handle Errors**: Validate inputs and handle failures gracefully
|
||||
4. **Version Plugins**: Use semantic versioning
|
||||
5. **Test Plugins**: Write tests for plugin functionality
|
||||
|
||||
## Testing Plugins
|
||||
|
||||
```typescript
|
||||
import { build } from 'gluegun'
|
||||
|
||||
test('plugin loads correctly', async () => {
|
||||
const cli = build().src(__dirname).plugins('./plugins').create()
|
||||
const toolbox = await cli.run()
|
||||
|
||||
expect(toolbox.myPlugin).toBeDefined()
|
||||
})
|
||||
```
|
||||
Reference in New Issue
Block a user