@hypnosis/docker-mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/dist/adapters/adapter-registry.d.ts +29 -0
- package/dist/adapters/adapter-registry.d.ts.map +1 -0
- package/dist/adapters/adapter-registry.js +47 -0
- package/dist/adapters/adapter-registry.js.map +1 -0
- package/dist/adapters/database-adapter.d.ts +33 -0
- package/dist/adapters/database-adapter.d.ts.map +1 -0
- package/dist/adapters/database-adapter.js +6 -0
- package/dist/adapters/database-adapter.js.map +1 -0
- package/dist/adapters/postgresql.d.ts +42 -0
- package/dist/adapters/postgresql.d.ts.map +1 -0
- package/dist/adapters/postgresql.js +202 -0
- package/dist/adapters/postgresql.js.map +1 -0
- package/dist/adapters/redis.d.ts +46 -0
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js +202 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +34 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +126 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/types.d.ts +53 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +5 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +319 -0
- package/dist/cli.js.map +1 -0
- package/dist/discovery/compose-parser.d.ts +35 -0
- package/dist/discovery/compose-parser.d.ts.map +1 -0
- package/dist/discovery/compose-parser.js +126 -0
- package/dist/discovery/compose-parser.js.map +1 -0
- package/dist/discovery/config-merger.d.ts +19 -0
- package/dist/discovery/config-merger.d.ts.map +1 -0
- package/dist/discovery/config-merger.js +60 -0
- package/dist/discovery/config-merger.js.map +1 -0
- package/dist/discovery/project-discovery.d.ts +53 -0
- package/dist/discovery/project-discovery.d.ts.map +1 -0
- package/dist/discovery/project-discovery.js +252 -0
- package/dist/discovery/project-discovery.js.map +1 -0
- package/dist/discovery/types.d.ts +47 -0
- package/dist/discovery/types.d.ts.map +1 -0
- package/dist/discovery/types.js +6 -0
- package/dist/discovery/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/compose-manager.d.ts +30 -0
- package/dist/managers/compose-manager.d.ts.map +1 -0
- package/dist/managers/compose-manager.js +70 -0
- package/dist/managers/compose-manager.js.map +1 -0
- package/dist/managers/container-manager.d.ts +81 -0
- package/dist/managers/container-manager.d.ts.map +1 -0
- package/dist/managers/container-manager.js +278 -0
- package/dist/managers/container-manager.js.map +1 -0
- package/dist/managers/env-manager.d.ts +37 -0
- package/dist/managers/env-manager.d.ts.map +1 -0
- package/dist/managers/env-manager.js +124 -0
- package/dist/managers/env-manager.js.map +1 -0
- package/dist/security/sql-validator.d.ts +23 -0
- package/dist/security/sql-validator.d.ts.map +1 -0
- package/dist/security/sql-validator.js +44 -0
- package/dist/security/sql-validator.js.map +1 -0
- package/dist/tools/container-tools.d.ts +31 -0
- package/dist/tools/container-tools.d.ts.map +1 -0
- package/dist/tools/container-tools.js +366 -0
- package/dist/tools/container-tools.js.map +1 -0
- package/dist/tools/database-tools.d.ts +22 -0
- package/dist/tools/database-tools.d.ts.map +1 -0
- package/dist/tools/database-tools.js +264 -0
- package/dist/tools/database-tools.js.map +1 -0
- package/dist/tools/env-tools.d.ts +52 -0
- package/dist/tools/env-tools.d.ts.map +1 -0
- package/dist/tools/env-tools.js +318 -0
- package/dist/tools/env-tools.js.map +1 -0
- package/dist/tools/executor-tool.d.ts +18 -0
- package/dist/tools/executor-tool.d.ts.map +1 -0
- package/dist/tools/executor-tool.js +95 -0
- package/dist/tools/executor-tool.js.map +1 -0
- package/dist/tools/mcp-health-tool.d.ts +65 -0
- package/dist/tools/mcp-health-tool.d.ts.map +1 -0
- package/dist/tools/mcp-health-tool.js +126 -0
- package/dist/tools/mcp-health-tool.js.map +1 -0
- package/dist/utils/cache.d.ts +43 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +77 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/compose-exec.d.ts +13 -0
- package/dist/utils/compose-exec.d.ts.map +1 -0
- package/dist/utils/compose-exec.js +33 -0
- package/dist/utils/compose-exec.js.map +1 -0
- package/dist/utils/docker-client.d.ts +33 -0
- package/dist/utils/docker-client.d.ts.map +1 -0
- package/dist/utils/docker-client.js +59 -0
- package/dist/utils/docker-client.js.map +1 -0
- package/dist/utils/logger.d.ts +18 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +38 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Danila Susak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Docker MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@hypnosis/docker-mcp-server)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Universal Docker MCP server for AI assistants (Cursor, Claude Desktop). Manage Docker containers, execute commands, query databases, and handle environment configurations — all through natural language.
|
|
7
|
+
|
|
8
|
+
## ✨ Features
|
|
9
|
+
|
|
10
|
+
- ✅ **16 MCP Commands** — Container management, database operations, environment handling
|
|
11
|
+
- ✅ **Database Support** — PostgreSQL, Redis, SQLite with extensible adapter pattern
|
|
12
|
+
- ✅ **Auto-Discovery** — Automatically finds and parses `docker-compose.yml` files
|
|
13
|
+
- ✅ **Security** — Automatic secrets masking in environment variables
|
|
14
|
+
- ✅ **Follow Logs** — Real-time log streaming with `follow` mode
|
|
15
|
+
- ✅ **Type-Safe** — Written in TypeScript with full type definitions
|
|
16
|
+
- ✅ **Universal** — Works with any Docker project
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
### Global Installation (Recommended)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g @hypnosis/docker-mcp-server
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### NPX (No Installation)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @hypnosis/docker-mcp-server
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Local Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @hypnosis/docker-mcp-server
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 🚀 Quick Start
|
|
39
|
+
|
|
40
|
+
### Configuration for Cursor
|
|
41
|
+
|
|
42
|
+
Add to `~/.cursor/mcp.json` (or `~/.config/cursor/mcp.json`):
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"docker": {
|
|
48
|
+
"command": "npx",
|
|
49
|
+
"args": ["-y", "@hypnosis/docker-mcp-server"],
|
|
50
|
+
"env": {
|
|
51
|
+
"DOCKER_MCP_AUTO_DISCOVER": "true",
|
|
52
|
+
"DOCKER_MCP_MASK_SECRETS": "true"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Configuration for Claude Desktop
|
|
60
|
+
|
|
61
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"docker": {
|
|
67
|
+
"command": "npx",
|
|
68
|
+
"args": ["-y", "@hypnosis/docker-mcp-server"]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### First Steps
|
|
75
|
+
|
|
76
|
+
1. **Restart your AI assistant** (Cursor or Claude Desktop)
|
|
77
|
+
2. **Navigate to your Docker project** directory (with `docker-compose.yml`)
|
|
78
|
+
3. **Ask your AI assistant:**
|
|
79
|
+
- "Show me the status of all containers"
|
|
80
|
+
- "Restart the web service"
|
|
81
|
+
- "Show me the last 50 lines of logs from the database"
|
|
82
|
+
|
|
83
|
+
## 📚 Available Commands
|
|
84
|
+
|
|
85
|
+
### Container Management (7 commands)
|
|
86
|
+
|
|
87
|
+
| Command | Description | Example |
|
|
88
|
+
|---------|-------------|---------|
|
|
89
|
+
| `docker_container_list` | List all containers in project | `docker_container_list()` |
|
|
90
|
+
| `docker_container_start` | Start a container | `docker_container_start("web")` |
|
|
91
|
+
| `docker_container_stop` | Stop a container | `docker_container_stop("web")` |
|
|
92
|
+
| `docker_container_restart` | Restart a container | `docker_container_restart("web")` |
|
|
93
|
+
| `docker_container_logs` | View container logs | `docker_container_logs("web", {follow: true, lines: 100})` |
|
|
94
|
+
| `docker_compose_up` | Start entire stack | `docker_compose_up({build: true})` |
|
|
95
|
+
| `docker_compose_down` | Stop entire stack | `docker_compose_down({volumes: false})` |
|
|
96
|
+
|
|
97
|
+
### Database Operations (4 commands)
|
|
98
|
+
|
|
99
|
+
| Command | Description | Example |
|
|
100
|
+
|---------|-------------|---------|
|
|
101
|
+
| `docker_db_query` | Execute SQL query | `docker_db_query("postgres", "SELECT * FROM users LIMIT 5;")` |
|
|
102
|
+
| `docker_db_backup` | Create database backup | `docker_db_backup("postgres", "./backup.sql")` |
|
|
103
|
+
| `docker_db_restore` | Restore from backup | `docker_db_restore("postgres", "./backup.sql")` |
|
|
104
|
+
| `docker_db_status` | Show database status | `docker_db_status("postgres")` |
|
|
105
|
+
|
|
106
|
+
### Environment & Config (3 commands)
|
|
107
|
+
|
|
108
|
+
| Command | Description | Example |
|
|
109
|
+
|---------|-------------|---------|
|
|
110
|
+
| `docker_env_list` | List environment variables | `docker_env_list()` |
|
|
111
|
+
| `docker_compose_config` | Show parsed compose config | `docker_compose_config()` |
|
|
112
|
+
| `docker_healthcheck` | Check health of all services | `docker_healthcheck()` |
|
|
113
|
+
|
|
114
|
+
### Universal Executor (1 command)
|
|
115
|
+
|
|
116
|
+
| Command | Description | Example |
|
|
117
|
+
|---------|-------------|---------|
|
|
118
|
+
| `docker_exec` | Execute any command in container | `docker_exec("web", "npm test")` |
|
|
119
|
+
|
|
120
|
+
## 💡 Usage Examples
|
|
121
|
+
|
|
122
|
+
### Example 1: Web Development (Next.js + Redis)
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Start the entire stack
|
|
126
|
+
docker_compose_up({build: true, detach: true})
|
|
127
|
+
|
|
128
|
+
// Check if services are healthy
|
|
129
|
+
docker_healthcheck()
|
|
130
|
+
|
|
131
|
+
// View logs in real-time
|
|
132
|
+
docker_container_logs("web", {follow: true, lines: 50})
|
|
133
|
+
|
|
134
|
+
// Check Redis cache
|
|
135
|
+
docker_db_query("redis", "KEYS *")
|
|
136
|
+
|
|
137
|
+
// Run tests
|
|
138
|
+
docker_exec("web", "npm test")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Example 2: Backend Development (Django + PostgreSQL)
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Restart backend after code changes
|
|
145
|
+
docker_container_restart("web")
|
|
146
|
+
|
|
147
|
+
// Run database migrations
|
|
148
|
+
docker_exec("web", "python manage.py migrate")
|
|
149
|
+
|
|
150
|
+
// Query database
|
|
151
|
+
docker_db_query("postgres", "SELECT COUNT(*) FROM auth_user;")
|
|
152
|
+
|
|
153
|
+
// Create backup before deployment
|
|
154
|
+
docker_db_backup("postgres", "./backups/pre-deploy.sql")
|
|
155
|
+
|
|
156
|
+
// View application logs
|
|
157
|
+
docker_container_logs("web", {lines: 100, timestamps: true})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## 🏗️ How It Works
|
|
161
|
+
|
|
162
|
+
### Project Discovery
|
|
163
|
+
|
|
164
|
+
The server automatically discovers your project structure:
|
|
165
|
+
|
|
166
|
+
1. **Finds `docker-compose.yml`** in current directory or parent directories
|
|
167
|
+
2. **Parses project configuration** (services, networks, volumes)
|
|
168
|
+
3. **Detects database types** (PostgreSQL, Redis, SQLite)
|
|
169
|
+
4. **Loads environment files** (`.env`, `.env.local`)
|
|
170
|
+
5. **Masks secrets** automatically (PASSWORD, TOKEN, KEY, etc.)
|
|
171
|
+
|
|
172
|
+
### Database Adapters
|
|
173
|
+
|
|
174
|
+
Extensible adapter pattern for different databases:
|
|
175
|
+
|
|
176
|
+
- **PostgreSQL** — `psql`, `pg_dump`, `pg_restore`
|
|
177
|
+
- **Redis** — `redis-cli`, `SAVE`, `BGSAVE`
|
|
178
|
+
- **SQLite** — `.dump`, `.restore`
|
|
179
|
+
- More databases can be added via adapters
|
|
180
|
+
|
|
181
|
+
## 🔒 Security
|
|
182
|
+
|
|
183
|
+
### Automatic Secrets Masking
|
|
184
|
+
|
|
185
|
+
Environment variables containing sensitive data are automatically masked:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Original .env
|
|
189
|
+
DATABASE_PASSWORD=super_secret_123
|
|
190
|
+
API_TOKEN=abc123xyz
|
|
191
|
+
|
|
192
|
+
// Output from docker_env_list()
|
|
193
|
+
DATABASE_PASSWORD=***MASKED***
|
|
194
|
+
API_TOKEN=***MASKED***
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Keywords that trigger masking: `PASSWORD`, `TOKEN`, `KEY`, `SECRET`, `API_KEY`
|
|
198
|
+
|
|
199
|
+
## 📖 Documentation
|
|
200
|
+
|
|
201
|
+
- **[Quick Start Guide](docs/QUICK_START.md)** — Detailed setup instructions
|
|
202
|
+
- **[API Reference](docs/API_REFERENCE.md)** — Complete command documentation
|
|
203
|
+
- **[Examples](docs/EXAMPLES.md)** — Real-world usage scenarios
|
|
204
|
+
- **[Troubleshooting](docs/TROUBLESHOOTING.md)** — Common issues and solutions
|
|
205
|
+
- **[FAQ](docs/FAQ.md)** — Frequently asked questions
|
|
206
|
+
|
|
207
|
+
For developer documentation, see [docs/DEV/README.md](docs/DEV/README.md)
|
|
208
|
+
|
|
209
|
+
## 🤝 Contributing
|
|
210
|
+
|
|
211
|
+
We welcome contributions! This is an open-source project built for the community.
|
|
212
|
+
|
|
213
|
+
### How to Contribute
|
|
214
|
+
|
|
215
|
+
1. Fork the repository
|
|
216
|
+
2. Create a feature branch
|
|
217
|
+
3. Make your changes
|
|
218
|
+
4. Add tests if applicable
|
|
219
|
+
5. Submit a pull request
|
|
220
|
+
|
|
221
|
+
See [docs/DEV/README.md](docs/DEV/README.md) for development setup and guidelines.
|
|
222
|
+
|
|
223
|
+
## 📝 License
|
|
224
|
+
|
|
225
|
+
MIT License - see [LICENSE](LICENSE) for details
|
|
226
|
+
|
|
227
|
+
Copyright (c) 2025 Danila Susak
|
|
228
|
+
|
|
229
|
+
## 🙏 Acknowledgments
|
|
230
|
+
|
|
231
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) by Anthropic
|
|
232
|
+
- [Docker](https://www.docker.com/) for containerization
|
|
233
|
+
- Community feedback and contributions
|
|
234
|
+
|
|
235
|
+
## 📬 Support
|
|
236
|
+
|
|
237
|
+
- **Issues:** [GitHub Issues](https://github.com/hypnosis/docker-mcp-server/issues)
|
|
238
|
+
- **Discussions:** [GitHub Discussions](https://github.com/hypnosis/docker-mcp-server/discussions)
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
**Made with ❤️ for the AI-powered development community**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry
|
|
3
|
+
* Регистрация и получение Database Adapters по типу БД
|
|
4
|
+
*/
|
|
5
|
+
import type { DatabaseAdapter } from './database-adapter.js';
|
|
6
|
+
export declare class AdapterRegistry {
|
|
7
|
+
private adapters;
|
|
8
|
+
/**
|
|
9
|
+
* Регистрировать адаптер
|
|
10
|
+
*/
|
|
11
|
+
register(type: string, adapter: DatabaseAdapter): void;
|
|
12
|
+
/**
|
|
13
|
+
* Получить адаптер по типу
|
|
14
|
+
*/
|
|
15
|
+
get(serviceType: string): DatabaseAdapter;
|
|
16
|
+
/**
|
|
17
|
+
* Проверить наличие адаптера
|
|
18
|
+
*/
|
|
19
|
+
has(serviceType: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Получить список всех зарегистрированных типов
|
|
22
|
+
*/
|
|
23
|
+
getRegisteredTypes(): string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Singleton registry
|
|
27
|
+
*/
|
|
28
|
+
export declare const adapterRegistry: AdapterRegistry;
|
|
29
|
+
//# sourceMappingURL=adapter-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-registry.d.ts","sourceRoot":"","sources":["../../src/adapters/adapter-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAsC;IAEtD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAMtD;;OAEG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;IAgBzC;;OAEG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;CAG/B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry
|
|
3
|
+
* Регистрация и получение Database Adapters по типу БД
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
export class AdapterRegistry {
|
|
7
|
+
adapters = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Регистрировать адаптер
|
|
10
|
+
*/
|
|
11
|
+
register(type, adapter) {
|
|
12
|
+
const normalizedType = type.toLowerCase();
|
|
13
|
+
this.adapters.set(normalizedType, adapter);
|
|
14
|
+
logger.debug(`Registered adapter for: ${type}`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Получить адаптер по типу
|
|
18
|
+
*/
|
|
19
|
+
get(serviceType) {
|
|
20
|
+
const type = serviceType.toLowerCase();
|
|
21
|
+
const adapter = this.adapters.get(type);
|
|
22
|
+
if (!adapter) {
|
|
23
|
+
const available = Array.from(this.adapters.keys()).join(', ');
|
|
24
|
+
throw new Error(`No adapter found for database type: ${serviceType}\n` +
|
|
25
|
+
`Available adapters: ${available || 'none'}`);
|
|
26
|
+
}
|
|
27
|
+
logger.debug(`Using adapter for: ${serviceType}`);
|
|
28
|
+
return adapter;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Проверить наличие адаптера
|
|
32
|
+
*/
|
|
33
|
+
has(serviceType) {
|
|
34
|
+
return this.adapters.has(serviceType.toLowerCase());
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Получить список всех зарегистрированных типов
|
|
38
|
+
*/
|
|
39
|
+
getRegisteredTypes() {
|
|
40
|
+
return Array.from(this.adapters.keys());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Singleton registry
|
|
45
|
+
*/
|
|
46
|
+
export const adapterRegistry = new AdapterRegistry();
|
|
47
|
+
//# sourceMappingURL=adapter-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-registry.js","sourceRoot":"","sources":["../../src/adapters/adapter-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,OAAO,eAAe;IAClB,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtD;;OAEG;IACH,QAAQ,CAAC,IAAY,EAAE,OAAwB;QAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,WAAmB;QACrB,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,uCAAuC,WAAW,IAAI;gBACtD,uBAAuB,SAAS,IAAI,MAAM,EAAE,CAC7C,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Adapter Interface
|
|
3
|
+
* Интерфейс для работы с разными типами БД
|
|
4
|
+
*/
|
|
5
|
+
import type { ServiceConfig } from '../discovery/types.js';
|
|
6
|
+
import type { QueryOptions, BackupOptions, RestoreOptions, DBStatus, ConnectionInfo } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Интерфейс для Database Adapters
|
|
9
|
+
* Все адаптеры должны реализовать этот интерфейс
|
|
10
|
+
*/
|
|
11
|
+
export interface DatabaseAdapter {
|
|
12
|
+
/**
|
|
13
|
+
* Выполнить query или команду
|
|
14
|
+
*/
|
|
15
|
+
query(service: string, query: string, options?: QueryOptions): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Создать backup
|
|
18
|
+
*/
|
|
19
|
+
backup(service: string, options: BackupOptions): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Восстановить из backup
|
|
22
|
+
*/
|
|
23
|
+
restore(service: string, backupPath: string, options?: RestoreOptions): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Получить статус БД
|
|
26
|
+
*/
|
|
27
|
+
status(service: string): Promise<DBStatus>;
|
|
28
|
+
/**
|
|
29
|
+
* Получить connection info из environment
|
|
30
|
+
*/
|
|
31
|
+
getConnectionInfo(service: ServiceConfig, env: Record<string, string>): ConnectionInfo;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=database-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/database-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,KAAK,CACH,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjE;;OAEG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE3C;;OAEG;IACH,iBAAiB,CACf,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,cAAc,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-adapter.js","sourceRoot":"","sources":["../../src/adapters/database-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Adapter
|
|
3
|
+
* Реализация DatabaseAdapter для PostgreSQL
|
|
4
|
+
*/
|
|
5
|
+
import type { DatabaseAdapter } from './database-adapter.js';
|
|
6
|
+
import type { QueryOptions, BackupOptions, RestoreOptions, DBStatus, ConnectionInfo } from './types.js';
|
|
7
|
+
import type { ServiceConfig } from '../discovery/types.js';
|
|
8
|
+
export declare class PostgreSQLAdapter implements DatabaseAdapter {
|
|
9
|
+
private containerManager;
|
|
10
|
+
private projectDiscovery;
|
|
11
|
+
private envManager;
|
|
12
|
+
constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Выполнить SQL query
|
|
15
|
+
*/
|
|
16
|
+
query(service: string, query: string, options?: QueryOptions): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Создать backup
|
|
19
|
+
*/
|
|
20
|
+
backup(service: string, options: BackupOptions): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Восстановить из backup
|
|
23
|
+
*/
|
|
24
|
+
restore(service: string, backupPath: string, options?: RestoreOptions): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Получить статус БД
|
|
27
|
+
*/
|
|
28
|
+
status(service: string): Promise<DBStatus>;
|
|
29
|
+
/**
|
|
30
|
+
* Получить connection info из environment
|
|
31
|
+
*/
|
|
32
|
+
getConnectionInfo(service: ServiceConfig, env: Record<string, string>): ConnectionInfo;
|
|
33
|
+
/**
|
|
34
|
+
* Парсит версию PostgreSQL из output
|
|
35
|
+
*/
|
|
36
|
+
private parseVersion;
|
|
37
|
+
/**
|
|
38
|
+
* Парсит одно значение из SQL output (первая строка, первый столбец)
|
|
39
|
+
*/
|
|
40
|
+
private parseSingleValue;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=postgresql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresql.d.ts","sourceRoot":"","sources":["../../src/adapters/postgresql.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAO3D,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,UAAU,CAAa;;IAQ/B;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA0CpF;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAgDtE;;OAEG;IACG,OAAO,CACX,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IA8ChB;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IA6ChD;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc;IAUtF;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAWzB"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Adapter
|
|
3
|
+
* Реализация DatabaseAdapter для PostgreSQL
|
|
4
|
+
*/
|
|
5
|
+
import { ContainerManager } from '../managers/container-manager.js';
|
|
6
|
+
import { ProjectDiscovery } from '../discovery/project-discovery.js';
|
|
7
|
+
import { EnvManager } from '../managers/env-manager.js';
|
|
8
|
+
import { sqlValidator } from '../security/sql-validator.js';
|
|
9
|
+
import { logger } from '../utils/logger.js';
|
|
10
|
+
export class PostgreSQLAdapter {
|
|
11
|
+
containerManager;
|
|
12
|
+
projectDiscovery;
|
|
13
|
+
envManager;
|
|
14
|
+
constructor() {
|
|
15
|
+
this.containerManager = new ContainerManager();
|
|
16
|
+
this.projectDiscovery = new ProjectDiscovery();
|
|
17
|
+
this.envManager = new EnvManager();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Выполнить SQL query
|
|
21
|
+
*/
|
|
22
|
+
async query(service, query, options) {
|
|
23
|
+
// Валидация SQL (если включена)
|
|
24
|
+
sqlValidator.validate(query);
|
|
25
|
+
const project = await this.projectDiscovery.findProject();
|
|
26
|
+
const serviceConfig = project.services[service];
|
|
27
|
+
if (!serviceConfig) {
|
|
28
|
+
throw new Error(`Service '${service}' not found in project`);
|
|
29
|
+
}
|
|
30
|
+
const env = this.envManager.loadEnv(project.projectDir, service, serviceConfig);
|
|
31
|
+
const conn = this.getConnectionInfo(serviceConfig, env);
|
|
32
|
+
const db = options?.database || conn.database;
|
|
33
|
+
const user = options?.user || conn.user;
|
|
34
|
+
// Строим команду psql
|
|
35
|
+
const format = options?.format || 'table';
|
|
36
|
+
let cmd = ['psql', '-U', user, '-d', db];
|
|
37
|
+
// Формат вывода
|
|
38
|
+
if (format === 'json') {
|
|
39
|
+
cmd.push('--json');
|
|
40
|
+
}
|
|
41
|
+
else if (format === 'csv') {
|
|
42
|
+
cmd.push('--csv');
|
|
43
|
+
}
|
|
44
|
+
// SQL query
|
|
45
|
+
cmd.push('-c', query);
|
|
46
|
+
// Пароль через PGPASSWORD env var
|
|
47
|
+
const envVars = conn.password ? [`PGPASSWORD=${conn.password}`] : [];
|
|
48
|
+
logger.debug(`Executing PostgreSQL query in ${service}: ${query}`);
|
|
49
|
+
const output = await this.containerManager.exec(service, project.name, cmd, {
|
|
50
|
+
env: envVars,
|
|
51
|
+
});
|
|
52
|
+
return output;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Создать backup
|
|
56
|
+
*/
|
|
57
|
+
async backup(service, options) {
|
|
58
|
+
const project = await this.projectDiscovery.findProject();
|
|
59
|
+
const serviceConfig = project.services[service];
|
|
60
|
+
if (!serviceConfig) {
|
|
61
|
+
throw new Error(`Service '${service}' not found in project`);
|
|
62
|
+
}
|
|
63
|
+
const env = this.envManager.loadEnv(project.projectDir, service, serviceConfig);
|
|
64
|
+
const conn = this.getConnectionInfo(serviceConfig, env);
|
|
65
|
+
const format = options.format || 'custom';
|
|
66
|
+
const output = options.output || `/backups/postgres-backup-${Date.now()}.dump`;
|
|
67
|
+
// Строим команду pg_dump
|
|
68
|
+
let cmd = ['pg_dump', '-U', conn.user, '-d', conn.database];
|
|
69
|
+
// Формат backup
|
|
70
|
+
if (format === 'custom') {
|
|
71
|
+
cmd.push('-Fc'); // Custom format (compressed)
|
|
72
|
+
}
|
|
73
|
+
else if (format === 'tar') {
|
|
74
|
+
cmd.push('-Ft'); // Tar format
|
|
75
|
+
}
|
|
76
|
+
else if (format === 'directory') {
|
|
77
|
+
cmd.push('-Fd'); // Directory format
|
|
78
|
+
}
|
|
79
|
+
// 'sql' format - по умолчанию (plain SQL)
|
|
80
|
+
// Backup конкретных таблиц
|
|
81
|
+
if (options.tables && options.tables.length > 0) {
|
|
82
|
+
for (const table of options.tables) {
|
|
83
|
+
cmd.push('-t', table);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Output file
|
|
87
|
+
cmd.push('-f', output);
|
|
88
|
+
// Пароль через PGPASSWORD
|
|
89
|
+
const envVars = conn.password ? [`PGPASSWORD=${conn.password}`] : [];
|
|
90
|
+
logger.info(`Creating PostgreSQL backup: ${output}`);
|
|
91
|
+
await this.containerManager.exec(service, project.name, cmd, {
|
|
92
|
+
env: envVars,
|
|
93
|
+
});
|
|
94
|
+
return output;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Восстановить из backup
|
|
98
|
+
*/
|
|
99
|
+
async restore(service, backupPath, options) {
|
|
100
|
+
const project = await this.projectDiscovery.findProject();
|
|
101
|
+
const serviceConfig = project.services[service];
|
|
102
|
+
if (!serviceConfig) {
|
|
103
|
+
throw new Error(`Service '${service}' not found in project`);
|
|
104
|
+
}
|
|
105
|
+
const env = this.envManager.loadEnv(project.projectDir, service, serviceConfig);
|
|
106
|
+
const conn = this.getConnectionInfo(serviceConfig, env);
|
|
107
|
+
const db = options?.database || conn.database;
|
|
108
|
+
// Определяем формат backup по расширению
|
|
109
|
+
const isCustomFormat = backupPath.endsWith('.dump') || backupPath.endsWith('.backup');
|
|
110
|
+
let cmd;
|
|
111
|
+
if (isCustomFormat) {
|
|
112
|
+
// Custom format → pg_restore
|
|
113
|
+
cmd = ['pg_restore', '-U', conn.user, '-d', db];
|
|
114
|
+
if (options?.clean) {
|
|
115
|
+
cmd.push('--clean');
|
|
116
|
+
}
|
|
117
|
+
if (options?.dataOnly) {
|
|
118
|
+
cmd.push('--data-only');
|
|
119
|
+
}
|
|
120
|
+
if (options?.schemaOnly) {
|
|
121
|
+
cmd.push('--schema-only');
|
|
122
|
+
}
|
|
123
|
+
cmd.push(backupPath);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// SQL format → psql
|
|
127
|
+
cmd = ['psql', '-U', conn.user, '-d', db, '-f', backupPath];
|
|
128
|
+
}
|
|
129
|
+
// Пароль через PGPASSWORD
|
|
130
|
+
const envVars = conn.password ? [`PGPASSWORD=${conn.password}`] : [];
|
|
131
|
+
logger.info(`Restoring PostgreSQL from backup: ${backupPath}`);
|
|
132
|
+
await this.containerManager.exec(service, project.name, cmd, {
|
|
133
|
+
env: envVars,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Получить статус БД
|
|
138
|
+
*/
|
|
139
|
+
async status(service) {
|
|
140
|
+
const project = await this.projectDiscovery.findProject();
|
|
141
|
+
const serviceConfig = project.services[service];
|
|
142
|
+
if (!serviceConfig) {
|
|
143
|
+
throw new Error(`Service '${service}' not found in project`);
|
|
144
|
+
}
|
|
145
|
+
const env = this.envManager.loadEnv(project.projectDir, service, serviceConfig);
|
|
146
|
+
const conn = this.getConnectionInfo(serviceConfig, env);
|
|
147
|
+
// Получаем версию
|
|
148
|
+
const versionOutput = await this.query(service, 'SELECT version();');
|
|
149
|
+
const version = this.parseVersion(versionOutput);
|
|
150
|
+
// Получаем размер БД
|
|
151
|
+
const sizeOutput = await this.query(service, "SELECT pg_size_pretty(pg_database_size(current_database())) as size;");
|
|
152
|
+
const size = this.parseSingleValue(sizeOutput);
|
|
153
|
+
// Получаем количество подключений
|
|
154
|
+
const connectionsOutput = await this.query(service, "SELECT count(*) as connections FROM pg_stat_activity WHERE datname = current_database();");
|
|
155
|
+
const connections = parseInt(this.parseSingleValue(connectionsOutput) || '0');
|
|
156
|
+
// Получаем uptime
|
|
157
|
+
const uptimeOutput = await this.query(service, "SELECT date_trunc('second', current_timestamp - pg_postmaster_start_time()) as uptime;");
|
|
158
|
+
const uptime = this.parseSingleValue(uptimeOutput);
|
|
159
|
+
return {
|
|
160
|
+
type: 'postgresql',
|
|
161
|
+
version,
|
|
162
|
+
status: 'healthy',
|
|
163
|
+
size,
|
|
164
|
+
connections,
|
|
165
|
+
uptime,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Получить connection info из environment
|
|
170
|
+
*/
|
|
171
|
+
getConnectionInfo(service, env) {
|
|
172
|
+
return {
|
|
173
|
+
host: 'localhost',
|
|
174
|
+
port: 5432,
|
|
175
|
+
user: env.POSTGRES_USER || 'postgres',
|
|
176
|
+
password: env.POSTGRES_PASSWORD,
|
|
177
|
+
database: env.POSTGRES_DB || 'postgres',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Парсит версию PostgreSQL из output
|
|
182
|
+
*/
|
|
183
|
+
parseVersion(versionOutput) {
|
|
184
|
+
const match = versionOutput.match(/PostgreSQL\s+(\d+\.\d+)/i);
|
|
185
|
+
return match ? match[1] : 'unknown';
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Парсит одно значение из SQL output (первая строка, первый столбец)
|
|
189
|
+
*/
|
|
190
|
+
parseSingleValue(output) {
|
|
191
|
+
// Простой парсинг: берем первую строку после заголовка
|
|
192
|
+
const lines = output.split('\n').filter((line) => line.trim().length > 0);
|
|
193
|
+
if (lines.length < 2) {
|
|
194
|
+
return '';
|
|
195
|
+
}
|
|
196
|
+
// Пропускаем заголовок, берем первую строку данных
|
|
197
|
+
const dataLine = lines[1];
|
|
198
|
+
// Убираем лишние пробелы
|
|
199
|
+
return dataLine.trim();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=postgresql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresql.js","sourceRoot":"","sources":["../../src/adapters/postgresql.ts"],"names":[],"mappings":"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"}
|