Skip to content

refactor(types)!: reclaim natural names GestureType / GestureConfig - #3600

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3363-name-reclaims
Aug 7, 2026
Merged

refactor(types)!: reclaim natural names GestureType / GestureConfig#3600
yinlianghui merged 1 commit into
mainfrom
claude/issue-3363-name-reclaims

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #3363

承接 PR #3568 留下的反向 tripwire。@objectstack/spec 17.0.0-rc.3 整删 ui/touch/ui/offline(objectstack#4988,PR objectstack#5321),腾空了 objectstack#4115 当年为避让而改掉的三个名字。#3568page-nav-misc-spec-parity.test.ts 的三行断言反转为「spec 已腾空」,并点名本单做回收。

三个名字里回收了两个,第三个经实测不能回收 —— 详见下文,这是本 PR 与派单预期唯一的偏差。


回收(2/3)

was now 概念
TouchGestureType GestureType objectui 的方向融合识别词表(tap / swipe-left / swipe-up …)
TouchGestureConfig GestureConfig 扁平的 gesture→action 处理器绑定

形状一字未改(成员、可选性完全一致),只是名字。@object-ui/types 声明,@object-ui/mobile 再导出。

spec 侧腾空已实测确认,不是从 issue 状态推断的:

node_modules/@objectstack/spec/dist/ui/index.d.ts
  grep -oE '\b(GestureType|GestureConfig|OfflineConfig)\b'  ->  0 hit

旧名直接删除,不留 deprecated alias

派单让我「按仓库既往改名先例实测定」。先例找到了,而且就是引入这三个前缀名的那一批(objectstack#4115),packages/types/CHANGELOG.md:496 的迁移说明原文:

Migration: the old names are gone, not deprecated — an alias would preserve exactly the ambiguity being removed.

该批次的 bump 是 minor(## 17.2.0### Minor Changes),与 AGENTS.md「破坏性变更也标 minor,绝不 major」的固定版本组约定一致,本 PR 照此办理。

这条先例在本例中比一般情形更有力:这几个改名要防的歧义,本就是两个同名类型;留下 TouchGestureTypeGestureType 并存,等于一边宣称退役一边把「一个概念两种拼法」原样恢复。

SpecGestureType / SpecGestureConfigSpec… 前缀全部保留不动 —— #3568 已写明该前缀是刻意的,如今它成了区分两套 contract 的唯一依据,useSpecGesture 仍旧把一套映射到另一套。


PWAOfflineConfig 不回收 —— 派单前提在此处不成立

spec 确实也腾空了 OfflineConfig,但spec 从来不是唯一的主张者。这个改名当年是两个 objectui 包之间的跨包仲裁,而 @object-ui/react 赢了。三处仓内证据:

  1. packages/react/src/hooks/useOffline.ts:104 ——

    This name stays with @object-ui/react (objectui#3156 / objectui#3159): the OfflineConfig that used to sit in @object-ui/types was a service-worker ROUTE cache and has been renamed PWAOfflineConfig, so there is no cross-package clash.

  2. packages/react/src/hooks/__tests__/offline-nav-performance-spec-parity.test.ts:299 —— 明确称其为 "a cross-package call"。
  3. 已发布的 packages/types/CHANGELOG.md:498 —— "@object-ui/react's useOffline config remains the spec-shaped OfflineConfig, so both concepts stay reachable under distinguishable names"。

关键在于 #3568 改变了这个名字的归属方式:在此之前 @object-ui/reactOfflineConfig 是从 spec 再导出的,所以 spec 侧的断言顺带覆盖了它;#3568 按 spec 退役 ledger 的指示把它本地声明了(export interface OfflineConfig,useOffline.ts:118)。于是 spec 的腾空不再能说明这个名字是否可用 —— 它不可用。

强行回收的代价:@object-ui/types@object-ui/react 会各自公开一个语义不同的 OfflineConfig(前者是 service-worker 路由缓存 { defaultStrategy, routes, maxCacheSize },后者是离线数据/同步模型 { strategy, cache, sync, queueMaxSize },连大小写风格都不同 —— kebab-case vs snake_case),而这两个包是常常一起被 import 的。这正是 objectstack#4115 当初把它改走的那个歧义,也正是「让 AI 写的代码不容易出错」最怕的形状:两个同名、字段相似、都合法的类型。

因此把理由从散文改成了机器校验的钉子。 page-nav-misc-spec-parity.test.ts 新增一条断言:@object-ui/react 仍然声明 OfflineConfig。若它哪天改名或消失,该断言变红,失败信息直接告诉下一位读者「回收现在可以做了」—— 解锁信号从此指向正确的仓库,而不是指向 spec。

注:该断言用 readFileSync 读取兄弟包源码,不是 import —— @object-ui/types 必须保持零依赖。同目录的 spec-ui-schema-reexports.test.ts 用的是同一种工具。


tripwire 的处置(逐条,非批量重拼)

断言 处置
GestureType / GestureConfig 两行 保留断言方向,改写标题与失败信息。改前改后都是绿的 —— 见下文「反向验证」对这一点的诚实说明。
OfflineConfig 移出「已腾空,可回收」块,替换为上述 @object-ui/react 归属钉。
「spec 不拥有 TouchGestureType / TouchGestureConfig」两行 删除。这两个名字已不存在;其覆盖面已被上面改写后的两行完全承接(断言的正是同一件事:spec 不得拥有该名)。
「spec 不拥有 PWAOfflineConfig 不动。

顺带:#3362 残余两行(objectstack#5015)

spec-ui-schema-reexports.test.tsDROPPED_SCHEMA_EXPORTS 删去 NotificationActionSchema / EmbedConfigSchema。该列表是「objectui 刻意不再导出的 spec/ui zod schema」拒绝名单;objectstack#5015 / PR objectstack#5300 把这两个 def 整个退役后,spec 已不发布这两个名字,断言退化为恒真(没有东西能再导出它)。实测确认:

'NotificationActionSchema' in require('@objectstack/spec/ui')  ->  false
'EmbedConfigSchema'        in require('@objectstack/spec/ui')  ->  false
'SharingConfigSchema'      in require('@objectstack/spec/ui')  ->  true   (对照:仍是真守卫,保留)

验证

全部在共享 heavy-verify 锁下串行执行,4 GB heap cap。

命令 结果
消费者全量清扫 git grep 'TouchGestureType|TouchGestureConfig|PWAOfflineConfig' 全仓 见下表,逐条处置
受影响包 type-check pnpm --filter types/mobile/react/core type-check 4/4 Done
全仓 type-check pnpm type-check 78 successful, 78 total(与 #3568 基线一致)
三个关键测试 vitest run (tripwire / gesture parity / reexports) 52 passed
受影响包全量测试 vitest run packages/types packages/mobile 31 files, 405 passed
lint pnpm --filter types/mobile lint 0 errors(18 warnings 均在未触碰的 useOfflineSync.ts,先前既有)
控制字节 node scripts/check-control-bytes.mjs OK,3637 files
changeset no-major node scripts/check-changeset-no-major.mjs OK
changeset fixed group node scripts/check-changeset-fixed.mjs OK

消费者逐条处置

位置 处置
types/src/mobile.ts 声明 ×2 + GestureContext.type + MobileComponentConfig.gestures 改名
types/src/index.ts 导出块 改名
mobile/src/index.ts 再导出 改名
mobile/src/useGesture.ts ×2 改名
mobile/src/useSpecGesture.ts ×4 改名;另修正两处因改名而产生歧义的注释(裸 GestureType 现在指本地类型)
mobile/src/MobileProvider.tsx ×3(PWAOfflineConfig) 不动 —— 该名不回收
react/.../offline-nav-performance-spec-parity.test.ts:302react/.../useOffline.ts:108 提及 PWAOfflineConfig 不动,且仍然准确(若回收则这两处需改,已越出本单文件面 —— 是不回收的又一佐证)
各包 CHANGELOG.md 不动 —— 历史记录

反向验证(先声明预期方向,再执行)

改名类变更没有 before-green/after-red 的通用方向,照实说明存在哪几种:

  1. 新增的 @object-ui/react 归属钉 —— 预期 RED,实测 RED。useOffline.tsexport interface OfflineConfig 改名为 OfflineDataConfig:

    × `@object-ui/react` still owns `OfflineConfig`, so `PWAOfflineConfig` keeps its prefix (objectui#3363)
    AssertionError: …/useOffline.ts no longer declares 'export interface OfflineConfig'. If the name
    was dropped or moved, the cross-package reason for 'PWAOfflineConfig' is gone — … the natural
    name is now free and @object-ui/types' mobile module may reclaim it …
    

    这条最要紧:新钉子的全部价值就在于它会响,且响的时候直接交出解锁指令。已还原。

  2. 旧名不得残存 —— 预期 RED,实测 RED。 在消费者里种回旧拼法(import type { TouchGestureType as GestureType }):

    src/useGesture.ts(10,15): error TS2724: '"@object-ui/types"' has no exported member named
    'TouchGestureType'. Did you mean 'GestureType'?
    

    这同时机械证明了「不留 alias」的决定确实落实 —— 若留了 deprecated alias,这一步会是绿的。已还原。

  3. 被改写的两行 tripwire —— 诚实说明:此处不存在方向翻转。 GestureType/GestureConfig 两行在 chore(deps): track the @objectstack family at 17.0.0-rc.5 and restore green #3568 之后就已经是绿的(spec 当时已腾空),本 PR 之后仍是绿的;变的是断言的含义而非判定:此前它守的是一个潜在冲突(当时没有任何包导出 GestureType),现在它守的是一个实际冲突(@object-ui/types 真的导出了这个名字)。制造一个「改前红」需要伪造 spec 的导出集,那只会验证测试框架而非本变更,故不做。这一点如实记录,不套模板。


越界记录:发现但

DROPPED_SCHEMA_EXPORTS 剩余 82 条里,还有 37 条与本次删掉的两条同类(spec 已不发布该名,断言恒真),绝大多数来自 objectstack#4988 那五个交互模块。已按 Prime Directive #10 另行立单(observation-class,finding,不带 pm:queue),不在本 PR 修 —— 本单文件面只覆盖 #3362 残余点名的那两条。


Draft —— 待远端 CI 全绿后再转 ready。

Generated by Claude Code


Generated by Claude Code

…3363)

`@objectstack/spec` 17.0.0-rc.3 deleted the whole `ui/touch` module
(objectstack#4988, PR objectstack#5321), vacating three names objectui had
renamed away from in objectstack#4115 purely to avoid a collision. The
inverted tripwire PR #3568 left in `page-nav-misc-spec-parity.test.ts` fired
and named this card as the follow-up.

Two of the three workarounds have outlived their reason and are undone:

  TouchGestureType   -> GestureType
  TouchGestureConfig -> GestureConfig

Old names are gone, not deprecated, following the precedent of the
objectstack#4115 batch that introduced them: "an alias would preserve exactly
the ambiguity being removed". The retired spec vocabulary keeps its `Spec…`
prefix, which is now the only thing distinguishing the two contracts.

`PWAOfflineConfig` is deliberately NOT reclaimed. The spec vacated
`OfflineConfig` too, but the spec was never its only claimant: that rename
was a cross-package arbitration between two objectui packages and
`@object-ui/react` won it. Since #3568 declared it locally, the spec's
vacancy no longer says anything about whether the name is free -- it is not.
The tripwire now pins the `@object-ui/react` owner directly, so that reason
cannot expire unnoticed either.

Also removes two inert `DROPPED_SCHEMA_EXPORTS` entries whose spec-side names
objectstack#5015 retired (#3362 residue).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 7, 2026 3:25pm

Request Review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 28.1 KB 350 KB
Entry file index-CVz6ARkO.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.66KB 3.13KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 480.72KB 105.64KB
core (index.js) 2.96KB 1.13KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 137.51KB 35.11KB
fields (index.js) 230.87KB 56.83KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.65KB 1.06KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 9.48KB 3.27KB
i18n (useObjectLabel.js) 26.14KB 6.07KB
i18n (useSafeTranslation.js) 4.52KB 1.96KB
layout (index.js) 38.53KB 10.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.98KB 12.37KB
plugin-charts (index.js) 61.04KB 17.31KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 112.03KB 28.88KB
plugin-designer (index.js) 210.51KB 42.51KB
plugin-detail (index.js) 232.79KB 57.42KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 112.10KB 27.10KB
plugin-gantt (index.js) 162.55KB 39.57KB
plugin-grid (index.js) 186.61KB 49.34KB
plugin-kanban (index.js) 48.30KB 13.28KB
plugin-list (index.js) 105.12KB 25.48KB
plugin-map (index.js) 16.81KB 5.24KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 40.58KB 10.58KB
plugin-timeline (index.js) 25.76KB 7.33KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.03KB 20.55KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 2.71KB 1.34KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@yinlianghui
yinlianghui marked this pull request as ready for review August 7, 2026 15:30
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 7, 2026
Merged via the queue into main with commit e6fdbdc Aug 7, 2026
19 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3363-name-reclaims branch August 7, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants