FUNC - 轻量类型化 CLI 框架

错误处理

func 会区分系统错误、运行时错误和 runtime-print 错误。局部命令 catch 会先于全局处理器运行。

错误类型

类型 何时出现 行为
F_SYSTEM 无效命令定义、重复注册、缺失处理器或无效注入配置。 立即抛出。系统错误不会传递给用户错误处理器。
F_RUNTIME 选中的命令处理器、catch 方法或全局错误处理器抛出错误。 先传递给局部 catch,再传递给全局错误处理器。没有处理器时会直接抛出。
F_RUNTIME_PRINT 输入错误,例如解析失败、未知选项、多个处理器标志同时命中或校验失败。 传递给处理器,并默认打印到 stderr,除非调用 preventDefaultPrint()。

系统错误

系统错误描述无效框架配置:重复命令名、重复选项 token、缺失处理器、不支持的数组类型、无效装饰器目标或缺失 provider。它们应该在开发阶段修复,不会传递给 @Catch@CatchAll

单命令 Catch

@Catch() 会在命令类上注册一个方法。它会在任何全局处理器运行前,捕获该命令产生的非系统错误。

import { Catch, Command, Exception, FuncException, Handler } from 'func'

@Command({ name: 'publish' })
export class PublishCommand {
  @Catch()
  onError(@Exception() exception: FuncException) {
    console.error(`publish failed: ${exception.message}`)
    exception.preventDefaultPrint()
  }

  @Handler()
  run() {
    throw new Error('missing package')
  }
}

全局错误处理器

@CatchAll() 注册全局错误处理器类。@CommandError()@CatchAll() 的别名。全局处理器需要和应用其他命令一起注册到同一个命令列表中。

import { CatchAll, Exception, FuncException } from 'func'

@CatchAll()
export class ErrorHandler {
  constructor(@Exception() exception: FuncException) {
    if (exception.level === 'runtime-print') {
      console.error(`Invalid input: ${exception.message}`)
      exception.preventDefaultPrint()
      return
    }

    console.error(exception.message)
  }
}
import { FuncModule } from 'func'
import { PublishCommand } from './commands/publish'
import { ErrorHandler } from './error-handler'

@FuncModule({
  commands: [PublishCommand, ErrorHandler],
})
export class AppModule {}

Runtime-print 错误

Runtime-print 错误默认会打印到 stderr。如果你的处理器已经打印了消息,可以调用 preventDefaultPrint()

import { F_RUNTIME_PRINT, createRuntimePrintError, errorTypes } from 'func'

throw createRuntimePrintError(
  F_RUNTIME_PRINT.VALIDATION,
  errorTypes.INPUT,
  'Token is required.',
  { option: 'token' },
)