import { execSync } from 'child_process'
import { fileURLToPath } from 'url'
import path from 'path'
import fs from 'fs'
import { loadJsonFile } from '../files.js'
// Can't include .json files without adding an experimental node flag, but we can use this workaround to use require, which works, instead
import { createRequire } from "module" ; // Bring in the ability to create the 'require' method
const require = createRequire ( import . meta . url ) ; // construct the require method
const packageVersion = require ( "../../package.json" ) . version
const _ _filename = fileURLToPath ( import . meta . url )
const _ _dirname = path . dirname ( _ _filename )
// Returns one of: off, installed, enabled, running, synced, error
function cliStatus ( ) {
try {
const stdout = execSync ( 'npm list -g @autonomousorganization/ao-cli' )
const isAoCliInstalled = stdout . includes ( '@autonomousorganization/ao-cli@' )
if ( isAoCliInstalled ) return 'installed'
} catch ( err ) {
return 'error'
}
return 'off'
}
// It is possible to run ao-cli with npx @autonomousorganization/ao-cli. In this case, it can help you install it permanently.
function installAoCli ( ) {
try {
execSync ( 'npm i -g @autonomousorganization/ao-cli 2>&1' )
console . log ( 'Installed ao-cli.' )
} catch ( err ) {
console . log ( 'Error installing ao-cli:' , err )
}
}
async function getAoCliVersion ( ) {
const npmGlobalPackagesPath = execSync ( 'npm root -g' ) . toString ( ) . replace ( /\n/ , '' )
const aoGlobalPackagePath = path . join ( npmGlobalPackagesPath , '@autonomousorganization/ao-cli/package.json' )
let jsonFileContents
try {
const contents = fs . readFileSync ( aoGlobalPackagePath )
jsonFileContents = JSON . parse ( contents )
} catch ( err ) {
if ( err . code === 'ENOENT' ) {
console . log ( 'The global ao-cli package.json file does not exist.' )
} else {
console . log ( 'Unknown error loading global ao-cli package.json file, aborting.' , err )
}
return null
}
if ( ! jsonFileContents . hasOwnProperty ( 'version' ) ) {
return null
}
return jsonFileContents . version
}
// Updates the globally-installed version of this package, ao-cli, using npm
async function selfUpdate ( ) {
try {
const beforeVersionNumber = await getAoCliVersion ( )
const result = execSync ( 'npm update -g @autonomousorganization/ao-cli 2>&1' )
const afterVersionNumber = await getAoCliVersion ( )
if ( beforeVersionNumber === afterVersionNumber ) {
console . log ( "ao-cli version is already current." )
} else {
console . log ( '\nao-cli self-updated automatically from version' , beforeVersionNumber , 'to version' , afterVersionNumber , 'from the official npm repository.' )
}
} catch ( err ) {
console . log ( 'Failed to update ao-cli: ' , err )
}
}
// Returns true if the 'ao' alias for ao-cli has already been addded to .bashrc
function checkAoAlias ( ) {
try {
execSync ( 'grep "ao=ao-cli" ~/.bashrc' )
} catch ( err ) {
return 'off'
}
return 'installed'
}
// Adds a line to .bashrc to make 'ao' an alias for 'ao-cli', to simplify using the AO from the command line
function installAoAlias ( ) {
try {
execSync ( 'echo alias ao=ao-cli >> $HOME/.bashrc' )
console . log ( 'Added alias line to ~/.bashrc. You can now type \'ao\' to launch ao-cli.' )
} catch ( err ) {
console . log ( 'Failed to add alias, sorry.' )
}
}
// Returns true if the cd hook function has already been addded to .bashrc
function checkCdHook ( ) {
try {
execSync ( 'grep "function cd \{ builtin cd.*--interstitial.* ; \}$" ~/\.bashrc' )
} catch ( err ) {
return 'off'
}
return 'installed'
}
// Adds a line to .bashrc to make 'ao' an alias for 'ao-cli', to simplify using the AO from the command line
function installCdHook ( ) {
try {
execSync ( 'echo \'function cd { builtin cd "\$@" && node \~/ao-cli \-\-interstitial "\$\@" ; }\' >> $HOME/.bashrc' )
console . log ( 'Added alias line to ~/.bashrc. Try typing \'cd\' in a terminal.' )
} catch ( err ) {
console . log ( 'Failed to add alias, sorry.' )
}
}
function removeCdHook ( ) {
try {
let result = execSync ( 'sed -i \'/^function cd.*/d\' ' + process . env . HOME + '/.bashrc' )
console . log ( 'sed:' , result . toString ( ) )
} catch ( error ) {
console . log ( error . output . toString ( ) )
}
}
export default {
description : 'this AO command-line interface' ,
status : cliStatus ,
install : installAoCli ,
version : getAoCliVersion ,
update : selfUpdate ,
add _alias : installAoAlias ,
remove _alias : ( ) => console . log ( "Not implemented yet." ) ,
add _cd : installCdHook ,
remove _cd : removeCdHook ,
menu : [
{ name : ( ) => checkAoAlias ( ) === 'installed' ? 'Remove \'ao\' shortcut for \'ao-cli\'' : 'Install \'ao\' shortcut for \'ao-cli\'' ,
value : ( ) => checkAoAlias ( ) === 'installed' ? 'remove_alias' : 'add_alias' } ,
{ name : ( ) => checkCdHook ( ) === 'installed' ? 'Remove \'cd\' fantasy hook' : 'Install \'cd\' fantasy hook' ,
value : ( ) => checkCdHook ( ) === 'installed' ? 'remove_cd' : 'add_cd' } ,
]
}