Initial commit
This commit is contained in:
115
skills/gluegun-patterns/examples/basic-cli/README.md
Normal file
115
skills/gluegun-patterns/examples/basic-cli/README.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Basic Gluegun CLI Example
|
||||
|
||||
A simple example demonstrating core Gluegun CLI patterns.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
basic-cli/
|
||||
├── src/
|
||||
│ ├── cli.ts # CLI entry point
|
||||
│ ├── commands/
|
||||
│ │ ├── hello.ts # Simple command
|
||||
│ │ └── generate.ts # Template generator
|
||||
│ └── extensions/
|
||||
│ └── helpers.ts # Custom toolbox extension
|
||||
├── templates/
|
||||
│ └── component.ts.ejs # Example template
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Basic command structure
|
||||
- Template generation
|
||||
- Custom toolbox extensions
|
||||
- TypeScript support
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Run hello command
|
||||
./bin/cli hello World
|
||||
|
||||
# Generate from template
|
||||
./bin/cli generate MyComponent
|
||||
|
||||
# Show help
|
||||
./bin/cli --help
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### hello
|
||||
|
||||
Simple greeting command demonstrating parameters.
|
||||
|
||||
```bash
|
||||
./bin/cli hello [name]
|
||||
```
|
||||
|
||||
### generate
|
||||
|
||||
Generate files from templates.
|
||||
|
||||
```bash
|
||||
./bin/cli generate <name>
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### 1. Command Structure
|
||||
|
||||
```typescript
|
||||
const command: GluegunCommand = {
|
||||
name: 'hello',
|
||||
run: async (toolbox) => {
|
||||
const { print, parameters } = toolbox
|
||||
const name = parameters.first || 'World'
|
||||
print.success(`Hello, ${name}!`)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Template Generation
|
||||
|
||||
```typescript
|
||||
await template.generate({
|
||||
template: 'component.ts.ejs',
|
||||
target: `src/components/${name}.ts`,
|
||||
props: { name }
|
||||
})
|
||||
```
|
||||
|
||||
### 3. Custom Extensions
|
||||
|
||||
```typescript
|
||||
toolbox.helpers = {
|
||||
formatName: (name: string) => {
|
||||
return name.charAt(0).toUpperCase() + name.slice(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Learning Path
|
||||
|
||||
1. Start with `src/cli.ts` - CLI initialization
|
||||
2. Review `src/commands/hello.ts` - Simple command
|
||||
3. Study `src/commands/generate.ts` - Template usage
|
||||
4. Explore `templates/component.ts.ejs` - EJS templates
|
||||
5. Check `src/extensions/helpers.ts` - Custom toolbox
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Add more commands
|
||||
- Create complex templates
|
||||
- Implement plugin system
|
||||
- Add interactive prompts
|
||||
27
skills/gluegun-patterns/examples/basic-cli/src/cli.ts
Normal file
27
skills/gluegun-patterns/examples/basic-cli/src/cli.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { build } from 'gluegun'
|
||||
|
||||
/**
|
||||
* Create the CLI and kick it off
|
||||
*/
|
||||
async function run(argv: string[] = process.argv) {
|
||||
// Create a CLI runtime
|
||||
const cli = build()
|
||||
.brand('mycli')
|
||||
.src(__dirname)
|
||||
.plugins('./node_modules', { matching: 'mycli-*', hidden: true })
|
||||
.help() // provides default --help command
|
||||
.version() // provides default --version command
|
||||
.create()
|
||||
|
||||
// Enable the following method if you'd like to skip loading one of these core extensions
|
||||
// this can improve performance if they're not necessary for your project:
|
||||
// .exclude(['meta', 'strings', 'print', 'filesystem', 'semver', 'system', 'prompt', 'http', 'template', 'patching', 'package-manager'])
|
||||
|
||||
// Run the CLI
|
||||
const toolbox = await cli.run(argv)
|
||||
|
||||
// Send it back (for testing, mostly)
|
||||
return toolbox
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
@@ -0,0 +1,88 @@
|
||||
import { GluegunCommand } from 'gluegun'
|
||||
|
||||
/**
|
||||
* Generate Command
|
||||
* Demonstrates template generation and filesystem operations
|
||||
*/
|
||||
const command: GluegunCommand = {
|
||||
name: 'generate',
|
||||
alias: ['g', 'create'],
|
||||
description: 'Generate a new component from template',
|
||||
|
||||
run: async (toolbox) => {
|
||||
const { template, print, parameters, filesystem, strings } = toolbox
|
||||
|
||||
// Get component name
|
||||
const name = parameters.first
|
||||
|
||||
if (!name) {
|
||||
print.error('Component name is required')
|
||||
print.info('Usage: mycli generate <ComponentName>')
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to different cases
|
||||
const pascalName = strings.pascalCase(name)
|
||||
const kebabName = strings.kebabCase(name)
|
||||
|
||||
// Target directory
|
||||
const targetDir = 'src/components'
|
||||
const targetFile = `${targetDir}/${kebabName}.ts`
|
||||
|
||||
// Ensure directory exists
|
||||
await filesystem.dir(targetDir)
|
||||
|
||||
// Check if file already exists
|
||||
if (filesystem.exists(targetFile)) {
|
||||
const overwrite = await toolbox.prompt.confirm(
|
||||
`${targetFile} already exists. Overwrite?`
|
||||
)
|
||||
|
||||
if (!overwrite) {
|
||||
print.warning('Generation cancelled')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Show spinner while generating
|
||||
const spinner = print.spin(`Generating ${pascalName} component...`)
|
||||
|
||||
try {
|
||||
// Generate from template
|
||||
await template.generate({
|
||||
template: 'component.ts.ejs',
|
||||
target: targetFile,
|
||||
props: {
|
||||
name: pascalName,
|
||||
kebabName,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
})
|
||||
|
||||
spinner.succeed(`Generated ${targetFile}`)
|
||||
|
||||
// Add to index if it exists
|
||||
const indexPath = `${targetDir}/index.ts`
|
||||
if (filesystem.exists(indexPath)) {
|
||||
await filesystem.append(
|
||||
indexPath,
|
||||
`export { ${pascalName} } from './${kebabName}'\n`
|
||||
)
|
||||
print.info(`Added export to ${indexPath}`)
|
||||
}
|
||||
|
||||
// Success message with details
|
||||
print.success('Component generated successfully!')
|
||||
print.info('')
|
||||
print.info('Next steps:')
|
||||
print.info(` 1. Edit ${targetFile}`)
|
||||
print.info(` 2. Import in your app: import { ${pascalName} } from './components/${kebabName}'`)
|
||||
|
||||
} catch (error) {
|
||||
spinner.fail('Generation failed')
|
||||
print.error(error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = command
|
||||
@@ -0,0 +1,41 @@
|
||||
import { GluegunCommand } from 'gluegun'
|
||||
|
||||
/**
|
||||
* Hello Command
|
||||
* Demonstrates basic parameter handling and print utilities
|
||||
*/
|
||||
const command: GluegunCommand = {
|
||||
name: 'hello',
|
||||
alias: ['hi', 'greet'],
|
||||
description: 'Say hello to someone',
|
||||
|
||||
run: async (toolbox) => {
|
||||
const { print, parameters } = toolbox
|
||||
|
||||
// Get name from first parameter
|
||||
const name = parameters.first || 'World'
|
||||
|
||||
// Get options
|
||||
const options = parameters.options
|
||||
const loud = options.loud || options.l
|
||||
|
||||
// Format message
|
||||
let message = `Hello, ${name}!`
|
||||
|
||||
if (loud) {
|
||||
message = message.toUpperCase()
|
||||
}
|
||||
|
||||
// Display with appropriate style
|
||||
print.success(message)
|
||||
|
||||
// Show some additional info if verbose
|
||||
if (options.verbose || options.v) {
|
||||
print.info('Command executed successfully')
|
||||
print.info(`Parameters: ${JSON.stringify(parameters.array)}`)
|
||||
print.info(`Options: ${JSON.stringify(options)}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = command
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* <%= name %> Component
|
||||
* Generated: <%= timestamp %>
|
||||
*/
|
||||
|
||||
export interface <%= name %>Props {
|
||||
// Add your props here
|
||||
}
|
||||
|
||||
export class <%= name %> {
|
||||
private props: <%= name %>Props
|
||||
|
||||
constructor(props: <%= name %>Props) {
|
||||
this.props = props
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
console.log('<%= name %> rendered')
|
||||
}
|
||||
}
|
||||
|
||||
// Export for convenience
|
||||
export default <%= name %>
|
||||
Reference in New Issue
Block a user