import * as FS from 'fs'; import * as OS from 'os'; import * as Path from 'path'; import { JSONConfigFile as AgentJSONConfigFile, logger, main as agentMain, } from '@makeflow/makescript-agent'; import {Command, command, metadata} from 'clime'; import prompts from 'prompts'; import {Tiva} from 'tiva'; import {v4 as uuidv4} from 'uuid'; import {JSONConfigFile} from '../config'; import {main} from '../main'; export const JSON_CONFIG_INDENTATION = 2; export const WORKSPACE_PATH = Path.resolve(OS.homedir(), '.makescript'); export const DEFAULT_AGENT_WORKSPACE_PATH = Path.join( WORKSPACE_PATH, 'default-agent', ); export const MAKESCRIPT_CONFIG_FILE_PATH = Path.join( WORKSPACE_PATH, 'makescript.json', ); export const MAKESCRIPT_DEFAULT_AGENT_CONFIG_FILE_PATH = Path.join( DEFAULT_AGENT_WORKSPACE_PATH, 'makescript-agent.json', ); export const MAKESCRIPT_CONFIG_DEFAULT: JSONConfigFile = { url: `http://localhost:8900`, listen: { host: 'localhost', port: 8900, }, agent: { token: uuidv4(), }, makeflow: { url: 'https://makeflow.com', powerApp: { name: 'makescript', displayName: 'MakeScript', description: 'Auto generated by makescript', }, }, }; export const MAKESCRIPT_DEFAULT_AGENT_CONFIG_DEFAULT = ( token: string, git: string, dir: string | undefined, ): AgentJSONConfigFile => { return { name: 'default', server: { url: `http://localhost:8900/${token}`, }, scripts: { git, dir, }, proxy: undefined, }; }; @command() export default class extends Command { @metadata async execute(): Promise { let configFileExists = FS.existsSync(MAKESCRIPT_CONFIG_FILE_PATH); if (!configFileExists) { let {withDefaultAgent} = await prompts({ type: 'confirm', name: 'withDefaultAgent', message: 'Run with a default agent?', initial: true, }); // There is a bug (or unhandled behavior) with 'prompts'. // When user press CTRL + C , program will continue to execute with empty answers. // https://github.com/terkelg/prompts/issues/252 if (withDefaultAgent === undefined) { return; } if (withDefaultAgent) { let {repoURL, subPath} = await prompts([ { type: 'text', name: 'repoURL', message: 'Enter the scripts repo url', validate: value => /^(https?:\/\/.+)|(\w+\.git)$/.test(value), }, { type: 'text', name: 'subPath', message: 'Enter the scripts definition dir path', }, ]); // There is a bug (or unhandled behavior) with 'prompts'. // When user press CTRL + C , program will continue to execute with empty answers. // https://github.com/terkelg/prompts/issues/252 if (!repoURL) { return; } writeConfig( MAKESCRIPT_DEFAULT_AGENT_CONFIG_FILE_PATH, MAKESCRIPT_DEFAULT_AGENT_CONFIG_DEFAULT( MAKESCRIPT_CONFIG_DEFAULT.agent.token, repoURL, subPath, ), ); } writeConfig(MAKESCRIPT_CONFIG_FILE_PATH, MAKESCRIPT_CONFIG_DEFAULT); } let makescriptConfig = readConfig( MAKESCRIPT_CONFIG_FILE_PATH, )!; let defaultAgentConfig = readConfig( MAKESCRIPT_DEFAULT_AGENT_CONFIG_FILE_PATH, ); let tiva = new Tiva({ project: Path.join(__dirname, '../../../src/program'), }); logger.info('Checking config file ...'); try { await tiva.validate( {module: './config', type: 'JSONConfigFile'}, makescriptConfig, ); await main({ ...makescriptConfig, workspace: WORKSPACE_PATH, }); if (defaultAgentConfig) { logger.info('Checking config file of default agent ...'); await tiva.validate( {module: '@makeflow/makescript-agent', type: 'JSONConfigFile'}, defaultAgentConfig, ); await agentMain(tiva, { ...defaultAgentConfig, agentModule: '@makeflow/makescript-agent', workspace: DEFAULT_AGENT_WORKSPACE_PATH, }); } } catch (error) { if (error.diagnostics) { logger.error( `Config file structure does not match:\n${error.diagnostics}`, ); } throw error; } } } function readConfig(path: string): T | undefined { if (!FS.existsSync(path)) { return undefined; } let jsonConfigText = FS.readFileSync(path).toString(); return JSON.parse(jsonConfigText); } function writeConfig(path: string, config: object): void { let jsonConfigText = JSON.stringify( config, undefined, JSON_CONFIG_INDENTATION, ); let dirname = Path.dirname(path); if (!FS.existsSync(dirname)) { FS.mkdirSync(dirname, {recursive: true}); } FS.writeFileSync(path, jsonConfigText); }