- 迁移 examples/rules/ 到 src/rules/,resources/devices.json 到 src/devices.json
- 迁移 resources/fetch-devlist.js 到 src/tools/fetch-devlist.ts 并改造为 ESM
- CLI 简化为零参数:bun run pack 自动编译并输出 dist/miot_{timestamp}.bak
- 移除备份合并能力:删除 mergeCompiledRules、RuleReplaceStrategy、dry-run、replace 参数
- 编译器简化为从零生成,不再支持 baseBackup 合并
- 新增 fetch-devices 命令用于从中枢网关更新设备清单
- 新增 bn.js、elliptic 依赖
- 更新测试路径引用,移除依赖合并逻辑的测试用例
- 更新 README.md 反映新项目结构和命令
87 lines
3.1 KiB
TypeScript
87 lines
3.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { readBackupFile } from "../src/index.ts";
|
|
import { collectRuleDefinitions, compileRule, compileWorkflow } from "../src/compiler.ts";
|
|
import examples, { conditionBeforeAction, eventTurnOn, mergedTriggers } from "../src/rules/index.ts";
|
|
|
|
const now = 1_760_000_000_000;
|
|
const devices = (await import("../src/devices.json")).default;
|
|
|
|
describe("规则编译", () => {
|
|
test("单条事件触发开灯规则生成稳定 JSON", () => {
|
|
const { rule } = compileRule(eventTurnOn, { now });
|
|
expect(rule).toEqual({
|
|
id: String(now),
|
|
cfg: {
|
|
id: String(now),
|
|
userData: {
|
|
name: "示例-事件触发开灯",
|
|
transform: { x: 0, y: 0, scale: 1, rotate: 0 },
|
|
lastUpdateTime: now,
|
|
version: 0,
|
|
},
|
|
uiType: "test",
|
|
enable: true,
|
|
},
|
|
nodes: [
|
|
{
|
|
id: "DI1",
|
|
type: "deviceInput",
|
|
props: {
|
|
did: "blt.3.1htiptpdgco00",
|
|
siid: 2,
|
|
eiid: 1008,
|
|
},
|
|
inputs: {},
|
|
outputs: { output: ["DO1.trigger"] },
|
|
cfg: {
|
|
urn: "urn:miot-spec-v2:device:motion-sensor:0000A014:xiaomi-pir1:2",
|
|
name: "deviceInput",
|
|
version: 1,
|
|
pos: { x: 240, y: 180, width: 450, height: 206 },
|
|
},
|
|
},
|
|
{
|
|
id: "DO1",
|
|
type: "deviceOutput",
|
|
props: {
|
|
did: "group.1815373077765824512",
|
|
siid: 2,
|
|
piid: 1,
|
|
value: true,
|
|
},
|
|
inputs: { trigger: null },
|
|
outputs: { output: [] },
|
|
cfg: {
|
|
urn: "urn:miot-spec-v2:device:light:0000A001:mijia-group3:3:0000C802",
|
|
name: "deviceOutput",
|
|
version: 1,
|
|
pos: { x: 800, y: 180, width: 528, height: 164 },
|
|
},
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
test("状态判断后动作会生成 deviceGet 并连接满足路径", () => {
|
|
const { rule } = compileRule(conditionBeforeAction, { now });
|
|
expect(rule.nodes.map((node) => node.type)).toEqual(["deviceInput", "deviceGet", "deviceOutput"]);
|
|
expect(rule.nodes[0]!.outputs.output).toEqual(["DG1.input"]);
|
|
expect(rule.nodes[1]!.outputs.output).toEqual(["DO1.trigger"]);
|
|
expect(rule.nodes[1]!.outputs.output2).toEqual([]);
|
|
});
|
|
|
|
test("多个触发器会生成 signalOr 合并节点", () => {
|
|
const { rule } = compileRule(mergedTriggers, { now });
|
|
expect(rule.nodes.map((node) => node.type)).toEqual(["deviceInput", "deviceInput", "signalOr", "deviceOutput"]);
|
|
expect(rule.nodes[0]!.outputs.output).toEqual(["SO1.input0"]);
|
|
expect(rule.nodes[1]!.outputs.output).toEqual(["SO1.input1"]);
|
|
expect(rule.nodes[2]!.outputs.output).toEqual(["DO1.trigger"]);
|
|
});
|
|
|
|
test("模块导出收集支持默认数组和命名规则", async () => {
|
|
const moduleExports = await import("../src/rules/index.ts");
|
|
const definitions = collectRuleDefinitions(moduleExports);
|
|
expect(definitions.map((definition) => definition.name)).toEqual(examples.map((definition) => definition.name));
|
|
});
|
|
});
|