@choiceopen/automation-plugin-cli 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/templates/OVERVIEW.md +58 -0
- package/dist/templates/common/.claude/commands/commit.md +13 -0
- package/dist/templates/common/.env +2 -0
- package/dist/templates/common/.gitignore.eta +6 -0
- package/dist/templates/common/.spec/ARCHITECTURE.md +193 -0
- package/dist/templates/common/LICENSE.md.eta +21 -0
- package/dist/templates/common/PRIVACY.md.eta +47 -0
- package/dist/templates/typescript/.editorconfig +15 -0
- package/dist/templates/typescript/.typesafe-i18n.json +8 -0
- package/dist/templates/typescript/README.md.eta +21 -0
- package/dist/templates/typescript/biome.json.eta +32 -0
- package/dist/templates/typescript/package.json.eta +57 -0
- package/dist/templates/typescript/src/README.md.eta +24 -0
- package/dist/templates/typescript/src/i18n/README.md +29 -0
- package/dist/templates/typescript/src/i18n/en-US/README.md +12 -0
- package/dist/templates/typescript/src/i18n/en-US/index.ts.eta +13 -0
- package/dist/templates/typescript/src/i18n/formatters.ts.eta +12 -0
- package/dist/templates/typescript/src/i18n/i18n-node.ts.eta +31 -0
- package/dist/templates/typescript/src/i18n/i18n-types.ts.eta +79 -0
- package/dist/templates/typescript/src/i18n/i18n-util.async.ts.eta +33 -0
- package/dist/templates/typescript/src/i18n/i18n-util.sync.ts.eta +26 -0
- package/dist/templates/typescript/src/i18n/i18n-util.ts.eta +63 -0
- package/dist/templates/typescript/src/i18n/zh-Hans/README.md +12 -0
- package/dist/templates/typescript/src/i18n/zh-Hans/index.ts.eta +13 -0
- package/dist/templates/typescript/src/index.ts.eta +25 -0
- package/dist/templates/typescript/src/tools/README.md +18 -0
- package/dist/templates/typescript/src/tools/demo.ts.eta +29 -0
- package/dist/templates/typescript/test/README.md +15 -0
- package/dist/templates/typescript/test/index.test.ts.eta +65 -0
- package/dist/templates/typescript/tsconfig.json.eta +20 -0
- package/dist/templates/typescript/tsdown.config.ts.eta +11 -0
- package/oclif.manifest.json +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @choiceopen/automation-plugin-cli
|
|
|
20
20
|
$ atomemo COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ atomemo (--version)
|
|
23
|
-
@choiceopen/automation-plugin-cli/0.2.
|
|
23
|
+
@choiceopen/automation-plugin-cli/0.2.3 darwin-arm64 node-v24.13.0
|
|
24
24
|
$ atomemo --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ atomemo COMMAND
|
|
@@ -63,7 +63,7 @@ EXAMPLES
|
|
|
63
63
|
$ atomemo auth login
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
_See code: [src/commands/auth/login.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
66
|
+
_See code: [src/commands/auth/login.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/auth/login.ts)_
|
|
67
67
|
|
|
68
68
|
## `atomemo auth status`
|
|
69
69
|
|
|
@@ -85,7 +85,7 @@ EXAMPLES
|
|
|
85
85
|
$ atomemo auth status
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
_See code: [src/commands/auth/status.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
88
|
+
_See code: [src/commands/auth/status.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/auth/status.ts)_
|
|
89
89
|
|
|
90
90
|
## `atomemo autocomplete [SHELL]`
|
|
91
91
|
|
|
@@ -160,7 +160,7 @@ EXAMPLES
|
|
|
160
160
|
$ atomemo plugin checksum
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
-
_See code: [src/commands/plugin/checksum.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
163
|
+
_See code: [src/commands/plugin/checksum.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/checksum.ts)_
|
|
164
164
|
|
|
165
165
|
## `atomemo plugin init`
|
|
166
166
|
|
|
@@ -197,7 +197,7 @@ EXAMPLES
|
|
|
197
197
|
$ atomemo plugin init
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
_See code: [src/commands/plugin/init.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
200
|
+
_See code: [src/commands/plugin/init.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/init.ts)_
|
|
201
201
|
|
|
202
202
|
## `atomemo plugin pack [FILE]`
|
|
203
203
|
|
|
@@ -221,7 +221,7 @@ EXAMPLES
|
|
|
221
221
|
$ atomemo plugin pack
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
-
_See code: [src/commands/plugin/pack.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
224
|
+
_See code: [src/commands/plugin/pack.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/pack.ts)_
|
|
225
225
|
|
|
226
226
|
## `atomemo plugin permission [FILE]`
|
|
227
227
|
|
|
@@ -245,7 +245,7 @@ EXAMPLES
|
|
|
245
245
|
$ atomemo plugin permission
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
_See code: [src/commands/plugin/permission.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
248
|
+
_See code: [src/commands/plugin/permission.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/permission.ts)_
|
|
249
249
|
|
|
250
250
|
## `atomemo plugin refresh-key`
|
|
251
251
|
|
|
@@ -262,7 +262,7 @@ EXAMPLES
|
|
|
262
262
|
$ atomemo plugin refresh-key
|
|
263
263
|
```
|
|
264
264
|
|
|
265
|
-
_See code: [src/commands/plugin/refresh-key.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
265
|
+
_See code: [src/commands/plugin/refresh-key.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/refresh-key.ts)_
|
|
266
266
|
|
|
267
267
|
## `atomemo plugin run [FILE]`
|
|
268
268
|
|
|
@@ -286,7 +286,7 @@ EXAMPLES
|
|
|
286
286
|
$ atomemo plugin run
|
|
287
287
|
```
|
|
288
288
|
|
|
289
|
-
_See code: [src/commands/plugin/run.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.
|
|
289
|
+
_See code: [src/commands/plugin/run.ts](https://github.com/choice-open/automation-plugin-cli/blob/v0.2.3/src/commands/plugin/run.ts)_
|
|
290
290
|
|
|
291
291
|
## `atomemo version`
|
|
292
292
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
Eta 模板引擎模板文件目录,用于生成新插件项目的脚手架代码。
|
|
4
|
+
|
|
5
|
+
## 目录结构
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
templates/
|
|
9
|
+
├── common/ # 语言无关的通用模板
|
|
10
|
+
│ ├── manifest.yaml.eta
|
|
11
|
+
│ ├── license.eta
|
|
12
|
+
│ └── privacy.eta
|
|
13
|
+
└── typescript/ # TypeScript 专用模板
|
|
14
|
+
├── package.json.eta
|
|
15
|
+
├── README.md.eta
|
|
16
|
+
├── tsconfig.json.eta
|
|
17
|
+
├── tsdown.config.ts.eta
|
|
18
|
+
├── src/
|
|
19
|
+
│ └── main.ts.eta
|
|
20
|
+
└── test/
|
|
21
|
+
└── main.test.ts.eta
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 模板引擎
|
|
25
|
+
|
|
26
|
+
使用 [Eta](https://eta.js.org/) 模板引擎,配置如下:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
new Eta({
|
|
30
|
+
autoTrim: false, // 保留空白
|
|
31
|
+
autoEscape: false, // 不转义 HTML
|
|
32
|
+
varName: "props", // 变量名
|
|
33
|
+
views: "templates/" // 模板根目录
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 模板语法
|
|
38
|
+
|
|
39
|
+
```eta
|
|
40
|
+
<%# 注释 %>
|
|
41
|
+
<%= props.name %> // 输出变量
|
|
42
|
+
<%- rawContent %> // 原始输出
|
|
43
|
+
<% for (const x of arr) { %> // 控制流
|
|
44
|
+
<%= x %>
|
|
45
|
+
<% } %>
|
|
46
|
+
<%- %> // 去除尾部空白
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 子目录
|
|
50
|
+
|
|
51
|
+
- [`common/`](./common/OVERVIEW.md) - 通用模板
|
|
52
|
+
- [`typescript/`](./typescript/OVERVIEW.md) - TypeScript 模板
|
|
53
|
+
|
|
54
|
+
## 扩展规划
|
|
55
|
+
|
|
56
|
+
未来将支持更多语言:
|
|
57
|
+
- `elixir/` - Elixir 插件模板(计划中)
|
|
58
|
+
- `python/` - Python 插件模板(计划中)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# 提交变更
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
提交代码并根据代码的变更创建或者更新变更日志。
|
|
6
|
+
|
|
7
|
+
## 步骤
|
|
8
|
+
|
|
9
|
+
1. 使用 Conventional Commits 编写提交信息,提交信息使用英文撰写
|
|
10
|
+
2. 如果你认为有必要,可以把提交拆分为多个,但是**你必须先向我展示你的提交计划并获得我的确认**
|
|
11
|
+
3. 如果当前项目还没有初始化 Git,你可以询问是否要初始化,并且询问 `config.name` 和 `config.email`
|
|
12
|
+
4. 创建或更新项目的变更日志,使用 keepachangelog 的约定:https://keepachangelog.com/zh-CN/1.1.0/
|
|
13
|
+
5. 遇到更新日期的时候,请务必使用当前的时间
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# 项目架构文档
|
|
2
|
+
|
|
3
|
+
**最后更新:** 2026-01-18
|
|
4
|
+
|
|
5
|
+
## 概述
|
|
6
|
+
|
|
7
|
+
这是一个基于 ChoiceOpen Automation Plugin SDK 的测试插件项目。插件提供工具执行功能,支持英文和简体中文两种语言。
|
|
8
|
+
|
|
9
|
+
## 技术栈
|
|
10
|
+
|
|
11
|
+
- **语言**: TypeScript
|
|
12
|
+
- **运行时**: Node.js / Bun
|
|
13
|
+
- **构建工具**: tsdown
|
|
14
|
+
- **国际化**: typesafe-i18n
|
|
15
|
+
- **测试框架**: Vitest
|
|
16
|
+
- **代码格式化**: Biome
|
|
17
|
+
- **SDK**: @choiceopen/automation-plugin-sdk-js
|
|
18
|
+
|
|
19
|
+
## 项目结构
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
testing-plugin/
|
|
23
|
+
├── src/ # 源代码目录
|
|
24
|
+
│ ├── tools/ # 工具定义
|
|
25
|
+
│ │ └── demo.ts # 演示工具
|
|
26
|
+
│ ├── i18n/ # 国际化
|
|
27
|
+
│ │ ├── en-US/ # 英文翻译
|
|
28
|
+
│ │ ├── zh-Hans/ # 中文翻译
|
|
29
|
+
│ │ ├── formatters.ts # 格式化器
|
|
30
|
+
│ │ ├── i18n-node.ts # Node.js 入口
|
|
31
|
+
│ │ ├── i18n-types.ts # 类型定义(自动生成)
|
|
32
|
+
│ │ ├── i18n-util.ts # 工具函数
|
|
33
|
+
│ │ ├── i18n-util.async.ts # 异步加载
|
|
34
|
+
│ │ └── i18n-util.sync.ts # 同步加载
|
|
35
|
+
│ ├── index.ts # 插件入口
|
|
36
|
+
│ └── README.md # 源码说明
|
|
37
|
+
├── tests/ # 测试文件
|
|
38
|
+
│ └── index.test.ts # 主测试文件(空)
|
|
39
|
+
├── dist/ # 构建输出
|
|
40
|
+
└── .spec/ # 架构文档
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 核心模块
|
|
44
|
+
|
|
45
|
+
### 1. 插件入口 (src/index.ts)
|
|
46
|
+
|
|
47
|
+
插件的主入口文件,负责:
|
|
48
|
+
- 异步加载所有国际化语言包
|
|
49
|
+
- 创建插件实例并配置基本信息(名称、描述、图标、作者等)
|
|
50
|
+
- 注册工具组件
|
|
51
|
+
- 启动插件服务
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const plugin = createPlugin({
|
|
55
|
+
name: packageJSON.name,
|
|
56
|
+
display_name: t("PLUGIN_DISPLAY_NAME"),
|
|
57
|
+
description: t("PLUGIN_DESCRIPTION"),
|
|
58
|
+
icon: "🎛️",
|
|
59
|
+
author: "Choiceform",
|
|
60
|
+
// ...
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
plugin.addTool(demoTool)
|
|
64
|
+
plugin.run()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. 工具模块 (src/tools/)
|
|
68
|
+
|
|
69
|
+
定义插件提供的可执行工具。当前包含一个演示工具 `demo-tool`:
|
|
70
|
+
|
|
71
|
+
- **名称**: demo-tool
|
|
72
|
+
- **图标**: 🧰
|
|
73
|
+
- **参数**:
|
|
74
|
+
- `location` (string, required) - 位置参数,支持表达式
|
|
75
|
+
|
|
76
|
+
工具执行时返回包含位置信息的消息。
|
|
77
|
+
|
|
78
|
+
### 3. 国际化模块 (src/i18n/)
|
|
79
|
+
|
|
80
|
+
基于 typesafe-i18n 实现类型安全的国际化系统:
|
|
81
|
+
|
|
82
|
+
**支持的语言**:
|
|
83
|
+
- 英文(en-US)
|
|
84
|
+
- 简体中文(zh-Hans)
|
|
85
|
+
|
|
86
|
+
**翻译键**:
|
|
87
|
+
- `PLUGIN_DISPLAY_NAME` - 插件显示名称
|
|
88
|
+
- `PLUGIN_DESCRIPTION` - 插件描述
|
|
89
|
+
- `DEMO_TOOL_DISPLAY_NAME` - 演示工具显示名称
|
|
90
|
+
- `DEMO_TOOL_DESCRIPTION` - 演示工具描述
|
|
91
|
+
- `LOCATION_DISPLAY_NAME` - 位置参数显示名称
|
|
92
|
+
- `LOCATION_HINT` - 位置参数提示
|
|
93
|
+
- `LOCATION_PLACEHOLDER` - 位置参数占位符
|
|
94
|
+
|
|
95
|
+
## 数据流
|
|
96
|
+
|
|
97
|
+
```mermaid
|
|
98
|
+
graph TD
|
|
99
|
+
A[index.ts] -->|加载| B[i18n 模块]
|
|
100
|
+
A -->|注册| C[工具模块]
|
|
101
|
+
|
|
102
|
+
C -->|使用| B
|
|
103
|
+
|
|
104
|
+
B -->|提供翻译| D[UI 文本]
|
|
105
|
+
|
|
106
|
+
E[Plugin SDK] -->|管理| A
|
|
107
|
+
A -->|运行| E
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 模块依赖关系
|
|
111
|
+
|
|
112
|
+
```mermaid
|
|
113
|
+
graph LR
|
|
114
|
+
A[index.ts] --> B[tools/demo.ts]
|
|
115
|
+
A --> C[i18n]
|
|
116
|
+
|
|
117
|
+
B --> C
|
|
118
|
+
|
|
119
|
+
C --> D[en-US]
|
|
120
|
+
C --> E[zh-Hans]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 构建流程
|
|
124
|
+
|
|
125
|
+
1. **开发模式**: `bun run dev`
|
|
126
|
+
- 使用 tsdown watch 模式监听文件变化
|
|
127
|
+
- 同时运行 typesafe-i18n 生成类型定义
|
|
128
|
+
|
|
129
|
+
2. **构建**: `bun run build`
|
|
130
|
+
- 使用 tsdown 编译 TypeScript
|
|
131
|
+
- 生成类型定义文件(.d.ts)
|
|
132
|
+
- 输出到 `dist/` 目录
|
|
133
|
+
|
|
134
|
+
3. **测试**: `bun run test`
|
|
135
|
+
- 使用 Vitest 运行测试用例
|
|
136
|
+
|
|
137
|
+
4. **类型检查**: `bun run typecheck`
|
|
138
|
+
- 使用 tsc 进行类型检查
|
|
139
|
+
|
|
140
|
+
## 国际化机制
|
|
141
|
+
|
|
142
|
+
插件使用 typesafe-i18n 实现类型安全的国际化:
|
|
143
|
+
|
|
144
|
+
1. **翻译文件**: 位于 `src/i18n/{locale}/index.ts`
|
|
145
|
+
2. **类型生成**: 自动生成 `i18n-types.ts` 包含所有翻译键的类型
|
|
146
|
+
3. **加载方式**:
|
|
147
|
+
- 同步加载(`i18n-util.sync.ts`)
|
|
148
|
+
- 异步加载(`i18n-util.async.ts`,用于动态导入)
|
|
149
|
+
4. **使用方式**: 通过 `t()` 函数获取翻译,编译时类型检查
|
|
150
|
+
|
|
151
|
+
## 插件注册流程
|
|
152
|
+
|
|
153
|
+
```mermaid
|
|
154
|
+
sequenceDiagram
|
|
155
|
+
participant Main as index.ts
|
|
156
|
+
participant I18n as i18n 模块
|
|
157
|
+
participant SDK as Plugin SDK
|
|
158
|
+
participant Tool as tools/demo.ts
|
|
159
|
+
|
|
160
|
+
Main->>I18n: loadAllLocalesAsync()
|
|
161
|
+
I18n-->>Main: 语言包加载完成
|
|
162
|
+
|
|
163
|
+
Main->>SDK: createPlugin()
|
|
164
|
+
SDK-->>Main: 插件实例
|
|
165
|
+
|
|
166
|
+
Main->>Tool: addTool(demoTool)
|
|
167
|
+
|
|
168
|
+
Main->>SDK: plugin.run()
|
|
169
|
+
SDK-->>Main: 插件运行中
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 待办事项
|
|
173
|
+
|
|
174
|
+
### 功能改进
|
|
175
|
+
- [ ] 完善测试用例(`tests/index.test.ts` 当前为空)
|
|
176
|
+
- [ ] 添加更多工具支持
|
|
177
|
+
- [ ] 实现工具的实际业务逻辑(当前仅为演示)
|
|
178
|
+
- [ ] 添加凭证管理功能(如需要 API 密钥)
|
|
179
|
+
- [ ] 添加模型定义功能(如需要 AI 模型支持)
|
|
180
|
+
|
|
181
|
+
### 代码质量
|
|
182
|
+
- [ ] 添加错误处理机制
|
|
183
|
+
- [ ] 完善类型定义和文档注释
|
|
184
|
+
- [ ] 添加代码示例和使用文档
|
|
185
|
+
|
|
186
|
+
### 国际化
|
|
187
|
+
- [ ] 考虑添加更多语言支持
|
|
188
|
+
- [ ] 完善翻译文本的内容
|
|
189
|
+
|
|
190
|
+
### 构建和部署
|
|
191
|
+
- [ ] 配置 CI/CD 流程
|
|
192
|
+
- [ ] 添加版本管理和发布流程
|
|
193
|
+
- [ ] 优化构建产物大小
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) <%= props.year %> <%= props.author %>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Privacy Policy
|
|
2
|
+
|
|
3
|
+
**Last Updated: <%= props.date %>**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
<%= props.name %> ("the Plugin") is committed to protecting your privacy. This policy explains how data is handled when you use the Plugin within the Choiceform Atomemo Platform.
|
|
8
|
+
|
|
9
|
+
## Data Collection
|
|
10
|
+
|
|
11
|
+
The Plugin may collect and process the following types of data:
|
|
12
|
+
|
|
13
|
+
- **Usage Data**: Information about how you interact with the Plugin
|
|
14
|
+
- **Configuration Data**: Settings and preferences you configure within the Plugin
|
|
15
|
+
- **Input Data**: Data you provide to the Plugin for processing
|
|
16
|
+
|
|
17
|
+
## Data Usage
|
|
18
|
+
|
|
19
|
+
Collected data is used solely for:
|
|
20
|
+
|
|
21
|
+
- Providing and improving Plugin functionality
|
|
22
|
+
- Debugging and error resolution
|
|
23
|
+
- Analytics and performance optimization
|
|
24
|
+
|
|
25
|
+
## Data Storage
|
|
26
|
+
|
|
27
|
+
- All data is processed in accordance with the Choiceform Atomemo Platform's data handling policies
|
|
28
|
+
- No personal data is stored beyond what is necessary for Plugin operation
|
|
29
|
+
- Data is not shared with third parties unless required by law
|
|
30
|
+
|
|
31
|
+
## Your Rights
|
|
32
|
+
|
|
33
|
+
You have the right to:
|
|
34
|
+
|
|
35
|
+
- Access your data
|
|
36
|
+
- Request data deletion
|
|
37
|
+
- Opt out of non-essential data collection
|
|
38
|
+
|
|
39
|
+
## Contact
|
|
40
|
+
|
|
41
|
+
For privacy-related inquiries, please contact:
|
|
42
|
+
|
|
43
|
+
<%= props.author %><% if (props.email) { %> (<%= props.email %>)<% } %>
|
|
44
|
+
|
|
45
|
+
## Changes to This Policy
|
|
46
|
+
|
|
47
|
+
We may update this privacy policy from time to time. Any changes will be reflected by updating the "Last Updated" date above.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
+
|
|
3
|
+
# top-most EditorConfig file
|
|
4
|
+
root = true
|
|
5
|
+
|
|
6
|
+
[*]
|
|
7
|
+
end_of_line = lf
|
|
8
|
+
charset = utf-8
|
|
9
|
+
indent_size = 2
|
|
10
|
+
indent_style = space
|
|
11
|
+
insert_final_newline = true
|
|
12
|
+
trim_trailing_whitespace = true
|
|
13
|
+
|
|
14
|
+
[*.md]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Atomemo Plugin - <%= props.name %>
|
|
2
|
+
|
|
3
|
+
## Development
|
|
4
|
+
|
|
5
|
+
- Install dependencies:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun install
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- Run the unit tests:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun run test
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- Build the library:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun run build
|
|
21
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": true
|
|
7
|
+
},
|
|
8
|
+
"assist": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"actions": {
|
|
11
|
+
"recommended": true
|
|
12
|
+
},
|
|
13
|
+
"includes": ["**", "!src/i18n"]
|
|
14
|
+
},
|
|
15
|
+
"formatter": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"includes": ["**"],
|
|
18
|
+
"indentStyle": "space"
|
|
19
|
+
},
|
|
20
|
+
"linter": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"includes": ["**", "!src/i18n"],
|
|
23
|
+
"rules": {
|
|
24
|
+
"recommended": true
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"javascript": {
|
|
28
|
+
"formatter": {
|
|
29
|
+
"semicolons": "asNeeded"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "<%= props.name %>",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "<%= props.version %>",
|
|
5
|
+
"description": "<%= props.description %>",
|
|
6
|
+
"author": "<%= props.author %> <<%= props.email %>>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/<%= props.author %>/<%= props.name %>#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/<%= props.author %>/<%= props.name %>.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/<%= props.author %>/<%= props.name %>/issues"
|
|
15
|
+
},
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"development": "./src/index.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsdown",
|
|
31
|
+
"dev": "concurrently -c=cyan.bold,blue.bold --names=DEV,I18N --pad-prefix \"tsdown --watch\" \"typesafe-i18n\"",
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"prepublishOnly": "bun run build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@choiceopen/automation-plugin-sdk-js": "@choiceopen/automation-plugin-sdk-js",
|
|
38
|
+
"dotenv": "^17.2.3",
|
|
39
|
+
"zod": "^4.3.5"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@biomejs/biome": "^2.3.11",
|
|
43
|
+
"@types/bun": "^1.3.6",
|
|
44
|
+
"bumpp": "^10.4.0",
|
|
45
|
+
"concurrently": "9.2.1",
|
|
46
|
+
"tsdown": "^0.19.0",
|
|
47
|
+
"typesafe-i18n": "^5.26.2",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vitest": "^4.0.17"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"exports": {
|
|
53
|
+
".": "./dist/index.js",
|
|
54
|
+
"./package.json": "./package.json"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# src
|
|
2
|
+
|
|
3
|
+
源代码主目录,包含插件的所有核心模块。
|
|
4
|
+
|
|
5
|
+
## 目录结构
|
|
6
|
+
|
|
7
|
+
- `tools/` - [工具定义模块](./tools/README.md)
|
|
8
|
+
- `i18n/` - [国际化模块](./i18n/README.md)
|
|
9
|
+
- `index.ts` - 插件入口文件
|
|
10
|
+
|
|
11
|
+
## 入口文件
|
|
12
|
+
|
|
13
|
+
`index.ts` 是插件的入口点,负责:
|
|
14
|
+
1. 加载所有国际化语言包
|
|
15
|
+
2. 创建插件实例
|
|
16
|
+
3. 注册工具
|
|
17
|
+
4. 启动插件
|
|
18
|
+
|
|
19
|
+
## 架构
|
|
20
|
+
|
|
21
|
+
插件基于 `@choiceopen/automation-plugin-sdk-js` SDK 构建,采用模块化设计:
|
|
22
|
+
- 工具独立定义
|
|
23
|
+
- 通过统一的国际化系统提供多语言支持
|
|
24
|
+
- 所有组件通过插件实例统一注册和管理
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# i18n
|
|
2
|
+
|
|
3
|
+
国际化模块,基于 typesafe-i18n 实现类型安全的国际化支持。
|
|
4
|
+
|
|
5
|
+
## 目录结构
|
|
6
|
+
|
|
7
|
+
- `en-US/` - 英文翻译
|
|
8
|
+
- `zh-Hans/` - 简体中文翻译
|
|
9
|
+
|
|
10
|
+
## 核心文件
|
|
11
|
+
|
|
12
|
+
- `i18n-node.ts` - 国际化入口,提供 `t()` 函数用于获取翻译文本
|
|
13
|
+
- `i18n-util.ts` - 国际化工具函数和类型定义(基础配置)
|
|
14
|
+
- `i18n-util.sync.ts` - 同步加载所有语言包
|
|
15
|
+
- `i18n-util.async.ts` - 异步加载语言包(用于动态导入)
|
|
16
|
+
- `i18n-types.ts` - 自动生成的类型定义(包含所有翻译键的类型)
|
|
17
|
+
- `formatters.ts` - 格式化函数配置(当前为空)
|
|
18
|
+
|
|
19
|
+
## 功能
|
|
20
|
+
|
|
21
|
+
- 支持英文(en-US)和简体中文(zh-Hans)两种语言
|
|
22
|
+
- 类型安全的翻译键,编译时检查
|
|
23
|
+
- 同步和异步两种加载方式
|
|
24
|
+
- 自动生成类型定义
|
|
25
|
+
|
|
26
|
+
## 关系
|
|
27
|
+
|
|
28
|
+
- 被所有需要国际化的模块导入(tools、index)
|
|
29
|
+
- 在 `src/index.ts` 中通过 `loadAllLocalesAsync()` 异步加载所有语言包
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BaseTranslation } from "../i18n-types"
|
|
2
|
+
|
|
3
|
+
const en_US = {
|
|
4
|
+
PLUGIN_DISPLAY_NAME: "Testing Plugin",
|
|
5
|
+
PLUGIN_DESCRIPTION: "A plugin for testing the plugin",
|
|
6
|
+
DEMO_TOOL_DISPLAY_NAME: "Demo Tool",
|
|
7
|
+
DEMO_TOOL_DESCRIPTION: "A tool for testing the plugin",
|
|
8
|
+
LOCATION_DISPLAY_NAME: "Location",
|
|
9
|
+
LOCATION_HINT: "The location to test",
|
|
10
|
+
LOCATION_PLACEHOLDER: "Enter the location to test",
|
|
11
|
+
} satisfies BaseTranslation
|
|
12
|
+
|
|
13
|
+
export default en_US
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FormattersInitializer } from "typesafe-i18n"
|
|
2
|
+
import type { Locales, Formatters } from "./i18n-types.js"
|
|
3
|
+
|
|
4
|
+
export const initFormatters: FormattersInitializer<Locales, Formatters> = (
|
|
5
|
+
locale: Locales,
|
|
6
|
+
) => {
|
|
7
|
+
const formatters: Formatters = {
|
|
8
|
+
// add your formatter functions here
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return formatters
|
|
12
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
import { i18n, locales } from "./i18n-util.js"
|
|
5
|
+
import { loadAllLocales } from "./i18n-util.sync.js"
|
|
6
|
+
import type { LocaleTranslationFunctions } from "typesafe-i18n"
|
|
7
|
+
import type {
|
|
8
|
+
Locales,
|
|
9
|
+
Translations,
|
|
10
|
+
TranslationFunctions,
|
|
11
|
+
} from "./i18n-types.js"
|
|
12
|
+
|
|
13
|
+
loadAllLocales()
|
|
14
|
+
|
|
15
|
+
export const L: LocaleTranslationFunctions<
|
|
16
|
+
Locales,
|
|
17
|
+
Translations,
|
|
18
|
+
TranslationFunctions
|
|
19
|
+
> = i18n()
|
|
20
|
+
|
|
21
|
+
export const t = (entry: keyof Translations) => {
|
|
22
|
+
return locales.reduce<{ en_US: string; [key: string]: string }>(
|
|
23
|
+
(entries, locale) => {
|
|
24
|
+
const underscoreLocale = locale.replace("-", "_")
|
|
25
|
+
return Object.assign(entries, { [underscoreLocale]: L[locale][entry]() })
|
|
26
|
+
},
|
|
27
|
+
{ en_US: "" },
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default L
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
import type {
|
|
4
|
+
BaseTranslation as BaseTranslationType,
|
|
5
|
+
LocalizedString,
|
|
6
|
+
} from "typesafe-i18n"
|
|
7
|
+
|
|
8
|
+
export type BaseTranslation = BaseTranslationType
|
|
9
|
+
export type BaseLocale = "en-US"
|
|
10
|
+
|
|
11
|
+
export type Locales = "en-US" | "zh-Hans"
|
|
12
|
+
|
|
13
|
+
export type Translation = RootTranslation
|
|
14
|
+
|
|
15
|
+
export type Translations = RootTranslation
|
|
16
|
+
|
|
17
|
+
type RootTranslation = {
|
|
18
|
+
/**
|
|
19
|
+
* Testing Plugin
|
|
20
|
+
*/
|
|
21
|
+
PLUGIN_DISPLAY_NAME: string
|
|
22
|
+
/**
|
|
23
|
+
* A plugin for testing the plugin
|
|
24
|
+
*/
|
|
25
|
+
PLUGIN_DESCRIPTION: string
|
|
26
|
+
/**
|
|
27
|
+
* Demo Tool
|
|
28
|
+
*/
|
|
29
|
+
DEMO_TOOL_DISPLAY_NAME: string
|
|
30
|
+
/**
|
|
31
|
+
* A tool for testing the plugin
|
|
32
|
+
*/
|
|
33
|
+
DEMO_TOOL_DESCRIPTION: string
|
|
34
|
+
/**
|
|
35
|
+
* Location
|
|
36
|
+
*/
|
|
37
|
+
LOCATION_DISPLAY_NAME: string
|
|
38
|
+
/**
|
|
39
|
+
* The location to test
|
|
40
|
+
*/
|
|
41
|
+
LOCATION_HINT: string
|
|
42
|
+
/**
|
|
43
|
+
* Enter the location to test
|
|
44
|
+
*/
|
|
45
|
+
LOCATION_PLACEHOLDER: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type TranslationFunctions = {
|
|
49
|
+
/**
|
|
50
|
+
* Testing Plugin
|
|
51
|
+
*/
|
|
52
|
+
PLUGIN_DISPLAY_NAME: () => LocalizedString
|
|
53
|
+
/**
|
|
54
|
+
* A plugin for testing the plugin
|
|
55
|
+
*/
|
|
56
|
+
PLUGIN_DESCRIPTION: () => LocalizedString
|
|
57
|
+
/**
|
|
58
|
+
* Demo Tool
|
|
59
|
+
*/
|
|
60
|
+
DEMO_TOOL_DISPLAY_NAME: () => LocalizedString
|
|
61
|
+
/**
|
|
62
|
+
* A tool for testing the plugin
|
|
63
|
+
*/
|
|
64
|
+
DEMO_TOOL_DESCRIPTION: () => LocalizedString
|
|
65
|
+
/**
|
|
66
|
+
* Location
|
|
67
|
+
*/
|
|
68
|
+
LOCATION_DISPLAY_NAME: () => LocalizedString
|
|
69
|
+
/**
|
|
70
|
+
* The location to test
|
|
71
|
+
*/
|
|
72
|
+
LOCATION_HINT: () => LocalizedString
|
|
73
|
+
/**
|
|
74
|
+
* Enter the location to test
|
|
75
|
+
*/
|
|
76
|
+
LOCATION_PLACEHOLDER: () => LocalizedString
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type Formatters = {}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
import { initFormatters } from "./formatters.js"
|
|
5
|
+
import type { Locales, Translations } from "./i18n-types.js"
|
|
6
|
+
import { loadedFormatters, loadedLocales, locales } from "./i18n-util.js"
|
|
7
|
+
|
|
8
|
+
const localeTranslationLoaders = {
|
|
9
|
+
"en-US": () => import("./en-US/index.js"),
|
|
10
|
+
"zh-Hans": () => import("./zh-Hans/index.js"),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const updateDictionary = (
|
|
14
|
+
locale: Locales,
|
|
15
|
+
dictionary: Partial<Translations>,
|
|
16
|
+
): Translations =>
|
|
17
|
+
(loadedLocales[locale] = { ...loadedLocales[locale], ...dictionary })
|
|
18
|
+
|
|
19
|
+
export const importLocaleAsync = async (
|
|
20
|
+
locale: Locales,
|
|
21
|
+
): Promise<Translations> =>
|
|
22
|
+
(await localeTranslationLoaders[locale]()).default as unknown as Translations
|
|
23
|
+
|
|
24
|
+
export const loadLocaleAsync = async (locale: Locales): Promise<void> => {
|
|
25
|
+
updateDictionary(locale, await importLocaleAsync(locale))
|
|
26
|
+
loadFormatters(locale)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const loadAllLocalesAsync = (): Promise<void[]> =>
|
|
30
|
+
Promise.all(locales.map(loadLocaleAsync))
|
|
31
|
+
|
|
32
|
+
export const loadFormatters = (locale: Locales): void =>
|
|
33
|
+
void (loadedFormatters[locale] = initFormatters(locale))
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
import { initFormatters } from "./formatters.js"
|
|
5
|
+
import type { Locales, Translations } from "./i18n-types.js"
|
|
6
|
+
import { loadedFormatters, loadedLocales, locales } from "./i18n-util.js"
|
|
7
|
+
|
|
8
|
+
import en_US from "./en-US/index.js"
|
|
9
|
+
import zh_Hans from "./zh-Hans/index.js"
|
|
10
|
+
|
|
11
|
+
const localeTranslations = {
|
|
12
|
+
"en-US": en_US,
|
|
13
|
+
"zh-Hans": zh_Hans,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const loadLocale = (locale: Locales): void => {
|
|
17
|
+
if (loadedLocales[locale]) return
|
|
18
|
+
|
|
19
|
+
loadedLocales[locale] = localeTranslations[locale] as unknown as Translations
|
|
20
|
+
loadFormatters(locale)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const loadAllLocales = (): void => locales.forEach(loadLocale)
|
|
24
|
+
|
|
25
|
+
export const loadFormatters = (locale: Locales): void =>
|
|
26
|
+
void (loadedFormatters[locale] = initFormatters(locale))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
i18n as initI18n,
|
|
6
|
+
i18nObject as initI18nObject,
|
|
7
|
+
i18nString as initI18nString,
|
|
8
|
+
} from "typesafe-i18n"
|
|
9
|
+
import type { LocaleDetector } from "typesafe-i18n/detectors"
|
|
10
|
+
import type {
|
|
11
|
+
LocaleTranslationFunctions,
|
|
12
|
+
TranslateByString,
|
|
13
|
+
} from "typesafe-i18n"
|
|
14
|
+
import { detectLocale as detectLocaleFn } from "typesafe-i18n/detectors"
|
|
15
|
+
import { initExtendDictionary } from "typesafe-i18n/utils"
|
|
16
|
+
import type {
|
|
17
|
+
Formatters,
|
|
18
|
+
Locales,
|
|
19
|
+
Translations,
|
|
20
|
+
TranslationFunctions,
|
|
21
|
+
} from "./i18n-types.js"
|
|
22
|
+
|
|
23
|
+
export const baseLocale: Locales = "en-US"
|
|
24
|
+
|
|
25
|
+
export const locales: Locales[] = ["en-US", "zh-Hans"]
|
|
26
|
+
|
|
27
|
+
export const isLocale = (locale: string): locale is Locales =>
|
|
28
|
+
locales.includes(locale as Locales)
|
|
29
|
+
|
|
30
|
+
export const loadedLocales: Record<Locales, Translations> = {} as Record<
|
|
31
|
+
Locales,
|
|
32
|
+
Translations
|
|
33
|
+
>
|
|
34
|
+
|
|
35
|
+
export const loadedFormatters: Record<Locales, Formatters> = {} as Record<
|
|
36
|
+
Locales,
|
|
37
|
+
Formatters
|
|
38
|
+
>
|
|
39
|
+
|
|
40
|
+
export const extendDictionary = initExtendDictionary<Translations>()
|
|
41
|
+
|
|
42
|
+
export const i18nString = (locale: Locales): TranslateByString =>
|
|
43
|
+
initI18nString<Locales, Formatters>(locale, loadedFormatters[locale])
|
|
44
|
+
|
|
45
|
+
export const i18nObject = (locale: Locales): TranslationFunctions =>
|
|
46
|
+
initI18nObject<Locales, Translations, TranslationFunctions, Formatters>(
|
|
47
|
+
locale,
|
|
48
|
+
loadedLocales[locale],
|
|
49
|
+
loadedFormatters[locale],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
export const i18n = (): LocaleTranslationFunctions<
|
|
53
|
+
Locales,
|
|
54
|
+
Translations,
|
|
55
|
+
TranslationFunctions
|
|
56
|
+
> =>
|
|
57
|
+
initI18n<Locales, Translations, TranslationFunctions, Formatters>(
|
|
58
|
+
loadedLocales,
|
|
59
|
+
loadedFormatters,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
export const detectLocale = (...detectors: LocaleDetector[]): Locales =>
|
|
63
|
+
detectLocaleFn<Locales>(baseLocale, locales, ...detectors)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Translation } from "../i18n-types"
|
|
2
|
+
|
|
3
|
+
const zh_Hans = {
|
|
4
|
+
PLUGIN_DISPLAY_NAME: "测试插件",
|
|
5
|
+
PLUGIN_DESCRIPTION: "一个用于测试插件的插件",
|
|
6
|
+
DEMO_TOOL_DISPLAY_NAME: "演示工具",
|
|
7
|
+
DEMO_TOOL_DESCRIPTION: "一个用于测试插件的工具",
|
|
8
|
+
LOCATION_DISPLAY_NAME: "位置",
|
|
9
|
+
LOCATION_HINT: "要测试的位置",
|
|
10
|
+
LOCATION_PLACEHOLDER: "输入要测试的位置",
|
|
11
|
+
} satisfies Translation
|
|
12
|
+
|
|
13
|
+
export default zh_Hans
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createPlugin } from "@choiceopen/automation-plugin-sdk-js"
|
|
2
|
+
import packageJSON from "../package.json"
|
|
3
|
+
import { t } from "./i18n/i18n-node"
|
|
4
|
+
import { locales } from "./i18n/i18n-util"
|
|
5
|
+
import { loadAllLocalesAsync } from "./i18n/i18n-util.async"
|
|
6
|
+
import { demoTool } from "./tools/demo"
|
|
7
|
+
|
|
8
|
+
await loadAllLocalesAsync()
|
|
9
|
+
|
|
10
|
+
const plugin = createPlugin({
|
|
11
|
+
name: packageJSON.name,
|
|
12
|
+
display_name: t("PLUGIN_DISPLAY_NAME"),
|
|
13
|
+
description: t("PLUGIN_DESCRIPTION"),
|
|
14
|
+
icon: "🎛️",
|
|
15
|
+
author: "Choiceform",
|
|
16
|
+
email: "support@choiceform.com",
|
|
17
|
+
version: packageJSON.version,
|
|
18
|
+
repo: "https://github.com/choice-open/automation-official-plugins/plugins/testing-plugin",
|
|
19
|
+
locales,
|
|
20
|
+
transporterOptions: {},
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
plugin.addTool(demoTool)
|
|
24
|
+
|
|
25
|
+
plugin.run()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# tools
|
|
2
|
+
|
|
3
|
+
工具定义模块,用于定义插件提供的可执行工具。
|
|
4
|
+
|
|
5
|
+
## 文件
|
|
6
|
+
|
|
7
|
+
- `demo.ts` - 演示工具定义,包含工具参数和执行逻辑
|
|
8
|
+
|
|
9
|
+
## 功能
|
|
10
|
+
|
|
11
|
+
定义 `demo-tool` 工具,包含:
|
|
12
|
+
- 参数定义(location 字符串)
|
|
13
|
+
- 执行逻辑(invoke 函数,返回测试消息)
|
|
14
|
+
|
|
15
|
+
## 关系
|
|
16
|
+
|
|
17
|
+
- 被 `src/index.ts` 导入并注册到插件
|
|
18
|
+
- 使用 `src/i18n/i18n-node.ts` 获取国际化文本
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@choiceopen/automation-plugin-sdk-js/types"
|
|
2
|
+
import { t } from "../i18n/i18n-node"
|
|
3
|
+
|
|
4
|
+
export const demoTool = {
|
|
5
|
+
name: "demo-tool",
|
|
6
|
+
display_name: t("DEMO_TOOL_DISPLAY_NAME"),
|
|
7
|
+
description: t("DEMO_TOOL_DESCRIPTION"),
|
|
8
|
+
icon: "🧰",
|
|
9
|
+
parameters: [
|
|
10
|
+
{
|
|
11
|
+
name: "location",
|
|
12
|
+
type: "string",
|
|
13
|
+
required: true,
|
|
14
|
+
display_name: t("LOCATION_DISPLAY_NAME"),
|
|
15
|
+
ui: {
|
|
16
|
+
component: "input",
|
|
17
|
+
hint: t("LOCATION_HINT"),
|
|
18
|
+
placeholder: t("LOCATION_PLACEHOLDER"),
|
|
19
|
+
support_expression: true,
|
|
20
|
+
width: "full",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
async invoke({ args }: { args: { location: string } }) {
|
|
25
|
+
return {
|
|
26
|
+
message: `Testing the plugin with location: ${args.location}`,
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
} satisfies ToolDefinition
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest"
|
|
2
|
+
|
|
3
|
+
// Mock the SDK before importing anything that uses it
|
|
4
|
+
vi.mock("@choiceopen/automation-plugin-sdk-js", () => ({
|
|
5
|
+
createPlugin: vi.fn(() => ({
|
|
6
|
+
addCredential: vi.fn(),
|
|
7
|
+
addTool: vi.fn(),
|
|
8
|
+
addModel: vi.fn(),
|
|
9
|
+
run: vi.fn(),
|
|
10
|
+
})),
|
|
11
|
+
}))
|
|
12
|
+
|
|
13
|
+
// Mock i18n
|
|
14
|
+
vi.mock("./i18n/i18n-node", () => ({
|
|
15
|
+
t: vi.fn((key: string) => key),
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
vi.mock("./i18n/i18n-util", () => ({
|
|
19
|
+
locales: ["en-US"],
|
|
20
|
+
}))
|
|
21
|
+
|
|
22
|
+
vi.mock("./i18n/i18n-util.async", () => ({
|
|
23
|
+
loadAllLocalesAsync: vi.fn(),
|
|
24
|
+
}))
|
|
25
|
+
|
|
26
|
+
import { createPlugin } from "@choiceopen/automation-plugin-sdk-js"
|
|
27
|
+
|
|
28
|
+
describe("createPlugin", () => {
|
|
29
|
+
it("should create a plugin object", () => {
|
|
30
|
+
const plugin = createPlugin({
|
|
31
|
+
name: "test-plugin",
|
|
32
|
+
display_name: {en_US: "Test Plugin"},
|
|
33
|
+
description: {en_US: "A test plugin"},
|
|
34
|
+
icon: "🧪",
|
|
35
|
+
author: "Test",
|
|
36
|
+
email: "test@test.com",
|
|
37
|
+
version: "1.0.0",
|
|
38
|
+
repo: "https://github.com/test/test",
|
|
39
|
+
locales: ["en"],
|
|
40
|
+
transporterOptions: {},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
expect(plugin).toBeDefined()
|
|
44
|
+
expect(plugin).toHaveProperty("run")
|
|
45
|
+
expect(typeof plugin.run).toBe("function")
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it("should be able to call run() method", () => {
|
|
49
|
+
const plugin = createPlugin({
|
|
50
|
+
name: "test-plugin",
|
|
51
|
+
display_name: {en_US: "Test Plugin"},
|
|
52
|
+
description: {en_US: "A test plugin"},
|
|
53
|
+
icon: "🧪",
|
|
54
|
+
author: "Test",
|
|
55
|
+
email: "test@test.com",
|
|
56
|
+
version: "1.0.0",
|
|
57
|
+
repo: "https://github.com/test/test",
|
|
58
|
+
locales: ["en"],
|
|
59
|
+
transporterOptions: {},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
expect(() => plugin.run()).not.toThrow()
|
|
63
|
+
expect(plugin.run).toHaveBeenCalledTimes(1)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"lib": ["es2023"],
|
|
5
|
+
"moduleDetection": "force",
|
|
6
|
+
"module": "preserve",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"types": ["bun"],
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noUnusedLocals": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"emitDeclarationOnly": true,
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"verbatimModuleSyntax": true,
|
|
17
|
+
"skipLibCheck": true
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"]
|
|
20
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@choiceopen/automation-plugin-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "A command-line utility for building and publishing Choiceform Atomemo Plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oclif"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"./oclif.manifest.json"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "shx rm -rf dist && tsc --build",
|
|
29
|
+
"build": "shx rm -rf dist && tsc --build && shx cp -r src/templates dist/",
|
|
30
30
|
"check": "biome check --write",
|
|
31
31
|
"prepack": "oclif manifest && oclif readme",
|
|
32
32
|
"postpack": "shx rm -f oclif.manifest.json",
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@inquirer/checkbox": "^5.0.4",
|
|
57
|
-
"@inquirer/confirm": "^6.0.
|
|
57
|
+
"@inquirer/confirm": "^6.0.4",
|
|
58
58
|
"@inquirer/input": "^5.0.4",
|
|
59
59
|
"@inquirer/select": "^5.0.4",
|
|
60
60
|
"@oclif/core": "^4.8.0",
|
|
61
61
|
"@oclif/plugin-autocomplete": "^3.2.39",
|
|
62
62
|
"@oclif/plugin-help": "^6.2.36",
|
|
63
63
|
"@oclif/plugin-version": "^2.2.36",
|
|
64
|
-
"es-toolkit": "^1.
|
|
64
|
+
"es-toolkit": "^1.44.0",
|
|
65
65
|
"eta": "^4.5.0",
|
|
66
66
|
"open": "^11.0.0",
|
|
67
67
|
"ts-dedent": "^2.2.0",
|