feat(spec)!: 跨形态同名三条收敛 — ShareRecipientType / TransformType / suggestFieldType (#4539) - #4571
Merged
Merged
Conversation
The three baseline rows where the two declarations sharing a name did not
even share a FORM (type vs const, or two unrelated functions), so a wrong
import-path pick had no shape overlap to hide behind. Each judged against a
three-repo import-level scan (framework, cloud, objectui — the latter two
contain zero references to all three names).
- ShareRecipientType: the security zod enum (authorable sharing-RULE
recipients) keeps the name; the contracts type is a DIFFERENT concept —
the recipient_type a sys_record_share ROW may carry — renamed
RecordShareRecipientType, member set aligned to the storage select it
actually mirrors ('role', never persistable, -> 'position', completing
the #2724 D3 rename its changelog already claimed). plugin-sharing
re-export renamed in lockstep; only 'user' is enforced today, unchanged.
- TransformType: the data import-mapping enum keeps the name; shared's
differently-shaped config-union pair (zero importers for either name in
all three repos) renamed FieldMappingTransformSchema /
FieldMappingTransform. Renamed rather than alias-deleted because
build-docs derives `import type` examples by stripping 'Schema' (filed
unassigned as #4570). json-schema.manifest key moved with it.
- suggestFieldType: diffed the two implementations FIRST — they were never
forks of one function: shared/suggestions.zod is the typo-suggester
(string -> string[] candidates, feeds the zod error map, keeps the name
on . and ./shared); data/type-compat is the deterministic SQL-column ->
FieldType mapper (ADR-0015), renamed suggestFieldTypeForSqlType.
Divergence pinned in type-compat.test.ts: ('varchar(255)') -> [] vs
'text'; ('text_area') -> ['textarea'] vs undefined; ('int') ->
['number'] vs 'number'. Not a live bug: each caller imports the one it
means; the hazard was authoring-time wrong-pick, where `[]` is truthy.
All 3 dual-source-exports.baseline.json rows deleted; api-surface and
reference docs regenerated via check:generated --fix (8/8 green);
check:dual-source-exports green at 35 baseline rows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
August 2, 2026 07:22
os-zhuang
enabled auto-merge
August 2, 2026 07:22
This was referenced Aug 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4539
基线里最阴险的三条:同名但不同形态(type≠const,或两个不相干的 function),选错一侧连"形状重叠、编译通过"的掩护都没有。每条都按三仓 import 级扫描(framework、
/workspace/cloud、objectui 浅克隆)单独判真源 —— cloud 与 objectui 对这三个名字的引用均为零,全部消费方都在本仓。逐条判定
1.
ShareRecipientType— 改名(两个活概念共用一名)security/sharing.zod.ts的 zod enum(user | team | position | unit_and_subordinates | business_unit)—— 可授权的共享规则收件人词表,被SharingRuleSchema.sharedWith.type直接消费,与 contracts 的SharingRuleRecipientType(多一个保留的queue)本来就是刻意配对。sys_record_share行的recipient_type。它自称 "mirrors spec/security" 早已失真(security 侧group→team、guest已删),且成员role与存储侧 select(user | group | position | unit_and_subordinates | guest)不符 ——role从来不是可持久化的值。改名RecordShareRecipientType,成员对齐存储 select(role→position,补完 ADR-0090 D3 leftovers in plugin-sharing: sys_record_sharerolerecipient enum + "角色及下级" translations #2724 D3 改名在 changelog 里声称完成、实际漏掉的那一半),注释改为指向它真正镜像的存储侧 gate。plugin-sharing的 re-export 同步改名;运行时仍只强制user(grant()拒绝其余值),行为零变化。测试里原本被迫的as any铸型随之删除 —— 类型现在能如实表达。2.
TransformType— 改名(shared 侧双名零消费者)data/mapping.zod.ts的导入映射 enum(none | constant | lookup | split | join | javascript | map),被 ImportMapping 的transform字段活消费。TransformTypeSchema(transform 配置对象的 discriminated union,形态完全不同)+ 推断类型别名TransformType,两个名字在三仓都是零 importer。整对改名FieldMappingTransformSchema/FieldMappingTransform(它就是FieldMapping.transform的取值)。为什么不是只删别名:build-docs 生成import type { X }示例时机械剥Schema后缀,别名不在了文档照样宣传一个不存在的导出 —— 该生成器缺陷已按第十条军规单独立案 build-docs.ts 用「剥掉 Schema 后缀」推导 import type 示例,类型别名不存在时生成的文档引用无法编译 #4570(unassigned)。json-schema.manifest.json的shared/TransformType键随之改为shared/FieldMappingTransform(蓄意改名,非静默下架)。不引入过渡别名:零消费者,干净断,changeset 带 FROM → TO。3.
suggestFieldType— 先 diff 两份实现,行为判定如下两份实现从来不是同一函数的分叉,是两个用途不相干的函数共用一名,签名、语义、返回类型全不同:
shared/suggestions.zod(.+./shared,同一符号)data/type-compat(./data)(input: string) => string[](rawType: string, dialect?: SqlDialect) => FieldType | undefined'varchar(255)'[](模糊匹配不到)'text''text_area'['textarea']undefined(不是 SQL 类型)'int'['number'](数组)'number'(标量)不是潜伏 bug:两个调用方(error map、service-datasource)各自 import 的都是自己要的那份,运行时行为无分歧。真正的危险在编写时选错:auto-import 按名挑错一侧后,标量位置来了个数组 —— 而
[]是 truthy,if (suggested)这类写法编译通过、静默走错分支。处置:./data侧改名suggestFieldTypeForSqlType(typo-suggester 保名保 root 导出);上表的行为分歧已固化为type-compat.test.ts里的交叉 pin,两函数若日后被人为归并,pin 会逼着显式删除。基线
dual-source-exports.baseline.json恰好删除 3 行(gate 点名的即这 3 行,main 移动未产生额外 stale 行):ShareRecipientType — [./contracts (type)] ≠ [./security (const)]TransformType — [./data (const)] ≠ [./shared (type)]suggestFieldType — [., ./shared (function)] ≠ [./data (function)]验证
pnpm --filter @objectstack/spec build✅check:generated8/8 up to date ✅(api-surface + reference docs 经--fix定向再生)check:dual-source-exports✅(self-test 通过;4306 名字 / 16 入口,基线 38 → 35)test:287 文件 / 7271 用例全过 ✅;spectypecheck✅pnpm build71/71 ✅、pnpm typecheck122/122 ✅、pnpm test132/132 ✅Changeset
@objectstack/spec: major、@objectstack/plugin-sharing: major,三条 FROM → TO 迁移各带一行修法(升级 agent grep 得到)。范围外发现
Schema后缀推导 import 示例、不校验导出真实存在 —— 本 PR 第 2 条的处置方向曾被它绑架。🤖 Generated with Claude Code
https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
Generated by Claude Code