Skip to content

Commit

Permalink
🧹 CLI: Configuration logic [5/N] (#700)
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista authored Jul 18, 2024
1 parent 4eb19e7 commit 72dfc71
Show file tree
Hide file tree
Showing 33 changed files with 1,248 additions and 18 deletions.
6 changes: 6 additions & 0 deletions .changeset/ten-kids-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@layerzerolabs/devtools-cli-test": patch
"@layerzerolabs/devtools-cli": patch
---

Add configuration logic to devtools-cli
1 change: 1 addition & 0 deletions packages/devtools-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"devDependencies": {
"@layerzerolabs/devtools": "~0.3.17",
"@layerzerolabs/io-devtools": "~0.1.11",
"@layerzerolabs/ua-devtools": "~0.3.20",
"@types/prompts": "^2.4.9",
"@types/react": "^17.0.74",
"commander": "^11.1.0",
Expand Down
158 changes: 141 additions & 17 deletions packages/devtools-cli/src/commands/oapp/wire/index.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,160 @@
import { Command } from 'commander'
import { printLogo } from '@layerzerolabs/io-devtools/swag'
import { createLogger, setDefaultLogLevel } from '@layerzerolabs/io-devtools'
import { printLogo, printRecords } from '@layerzerolabs/io-devtools/swag'
import {
createConfigLoader,
createLogger,
printBoolean,
printJson,
setDefaultLogLevel,
} from '@layerzerolabs/io-devtools'
import { configureOApp, OAppOmniGraphSchema } from '@layerzerolabs/ua-devtools'
import {
WithAssertFlag,
WithDryRunFlag,
type WithLogLevelOption,
WithOAppConfigOption,
type WithSetupOption,
WithTsConfigOption,
createAssertFlag,
createDryRunFlag,
createLogLevelOption,
createOAppConfigFileOption,
createSetupFileOption,
createTsConfigFileOption,
} from '@/commands/options'
import { setupTypescript } from '@/setup'
import { createSetupLoader, setupTypescript } from '@/setup'
import { Configurator, formatOmniTransaction, OmniGraph, OmniTransaction } from '@layerzerolabs/devtools'
import { CLISetup } from '@/types'

interface Args extends WithLogLevelOption, WithSetupOption, WithTsConfigOption {}
interface Args
extends WithLogLevelOption,
WithSetupOption,
WithOAppConfigOption,
WithAssertFlag,
WithDryRunFlag,
WithTsConfigOption {}

export const wire = new Command('wire')
.addOption(createLogLevelOption())
.addOption(createSetupFileOption())
.addOption(createOAppConfigFileOption())
.addOption(createTsConfigFileOption())
.addOption(createLogLevelOption())
.action(async ({ setup, logLevel, tsConfig: tsConfigPath }: Args) => {
printLogo()
.addOption(createAssertFlag())
.addOption(createDryRunFlag())
.action(
async ({
setup: setupPath,
logLevel,
oappConfig: oappConfigPath,
assert = false,
dryRun = false,
tsConfig: tsConfigPath,
}: Args) => {
printLogo()

// We'll set the global logging level to get as much info as needed
setDefaultLogLevel(logLevel)

// We'll setup TypeScript support so that we can dynamically load TypeScript config files
setupTypescript(tsConfigPath)

// We'll need a logger
const logger = createLogger(logLevel)

// And since this command is not complete yet, we'll warn the user
logger.warn(
`This command is just a placeholder. Please use @layerzerolabs/toolbox-hardhat package for the time being.`
)

if (assert) {
logger.info(`Running in assertion mode`)
} else if (dryRun) {
logger.info(`Running in dry run mode`)
}

let setup: CLISetup

// Now it's time to load the setup file tht contains all the bits required to do the wiring
const loadSetup = createSetupLoader()

try {
logger.verbose(`Loading setup from ${setupPath}`)

setup = await loadSetup(setupPath)

logger.verbose(`Loaded setup from ${setupPath}`)
} catch (error) {
logger.error(`Failed to load setup from ${setupPath}:\n\n${error}`)

process.exit(1)
}

// The first thing we'll need is the graph of our app
//
// In order to get the graph, we'll first need some means of loading it.
// By default, the OApp graph loader will be used but users might choose to supply their own
// config loader
logger.verbose(
setup.loadConfig == null
? `Using default OApp config loader`
: `Using custom config loader from ${setupPath}`
)

let graph: OmniGraph

// Now it's time to load the config file
const loadConfig = setup.loadConfig ?? createConfigLoader(OAppOmniGraphSchema)

try {
logger.info(`Loading config file from ${oappConfigPath}`)

graph = await loadConfig(oappConfigPath)

logger.info(`${printBoolean(true)} Successfully loaded config file from ${oappConfigPath}`)
logger.debug(`Loaded config file from ${oappConfigPath}:\n\n${printJson(graph)}`)
} catch (error) {
logger.error(`Failed to load config from ${setupPath}:\n\n${error}`)

process.exit(1)
}

// With the setup & config in place, the only missing piece to get the OApp configuration
// is the configurator that will get the list of transactions needed
const configure: Configurator<any, any> =
setup.configure == null
? (logger.verbose(`Using default OApp configurator`), configureOApp)
: (logger.verbose(`Using custom configurator from ${setupPath}`), setup.configure)

let transactions: OmniTransaction[]

try {
logger.info(`Checking configuration`)

transactions = await configure(graph, setup.createSdk)
} catch (error) {
logger.error(`Failed to check OApp configuration:\n\n${error}`)

// We'll set the global logging level to get as much info as needed
setDefaultLogLevel(logLevel)
process.exit(1)
}

// We'll setup TypeScript support so that we can dynamically load TypeScript config files
setupTypescript(tsConfigPath)
// If there are no transactions that need to be executed, we'll just exit
if (transactions.length === 0) {
return logger.info(`The OApp is wired, no action is necessary`), undefined
} else if (assert) {
// If we are in assertion mode, we'll print out the transactions and exit with code 1
// if there is anything left to configure
logger.error(`The OApp is not fully wired, following transactions are necessary:`)

const logger = createLogger(logLevel)
// Print the outstanding transactions
printRecords(transactions.map(formatOmniTransaction))

logger.debug(`Loading setup from ${setup}`)
// Exit with non-zero error code
process.exit(1)
}

logger.warn(
`This command is just a placeholder. Please use @layerzerolabs/toolbox-hardhat package for the time being.`
)
})
// If we are in dry run mode, we'll just print the transactions and exit
if (dryRun) {
printRecords(transactions.map(formatOmniTransaction))
}
}
)
23 changes: 23 additions & 0 deletions packages/devtools-cli/src/commands/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ export interface WithSetupOption {

export const createSetupFileOption = () => new Option('-s,--setup <path>', 'Path to a setup file').makeOptionMandatory()

export interface WithOAppConfigOption {
oappConfig: string
}

export const createOAppConfigFileOption = () =>
new Option('--oapp-config <path>', 'Path to an OApp config file').makeOptionMandatory()

export interface WithLogLevelOption {
logLevel: LogLevel
}
Expand All @@ -22,6 +29,22 @@ export const createLogLevelOption = () =>
return value
})

export interface WithAssertFlag {
assert?: boolean
}

export const createAssertFlag = () =>
new Option(
'--assert',
'Will not execute any transactions and fail if there are any transactions required to configure the OApp'
)

export interface WithDryRunFlag {
dryRun?: boolean
}

export const createDryRunFlag = () => new Option('--dry-run', 'Will not execute any transactions')

export interface WithTsConfigOption {
tsConfig?: string
}
Expand Down
Loading

0 comments on commit 72dfc71

Please sign in to comment.