Skip to content

Commit 466f83f

Browse files
committed
Updated plugins
1 parent e6a1749 commit 466f83f

29 files changed

+1511
-14
lines changed

PROJECT.md

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,17 @@ This document outlines the planned features, improvements, and tasks for V2 of t
169169
- Existing database config
170170
- Existing Docker files
171171
- Environment files
172+
- Node.js version detection
172173

173-
2. **Environment Selection**
174+
2. **Environment Selection**
174175
```
175176
? Select environment setup:
176177
❯ Development (Optimized for local development with hot-reload)
177178
❯ Production (Optimized for deployment)
178179
❯ Both (Development + Production setup)
179180
```
180181

181-
3. **Production Setup** (Only if Production/Both selected)
182+
3. **Production Setup**
182183
- If Production was selected:
183184
```
184185
? Choose deployment setup:
@@ -191,7 +192,7 @@ This document outlines the planned features, improvements, and tasks for V2 of t
191192
- Development: docker-compose.yml
192193
- Production: Both Dockerfile and docker-compose.prod.yml
193194
194-
4. **Database Configuration**
195+
4. **Database Configuration**
195196
```
196197
? Select database setup:
197198
❯ PostgreSQL (Recommended for production)
@@ -203,41 +204,53 @@ This document outlines the planned features, improvements, and tasks for V2 of t
203204
- Show warning if SQLite selected for production
204205
- Additional configuration based on database type
205206
206-
5. **Node.js Configuration**
207+
5. **Node.js Configuration**
207208
```
208209
? Select Node.js version:
209-
❯ LTS (Recommended, currently Node.js 20)
210-
❯ Current (Latest stable)
210+
❯ Project Version (if detected)
211+
❯ Node 20 LTS (v20.11.1) - Latest minor version
212+
❯ Node 18 LTS (v18.19.1) - Latest minor version
213+
❯ Latest (v21.x) - Not LTS
211214
❯ Custom Version
212215
```
213-
214-
#### Smart Defaults & Validation
216+
- Auto-detects project version from:
217+
- .nvmrc
218+
- .node-version
219+
- local node_modules
220+
- system Node.js
221+
- Shows latest minor version for each LTS major
222+
- Validates custom version input
223+
224+
#### Smart Defaults & Validation ✅
215225
- [x] Use detected values when available
216226
- [x] Skip questions if valid configuration exists
217227
- [x] Validate database credentials
218228
- [x] Ensure password strength
219229
- [x] Verify port availability
230+
- [x] Validate Node.js versions
231+
- [x] Smart version selection based on project
220232
221233
### Current Progress
222234
- [x] Basic project structure
223235
- [x] TypeScript migration
224236
- [x] Project detection
225237
- [x] Interactive UI with Ink
226238
- [x] Basic flow implementation
239+
- [x] Node.js version management
227240
- [ ] Database configuration
228241
- [ ] Docker file generation
229242
- [ ] Environment handling
230243
- [ ] Plugin system
231244
232245
### Next Steps
233-
1. Implement database configuration handlers
234-
2. Create Docker template system
235-
3. Add environment variable management
246+
1. Implement Docker file generation based on selected options
247+
2. Add environment variable management
248+
3. Create database configuration handlers
236249
4. Implement plugin system for extensibility
237250
238251
### 5. Project Detection & Configuration 🔍
239-
- [ ] Improve Strapi version detection
240-
- [ ] Add Node.js version compatibility check
252+
- [x] Improve Strapi version detection
253+
- [x] Add Node.js version compatibility check
241254
- [ ] Implement project structure validation
242255
- [ ] Add support for custom Strapi configurations
243256
- [ ] Implement configuration file support
@@ -328,4 +341,31 @@ This document outlines the planned features, improvements, and tasks for V2 of t
328341
- Cloud platform integrations
329342
- Additional template support
330343
- Performance optimizations
331-
- Community-requested features
344+
- Community-requested features
345+
346+
## Example Usage
347+
348+
```typescript
349+
// Initialize the generator
350+
const generator = new DockerGenerator('/path/to/plugins');
351+
await generator.initialize();
352+
353+
// Get available databases
354+
const databases = generator.getAvailableDatabases();
355+
356+
// Generate Docker files
357+
await generator.generate({
358+
environment: 'development',
359+
database: {
360+
type: 'postgresql',
361+
config: {
362+
host: 'localhost',
363+
port: 5432,
364+
// ... other config
365+
}
366+
},
367+
node: {
368+
version: '20.11.1'
369+
}
370+
}, './output');
371+
```

src/plugins/core/docker-generator.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { PluginManager } from './plugin-manager';
2+
import { TemplateRenderer } from './template-renderer';
3+
import path from 'path';
4+
5+
export interface DockerConfig {
6+
environment: 'development' | 'production' | 'both';
7+
database: {
8+
type: string;
9+
config: Record<string, any>;
10+
};
11+
node: {
12+
version: string;
13+
};
14+
}
15+
16+
export class DockerGenerator {
17+
private pluginManager: PluginManager;
18+
private templateRenderer: TemplateRenderer;
19+
20+
constructor(pluginsPath: string) {
21+
this.pluginManager = new PluginManager(pluginsPath);
22+
this.templateRenderer = new TemplateRenderer();
23+
}
24+
25+
// Initialize the generator
26+
async initialize(): Promise<void> {
27+
await this.pluginManager.loadPlugins();
28+
}
29+
30+
// Get available database types
31+
getAvailableDatabases(): string[] {
32+
return this.pluginManager.getAllDatabasePlugins().map(plugin => plugin.name);
33+
}
34+
35+
// Generate Docker configuration files
36+
async generate(config: DockerConfig, targetDir: string): Promise<void> {
37+
// Load database plugin and templates
38+
const { templates, variables } = await this.pluginManager.generateDockerConfig(
39+
config.database.type,
40+
config.database.config
41+
);
42+
43+
// Add environment-specific variables
44+
const templateVars = {
45+
...variables,
46+
environment: config.environment,
47+
node: {
48+
version: config.node.version
49+
}
50+
};
51+
52+
// Generate docker-compose.yml
53+
if (config.environment !== 'production' || config.database.type === 'sqlite') {
54+
const composePath = path.join(targetDir,
55+
config.environment === 'both' ? 'docker-compose.dev.yml' : 'docker-compose.yml'
56+
);
57+
await this.templateRenderer.renderToFile(
58+
templates['compose'],
59+
templateVars,
60+
composePath
61+
);
62+
}
63+
64+
// Generate production docker-compose if needed
65+
if (config.environment === 'production' || config.environment === 'both') {
66+
const prodComposePath = path.join(targetDir, 'docker-compose.prod.yml');
67+
await this.templateRenderer.renderToFile(
68+
templates['compose'],
69+
{ ...templateVars, environment: 'production' },
70+
prodComposePath
71+
);
72+
}
73+
74+
// Generate Dockerfile
75+
const dockerfilePath = path.join(targetDir,
76+
config.environment === 'both' ? 'Dockerfile.prod' : 'Dockerfile'
77+
);
78+
79+
if (templates['dockerfile']) {
80+
await this.templateRenderer.renderToFile(
81+
templates['dockerfile'],
82+
templateVars,
83+
dockerfilePath
84+
);
85+
}
86+
87+
// Generate development Dockerfile if needed
88+
if (config.environment === 'both') {
89+
await this.templateRenderer.renderToFile(
90+
templates['dockerfile'],
91+
{ ...templateVars, environment: 'development' },
92+
path.join(targetDir, 'Dockerfile.dev')
93+
);
94+
}
95+
}
96+
97+
// Validate configuration
98+
async validateConfig(config: DockerConfig): Promise<boolean> {
99+
const plugin = this.pluginManager.getDatabasePlugin(config.database.type);
100+
if (!plugin) {
101+
throw new Error(`Unsupported database type: ${config.database.type}`);
102+
}
103+
104+
const validation = plugin.validateAnswers(config.database.config);
105+
return validation.isValid;
106+
}
107+
}

src/plugins/core/load-plugins.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { DatabasePlugin } from './types';
4+
5+
export async function loadDatabasePlugins(pluginsPath: string): Promise<Map<string, DatabasePlugin>> {
6+
const plugins = new Map<string, DatabasePlugin>();
7+
const databasesPath = path.join(pluginsPath, 'databases');
8+
9+
try {
10+
const entries = fs.readdirSync(databasesPath, { withFileTypes: true });
11+
12+
for (const entry of entries) {
13+
if (entry.isDirectory()) {
14+
const plugin = await loadDatabasePlugin(path.join(databasesPath, entry.name));
15+
if (plugin) {
16+
plugins.set(plugin.name, plugin);
17+
}
18+
}
19+
}
20+
} catch (error) {
21+
console.error('Error loading plugins:', error);
22+
}
23+
24+
return plugins;
25+
}
26+
27+
async function loadDatabasePlugin(pluginPath: string): Promise<DatabasePlugin | null> {
28+
try {
29+
const [questions, config, validation] = await Promise.all([
30+
import(path.join(pluginPath, 'questions')),
31+
import(path.join(pluginPath, 'config')),
32+
import(path.join(pluginPath, 'validation'))
33+
]);
34+
35+
return {
36+
name: path.basename(pluginPath),
37+
getQuestions: questions.getQuestions,
38+
validateConfig: validation.validateConfig,
39+
getTemplateVariables: config.getTemplateVariables
40+
};
41+
} catch (error) {
42+
console.error(`Error loading plugin from ${pluginPath}:`, error);
43+
return null;
44+
}
45+
}
46+
47+
export function getDatabasePlugin(plugins: Map<string, DatabasePlugin>, name: string): DatabasePlugin | undefined {
48+
return plugins.get(name);
49+
}
50+
51+
export function getAllDatabasePlugins(plugins: Map<string, DatabasePlugin>): DatabasePlugin[] {
52+
return Array.from(plugins.values());
53+
}

0 commit comments

Comments
 (0)