Skip to content

refactor: consume Option at render/wire boundaries / 在渲染与 wire 边界消费 Option - #118

Merged
tiye merged 1 commit into
mainfrom
fix/option-render-wire-boundaries
Oct 16, 2026
Merged

tiye merged 1 commit into
mainfrom
fix/option-render-wire-boundaries

Conversation

@tiye

@tiye tiye commented Oct 16, 2026

Copy link
Copy Markdown
Member

本次继续收敛 Timegrass 的 Option 使用:根渲染在选中的分支直接生成组件,服务端 router 保留为 Option 直到真正解码的位置。离线页、未登录路由、访客、旧笔记和现有 wire 数据格式保持不变;缺失或非法字段仍在原消费阶段报错,不替用户选择新默认值。本 PR 不升级依赖、不部署或重启生产,也不宣称 0.30.1 全部验收完成。

中文

关联 calcit-lang/calcit#2080,继续 #117 的已合并迁移。

实现与合同

  • render-app! 不再先把 Option 还原为开放中间值;选中分支直接调用原 comp-container,输出独立推断为 Component。保持 mount、根状态读取、store 读取、组件调用和 dispatch 参数的原顺序与次数。缺失状态仍交由原组件的离线/loaded 分支处理,不提前 unwrap/decode。
  • twig-container 的 router 中间变量保留 Option<Dynamic>;登录后在原位置解码 Map,仍先校验用户。只在现有 wire Map 的 router 字段恢复旧 nil/opaque 表示。
  • 给既有 prompt、递归路径读取和 wire 字段补 source doc。read-path 的空路径、非 Map 中间节点、nil key、false/0/空字符串不同于通用 throwing walker;prompt 原有 nullable 初值校验先运行,随后时间、可见文本和交互时 ID 分别在原位置校验。这些是保留的旧兼容边界,不是已完成容器精确化或可增加 Dynamic 的许可。
  • 不改变任何 schema、导入、旧测试/断言或配置。程序经 CLI transaction、dry-run 与 scoped revision 写入;独立完整 AST 对照只允许四处 subtree 改写、四项 doc 和四组新测试,其他数据与语法保持相等。私有审计工具不加入 CI 或数量门槛。

验证

  • 新回归先在原实现执行:twig 11/11、路径 3/3;同源 JS 22 组 / 111 项通过。最初两处新预期经原实现与 Alerts 源码校正:不同 router 类型保留各自完整 decoder 错误,非法非空 prompt 初值早于时间错误。没有修改旧预期或运行时来迎合测试。
  • 改后完整 fix --workflow strict --verify passed、diagnostics 为空;native 152/152、client 48/48;同源 JS 同样 22 组 / 111 项和原 host 断言通过。
  • 原 title/惰性排序/登录/容器、session/wire、typed database/隐私/持久化检查,以及 client/server codegen、Vite production build、canonical format、完整 AST 审计和 diff check 通过。所有 Node 检查使用项目要求的 Node 24。
  • 独立 type-at:根分支为 Component,confidence exact、expected null;router 输入为 Option<Dynamic>、消费结果为 Map,仍是 partial,未声称字段已全部具体化。
  • 实际浏览器使用隔离副本、同一正式依赖图与 0.30.1-alpha.4 CLI/procs、WSS 0.2.36,仅加入测试入口设置根 states 缺失及 offline store,再调用真实 render-app!。页面显示原 Socket broken! Click to retry.,控制台无 error;测试没有启动 WebSocket 或访问生产,标签和 loopback Vite 端口已关闭。
  • 既有冗余 require 标记和 bundle 大小告警仍如实保留,本 PR 未新增这些标记。

剩余门禁:本 PR 最新 HEAD CI/review;最终维护版 CLI/procs 配对发布后重跑全部消费者,以及独立的生产配对确认。此处不关闭主 issue 或 milestone。

English

Refs calcit-lang/calcit#2080 and continues merged #117.

Implementation and preserved contracts

Root rendering consumes the Option in the original component call rather than reconstructing an open intermediate value. Both selected branches return the existing Component; mount/state/store reads, component invocation and dispatch-argument evaluation retain their order and count. Missing states still reach the existing offline/loaded behavior without an earlier unwrap or decoder.

The server router binding remains Option<Dynamic> until the original logged-in Map decoder, after user validation. Its legacy nil/opaque representation is restored only when constructing the existing wire Map. Source docs explicitly distinguish retained prompt, wire and Map-only path adapters from fully typed business data. The path adapter preserves nil keys, false/zero/empty-text leaves and non-Map traversal behavior. Prompt nullable-initial validation, timestamp validation, visible text validation and interaction-only ID decoding keep their original timing.

No schemas, imports, original tests/assertions or configuration change. Snapshot writes use guarded CLI transactions. An independent full-AST comparison permits only the four reviewed subtree edits, four docs and four added regression groups; private proof scripts are not committed or made into count-based gates.

Verification

The new groups first pass against the original implementation: 11 twig and 3 path tests, plus the same 22-group/111-test JS replay. Two initial new expectations were corrected from original behavior and Alerts source: decoder messages distinguish router input types, and a non-null invalid prompt initial fails before the timestamp. No old assertion or runtime was changed to accommodate them.

After the edits, complete strict verification passes with empty diagnostics; 152 native and 48 client tests pass. The same JS replay and all original host assertions pass. Existing title/sort/login/container, session/wire and typed-DB/privacy/persistence checks, both codegen targets, production build, canonical formatting and full AST/diff audits pass using Node 24.

Independent type queries infer the root result as exact Component without an expected type. Router input remains partial Option<Dynamic> and its checked consumer remains partial Map; this is not a claim of precise field schemas.

A real-browser isolated fixture calls the actual renderer with missing root states and an offline store, using the published alpha.4 pair and formal module graph. It displays the original offline message with no console error. No WebSocket or production connection is started, and the temporary tab/loopback Vite service are closed. Existing require-marker and bundle-size warnings remain disclosed.

Latest-HEAD CI/review, final published maintenance-pair consumer acceptance and separate production pairing are still required. This PR neither deploys/restarts production nor closes the umbrella issue/milestone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant