diff --git a/package-lock.json b/package-lock.json index db7ed57..a2937f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,8 @@ "license": "MIT", "dependencies": { "child_process": "^1.0.2", - "inquirer": "^8.2.6" + "inquirer": "^8.2.6", + "js-yaml": "^4.1.0" }, "bin": { "vail": "src/index.js" @@ -251,8 +252,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -1326,7 +1326,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, diff --git a/package.json b/package.json index f2fd7c7..1e2b5af 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,13 @@ }, "files": [ "src", - "runtimes" + "runtimes", + "stubs" ], "dependencies": { "child_process": "^1.0.2", - "inquirer": "^8.2.6" + "inquirer": "^8.2.6", + "js-yaml": "^4.1.0" }, "devDependencies": { "eslint": "^8.46.0", diff --git a/src/console/init-command.js b/src/console/init-command.js index 389ed6e..9be98f6 100644 --- a/src/console/init-command.js +++ b/src/console/init-command.js @@ -1,8 +1,17 @@ const fs = require('fs'); const path = require('path'); -const { displayErrorMessage, displaySuccessMessage } = require('../utils'); +const { + displayErrorMessage, + displaySuccessMessage, + writeDockerComposeFileWithService, +} = require('../utils'); const inquirer = require('inquirer'); -const { NODE_VERSIONS, NODE_16 } = require('../constants/services'); +const { + NODE_VERSIONS, + NODE_16, + SERVICES, + SERVICES_WITH_VOLUME, +} = require('../constants/services'); const initCommand = async () => { const dockerComposePath = path.resolve(process.cwd(), 'docker-compose.yml'); @@ -79,7 +88,7 @@ const initCommand = async () => { const ports = portsAnswer.ports.split(',').map((port) => port.trim()); // Ask the user to select the services - /* const servicesAnswer = await inquirer.prompt([ + const servicesAnswer = await inquirer.prompt([ { type: 'checkbox', message: 'Select the services you want to include:', @@ -89,7 +98,7 @@ const initCommand = async () => { }, ]); - const selectedServices = servicesAnswer.services; */ + const selectedServices = servicesAnswer.services; let dockerfileLocation = `./node_modules/vail/runtimes/${selectedPackageManager}`; if (!fs.existsSync(dockerfileLocation)) { @@ -120,23 +129,12 @@ networks: driver: bridge `; - /* if (selectedServices.includes(MY_SQL)) { - dockerComposeContent += ` - mysql: - # Add MySQL service configuration here - `; - } - - if (selectedServices.includes('minio')) { - dockerComposeContent += ` - minio: - # Add Minio service configuration here - `; - } */ - - // Write docker-compose.yml with the selected services + // Write docker-compose.yml fs.writeFileSync(dockerComposePath, dockerComposeContent); + // Call writeDockerComposeFile function with selected services and volumes + writeDockerComposeFileWithService(selectedServices, SERVICES_WITH_VOLUME); + displaySuccessMessage('Vail successfully initialized.'); }; diff --git a/src/constants/services.js b/src/constants/services.js index 7b99bdb..403410f 100644 --- a/src/constants/services.js +++ b/src/constants/services.js @@ -1,21 +1,21 @@ const MY_SQL = 'mysql'; -const MINIO = 'minio'; const NODE_14 = '14'; const NODE_16 = '16'; const NODE_18 = '18'; -const SERVICES = [MY_SQL, MINIO]; +const SERVICES = [MY_SQL]; + +const SERVICES_WITH_VOLUME = [MY_SQL]; const NODE_VERSIONS = [NODE_14, NODE_16, NODE_18]; // export all module.exports = { - MY_SQL, - MINIO, NODE_VERSIONS, NODE_14, NODE_16, NODE_18, SERVICES, + SERVICES_WITH_VOLUME, }; diff --git a/src/utils/index.js b/src/utils/index.js index 6d2d137..fd54b91 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,3 +1,7 @@ +const fs = require('fs'); +const yaml = require('js-yaml'); +const path = require('path'); + const { RED_COLOR_CODE, RESET_COLOR_CODE, @@ -12,4 +16,55 @@ const displaySuccessMessage = (message) => { console.log(`${GREEN_COLOR_CODE}${message}${RESET_COLOR_CODE}`); }; -module.exports = { displayErrorMessage, displaySuccessMessage }; +const writeDockerComposeFileWithService = ( + selectedServices, + availableVolumes, +) => { + const dockerComposePath = path.resolve(process.cwd(), 'docker-compose.yml'); + + // Read the current docker-compose.yml file + const dockerComposeContent = fs.readFileSync(dockerComposePath, 'utf8'); + + // Parse the YAML content into a JavaScript object + const parsedCompose = yaml.load(dockerComposeContent); + + // Check if 'volumes' property exists in 'parsedCompose' object + if (!parsedCompose.volumes) { + parsedCompose.volumes = {}; + } + + // Add selected services to the services section + selectedServices.forEach((service) => { + if (!(service in parsedCompose.services)) { + const serviceStubPath = `./node_modules/vail/stubs/${service}.stub`; + const serviceStubContent = fs.readFileSync(serviceStubPath, 'utf8'); + + const serviceStub = yaml.load(serviceStubContent); + parsedCompose.services[service] = serviceStub[service]; + } + }); + + // Remove volumes if no services are selected + if (selectedServices.length === 0) { + delete parsedCompose.volumes; + } else { + // Add selected volumes to the volumes section + availableVolumes.forEach((volume) => { + if (!(volume in parsedCompose.volumes)) { + parsedCompose.volumes[`vail-${volume}`] = { driver: 'local' }; + } + }); + } + + // Convert the JavaScript object back to YAML format + const updatedComposeContent = yaml.dump(parsedCompose); + + // Write the updated YAML content to docker-compose.yml + fs.writeFileSync(dockerComposePath, updatedComposeContent, 'utf8'); +}; + +module.exports = { + displayErrorMessage, + displaySuccessMessage, + writeDockerComposeFileWithService, +}; diff --git a/stubs/mysql.stub b/stubs/mysql.stub new file mode 100644 index 0000000..309ed11 --- /dev/null +++ b/stubs/mysql.stub @@ -0,0 +1,20 @@ +mysql: + image: 'mysql/mysql-server:8.0' + ports: + - '${FORWARD_DB_PORT:-3306}:3306' + environment: + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_ROOT_HOST: "%" + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 1 + volumes: + - 'vail-mysql:/var/lib/mysql' + networks: + - vail + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] + retries: 3 + timeout: 5s + \ No newline at end of file