首页
/ ToolJet CLI 深度解析:用 @tooljet/cli 在命令行完成插件全生命周期管理

ToolJet CLI 深度解析:用 @tooljet/cli 在命令行完成插件全生命周期管理

2026-09-05 10:06:22作者:董灵辛Dennis

本篇技术指南基于 ToolJet 仓库中的 cli/README.md 展开,系统讲解官方 CLI 工具 @tooljet/cli 的安装方式与全部四个命令(infoplugin createplugin deleteplugin install),并结合 cli/src/commands/ 下的命令实现源码,剖析每条命令背后的目录校验、交互式提问、hygen 模板生成与 plugins.json 注册机制。读完本文,你可以直接在 ToolJet 仓库根目录用命令行创建、删除并构建 marketplace 插件,以及为核心插件安装 npm 依赖。

一、CLI 是什么:基于 oclif 的插件管理工具

@tooljet/cli 是 ToolJet 官方提供的命令行工具,采用 oclif 框架(@oclif/core)构建,用于管理 ToolJet 的插件体系。从 cli/package.json 可以确认以下关键事实:

配置项 含义
name @tooljet/cli npm 包名
version 0.0.14 当前仓库中的包版本
bin.tooljet ./bin/run 安装后暴露的全局命令为 tooljet
oclif.commands ./dist/commands 命令入口目录(编译产物)
oclif.topics.plugin "manage plugins options: create, delete and install" plugin 子命令主题
engines.node >=12.0.0 Node.js 版本要求

从源码结构看,cli/src/commands/ 目录与 package.json 声明的命令路由一一对应:

值得一提的是,cli/README.md 中的 <!-- usage --><!-- commands --> 标记区域是由 oclif 自动生成的:package.json 中定义了 "prepack": "npm run build && oclif manifest && oclif readme""version": "oclif readme && git add README.md" 脚本,即每次打包或升版时,tooljet --help 输出的 USAGE/FLAGS/EXAMPLES 内容会自动同步回 README。因此该文档的命令行说明与源码中的 static flags / static examples 定义严格一致。

二、安装与基础用法

cli/README.md 给出的安装方式:

$ npm install -g @tooljet/cli
$ tooljet COMMAND
running command...
$ tooljet (--version)
@tooljet/cli/0.0.13 darwin-x64 node-v14.17.3
$ tooljet --help [COMMAND]
USAGE
  $ tooljet COMMAND
...
  • --version:输出格式为 <包名>/<版本> <平台> node-<node 版本>,例如 @tooljet/cli/0.0.13 darwin-x64 node-v14.17.3
  • --help [COMMAND]:可带子命令查看该命令的完整 USAGE 帮助。

所有命令都必须在 ToolJet 仓库根目录下执行(README 明确说明 "Command should be executed inside Tooljet directory"),因为命令内部通过相对路径操作 marketplace/plugins/docs/ 等仓库目录。

三、tooljet info:运行环境自检

USAGE
  $ tooljet info

DESCRIPTION
  This command returns the information about where tooljet is being run

该命令打印当前 CLI 的运行环境,实现见 cli/src/commands/info.ts。输出内容分三组:

Operating System:
  platform: ...   # os.platform()
  arch: ...       # os.arch()
  version: ...    # os.version()
Binaries:
  node: ...       # process.versions.node
  npm: ...        # execSync('npm --version')
Relevant packages:
  tooljet: ...    # require('./package.json').version

从源码可以看到几个健壮性细节:getBinaryVersion()getPackageVersion() 都用 try/catch 包裹,npm 不存在或 package.json 解析失败时会优雅降级输出 N/A,而不是直接抛错退出。在排查"CLI 报错了但环境本身有问题"的场景时,这条命令是最快的定位手段。

四、tooljet plugin create:模板化生成 marketplace 插件

USAGE
  $ tooljet plugin create [PLUGIN_NAME] [--type database|api|cloud-storage] [-b]

ARGUMENTS
  PLUGIN_NAME  Name of the plugin

FLAGS
  -b, --build
  --type=<option>    <options: database|api|cloud-storage>

DESCRIPTION
  Create a new tooljet plugin

EXAMPLES
  $ tooljet plugin create <name> --type=<database | api | cloud-storage> [--build]

该命令基于 hygen 模板引擎 + marketplace/_templates/plugin/new/ 下的 EJS 模板,一键生成一个 marketplace 插件骨架。以 cli/src/commands/plugin/create.ts 源码为准,完整执行流程如下:

4.1 参数校验与交互式补全

  1. 插件名不能是纯数字Number(args.plugin_name) 为真时直接报错退出(create.ts#L24-L27);
  2. 交互式输入 display name:即使传了位置参数,命令仍会 prompt 一次 Enter plugin display name,作为插件在界面上的展示名,同样禁止纯数字(create.ts#L31-L36);
  3. --type 缺省时进入选择器:未指定类型时,用 inquirer 弹出 database / api / cloud-storage 三项单选列表(create.ts#L38-L48)。

4.2 目录前置检查

命令会校验三个路径必须同时存在,否则提示 "make sure that you are running this command in Tooljet directory" 并退出(create.ts#L50-L60):

路径 用途
marketplace/ 插件输出根目录
docs/ 文档目录
marketplace/_templates/ hygen 模板目录

4.3 插件 ID 唯一性检查

命令会读取 server/src/assets/marketplace/plugins.json(marketplace 插件注册表,当前已登记 Plivo、GitHub 等条目),若已有插件的 id 与新插件小写名相同,则报 "Plugin id already exists" 并退出(create.ts#L75-L82)。这保证了注册表中 id 不冲突。

4.4 hygen 模板渲染

校验通过后,命令构造 hygen 参数 ['plugin', 'new', '--name', <name>, '--type', <type>, '--display_name', <name>, '--plugins_path', 'marketplace'] 并调用 runner(),模板目录指向 marketplace/_templates。模板目录中包含以下 EJS 模板(文件名后缀 .ejs.t 是 hygen 模板约定):

  • manifest.ejs.t — 生成 lib/manifest.json
  • packagejson.ejs.t — 生成插件 package.json
  • index.ejs.toperations.ejs.ttypes.ejs.treadme.ejs.ttests.ejs.ticon.ejs.ttsconfig.ejs.tgitignore.ejs.t

从模板内容可以确认生成骨架的关键结构:

  1. manifest.json:包含 $schema 指向 plugins/schemas/manifest.schema.json,以及 titletype(即 --type 的值)、sourcenamekindexposedVariablesoptions)、defaultspropertiesrequired 字段,是后续在 ToolJet 界面配置数据源选项的 schema 基础;
  2. package.json:插件包名为 @tooljet-marketplace/<name>,构建脚本为 ncc build lib/index.ts -o dist(即使用 @vercel/ncc 打成单文件 bundle,这是 ToolJet 插件在服务端运行时可独立加载的前提),并默认依赖 @tooljet-marketplace/common 公共库(对应 marketplace/plugins/common/)。

4.5 注册到 plugins.json 与可选构建

模板渲染完成后,命令把新插件写入注册表(create.ts#L98-L110),条目结构为:

{
  "name": "插件名(原样)",
  "description": "<type> plugin from <插件名>",
  "version": "1.0.0",
  "id": "插件名(小写)",
  "author": "Tooljet",
  "timestamp": "UTC 时间字符串"
}

若带了 --build(或 -b)标志,命令会在 marketplace/ 目录内执行 npm run build --workspacescreate.ts#L116-L120),把整个 workspace(包括 marketplace/plugins/common)统一构建一遍。

4.6 实际示例

# 在 ToolJet 仓库根目录执行,交互式输入 display name
tooljet plugin create mydb --type database --build

执行成功后终端会以 oclif tree 形式展示生成的目录结构:marketplace/ → plugins/ → mydb/

五、tooljet plugin delete:区分 marketplace 与核心插件的删除

USAGE
  $ tooljet plugin delete [PLUGIN_NAME] [-b]

ARGUMENTS
  PLUGIN_NAME  Name of the plugin

FLAGS
  -b, --build

DESCRIPTION
  Delete a tooljet plugin

EXAMPLES
  $ tooljet plugin delete <name> [--build]

该命令的实现(cli/src/commands/plugin/delete.ts)比 README 展示的更完整:源码中还有一个 -m, --marketplace 标志(delete.ts#L11-L14,源码注释标注了 "TODO: remove this flag, and make it default"),用于指定删除目标属于哪类插件。

5.1 交互式确认市场类型

未带 -m 时,命令会先询问 Is this a marketplace plugin?(默认 no),据此决定插件根路径(delete.ts#L23-L35):

类型 插件目录 附加要求
marketplace(-m marketplace/plugins/<name>
核心插件(默认) plugins/packages/<name> 同时要求 docs/docs/data-sources/<name>.md 存在

任一前置路径不存在即报 "Plugin not found, make sure that you are running this command in Tooljet directory"。核心插件必须附带数据源文档页,是因为 ToolJet 官方数据源的文档(如 docs/docs/data-sources/ 下的条目)与插件包成对维护,删除插件时文档一并清理。

5.2 确认删除与执行

再次弹出 Do you want to proceed with deleting the plugin [...] 确认框(默认 yes),确认后按类型执行不同清理逻辑(delete.ts#L64-L95):

  • marketplace 插件rimraf 删除插件目录;随后读取 server/src/assets/marketplace/plugins.json,按 name 找到条目并 splice 移除、写回注册表;--build 时在 marketplace/ 内执行 npm run build --workspaces 重新构建。
  • 核心插件rimraf 删除插件目录与 docs/docs/data-sources/<name>.md 文档;在 plugins/ 目录执行 npx lerna link convert 清理 lerna workspace 链接;--build 时在仓库根目录执行 npm run build:plugins

用户回答 no 则输出 Aborted by user,不产生任何删除。

六、tooljet plugin install:为核心插件安装 npm 依赖

USAGE
  $ tooljet plugin install [NPM_MODULE] --plugin <value>

ARGUMENTS
  NPM_MODULE  Name of the npm module

FLAGS
  --plugin=<value>  (required)

DESCRIPTION
  Installs a new npm module inside a tooljet plugin

EXAMPLES
  $ tooljet plugin install <npm_module> --plugin <plugin_name>

实现见 cli/src/commands/plugin/install.ts,逻辑非常精简:

  1. 定位插件目录为 plugins/packages/<plugin>(注意:该命令只作用于核心插件,不作用于 marketplace 插件);
  2. 目录不存在则报 "Plugin not found" 并退出;
  3. 在该目录下执行 npm i <npm_module>install.ts#L29-L31)。

例如为核心插件 mysql 安装一个 SDK:

tooljet plugin install mysql2 --plugin mysql

由于核心插件的依赖最终会通过 workspace 构建被 ncc 打入 bundle,这条命令的意义在于把"进入插件目录手动 npm i"这一重复操作收敛为一条命令。

七、典型开发工作流串联

结合上述命令,一个完整的 marketplace 插件开发闭环如下(均在 ToolJet 仓库根目录执行):

# 1. 环境自检
tooljet info

# 2. 生成插件骨架(自动写入 plugins.json 注册表)
tooljet plugin create weatherapi --type api --build
#    → 生成 marketplace/plugins/weatherapi/
#      其中 lib/manifest.json 由 manifest.ejs.t 渲染,
#      package.json 使用 ncc 构建脚本

# 3. 编辑插件代码(manifest.json 定义选项 schema,operations 定义查询逻辑)

# 4. 需要第三方 SDK 时(核心插件场景)
tooljet plugin install axios --plugin <core_plugin>

# 5. 不再需要时删除
tooljet plugin delete weatherapi -m --build

配套的背景资料可参考 docs/docs/contributing-guide/marketplace/creating-a-plugin.md 中关于创建 marketplace 插件的贡献指南,以及 plugins/README.mdmarketplace/README.md 中两个插件体系的说明。

八、适用前提与注意事项

  1. 必须在仓库根目录运行:三条 plugin 子命令都依赖 marketplace/plugins/docs/ 等相对路径,脱离仓库根目录会直接报错退出;
  2. Node 版本package.json 要求 node >= 12.0.0;README 示例环境为 node-v14.17.3;
  3. README 与源码的轻微差异cli/README.md 由 oclif 在 v0.0.13 时生成,create 命令 USAGE 中的 [-m] 标志在当前源码 create.ts 中并不存在(源码只有 --type--build),而 delete 命令的 -m 标志在 README 中未展示、源码中实际存在。使用时以 tooljet --help <command> 的实时输出为准最可靠;
  4. 构建标志的作用域create/delete--build 分别触发 marketplace/ 下的 workspace 构建或 npm run build:plugins,构建耗时取决于插件数量,CI 或频繁调试时可省略、手动统一构建。

小结

@tooljet/cli 虽只有四个命令,但覆盖了 ToolJet 插件开发的核心环节:info 提供环境自检,plugin create 通过 hygen 模板 + plugins.json 注册表生成标准化的 marketplace 插件骨架,plugin delete 按 marketplace/核心两类路径安全清理并维护注册表一致性,plugin install 简化核心插件的依赖安装。理解 cli/src/commands/ 的源码实现后,你可以将这套命令嵌入本地开发流或脚本化流程,而不必手改模板文件与注册表。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384