From 216ff83577c5f1ed5f54e63b15e3260ba33a6b5a Mon Sep 17 00:00:00 2001 From: Kien La Date: Sat, 5 Oct 2024 14:41:11 -0400 Subject: [PATCH] basic setup wizard --- src/cli.ts | 14 ++++++++--- src/settings.ts | 2 +- src/setup_wizard.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/setup_wizard.ts diff --git a/src/cli.ts b/src/cli.ts index 3dbf7a5..b88be87 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -4,9 +4,10 @@ import { capture, run } from '~/shell' import { exit, parseAndRemoveWildcardOptions, pp } from '~/utils' import { StaxConfig } from '~/types' import Stax from '~/stax' -import path from 'path' +import * as path from 'path' import tmp from 'tmp' import settings from './settings' +import setupWizard from './setup_wizard' const DEFAULT_CONTEXT_NAME = 'stax' @@ -187,11 +188,18 @@ program.command('set') }) program.command('setup') - .argument('', 'Path to a local directory or git repo of application') + .argument('[location]', 'Path to a local directory or git repo of application') .option('-s, --staxfile ', 'Staxfile to use for setup') .option('-i, --inspect', 'Show the compose file') .description('Setup an application') - .action(async (location, options) => stax.setup({ source: location, ...options }, { ...options, overrides: overrides })) + .action(async (location, options) => { + if (location) + stax.setup({ source: location, ...options }, { ...options, overrides: overrides }) + else if (settings.read('services_home')) + await setupWizard(stax) + else + console.log('Please specify an application location or set the services home directory.') + }) program.command('shell') .alias('sh') diff --git a/src/settings.ts b/src/settings.ts index 5271290..570789d 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -11,7 +11,7 @@ function load() { } const settings = { - read: function(name: string, defaultValue: any | undefined) { + read: function(name: string, defaultValue: any | undefined = undefined) { const settings = load() return settings[name] || defaultValue }, diff --git a/src/setup_wizard.ts b/src/setup_wizard.ts new file mode 100644 index 0000000..4422b23 --- /dev/null +++ b/src/setup_wizard.ts @@ -0,0 +1,59 @@ +import { StaxConfig } from './types' +import { exit, presence } from './utils' +import * as fs from 'fs' +import * as path from 'path' +import settings from './settings' +import stax from './stax' +import icons from './icons' +import inquirer from 'inquirer' +import App from './app' + +function search(dir: string): string[] { + const entries = fs.readdirSync(dir, { withFileTypes: true }) + const staxfiles: string[] = [] + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name) + + if (entry.isDirectory()) { + staxfiles.push(...search(fullPath)) + } else if (entry.name === 'Staxfile' || entry.name.endsWith('.staxfile')) { + staxfiles.push(fullPath) + } + } + return staxfiles +} + +function findStaxfiles(context: string): string[] { + const servicesHome = settings.read('services_home') || exit(1, { message: `${icons.error} services_home is not set in settings` }) + const allStaxfiles = presence(search(servicesHome)) || exit(1, { message: `${icons.error} No Staxfiles found in ${servicesHome}` }) + const installedStaxfiles = App.allContainers(context).map(container => container.staxfile) + + return presence(allStaxfiles.filter(file => !installedStaxfiles.includes(file))) || exit(1, { message: `${icons.error} All services in ${servicesHome} are already installed`}) +} + +function getStaxfileName(filePath: string): string { + const fileName = path.basename(filePath) + const dirName = path.basename(path.dirname(filePath)) + + return fileName === 'Staxfile' ? dirName : fileName.replace('.staxfile', '') +} + +async function pickStaxfile(staxfiles: string[]) { + const { selected } = await inquirer.prompt([ + { + type: 'list', + name: 'selected', + message: 'Select service to install:', + choices: staxfiles.map(file => ({ name: getStaxfileName(file), value: file })), + loop: false + } + ]) + return selected +} + +export default async function setupWizard(stax: stax) { + const staxfile: string = await pickStaxfile(findStaxfiles(stax.context)) + console.log(`Selected service to install: ${staxfile}`) + await stax.setup({ source: staxfile } as unknown as StaxConfig) +}