Files
shrimp-admin/scripts/check-contract.mjs
T
wc24 603e33d17f 0.8.0: 契约副本刷齐并改为自动同步;未注册字段类型不再静默回落
契约副本(src/IShrimpType.ts)此前漂了一整代:停在旧的 json 类型,
缺 object / array / IFieldConfig.fields / IFieldConfig.item / parse / IPageResult.refs。
而本包自己的组件早就在读这些字段——FieldArray 读 field.item、FieldObject 读 fields、
FieldRelation 与 ShrimpTable 读 refs。等于组件在用、类型说没有。
接入方照这份副本理解 shrimp 能渲染什么,只会得出"结构化数据只有 json"的结论。

现在由 shrimp-server 的 postbuild 单向覆盖过来(它是契约真身),
本仓库另提供 npm run check:contract / sync:contract 手动比对与同步。
注释头不参与同步,它声明的是"我是副本",与契约正文是两回事。

VueAdmin.getFieldComponent:未注册类型仍回落成 string(类型词汇表是开放的,
消费侧放个 Field<X>.vue 就能扩,改成严格校验会当场打死 theseus 的 gesture/goodsList
和 hand 的 dropList/matterPointDropList),但按类型去重告警一次,
打印出现位置、已注册类型和两条修法。上面那个 json 就是这么静默活下来的。

resolveVue:内置组件表为空时报"本包没被 vite 正常转换、消费侧缺 optimizeDeps.exclude",
不再报"找不到 layout.vue"把人引去查文件路径。

README 重写成可照抄的接入模板 + 出错对照表 + "那几行为什么不能删"。
版本与 shrimp-server 归一到 0.8.0,删掉 @syncedFrom 这条手维护的版本标记。
2026-08-10 19:48:57 +08:00

62 lines
2.4 KiB
JavaScript

/**
* 契约副本工具:比对 / 同步 src/IShrimpType.ts 与 shrimp-server 那份。
*
* node scripts/check-contract.mjs 比对,漂了就非零退出
* node scripts/check-contract.mjs --fix 从 shrimp-server 复制过来(自动保留前端副本的注释头)
*
* 为什么需要它:副本靠人工同步,漂了一整代都没被发现——
* 副本停在旧的 json 类型、缺 object/array/fields/item/parse/refs。
* 前端对未注册的字段类型静默回落到 string,所以漂移不报错、只悄悄渲染错。
* (同样是"改了就复制过去"的约定,goby 的 GobyClient.ts 四份拷贝已经全漂了,
* 区别只在于那份复制后归消费侧拥有、漂了无所谓,而这份两边必须字节一致。)
*
* 只比对注释块之后的正文:两边的头部本来就该不同,一份是契约、一份声明自己是副本。
*/
import { readFileSync, writeFileSync, existsSync } from "node:fs"
import { fileURLToPath } from "node:url"
import { dirname, resolve } from "node:path"
const here = dirname(fileURLToPath(import.meta.url))
const mine = resolve(here, "../src/IShrimpType.ts")
const fix = process.argv.includes("--fix")
const argPath = process.argv.find(a => !a.startsWith("--") && a !== process.argv[0] && a !== process.argv[1])
const theirs = [
argPath && resolve(argPath, "src/IShrimpType.ts"),
resolve(here, "../node_modules/shrimp-server/src/IShrimpType.ts"),
resolve(here, "../../shrimp-server/src/IShrimpType.ts"),
].filter(Boolean).find(existsSync)
if (!theirs) {
// 消费侧的前端项目不装后端包,找不到是正常的,不该让它们的构建挂掉
console.log("skip: 找不到 shrimp-server 源码,无从比对")
process.exit(0)
}
const split = f => {
const s = readFileSync(f, "utf8")
const i = s.indexOf("*/") + 2
return { head: s.slice(0, i), body: s.slice(i) }
}
const a = split(mine)
const b = split(theirs)
if (a.body === b.body) {
console.log("✅ 契约副本与 shrimp-server 一致")
process.exit(0)
}
if (fix) {
writeFileSync(mine, a.head + b.body)
console.log("✅ 已从 shrimp-server 同步契约副本(保留原注释头)")
console.log(" " + theirs + "\n → " + mine)
process.exit(0)
}
console.error("❌ 契约副本已漂移")
console.error(" 副本: " + mine)
console.error(" 契约: " + theirs)
console.error(" 修法: npm run sync:contract")
process.exit(1)