import chalk from 'chalk'; import { Command } from 'commander'; import { pullTaskByIdOrName } from './test/pull'; import inquirer from 'inquirer'; import fs from 'fs'; import path from 'path'; import yaml from 'js-yaml'; import Fuse from 'fuse.js'; export function WorkerSetContextCommand(): Command { const cmd = new Command('set-context') .alias('sc') .description( 'Set a profile and configuration location to test HexaSync Worker', ) .option('--worker ', 'Path to worker directory') .option('--profile ', 'Profile name or alias to search') .action(async (options) => { const workerPath = options.worker; const profileName = options.profile; if (!workerPath || !profileName) { console.error( chalk.red('Both --worker and --profile options are required.'), ); return; } const profilesYamlPath = path.join(workerPath, 'profiles.yaml'); if (!fs.existsSync(profilesYamlPath)) { console.error( chalk.red(`profiles.yaml not found at ${profilesYamlPath}`), ); return; } const profilesRaw = fs.readFileSync(profilesYamlPath, 'utf8'); const profiles = yaml.load(profilesRaw); if (!Array.isArray(profiles)) { console.error(chalk.red('profiles.yaml is not a valid array.')); return; } const fuse = new Fuse(profiles, { includeScore: true, keys: [{ name: 'alias', weight: 2 }], }); const result = fuse.search(profileName); if (result.length === 0) { console.error(chalk.red(`No profile found matching: ${profileName}`)); return; } let selectedProfile; if (result.length === 1) { selectedProfile = result[0].item; } else { const answer = await inquirer.prompt([ { type: 'list', name: 'selectedProfile', message: 'Multiple profiles found. Please select one:', choices: result.map((x, i) => ({ name: `${i + 1}. ${x.item.alias}`, value: x.item, })), }, ]); selectedProfile = answer.selectedProfile; } // (*) set env const apiPath = path.join(workerPath, 'hexasync.api'); const envPath = path.join(apiPath, '.env'); if (!fs.existsSync(envPath)) { console.error(chalk.red(`.env file not found at ${envPath}`)); return; } let envContent = fs.readFileSync(envPath, 'utf8'); const profileId = selectedProfile.id; const dbName = `worker_${profileId.replace(/-/g, '_')}`; const storagePath = selectedProfile.path; // Replace or add env variables envContent = envContent.replace( /HEXASYNC_PROFILE_ID=.*/g, `HEXASYNC_PROFILE_ID=${profileId}`, ); if (!/HEXASYNC_PROFILE_ID=/.test(envContent)) { envContent += `\nHEXASYNC_PROFILE_ID=${profileId}`; } envContent = envContent.replace( /HEXASYNC_DB_NAME=.*/g, `HEXASYNC_DB_NAME=${dbName}`, ); if (!/HEXASYNC_DB_NAME=/.test(envContent)) { envContent += `\nHEXASYNC_DB_NAME=${dbName}`; } envContent = envContent.replace( /HEXASYNC_PROFILES_STORAGE=.*/g, `HEXASYNC_PROFILES_STORAGE=${storagePath}`, ); if (!/HEXASYNC_PROFILES_STORAGE=/.test(envContent)) { envContent += `\nHEXASYNC_PROFILES_STORAGE=${storagePath}`; } // Overwrite required envs to exact values const requiredEnvs = { HEXASYNC_PLAY_QUEUE: '0', HEXASYNC_DO_NOT_PUSH: '1', SHOULD_NOT_RUN_QUEUES: '0', USE_LOCAL_ENVIRONMENTS: '1', HEXASYNC_LOCAL_DEV: '1', HEXASYNC_SHOULD_NOT_RUN_WEBHOOK: '1', USE_CONFIGURATION_SERVICE: '0', HEXASYNC_PUSH_PARALLEL: '1', HEXASYNC_PUSH_THROTTLING: '1', HSS_USE_K8S: 'false', IS_DISABLE_REDIS_CLEANUP: '0', IS_DISABLE_NOTIFICATION: '1', QUEUE_BACKGROUND_JOB: '0', PULL_BACKGROUND_JOB: '0', DEFAULT_DATABASE_SCHEMA: 'public', }; for (const [key, value] of Object.entries(requiredEnvs)) { const regex = new RegExp(`${key}=.*`, 'g'); if (regex.test(envContent)) { envContent = envContent.replace(regex, `${key}=${value}`); } else { envContent += `\n${key}=${value}`; } } fs.writeFileSync(envPath, envContent, 'utf8'); console.log( `Environment updated for profile: ${chalk.green(selectedProfile.alias)}`, ); console.log(` - Id: ${selectedProfile.id}`); console.log(` - Path: ${selectedProfile.path}`); }); return cmd; } export function WorkerCommand(): Command { const cmd = new Command('worker') .alias('w') .description('Provides a list of commands that are helpful for worker'); cmd.addCommand(WorkerSetContextCommand()); return cmd; }