UNPKG

@gluestack-seal/cli

Version:
209 lines (178 loc) 5.73 kB
import { join, relative } from "path"; import { readdir } from "fs/promises"; import { exists } from "../helpers/fs-exists"; import { parseYAML } from "../helpers/parse-yaml"; import { exitWithMsg } from "../helpers/exit-with-msg"; import { SealService } from "../typings/seal-service"; import { RunServiceOptions } from "../typings/run-service-options"; import { validateSealService } from "../validations/seal-service"; import Local from "../runners/local"; import Docker from "../runners/docker"; import { find, isEmpty } from "lodash"; import { validateSeal } from "../validations/seal"; import { Seal } from "../typings/seal"; import { closestMatch } from "closest-match"; import chalk from "chalk"; import * as os from "os"; import { readfile } from "../helpers/fs-readfile-json"; import { writefile } from "../helpers/fs-writefile"; import { execute } from "../helpers/execute"; import getStore from "../helpers/get-store"; export async function getAndValidate(serviceName: string) { const _yamlPath = join("seal.yaml"); if (!(await exists(_yamlPath))) { await exitWithMsg(`> "${_yamlPath}" doesn't exists`); } const _yamlContent: Seal = await validateSeal(await parseYAML(_yamlPath)); if ( !_yamlContent || !_yamlContent.services || isEmpty(_yamlContent.services) ) { await exitWithMsg(`> "seal.yaml" services does not exists`); } if (!_yamlContent.services[serviceName]) { const closestWord = closestMatch( serviceName, Object.keys(_yamlContent.services), ); console.log( chalk.bgRed(`\nUnknown service: "${serviceName}".`), chalk.cyan(`Did you mean "${closestWord}"?`), ); await exitWithMsg(""); } return { _yamlPath, _yamlContent }; } export async function getAndValidateService( serviceName: string, _yamlContent: any, ) { // if service doesn't exists, exit const servicePath: string = join( process.cwd(), _yamlContent.services[serviceName].path, ); if (!(await exists(servicePath))) { await exitWithMsg(`> service ${relative(".", servicePath)} doesn't exists`); } // check if given service has a seal.service.yaml file const _serviceYamlPath: string | boolean = await exists( join(servicePath, "seal.service.yaml"), ); const _ymlPath: string | boolean = await exists( join(servicePath, "seal.service.yaml"), ); // if yaml doesn't exists, exit if (!_serviceYamlPath && !_ymlPath) { await exitWithMsg( `> service ${relative( ".", join(servicePath, "seal.service.yaml"), )} file doesn't exists`, ); } const yamlPath: string = ( _serviceYamlPath ? _serviceYamlPath : _ymlPath ) as string; const content: SealService = await validateSealService( await parseYAML(yamlPath), ); return { servicePath, _serviceYamlPath, _ymlPath, yamlPath, content }; } async function checkIfAnotherProjectIsUp(_yamlContent: any) { const _sealFolderPath = join(os.homedir(), ".seal"); const files: string[] = await readdir(_sealFolderPath); for await (const file of files) { if (!file.endsWith(".json") || file === "projects.json") { continue; } if (file !== `${_yamlContent.project_id}.json`) { const data: any[] = (await readfile(join(_sealFolderPath, file))) || []; const serviceUp = find(data, { status: "up" }); if (serviceUp) { await exitWithMsg( `> seal project with ID: ${file.split(".")[0]} is already up`, ); } } } } async function checkIfAlreadyUp(_yamlContent: any, serviceName: string) { const store = await getStore(); const data = store.get("services") || []; const service = find(data, { service: serviceName }); if (service && service.status === "up") { await exitWithMsg( `> "${serviceName}" service is already up on ${service.platform}`, ); } } async function generateEnv() { const args: string[] = ["env:generate"]; console.log(chalk.gray("$ seal", args.join(" "))); await execute("seal", args, { cwd: process.cwd(), shell: true, }); } export default async ( serviceName: string, options: RunServiceOptions, ): Promise<void> => { const { platform } = options; const { _yamlPath, _yamlContent } = await getAndValidate(serviceName); await checkIfAlreadyUp(_yamlContent, serviceName); const { servicePath, _serviceYamlPath, _ymlPath, yamlPath, content } = await getAndValidateService(serviceName, _yamlContent); // if service doesn't contain given platform, exit if (!content.platforms[platform]) { await exitWithMsg( `> service ${serviceName}: "${relative( ".", join(servicePath, "seal.service.yaml"), )}" doesn't support ${platform} platform`, ); } const { envfile, build, ports, volumes, context } = content.platforms[platform]; // generates .env await generateEnv(); switch (platform) { case "docker": await Docker.start( content.container_name, servicePath, build, ports || [], envfile, volumes, ); break; case "local": await Local.start(context || servicePath, build); break; } const store = await getStore(); const data = store.get("services") || []; let found = false; const json = { service: serviceName, status: "up", platform: platform, port: ports, }; data.map((service: any, index: number): any => { if (service.service === serviceName) { found = true; data[index] = json; } }); if (!found) { data.push(json); } store.set("services", data); console.log( chalk.green(`\n"${serviceName}" service is up on ${platform} platform\n`), ); store.save(); };