Skip to content

Commit 245859c

Browse files
committed
Refactor project structure and enhance type definitions for database plugins
- Updated tsconfig with improved path aliases - Restructured database plugin types and configurations - Added comprehensive type definitions for database plugins - Implemented core plugin management and template generation utilities - Introduced project detection and configuration generation functions
1 parent 9a0dcf2 commit 245859c

28 files changed

+949
-478
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"editor.codeActionsOnSave": {
3-
"source.fixAll.eslint": true
3+
"source.fixAll.eslint": "explicit"
44
},
55
"eslint.validate": ["javascript"]
66
}

src/commands/dockerize.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { generateDockerCompose } from '../templates';
2+
import { getAvailablePlugins, processPluginAnswers } from '../core/plugin-manager';
3+
4+
export async function dockerize(answers: any) {
5+
const options = {
6+
nodeVersion: answers.nodeVersion,
7+
environment: answers.environment,
8+
customModifications: [
9+
// Example: Add Redis service
10+
{
11+
service: 'redis',
12+
config: {
13+
image: 'redis:alpine',
14+
ports: ['6379:6379'],
15+
volumes: ['redis_data:/data']
16+
}
17+
},
18+
// Example: Modify Strapi service
19+
{
20+
service: 'strapi',
21+
config: {
22+
environment: {
23+
REDIS_HOST: 'redis'
24+
},
25+
depends_on: ['redis']
26+
}
27+
}
28+
]
29+
};
30+
31+
if (answers.database) {
32+
const plugin = getAvailablePlugins().find(p => p.name === answers.database);
33+
if (plugin) {
34+
options.database = {
35+
plugin,
36+
config: await processPluginAnswers(plugin.name, answers)
37+
};
38+
}
39+
}
40+
41+
const composeFile = await generateDockerCompose(options);
42+
43+
// Write to appropriate docker-compose file
44+
const filename = options.environment === 'production'
45+
? 'docker-compose.prod.yml'
46+
: 'docker-compose.yml';
47+
48+
await writeFile(filename, composeFile);
49+
}

src/core/plugin-manager.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { DatabasePlugin } from '@types';
2+
3+
const plugins = new Map<string, DatabasePlugin>();
4+
5+
export async function loadPlugins() {
6+
const plugins = new Map<string, DatabasePlugin>();
7+
8+
// Dynamic imports to get the actual plugin instances
9+
const postgresql = (await import('@plugins/databases/postgresql')).default;
10+
const mysql = (await import('@plugins/databases/mysql')).default;
11+
const mariadb = (await import('@plugins/databases/mariadb')).default;
12+
const sqlite = (await import('@plugins/databases/sqlite')).default;
13+
14+
plugins.set('postgresql', postgresql);
15+
plugins.set('mysql', mysql);
16+
plugins.set('mariadb', mariadb);
17+
plugins.set('sqlite', sqlite);
18+
19+
return plugins;
20+
}
21+
22+
export function registerPlugin(plugin: DatabasePlugin) {
23+
plugins.set(plugin.name, plugin);
24+
}
25+
26+
export function getPlugin(name: string): DatabasePlugin | undefined {
27+
return plugins.get(name);
28+
}
29+
30+
export function getPluginQuestions(pluginName: string) {
31+
const plugin = plugins.get(pluginName);
32+
if (!plugin) {
33+
throw new Error(`Plugin ${pluginName} not found`);
34+
}
35+
36+
return [
37+
{
38+
type: 'text',
39+
name: 'database',
40+
message: 'Database name?',
41+
default: 'strapi'
42+
},
43+
{
44+
type: 'text',
45+
name: 'username',
46+
message: 'Database username?',
47+
default: 'strapi'
48+
},
49+
{
50+
type: 'password',
51+
name: 'password',
52+
message: 'Database password?',
53+
validate: (input: string) => input.length >= 8
54+
},
55+
{
56+
type: 'text',
57+
name: 'port',
58+
message: 'Database port?',
59+
default: plugin.defaultPort.toString()
60+
},
61+
// Add additional questions if they exist
62+
...(plugin.additionalQuestions || [])
63+
];
64+
}
65+
66+
export function processPluginAnswers(pluginName: string, answers: any) {
67+
const plugin = plugins.get(pluginName);
68+
if (!plugin) {
69+
throw new Error(`Plugin ${pluginName} not found`);
70+
}
71+
72+
if (!plugin.validateConfig(answers)) {
73+
throw new Error('Invalid configuration');
74+
}
75+
76+
return {
77+
templateVariables: plugin.getTemplateVariables(answers),
78+
containerName: plugin.containerName,
79+
volumePath: plugin.volumePath
80+
};
81+
}
82+
83+
export function getAvailablePlugins(): DatabasePlugin[] {
84+
return Array.from(plugins.values());
85+
}

src/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { getProjectInfo } from './utils/project-detection';
2+
import { loadPlugins } from './core/plugin-manager';
3+
import { promptQuestions } from './prompts';
4+
import { generateConfiguration } from './templates';
5+
6+
export async function main() {
7+
// 1. Auto-Detection Phase
8+
const projectInfo = await getProjectInfo();
9+
// - Project type (TS/JS)
10+
// - Existing database config
11+
// - Node.js version
12+
// - Environment files
13+
14+
// 2. Load Available Plugins
15+
const plugins = await loadPlugins();
16+
17+
// 3. Interactive Questions
18+
const answers = await promptQuestions({
19+
projectInfo,
20+
availablePlugins: plugins
21+
});
22+
23+
// 4. Generate Configuration
24+
await generateConfiguration({
25+
projectInfo,
26+
answers,
27+
selectedPlugin: plugins[answers.database]
28+
});
29+
}

src/plugins/core/types.ts

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,61 @@
1-
export type Environment = 'development' | 'production' | 'both';
2-
3-
export interface DatabaseConfig {
4-
type: string;
5-
config: Record<string, any>;
6-
}
7-
8-
export interface NodeConfig {
9-
version: string;
10-
}
11-
12-
export interface DockerConfig {
13-
environment: Environment;
14-
database: DatabaseConfig;
15-
node: NodeConfig;
16-
}
17-
18-
export interface Question {
19-
type: string;
1+
export interface DatabasePluginConfig {
202
name: string;
21-
message: string;
22-
default?: any;
23-
choices?: string[];
24-
validate?: (value: any) => boolean | string;
3+
defaultPort: number;
4+
containerName: string;
5+
volumePath: string;
6+
envPrefix: string;
7+
defaultVersion: string;
8+
image: {
9+
name: string;
10+
tag: string;
11+
};
12+
healthcheck?: {
13+
test: string[] | string;
14+
interval: string;
15+
timeout: string;
16+
retries: number;
17+
};
18+
}
19+
20+
export interface DatabaseAnswers {
21+
database: string;
22+
username: string;
23+
password: string;
24+
port: string;
25+
version?: string;
26+
charset?: string;
27+
collation?: string;
28+
rootPassword?: string;
2529
}
2630

2731
export interface ValidationResult {
2832
isValid: boolean;
29-
errors?: string[];
30-
}
31-
32-
export interface Template {
33-
name: string;
34-
content: string;
35-
variables: Record<string, any>;
36-
}
37-
38-
export interface DatabasePlugin {
39-
name: string;
40-
getQuestions: () => Question[];
41-
validateConfig: (config: Record<string, any>) => ValidationResult;
42-
getTemplateVariables: (config: Record<string, any>) => Record<string, any>;
33+
errors: string[];
4334
}
4435

4536
export interface TemplateVariables {
46-
[key: string]: string | number | boolean | object;
37+
database: {
38+
type: string;
39+
name: string;
40+
user: string;
41+
password: string;
42+
port: string;
43+
host: string;
44+
};
45+
environment: Record<string, string>;
46+
volumes: {
47+
data: string;
48+
};
49+
image: {
50+
name: string;
51+
tag: string;
52+
};
4753
}
4854

49-
export interface Plugin {
50-
type: string;
55+
export interface DatabasePlugin {
5156
name: string;
52-
version: string;
53-
description: string;
54-
55-
// Get questions to ask user
56-
getQuestions(): Question[];
57-
58-
// Validate user's answers
59-
validateAnswers(answers: Record<string, any>): ValidationResult;
60-
61-
// Get templates with variables
62-
getTemplates(answers: Record<string, any>): Template[];
63-
64-
// Get environment variables
65-
getEnvironmentVariables(answers: Record<string, any>): Record<string, string>;
57+
defaultPort: number;
58+
getTemplateVariables(answers: DatabaseAnswers): TemplateVariables;
59+
validateConfig(answers: DatabaseAnswers): ValidationResult;
60+
validateConnectionString(url: string): boolean;
6661
}

0 commit comments

Comments
 (0)