ONES插件开发的学习笔记

首先插件的功能是私有化部署的功能, 只能在私有化部署的 ONES 上能安装和使用插件。

安装最新版本 Node.js 的稳定版, 配置 ONES 的私有 npm 仓库:

shell 复制代码
$ npm config set registry=https://registry.npmjs.org/
$ npm config set @ones:registry=https://npm.partner.ones.cn/registry/
$ npm config set @ones-op:registry=https://npm.partner.ones.cn/registry/

这里本来想先安装 Homebrew 后通过 brew install n 安装 n 工具, 再使用 sudo n 16.13.0 安装 v16.13.0 版本的 Node.js 环境, 但是出现 github.com port 443: Operation timed out 异常, 尝试过更换中科院的镜像地址和 Leensa 网络代理工具均无效时, 放弃这个方案。

下载 cmake-3.22.2-macos-universal.dmg 安装 CMake 工具, 然后通过 cmake --version 检查是否安装成功。

这里遇到了 Error: Running Homebrew as root is extremely dangerous and no longer supported. 异常, 通过下面的命令解决:

shell 复制代码
$ sudo chown -R `whoami` /usr/local/Homebrew/
$ sudo chown -R $(whoami) $(brew --prefix)/*
$ sudo mkdir /usr/local/Frameworks
$ sudo chown -R `whoami` /usr/local/Frameworks/

使用 npm install -g @ones/cli 安装 ONES CLI 脚手架工具, 再使用 ones --version 验证是否正确安装, 以后的升级用 npm update -g @ones/cli 命令来完成。

创建插件

插件在作用范围上, 分为 组织级别团队级别 两种;在功能范围上, 分为 业务插件账号管理与通知托管独立服务 三种。

新建一个目录作为插件工程的根目录, 进入目录执行 ones create -d 命令创建一个插件工程, 其中的 -d 选项表示使用默认的工程创建预设配置。这样创建的是 团队级别 的插件, 可以用 --plugin-type organization 选项表示创建 组织级别 的插件。

插件项目的目录 (ONES CLI 创建的插件工程目录结构) 生成后, 使用 npx op packup Demo 命令对插件进行打包, 模式 (no-modify-无修改 | major-主版本 | minor-次版本 | patch-修复版本 ) 选择 no-modify 无修改。

打包完成后, 工程根目录中就可以看到 Demo.opk 这个 opk 包, 这个是 团队级别 的插件, 在 "配置中心 -> 插件管理" 选择 Demo.opk 文件完成安装, 如果是 组织级别 的则在 "组织管理 -> 插件管理" 页面安装。

调试插件

执行 npx op login 命令在私有化部署环境中获取用户凭证的参数 (执行前需要在 "配置中心 -> 插件管理" 删除掉之前安装), 并存储到 config/local.yaml 中。命令要求输入的参数 base URL 是私有化 ONES 平台的域名地址 (例如 "https://xxxx/"), 参数 host URL 是私有化 ONES 平台的 TCP 主机地址和 9006 端口号 (例如 "tcp://127.0.0.1:9006"), 还有就是登录私有化 ONES 平台的账号密码, 以及选择进入的团队。

生成 config/local.yaml 后, 执行 npx op invoke run 启动本地调试, 这个命令会为插件工程的前端部分 (/web) 启动一个热更新的开发服务器, 第一次启动后控制台会返回 instance_uuid 值, 这个值是插件被安装到具体环境时动态生成的实例 uuid 值。

现在 "配置中心 -> 插件管理" 里刷新, 可以看到插件已经被安装了, 中断前面的 npx op invoke run 进程, 再执行 npx op invoke clear 就可以卸载插件, 卸载完成后再中断当前进程, 这个就是插件的调试过程。

修改插件的配置文件 (config/plugin.yaml) 后需要卸载插件后重新安装, 即重新执行 npx op invoke runnpx op invoke clear 命令。

添加插槽

插槽是纯前端的能力, 存放于 /web/src/modules/ 目录下以插槽模块命名的目录中, 插槽模块相当于一个独立的 React 应用, 支持 TypeScript 语言。

以全局的顶栏公告插槽 ones:global:banner 为例, 执行 npx op add module 命令并选择 ones:global:banner 插槽, 输入 banner 或其他标题, 就完成插槽的创建, 在 /config/plugin.yaml 文件的最后多了一个 modules 字段, 在这个字段下有一个 entry 字段, 对应的是 /web/src/{entry} 目录下的文件路径, 这个文件目录下包含 index.tsxindex.css 两个文件。

插槽模块目录下的 index.css 文件是样式代码, 自动生成的 #ones-mf-root {} 是插槽模块的根元素, 插槽支持 PostCSS 框架, 例如可以创建一个单独的样式文件 banner.css 并输入下面代码:

css 复制代码
.banner {
    width: 100%;
}

然后在 index.css 中引入这个 banner.css 文件:

css 复制代码
@import 'banner.css';

#ones-mf-root {}

保存以上代码后, 在 ONES 平台页面的顶部就可以看到插槽模块的效果, 插件在打包时仅执行 .ts.tsx 文件的转译, 插件模块的打包以模块内的 index.tsx 文件为入口, 这个文件里的 <ConfigProvider> 组件必须保留。

添加能力

能力有 基础能力-平台开放能力业务能力-应用开放能力 两种, 以 简单登录 能力为例, 执行 npx op add ability 指令向插件新增开放能力, 并选择 simple-auth 能力, 就完成能力的创建, 在 /config/plugin.yaml 文件的最后多了一个 abilities 字段, 同时在 /backend/src 目录下, 生成了 index.tssimple-auth.ts 两个文件。

大概得出一个小结, 插槽是前端的显示, 能力是后端的实现, 插槽和能力如何进行关联需要更深入的了解。

接口请求

首先是前端请求, 进入插件工程的 /web 目录执行 npm install @ones-op/fetch 命令进行依赖安装, 使用 ONES CLI 创建工程的时默认帮注册的 APIhello 接口, 在 plugin.yaml 中有一个 apis 字段, 它的 url 字段是 /hello, 对应的是在 /backend/src/index.ts 里有一个 export async function hello(request: PluginRequest) 函数, 这个就是 API 的实现。这样就可以在插件中使用 OPFetch 来请求这个接口。

直接用 Postman 请求时需要带上 Ones-Check-PointOnes-Plugin-IdOnes-Check-Id 三个请求头, 插件 ID 在 "配置中心 -> 插件管理 -> 插件详情" 的 URL 里看, 团队 ID 在 "配置中心 -> 团队配置 -> 团队消息" 的 URL 里看, 然后用 POST 请求 https://xxxx/project/api/project/hello 地址就可以获得响应。

然后是后端请求, 进入插件工程的 /backend 目录执行 npm install @ones-op/node-fetch 命令进行依赖安装, 在 /backend/src/index.ts 文件里修改代码, 用 const projects = await fetchONES<ProjectResponseBody>({...})... 就可以调用接口请求。

数据获取

在插件里可以获取平台的 全局数据特定上下文数据 两种, 进入插件工程的 /web 目录执行 npm install @ones-op/store 命令进行依赖安装, 然后就可以通过下面代码获取当前团队信息:

javascript 复制代码
import { useTeamInfo } from '@ones-op/store'

const { uuid, name } = useTeamInfo()

把上面代码加到插槽模块里, 这样就可以在前面的插槽模块里显示当前团队信息。

事件通信

平台提供了一套事件通信库, 通过进入插件工程的 /web 目录执行 npm install @ones-op/event 命令进行依赖安装, 就可以使用一套事件通信库:

大概实现的通过插槽模块里调用事件通信库, 来使用平台提供的事件, 例如在 "创建新用户时" 调用 "触发成员列表刷新"、"访问自定义的项目概率插件" 时 "激活全局进度管理器" 等实现。

生命周期

插件的生命周期是指插件在 ONES 私有环境中从上传到卸载整个阶段的完整过程, 包括 "未安装"、"未启用"、"启用" 三个过程, 而在这个过程中伴随着一系列的生命周期事件的钩子函数, 这些钩子函数在插件工程初始化后就包含在 /backend/src/index.ts 文件中, 直接看注释就可以理解其含义。

插件打包

在插件工程的根目录下执行 npx op packup 命令就可以打包插件了。

插件自定义配置

插件支持在 plugin.yaml 文件下的 config 字段添加自定义配置项, 配置项分3个类型, 通过配置项字段 type 区分:

  • type: Input # 单行输入框
  • type: TextArea # 多行输入框
  • type: Password # 密码输入框

除了 type 还有另外4个配置项字段, 其中必填的有1个:

配置项字段 说明 类型
key 唯一标识 string

其中必填的有3个:

配置项字段 说明 类型 默认值
required 字段是否必填 boolean false
label 字段别名 string 取 key 字段的值
value 字段默认值 string

还可以在详情页面里新建选项卡, 在插件工程目录下执行 npx op add module 命令, 选择创建 settings 插槽的模块, 再输入一个标签页标题, 这样在插件详情页, 就可以在插件详情页面看到新的标签页。

接口注册

接口注册属于插件能力, 插件能力允许插件注册 插件级别团队级别 两种级别的接口, 它们在注册时的区别在于在 config/plugin.yaml 文件的 apis 字段的 type 子字段, 片段type: addition 表示 插件级别 的接口, 片段type: external 表示 团队级别 的接口, 它们的访问路径也不同:

  • 插件级别通过URL https://xxx/project/api/project/hello 访问
  • 团队级别通过URL https://xxx/project/api/project/team/:teamUUID/hello1 访问

除了文档中提供的内容, 还有另外一种区分方法:

  • URL包含 /project/api/project/ 的为全局接口
  • URL包含 /project/api/project/team/:teamUUID/ 的为团队接口
  • URL包含 /project/api/project/organization/:organizationUUID/ 的为组织接口

此外 apis 字段还有一个 scope 子字段, 用于定义当前接口的路由是 project 还是 wiki 路径:

  • scope: project 时URL为 /project/api/project/ 路径
  • scope: wiki 时URL为 /wiki/api/wiki/ 路径

还有一些特殊情况, 例如 https://xxx/wiki/api/project/organization/:organizationUUID/user_list_filter_rules 接口, 就是 /wiki/api/project/ 这样的路径。

接口劫持

接口劫持可以替换平台已有的接口, 也可以对已有的接口请求前后添加 前置处理后置处理 逻辑, 实现接口劫持同样是在 config/plugin.yaml 文件 apis 字段的 type 子字段里:

  • type: replace 时为接口替换, 即重写接口
  • type: prefix 时为前置劫持, 即前置处理
  • type: suffix 时为后置劫持, 即后置处理

因为是对已有接口做处, 所以填写的 url 必须跟访问 ONES API 的 url 保持一致, 同时要确认被操作接口是 POST 请求还是 GET 请求, 还要注意请求参数和响应内容。此外 apis 字段还有一个 query 子字段, 用于控制接口劫持的前置条件, 只有当请求值包含某些参数时才劫持接口。

自定义权限点

第一个 场景:系统顶栏右侧组件 例子中, 是通过 permission 字段和 permission: component_permissions插槽模块 直接配置一个独立的权限管理:

yaml 复制代码
service:
  permission:
    - name: Component permissions
      field: component_permissions
      desc: System sider permissions
modules:
  - id: ones-layout-header-action-new-LZrd
    title: layoutHeaderAction
    moduleType: ones:layout:header:action:new
    enableMemoryRouter: true
    entry: modules/ones-layout-header-action-new-LZrd/index.html
    permission: component_permissions

第二个 场景:支持权限上下文的自定义迭代组件 例子中, 先使用 npx op add ability 添加了 custom-permission 这个 插件能力 并将其与 插槽模块 关联, 实现权限控制。

相关推荐
数据的世界011 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐1 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
OopspoO3 小时前
qcow2镜像大小压缩
学习·性能优化
A懿轩A4 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
居居飒4 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
kkflash34 小时前
提升专业素养的实用指南
学习·职场和发展
Hejjon5 小时前
SpringBoot 整合 SQLite 数据库
笔记
1 9 J5 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
6.946 小时前
Scala——身份证号码查询籍贯
学习·scala
爱吃西瓜的小菜鸡6 小时前
【C语言】矩阵乘法
c语言·学习·算法