Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@types/lodash": "^4.17.15",
"@types/mocha": "^10.0.1",
"@types/node": "^22.10.5",
"@types/sinon": "^21.0.0",
"axios-mock-adapter": "^2.1.0",
"chai": "^4.3.7",
"eslint-config-mimic": "^0.0.3",
Expand Down
34 changes: 31 additions & 3 deletions packages/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Command, Flags } from '@oclif/core'

import { filterTasks, taskFilterFlags } from '../helpers'
import MimicConfigHandler from '../lib/MimicConfigHandler'
import log from '../log'
import { RequiredTaskConfig } from '../types'

import Codegen from './codegen'
import Compile from './compile'

Expand All @@ -20,18 +25,41 @@ export default class Build extends Command {
description: 'remove existing generated types before generating new files',
default: false,
}),
...taskFilterFlags,
}

public async run(): Promise<void> {
const { flags } = await this.parse(Build)
const { manifest, task, output, types, clean } = flags
const { manifest, task, output, types, clean, include, exclude } = flags

if (MimicConfigHandler.exists()) {
const mimicConfig = MimicConfigHandler.load(this)
const allTasks = MimicConfigHandler.getTasks(mimicConfig)
const tasks = filterTasks(this, allTasks, include, exclude)
for (const taskConfig of tasks) {
console.log(`\n${log.highlightText(`[${taskConfig.name}]`)}`)
await this.runForTask(taskConfig, clean)
}
} else {
await this.runForTask({ manifest, entry: task, output, types }, clean)
}
}

const codegenArgs: string[] = ['--manifest', manifest, '--output', types]
private async runForTask(task: Omit<RequiredTaskConfig, 'name'>, clean: boolean): Promise<void> {
const codegenArgs: string[] = ['--manifest', task.manifest, '--output', task.types, '--skip-config']
if (clean) codegenArgs.push('--clean')

await Codegen.run(codegenArgs)

const compileArgs: string[] = ['--task', task, '--manifest', manifest, '--output', output]
const compileArgs: string[] = [
'--task',
task.entry,
'--manifest',
task.manifest,
'--output',
task.output,
'--skip-config',
]
await Compile.run(compileArgs)
}
}
30 changes: 27 additions & 3 deletions packages/cli/src/commands/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, Flags } from '@oclif/core'
import * as fs from 'fs'
import { join } from 'path'

import { AbisInterfaceGenerator, InputsInterfaceGenerator, ManifestHandler } from '../lib'
import { filterTasks, taskFilterFlags } from '../helpers'
import { AbisInterfaceGenerator, InputsInterfaceGenerator, ManifestHandler, MimicConfigHandler } from '../lib'
import log from '../log'
import { Manifest } from '../types'
import { Manifest, RequiredTaskConfig } from '../types'

export default class Codegen extends Command {
static override description = 'Generates typed interfaces for declared inputs and ABIs from your manifest.yaml file'
Expand All @@ -20,11 +21,34 @@ export default class Codegen extends Command {
description: 'Remove existing generated types before generating new files',
default: false,
}),
['skip-config']: Flags.boolean({
hidden: true,
description: 'Skip mimic.yaml config (used internally by build command)',
default: false,
}),
...taskFilterFlags,
}

public async run(): Promise<void> {
const { flags } = await this.parse(Codegen)
const { manifest: manifestDir, output: outputDir, clean } = flags
const { manifest: manifestDir, output: outputDir, clean, include, exclude, ['skip-config']: skipConfig } = flags

if (!skipConfig && MimicConfigHandler.exists()) {
const mimicConfig = MimicConfigHandler.load(this)
const allTasks = MimicConfigHandler.getTasks(mimicConfig)
const tasks = filterTasks(this, allTasks, include, exclude)
for (const task of tasks) {
console.log(`\n${log.highlightText(`[${task.name}]`)}`)
await this.runForTask(task, clean)
}
} else {
await this.runForTask({ manifest: manifestDir, types: outputDir }, clean)
}
}

private async runForTask(task: Omit<RequiredTaskConfig, 'name' | 'entry' | 'output'>, clean: boolean): Promise<void> {
const manifestDir = task.manifest
const outputDir = task.types
const manifest = ManifestHandler.load(this, manifestDir)

if (clean) {
Expand Down
42 changes: 36 additions & 6 deletions packages/cli/src/commands/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import { Command, Flags } from '@oclif/core'
import * as fs from 'fs'
import * as path from 'path'

import { filterTasks, taskFilterFlags } from '../helpers'
import ManifestHandler from '../lib/ManifestHandler'
import MimicConfigHandler from '../lib/MimicConfigHandler'
import { execBinCommand } from '../lib/packageManager'
import log from '../log'
import { RequiredTaskConfig } from '../types'

export default class Compile extends Command {
static override description = 'Compiles task'
Expand All @@ -15,19 +18,46 @@ export default class Compile extends Command {
task: Flags.string({ char: 't', description: 'task to compile', default: 'src/task.ts' }),
manifest: Flags.string({ char: 'm', description: 'manifest to validate', default: 'manifest.yaml' }),
output: Flags.string({ char: 'o', description: 'output directory', default: './build' }),
['skip-config']: Flags.boolean({
hidden: true,
description: 'Skip mimic.yaml config (used internally by build command)',
default: false,
}),
...taskFilterFlags,
}

public async run(): Promise<void> {
const { flags } = await this.parse(Compile)
const { task: taskFile, output: outputDir, manifest: manifestDir } = flags
const {
task: taskFile,
output: outputDir,
manifest: manifestDir,
include,
exclude,
['skip-config']: skipConfig,
} = flags

const absTaskFile = path.resolve(taskFile)
const absOutputDir = path.resolve(outputDir)
if (!skipConfig && MimicConfigHandler.exists()) {
const mimicConfig = MimicConfigHandler.load(this)
const allTasks = MimicConfigHandler.getTasks(mimicConfig)
const tasks = filterTasks(this, allTasks, include, exclude)
for (const task of tasks) {
console.log(`\n${log.highlightText(`[${task.name}]`)}`)
await this.runForTask(task)
}
} else {
await this.runForTask({ manifest: manifestDir, entry: taskFile, output: outputDir })
}
}

private async runForTask(task: Omit<RequiredTaskConfig, 'name' | 'types'>): Promise<void> {
const absTaskFile = path.resolve(task.entry)
const absOutputDir = path.resolve(task.output)

if (!fs.existsSync(absOutputDir)) fs.mkdirSync(absOutputDir, { recursive: true })

log.startAction('Verifying Manifest')
const manifest = ManifestHandler.load(this, manifestDir)
const manifest = ManifestHandler.load(this, task.manifest)
log.startAction('Compiling')

const ascArgs = [
Expand All @@ -52,8 +82,8 @@ export default class Compile extends Command {

log.startAction('Saving files')

fs.writeFileSync(path.join(outputDir, 'manifest.json'), JSON.stringify(manifest, null, 2))
fs.writeFileSync(path.join(absOutputDir, 'manifest.json'), JSON.stringify(manifest, null, 2))
log.stopAction()
console.log(`Build complete! Artifacts in ${outputDir}/`)
console.log(`Build complete! Artifacts in ${task.output}/`)
}
}
55 changes: 51 additions & 4 deletions packages/cli/src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import * as fs from 'fs'
import { join, resolve } from 'path'

import { GENERIC_SUGGESTION } from '../errors'
import { filterTasks, taskFilterFlags } from '../helpers'
import MimicConfigHandler from '../lib/MimicConfigHandler'
import { execBinCommand } from '../lib/packageManager'
import log from '../log'
import { RequiredTaskConfig } from '../types'

const MIMIC_REGISTRY_DEFAULT = 'https://api-protocol.mimic.fi'

Expand All @@ -21,20 +24,64 @@ export default class Deploy extends Command {
output: Flags.string({ char: 'o', description: 'Output directory for deployment CID', default: './build' }),
url: Flags.string({ char: 'u', description: `Mimic Registry base URL`, default: MIMIC_REGISTRY_DEFAULT }),
'skip-compile': Flags.boolean({ description: 'Skip codegen and compile steps before uploading', default: false }),
...taskFilterFlags,
}

public async run(): Promise<void> {
const { flags } = await this.parse(Deploy)
const { key, input: inputDir, output: outputDir, 'skip-compile': skipCompile, url: registryUrl } = flags
const {
key,
input: inputDir,
output: outputDir,
'skip-compile': skipCompile,
url: registryUrl,
include,
exclude,
} = flags

if (MimicConfigHandler.exists()) {
const mimicConfig = MimicConfigHandler.load(this)
const allTasks = MimicConfigHandler.getTasks(mimicConfig)
const tasks = filterTasks(this, allTasks, include, exclude)
for (const task of tasks) {
console.log(`\n${log.highlightText(`[${task.name}]`)}`)
await this.runForTask(task, key, registryUrl, skipCompile, task.output)
}
} else {
await this.runForTask(
{ manifest: 'manifest.yaml', entry: 'src/task.ts', types: './src/types', output: outputDir },
key,
registryUrl,
skipCompile,
inputDir
)
}
}

private async runForTask(
task: Omit<RequiredTaskConfig, 'name'>,
key: string,
registryUrl: string,
skipCompile: boolean,
inputDir: string
): Promise<void> {
const fullInputDir = resolve(inputDir)
const fullOutputDir = resolve(outputDir)
const fullOutputDir = resolve(task.output)

if (!skipCompile) {
const codegen = execBinCommand('mimic', ['codegen'], process.cwd())
const codegen = execBinCommand(
'mimic',
['codegen', '--manifest', task.manifest, '--output', task.types],
process.cwd()
)
if (codegen.status !== 0)
this.error('Code generation failed', { code: 'CodegenError', suggestions: ['Fix manifest and ABI files'] })

const compile = execBinCommand('mimic', ['compile', '--output', fullInputDir], process.cwd())
const compile = execBinCommand(
'mimic',
['compile', '--task', task.entry, '--manifest', task.manifest, '--output', fullInputDir],
process.cwd()
)
if (compile.status !== 0)
this.error('Compilation failed', { code: 'BuildError', suggestions: ['Check the task source code'] })
}
Expand Down
63 changes: 54 additions & 9 deletions packages/cli/src/commands/test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Command, Flags } from '@oclif/core'
import * as path from 'path'

import { filterTasks, taskFilterFlags } from '../helpers'
import MimicConfigHandler from '../lib/MimicConfigHandler'
import { execBinCommand } from '../lib/packageManager'
import log from '../log'
import { RequiredTaskConfig } from '../types'

export default class Test extends Command {
static override description = 'Runs task tests'
Expand All @@ -11,22 +15,63 @@ export default class Test extends Command {
static override flags = {
directory: Flags.string({ char: 'd', description: 'task directory', default: './' }),
'skip-compile': Flags.boolean({ description: 'skip codegen and compile steps' }),
...taskFilterFlags,
}

public async run(): Promise<void> {
const { flags } = await this.parse(Test)
const { directory, 'skip-compile': skipCompile } = flags
const { directory, 'skip-compile': skipCompile, include, exclude } = flags
const baseDir = path.resolve(directory)
const testPath = path.join(baseDir, 'tests')

if (!skipCompile) {
const cg = execBinCommand('mimic', ['codegen'], baseDir)
if (cg.status !== 0) this.exit(cg.status ?? 1)
const cp = execBinCommand('mimic', ['compile'], baseDir)
if (cp.status !== 0) this.exit(cp.status ?? 1)
const testPaths = new Set<string>()

if (MimicConfigHandler.exists(baseDir)) {
const mimicConfig = MimicConfigHandler.load(this, baseDir)
const allTasks = MimicConfigHandler.getTasks(mimicConfig)
const tasks = filterTasks(this, allTasks, include, exclude)

for (const task of tasks) {
if (!skipCompile) {
console.log(`\n${log.highlightText(`[${task.name}]`)}`)
await this.compileTask(task, baseDir)
}
testPaths.add(this.getTestPath(baseDir))
}
} else {
const defaultTask = {
manifest: 'manifest.yaml',
entry: 'src/task.ts',
types: './src/types',
output: './build',
}
if (!skipCompile) await this.compileTask(defaultTask, baseDir)
testPaths.add(this.getTestPath(baseDir))
}

const result = execBinCommand('tsx', ['./node_modules/mocha/bin/mocha.js', `${testPath}/**/*.spec.ts`], baseDir)
this.exit(result.status ?? 1)
if (testPaths.size > 0) this.runTests(Array.from(testPaths), baseDir)
}

private async compileTask(task: Omit<RequiredTaskConfig, 'name'>, baseDir: string): Promise<void> {
const cg = execBinCommand(
'mimic',
['codegen', '--manifest', task.manifest, '--output', task.types, '--skip-config'],
baseDir
)
if (cg.status !== 0) this.exit(cg.status ?? 1)
const cp = execBinCommand(
'mimic',
['compile', '--task', task.entry, '--manifest', task.manifest, '--output', task.output, '--skip-config'],
baseDir
)
if (cp.status !== 0) this.exit(cp.status ?? 1)
}

private getTestPath(baseDir: string): string {
return path.join(baseDir, 'tests', '**', '*.spec.ts')
}

private runTests(testPaths: string[], baseDir: string): void {
const result = execBinCommand('tsx', ['./node_modules/mocha/bin/mocha.js', ...testPaths], baseDir)
if (result.status !== 0) this.exit(result.status ?? 1)
}
}
Loading