Skip to content

Commit

Permalink
feat: config file support
Browse files Browse the repository at this point in the history
  • Loading branch information
jenslys committed Dec 26, 2024
1 parent 8a32655 commit 8e1b916
Show file tree
Hide file tree
Showing 9 changed files with 544 additions and 415 deletions.
290 changes: 100 additions & 190 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ A beautiful process runner for parallel commands with interactive filtering and
- 📊 Real-time output monitoring
- 🔄 Process state management
- 💾 Configurable output buffer size
- 🔗 Optional dependency ordering with ready state detection
- 🔗 Optional dependency ordering with ready state detection (via config file)
- 📝 Automatic log file generation with customizable paths
- 📋 JSON Schema for config file validation and IDE support

## Installation 📦

Expand All @@ -37,205 +38,134 @@ yarn global add sinfonia

## Usage 🛠️

Basic usage:
Sinfonia offers two modes of operation:

```bash
sinfonia "NAME=COMMAND" "NAME2=COMMAND2"
```
### Simple Mode (CLI)

Using groups:
For basic usage without dependencies:

```bash
sinfonia "GROUP:NAME=COMMAND" "GROUP:NAME2=COMMAND2"
```
# Single command
sinfonia "web=npm run dev"

Using dependencies and ready patterns:
# Multiple commands
sinfonia "web=npm run dev" "api=npm run server"

```bash
# Basic dependency (no ready pattern)
sinfonia "api@db=npm run api"

# Single dependency with ready pattern
sinfonia "api@db=npm run api :: {
db: 'Database ready'
}"

# Multiple dependencies
sinfonia "api@db,cache=npm run api"

# Multiple dependencies with ready patterns
sinfonia "api@db,cache,auth=npm run api :: {
db: 'Database system is ready',
cache: 'Ready to accept connections',
auth: 'Auth service started'
}"

# Complex example with groups and multiple dependencies
sinfonia \
"infra:db=docker compose up" \
"infra:cache=redis-server" \
"infra:auth=npm run auth" \
"backend:api@db,cache,auth=npm run api :: {
db: 'Database system is ready',
cache: 'Ready to accept connections',
auth: 'Auth service started'
}" \
"backend:worker@db,cache=npm run worker :: {
db: 'Database system is ready',
cache: 'Ready to accept connections'
}" \
"frontend:web@api=npm run dev :: {
api: 'Server started on port 3000'
}"
# With groups
sinfonia "frontend:web=npm run dev" "backend:api=npm run server"
```

Real-world examples:
Features available in CLI mode:

```bash
# Next.js + API + Database
sinfonia \
"db=docker compose up" \
"api@db=npm run api :: {
db: 'Database system is ready'
}" \
"web@api=next dev :: {
api: 'Server started on port'
}"

# Microservices with shared dependencies
sinfonia \
"db=docker compose up" \
"cache=redis-server" \
"auth@db,cache=npm run auth :: {
db: 'Database ready',
cache: 'Ready to accept'
}" \
"users@db,cache=npm run users :: {
db: 'Database ready',
cache: 'Ready to accept'
}" \
"gateway@auth,users=npm run gateway :: {
auth: 'Auth ready on port 4000',
users: 'Users ready on port 4001'
}"

# Full-stack with background workers
sinfonia \
"db=docker compose up" \
"cache=redis-server" \
"queue=rabbitmq-server" \
"api@db,cache,queue=npm run api :: {
db: 'PostgreSQL init process complete',
cache: 'Ready to accept connections',
queue: 'Server startup complete'
}" \
"worker@db,queue=npm run worker :: {
db: 'PostgreSQL init process complete',
queue: 'Server startup complete'
}" \
"web@api=npm run dev :: {
api: 'Ready on port 3000'
}"
```
- Basic command running (`name=cmd`)
- Basic grouping (`group:name=cmd`)
- Global color settings (`--color`)
- Buffer size (`-b, --buffer-size`)
- Log file (`-l, --log-file`)

### Command Format

```text
┌─ Optional group name
│ ┌─ Process name
│ │ ┌─ Optional dependencies
│ │ │ ┌─ The command to run
│ │ │ │
GROUP:NAME@DEP1,DEP2=COMMAND :: {
DEP1: 'ready pattern for DEP1',
DEP2: 'ready pattern for DEP2'
}
└─ Optional ready patterns
```

#### Components

| Component | Description | Example |
|-----------|-------------|---------|
| `GROUP:` | Optional group name for organizing processes | `frontend:`, `backend:` |
| `NAME` | Required process name | `web`, `api`, `db` |
| `@DEP1,DEP2` | Optional comma-separated dependencies | `@db,cache,auth` |
| `COMMAND` | The command to run | `npm run dev` |
| `:: {...}` | Optional ready patterns for dependencies | `:: {db: 'Database ready'}` |
### Advanced Mode (Config File)

#### Examples
For complex setups with dependencies, use a config file. You can generate a starter config with:

```bash
# Basic process
"web=npm run dev"

# With group
"frontend:web=npm run dev"

# With dependency
"api@db=npm run api"

# With ready pattern
"api@db=npm run api :: {
db: 'Database ready'
}"
# Generate a starter config file (sinfonia.json)
sinfonia init

# Full example
"backend:api@db,cache=npm run api :: {
db: 'Database ready',
cache: 'Cache ready'
}"
# Generate and overwrite existing config
sinfonia init --force
```

### Dependencies and Ready Patterns

Dependencies can be specified in two ways:

1. Simple dependency (wait for process to start):
Then run it with:

```bash
"api@db=npm run api"
```

1. Pattern dependency (wait for specific output):
# Uses sinfonia.json by default
sinfonia

```bash
"api@db=npm run api :: {
db: 'Database ready'
}"
# Or specify a different config file
sinfonia -c custom.json
```

#### Behavior

- **Without ready pattern**: Process starts as soon as its dependency is running

```bash
"web@api=npm run web" # Web starts as soon as API process is running
```

- **With ready pattern**: Process waits for both:
1. Dependency process to be running
2. Dependency output to match the specified pattern

```bash
"web@api=npm run web :: {
api: 'API server ready on port 3000'
}" # Web starts only after API outputs the ready message
```
Additional features in config mode:

- Everything from CLI mode
- Dependencies between commands (`dependsOn`)
- Ready patterns for dependencies (`readyPatterns`)
- Per-command and per-group color customization
- Reusable configuration

Example config file (`sinfonia.json`):

```json
{
"$schema": "https://raw.githubusercontent.com/cursor-inc/sinfonia/main/schema.json",
"commands": [
{
"name": "DB",
"cmd": "docker compose up",
"color": "blue"
},
{
"name": "API",
"cmd": "npm run api",
"group": "BACKEND",
"dependsOn": ["DB"],
"readyPatterns": {
"db": "Database system is ready"
}
},
{
"name": "WORKER",
"cmd": "npm run worker",
"group": "BACKEND",
"dependsOn": ["DB"],
"readyPatterns": {
"db": "Database system is ready"
}
},
{
"name": "WEB",
"cmd": "npm run dev",
"group": "FRONTEND",
"dependsOn": ["API"],
"readyPatterns": {
"api": "Server started on port"
}
}
],
"groups": [
{
"name": "BACKEND",
"color": "cyan",
"commands": ["API", "WORKER"]
},
{
"name": "FRONTEND",
"color": "magenta",
"commands": ["WEB"]
}
],
"options": {
"bufferSize": 100
}
}
```

This allows for flexible dependency management - use simple dependencies when you just need a process to be running, or add ready patterns when you need to wait for specific initialization steps.
The config file supports JSON Schema validation for better IDE support and validation.

### Options

```bash
# Custom colors
sinfonia -c "red,blue,green" "web=npm run dev" "api=npm run server"
# Custom colors (CLI only)
sinfonia --color "red,blue,green" "web=npm run dev" "api=npm run server"

# Custom buffer size (default: 100 lines per process)
# Custom buffer size
sinfonia -b 200 "web=npm run dev" "api=npm run server"

# Save logs to file (default: sinfonia_{timestamp}.log)
# Enable logging to file
sinfonia -l "output_{timestamp}.log" "web=npm run dev" "api=npm run server"

# Use custom config file
sinfonia -c custom.json
```

## Controls 🎮
Expand All @@ -252,26 +182,6 @@ sinfonia -l "output_{timestamp}.log" "web=npm run dev" "api=npm run server"

![preview-screenshot](https://media.cleanshot.cloud/media/19237/ssEkSOOhpPhptEMQmvuJYH8JuprioiRt5Gk30POR.jpeg?Expires=1735168137&Signature=KqCIliVJBpjOuU3AEWXgb8TOpcG-sexSnDup2q5bAGIPh1oViF5AvLVbBZIWj7GVRhS~jHDejavruyXBqRZ0BUdXxuaR6q1CsduiSmyf0T3toyJIp1605sAo8EzM8V7CphA~xKMbnUMDPQFyRmGzb5Na6F3iGUjPQ2u8ntkHjZ05BPfhvWeQoxAcjMqFzd-RxZfSt3ny~fzt~1kiTcz02hCZQxDQStOqhR7rGzepVSbiLpHurpfjrpi94Q52chxVsUT~oajBE4RZ1hWCJGpICEKT~uy7m4rGDXh9fgy3Ux0MV5UGUG6AUSZld77uP5vu0c0pZ0mbOETfdeVIf6O8dQ__&Key-Pair-Id=K269JMAT9ZF4GZ)

## Comparison with Other Tools 🔍

Sinfonia brings features that aren't available in other process managers:

### Feature Comparison

| Feature | Sinfonia | Concurrently | npm-run-all | Foreman |
|---------------------------------|----------|--------------|-------------|----------|
| Parallel Execution |||||
| Process Grouping |||||
| Interactive Output Filtering |||||
| Color-coded Output |||||
| Interactive Process Control |||||
| Real-time Output Monitoring |||||
| Process State Management |||||
| Configurable Output Buffer |||||
| Dependency Ordering |||||
| Ready State Detection |||||
| Setup Complexity | Simple | Simple | Simple | Medium |

## License 📄

[MIT](LICENSE)
45 changes: 45 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"files": {
"ignore": ["dist/**", "node_modules/**"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noControlCharactersInRegex": "off",
"noExplicitAny": "error"
},
"complexity": {
"useLiteralKeys": "error",
"noStaticOnlyClass": "error",
"noForEach": "off"
},
"style": {
"noUnusedTemplateLiteral": "off",
"noNonNullAssertion": "warn",
"useNodejsImportProtocol": "error",
"useConst": "error",
"noVar": "error"
},
"correctness": {
"noUnusedVariables": "error",
"noUndeclaredVariables": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "es5",
"semicolons": "always"
}
}
}
Binary file modified bun.lockb
Binary file not shown.
Loading

0 comments on commit 8e1b916

Please sign in to comment.