feat: 平台标记单一源 PLATFORM_GROUPS + catalog 重生成 platformTag 生效
迁移前置项(指南五件小事 #1 + 第 0 步作业 #2): - register-all.ts 新增 PLATFORM_GROUPS 单一权威表(33 域全标 win32,darwin/linux 仅类型占位) - registerAll 逐域加载时把平台默认值落进 meta.platforms(能力显式声明优先); 新增 buildDomainPlatformMap 供构建脚本与运行时共用同一张表 - build-catalog.mjs 删除 WIN32_GROUPS 硬编码,platformTag 从包内分组表派生(改 tsx 运行) - 守卫测试 platform-groups.test.ts:域无缺行 / 不偷填非 win32 数据 / meta 派生一致 - catalog.json 重生成:687 个组件获得 platformTag=win32(此前从未生效) - 源数据恢复:对面重构删了 shizai-catalog-data.js,从其历史 commit 7bc627c8 恢复到 temp/catalog-source/(不入库)并作为回退路径 - catalog-overrides 增强 addFields 支持;把此前直接改 catalog.json 的 96 处假必填修正、 label 修正、Screenlock 字段清理、12 个实现读取但源数据缺失的字段全部沉淀进 overrides, 重生成后参数审计 A/B 类保持 0/0
This commit is contained in:
1 parent
a7709aefbb
commit
8414c4f355
9 files changed
+1002
-125520
No files matched your search
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { capabilityCount, getCapabilityMeta } from "../engine/registry";
|
||||
import {
|
||||
PLATFORM_GROUPS,
|
||||
buildDomainPlatformMap,
|
||||
capabilityDomains
|
||||
} from "./register-all";
|
||||
|
||||
describe("PLATFORM_GROUPS 平台单一源(迁移指南五件小事 #1)", () => {
|
||||
it("每个能力域都有平台行,不允许缺行", () => {
|
||||
for (const domain of capabilityDomains) {
|
||||
expect(PLATFORM_GROUPS[domain], `域 ${domain} 缺少 PLATFORM_GROUPS 行`).toBeDefined();
|
||||
}
|
||||
expect(Object.keys(PLATFORM_GROUPS).sort()).toEqual([...capabilityDomains].sort());
|
||||
});
|
||||
|
||||
it("现阶段数据只允许 win32,darwin/linux 仅类型占位不填数据", () => {
|
||||
for (const [domain, platforms] of Object.entries(PLATFORM_GROUPS)) {
|
||||
expect(
|
||||
platforms.every((p) => p === "win32"),
|
||||
`域 ${domain} 填了 win32 以外的平台数据`
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("registerAll 后所有能力 meta.platforms 与分组表一致(运行时派生)", async () => {
|
||||
// buildDomainPlatformMap 逐域加载(动态 import 有缓存,必须在 registerAll 语义内一次完成)
|
||||
const map = await buildDomainPlatformMap();
|
||||
expect(capabilityCount()).toBeGreaterThan(700);
|
||||
expect(map.size).toBe(capabilityCount());
|
||||
for (const id of map.keys()) {
|
||||
const meta = getCapabilityMeta(id);
|
||||
expect(meta, `能力 ${id} 无 meta`).toBeTruthy();
|
||||
expect(meta!.platforms, `能力 ${id} 的 meta.platforms 未从分组表派生`).toEqual(["win32"]);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,53 @@
|
||||
import type { RpaEngine } from "../engine/engine";
|
||||
import { applyPlatformDefaults, capabilityIds, type CapabilityPlatform } from "../engine/registry";
|
||||
|
||||
export type { CapabilityPlatform } from "../engine/registry";
|
||||
|
||||
/**
|
||||
* 平台归属单一权威表(迁移指南「五件小事 #1」,dev-conventions 规则 4)。
|
||||
*
|
||||
* - 运行时 `meta.platforms` 与构建期 catalog `platformTag` 都从这张表派生,
|
||||
* 任何代码不得自行声明第二份平台数据(守卫测试 platform-groups.test.ts 把关)。
|
||||
* - 现阶段所有能力只在 Windows 交互会话验证过,全部标 `["win32"]`;
|
||||
* `darwin`/`linux` 仅类型占位,不填数据。将来支持新平台 = 对应行加平台,仅此而已。
|
||||
* - 后续若某域内出现平台混装(如 remaining-core 里混着 PS 专用能力),
|
||||
* 先把域拆细,再在能力 meta.platforms 里显式声明更窄限制。
|
||||
*/
|
||||
export const PLATFORM_GROUPS: Record<string, CapabilityPlatform[]> = {
|
||||
control: ["win32"],
|
||||
files: ["win32"],
|
||||
http: ["win32"],
|
||||
data: ["win32"],
|
||||
office: ["win32"],
|
||||
desktop: ["win32"],
|
||||
desktopUia: ["win32"],
|
||||
time: ["win32"],
|
||||
windowsSystem: ["win32"],
|
||||
ftp: ["win32"],
|
||||
ocr: ["win32"],
|
||||
pdf: ["win32"],
|
||||
word: ["win32"],
|
||||
wordExtended: ["win32"],
|
||||
message: ["win32"],
|
||||
vision: ["win32"],
|
||||
cvVision: ["win32"],
|
||||
extended: ["win32"],
|
||||
systemExtended: ["win32"],
|
||||
officeFileExtended: ["win32"],
|
||||
officeAliases: ["win32"],
|
||||
excelCommon: ["win32"],
|
||||
excelCom: ["win32"],
|
||||
dataExtended: ["win32"],
|
||||
utilityExtended: ["win32"],
|
||||
dataTableCommon: ["win32"],
|
||||
basicEncryption: ["win32"],
|
||||
mailRemaining: ["win32"],
|
||||
remainingCore: ["win32"],
|
||||
commonFinal: ["win32"],
|
||||
humanDialog: ["win32"],
|
||||
aiService: ["win32"],
|
||||
windowExtended: ["win32"]
|
||||
};
|
||||
|
||||
/**
|
||||
* 显式注册入口(任务 4.2,决策点 9:双入口过渡)。
|
||||
@@ -46,14 +95,35 @@ const DOMAINS: Record<string, () => Promise<unknown>> = {
|
||||
windowExtended: () => import("./window-extended")
|
||||
};
|
||||
|
||||
async function loadDomainWithPlatformDefaults(domain: string): Promise<Set<string>> {
|
||||
const load = DOMAINS[domain];
|
||||
if (!load) throw new Error(`未知能力域:${domain}(可选:${Object.keys(DOMAINS).join(", ")})`);
|
||||
const before = new Set(capabilityIds());
|
||||
await load();
|
||||
const fresh = [...capabilityIds()].filter((id) => !before.has(id));
|
||||
// 平台默认值从 PLATFORM_GROUPS 派生(单一源);能力显式声明的 platforms 优先
|
||||
applyPlatformDefaults(fresh, PLATFORM_GROUPS[domain] ?? []);
|
||||
return new Set(fresh);
|
||||
}
|
||||
|
||||
export async function registerAll(engine: RpaEngine, groups?: string[]): Promise<RpaEngine> {
|
||||
const wanted = groups && groups.length ? groups : Object.keys(DOMAINS);
|
||||
for (const group of wanted) {
|
||||
const load = DOMAINS[group];
|
||||
if (!load) throw new Error(`未知能力域:${group}(可选:${Object.keys(DOMAINS).join(", ")})`);
|
||||
await load();
|
||||
}
|
||||
for (const group of wanted) await loadDomainWithPlatformDefaults(group);
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 逐域加载并返回「能力 id → 平台数组」映射(副作用:完成全量注册)。
|
||||
* 供构建脚本(build-catalog)派生 catalog platformTag,与运行时同一张表。
|
||||
*/
|
||||
export async function buildDomainPlatformMap(): Promise<Map<string, CapabilityPlatform[]>> {
|
||||
const map = new Map<string, CapabilityPlatform[]>();
|
||||
for (const domain of Object.keys(DOMAINS)) {
|
||||
const fresh = await loadDomainWithPlatformDefaults(domain);
|
||||
const platforms = PLATFORM_GROUPS[domain] ?? [];
|
||||
for (const id of fresh) map.set(id, platforms);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
export const capabilityDomains = Object.keys(DOMAINS);
|
||||
Reference in new issue
Block a user