An interactive command-line interface (CLI) tool to help you install, use, and administer an AO instance.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.2 KiB

3 years ago
#!/usr/bin/env node
import chalk from 'chalk'
import inquirer from 'inquirer'
3 years ago
import { execSync } from 'child_process'
// Import ao-cli core features
import { exitIfRoot, detectOS, updateSoftware } from './scripts/system.js'
import { checkAoEnvFile, aoEnv, setAoEnv, AO_ENV_FILE_PATH } from './scripts/settings.js'
import { unicornPortal, asciiArt, clearScreen } from './scripts/console.js'
import { welcome, exclaim, farewell, yesOrNo } from './scripts/welcome.js'
import useAoMenu from './scripts/ao.js'
import aoInstallWizard, { chooseAoVersion, checkAo } from './scripts/wizard.js'
import testsMenu from './scripts/tests.js'
import { headerStyle } from './scripts/styles.js'
import { sleep } from './scripts/util.js'
import './scripts/strings.js'
// Import AO modular features
import { featuresMenu } from './scripts/features/index.js'
import manual, { printManualPage, manualFolderAsMenu, AO_MANUAL_PATH } from './scripts/features/manual.js'
import aoCli from './scripts/features/ao-cli.js'
// Enable keyboard shortcut interruption of inquirer menus
import './scripts/keyboard.js'
3 years ago
// Prints the AO Main Menu and executes the user's choice
async function mainMenu() {
console.log(`\n${headerStyle('AO Main Menu')}\n`)
let mainMenuChoices = [
'AO',
'Alchemy',
'Configure',
'Manual',
'Exit'
]
let answer
try {
answer = await inquirer.prompt({
name: 'main_menu',
type: 'list',
message: 'Please choose:',
choices: mainMenuChoices,
pageSize: mainMenuChoices.length
})
} catch(error) {
if (error === 'EVENT_INTERRUPTED') {
console.log('\nESC')
answer = { main_menu: 'Exit' }
}
}
let previousChoice
3 years ago
switch(answer.main_menu) {
case 'AO':
while(await useAoMenu()) {}
break
case 'Alchemy':
while(await adminMenu()) {}
break
case 'Configure':
do {
previousChoice = await featuresMenu(previousChoice)
} while(previousChoice !== false)
3 years ago
break
case 'Manual':
if(!manual.isInstalled()) {
console.log("Downloading the AO manual...")
if(manual.install()) {
console.log("Downloaded the AO Manual from the official git repo via http and saved to", AO_MANUAL_PATH + '.')
} else {
console.log('Failed to download the AO manual, sorry.')
return false
}
} else {
manual.update()
}
await printManualPage(AO_MANUAL_PATH) // Fencepost case - print overview page
3 years ago
do {
previousChoice = await manualFolderAsMenu(AO_MANUAL_PATH, 'AO User Manual', 'Back to Main Menu', previousChoice + 1)
} while(previousChoice !== false)
3 years ago
break
case 'Exit':
farewell()
3 years ago
await sleep(310)
return false
}
return true
}
// Prints the AO Admin Menu and executes the user's choice
// Maybe Alchemy menu should be installation and update, and admin menu should be more configuration & AO member admin
3 years ago
async function adminMenu() {
console.log(`\n${headerStyle('System Alchemy')}`)
3 years ago
const adminChoices = [
{ name: 'Check AO install', value: 'check_AO' },
'Update system software',
//'Update AO',
//{ name: 'Install AO prerequisites', value: 'prereqs' }, // move to feature module? calls installRequired()
'AO install wizard',
//'Switch AO target server',
//'Switch AO database',
'Switch AO version',
//'Check AO service',
//'Start/Stop AO service',
//'Import/export state/decks',
//'Watch logs now',
'Tests',
//'Update remote AOs',
3 years ago
'Back to Main Menu'
]
let answer
try {
answer = await inquirer.prompt({
name: 'admin_menu',
type: 'list',
message: 'Please choose:',
choices: adminChoices,
pageSize: adminChoices.length,
})
} catch(error) {
if (error === 'EVENT_INTERRUPTED') {
console.log('\nESC')
return false
}
}
3 years ago
switch(answer.admin_menu) {
case 'check_AO':
await checkAo()
break
case 'Update system software':
updateSoftware()
break
case 'AO install wizard':
await aoInstallWizard()
break
case 'Switch AO version':
await chooseAoVersion()
break
case 'Switch AO target server':
case 'Import/Export state/decks':
case 'Watch logs now':
case 'Update remote AOs':
3 years ago
console.log("Not yet implemented.")
break
case 'Tests':
while(await testsMenu()) {}
break
3 years ago
default:
return false
}
return true
}
// Returns false if a flag means the program should now terminate
// -v Print version info
async function handleArgs(args) {
switch (args[0]) {
case '--version':
case '-v':
console.log(await aoCli.version())
return false
}
return true
}
3 years ago
// Main entry point
async function main() {
// Print version info etc. no matter what
const nodePath = process.argv[0]
const aoCliPath = process.argv[1]
const args = process.argv.slice(2)
const shouldTerminate = !await handleArgs(args)
if(shouldTerminate) {
process.exit(0)
}
// No root allowed
3 years ago
exitIfRoot()
// Loading screen, display some quick info during the fun animation
const DISTRO = aoEnv('DISTRO')
if(!DISTRO) {
setAoEnv('DISTRO', detectOS())
}
if(checkAoEnvFile()) {
console.log('AO .env file exists at', AO_ENV_FILE_PATH)
} else {
console.log('AO .env file does not exist at', AO_ENV_FILE_PATH)
3 years ago
}
await unicornPortal(650)
if(!aoEnv('AO_FIRST_RUN')) {
clearScreen()
asciiArt()
console.log('\n' + exclaim(), 'It looks like this is the first time you\'re running ao-cli on this computer! ao-cli stands for Autonomous Organization-Command Line Interface.\n\nWould you like to run the AO install wizard? It will walk you through setting up an AO server instance so you can use the AO on this computer as a full node. (Press Ctrl-C at any time to exit.)\n')
const pleaseInstall = await yesOrNo('Start the AO install wizard?', true)
setAoEnv('AO_FIRST_RUN', true)
if(pleaseInstall) {
await aoInstallWizard()
} else {
console.log('You can start the AO install wizard at any time from the Configure menu.')
}
}
3 years ago
// Main AO title screen and flavor text
clearScreen()
asciiArt()
await welcome()
// Main loop
while(await mainMenu()) {}
process.exit(0)
}
await main()