Skip to content

Commit af3451b

Browse files
refactor(objectql): move the find and findOne bodies into the find facet through the facade port (E2) (#31116)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSiP9RS1KjicEPyef7VNhFzFa)_ domain:server#2 · marchtian · session_017ihL2fL8RrJDkowuFhXUPG Refs #30020 Clause-②: no Metadata-protocol: none Skills-docs: none — an internal move inside `@objectstack/objectql`; nothing a metadata author writes changes ## 维护者速读 - 改了什么:用 `scripts/codemod-split-engine.mjs --members find,findOne` 把 `ObjectQL` 的 `find` 和 `findOne` 两个方法体搬进已有的 `engine-find.ts` facet,类上只留一行委托桩(签名和 docblock 原样保留);同时删掉登记表里这两行例外(19 → 17)。这是 #30020 §5 系列的 E2,codemod 本身一行没改。 - 为什么改:#30020 要把门面类剩下的例外行换成委托,让 `engine.ts` 继续变小(11,111 → 10,739 行)。这两个方法体把引擎本身交给钩子(`ql: this`),按规则 A 改读宿主的 `facade` 端口。 - 风险与回滚:纯搬移,运行时行为不变。撤销证明逐字节通过;`@objectstack/objectql` 的三个公开 `.d.ts` 与 main 构建结果逐字节相同。回滚即 revert 本 PR。 - 先看:`packages/objectql/src/engine-find.ts` 的 `FindHost` 接口与 `ql: this.facade` 两处;`packages/objectql/src/engine.ts` 的 `find` / `findOne` 桩和 `findHost` 安装行;`scripts/facade-delegation-registry.json`。 - 两分钟验证:`node scripts/codemod-split-engine.mjs --members --verify --base origin/main` 预期 exit 0,输出 “2 moved method(s) (find, findOne); engine.ts 11111 -> 10739 lines; undoing the moves does rebuild the base … byte-for-byte”。 - 需要你做的:无,席位落地。 ## What changes - **The move (E2 of the #30020 §5 order).** `node scripts/codemod-split-engine.mjs --members find,findOne --write` on `main` `5f0037449`. Both bodies move into `packages/objectql/src/engine-find.ts`, the facet that already holds their read helpers (`requireFindOnePredicate`, `reportFindFailure`); no new module. The stubs, the `FindHost` members, the host factory entries and the imports are the codemod's own output; nothing was hand-edited. - `find` and `findOne` stay on the class with their docblocks and signatures byte for byte; only `async` is dropped from the stub, as every stub of the series does. Each is `return FindFacet.X.call(findHost.of(this), …)`. - Each body handed the engine itself into its hook context (`ql: this`). Under rule R1 that reads `ql: this.facade`, and `FindHost` gains the `readonly facade: ObjectQL` port with its docblock, plus a `facade: engine` install entry. - 19 import bindings only the moved bodies read leave `engine.ts` (the prune the proof recomputes). - **`scripts/facade-delegation-registry.json`**: the `find` and `findOne` rows (`#30020`, `bare-this`) are removed; nothing added. Exceptions 19 → 17; `engine.ts`'s `#30020` rows left: `update`, `insert`, `delete`, `constructor`, `[SEED_USER_GRANTS]`, `transaction`. - **`.changeset/30020-objectql-find-findone-facet.md`**: `@objectstack/objectql` patch (source maps ship), the two declaration lines in its body. - **Anchors repointed (patch round, `8c46a17a83`):** the move pruned three import bindings from `engine.ts` that evidence anchors named. `packages/spec/liveness/query.json` (`query.fields` → `engine-top-level.ts#planFormulaProjection`; `query.top` → `engine-top-level.ts#ENGINE_QUERY_SLOTS` and `engine-find.ts#foldEngineOptionAliases`, each row's note dated) and `docs/qa/platform-checklist/areas/api-backend.json` (`engine-top-level.ts#applyFormulaPlan`). Anchor text only, same precedent as #30415 and #30838; the changeset adds `'@objectstack/spec': patch` because `liveness/` ships in its `files[]`. These two files are outside the original claim surface; the seat amended the claim (6707298150). The red this fixed: Test Core (2/8), `packages/spec/scripts/liveness/evidence.test.ts` "every local path#symbol anchor names a symbol its file contains". - **Not changed:** `scripts/codemod-split-engine.mjs`. E2 needs no capability E1 did not ship. ### Rules applied (reconstructed) The previous seat's `design.md` (R1–R7, H2) is not reachable from this seat. The rules below are rebuilt from the card's design comment 6677924765, ruling 6687865760 and PR #30987's body. - **Ruling A (6687865760):** the facade stays the sole state owner. No field moves; the facet reaches state through its host. - **R1, the identity port (#30987):** a bare `this` a moved body hands on becomes `this.facade`. Two sites here, `ql: this.facade` in `find`'s and `findOne`'s hook contexts. This is the only rule E2 exercises. - **R3 (computed field keys), R4 (a name `engine.ts` exports) and H2 (`--hand-slots`):** not reached. The plan asked for none of them and wrote no `this[k]` host access, no `./engine.js` value import and no hand-slot move. - **R7:** deferred to E6 by #30987, its only caller; not reached. - **R2, R5, R6:** their numbering is not recoverable from the comments. The design comment lists the other smaller rules (constructor, symbol-keyed members, another instance's private write); none applies to these two bodies, and the codemod's plan named no stay reason for either. - **Docblock rule (first pass):** a public method keeps its docblock on the class. Both members are public, so no docblock moved and the `.d.ts` stays byte-equal. (#30987's `.d.ts` delta came from private docblocks; there are none here.) - **Stop condition (the dispatch order):** not hit. Neither body needed any edit beyond `this` → `this.facade`. ## Tests No test file changes: a byte-proven move with no behaviour change. The suites run unchanged against the moved bodies. ## Acceptance notes - `.d.ts`: byte-equal at base and head. This is stronger than #30987, which lost 83 lines of private docblocks from the shared chunk. - Contract review: none owed for a byte-proven move with no surface change, per the series' standing note (6690792197); the seat decides. - The series continues with E3 (constructor) after this lands. ## Verification All readings are at head `df1ae02829`, whose base is `origin/main` `5f0037449` (`main` had not moved when the PR opened). <details><summary>Undo proof (byte-exact) and determinism</summary> - `node scripts/codemod-split-engine.mjs --members find,findOne --write`: exit 0. Output tree sha256 `5e6887d1e3d389d599d28d3ac70e4a8db35f0bd36232cf254bd24f9266220020`, input sha256 `4e979556f4ab17da5c087a435bb5bf56928d025ea3eaabe191ed99542c4f43a1` (= `git show 5f00374:packages/objectql/src/engine.ts | sha256sum`). The plan-only run before it printed the same output sha256. - `node scripts/codemod-split-engine.mjs --members --verify --base origin/main` on the committed head: exit 0. "undo proof: 2 moved method(s) (find, findOne); engine.ts 11111 -> 10739 lines; undoing the moves does rebuild the base engine.ts and its modules byte-for-byte once the 19 import binding(s) only moved bodies read are pruned from the base (ENGINE_FIND_OPTION_KEYS, ENGINE_QUERY_SLOTS, ENGINE_WIRE_ONLY_SLOTS, FindHookResultNotArrayError, FindOneHookResultNotRecordError, PLATFORM_PROVISIONED_COLUMNS, applyFormulaPlan, assertOrderByIsMaterializable, assertProjectionHasNoDottedPaths, assertProjectionNamesAField, isFindOneResultShape, mergeReadContext, planFormulaProjection, refuseProjectionOfUnknownColumns, rejectInternalFieldEvaluation, rowsWithSelectedColumnsAnswered, rowsWithoutFormulaWidening, withFileOwnerKey, withoutFormulaWidening)". - File hashes: `engine.ts` base `4e979556…` → head `9f090702…`; `engine-find.ts` base `76b336ec…` (476 lines) → head `5bfcb0a4…` (910 lines). - `node scripts/codemod-split-engine.mjs --self-test`: exit 0, 169 cases in 11 batteries. </details> <details><summary>Public declaration files</summary> `@objectstack/objectql` built with `pnpm --filter @objectstack/objectql build` with the two source files at base `5f0037449`, then at head. `dist/core.d.ts` (`a8fd9093…`), `dist/index.d.ts` (`3a798237…`) and `dist/util-BK7LVy6k.d.ts` (`24ed9187…`) are byte-equal: `diff -r` is empty, and the chunk hash itself does not change. Control: the stub's text, matched by the regex `\.find\.call\(findHost\.of\(this\)`, occurs 0 times in the base `dist/index.mjs` and once in the head's. </details> <details><summary>Package suites and gates</summary> - `pnpm --filter @objectstack/objectql typecheck` (tsc plus `check:test-typecheck`) and `pnpm --filter @objectstack/objectql test`, under `os-verify-lock`: VERDICT command-exit 0. Test Files 564 passed (564), Tests 11422 passed (11422). - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `8c46a17a83`: 76 families (the anchor files add `check:liveness` and `check:platform-checklist` among others), all 76 exit 0, `--ran` 76/76, 0 NOT-MEASURED; `evidence.test.ts` 48/48. At `df1ae02829`: 66 families, all 66 exit 0. Two first answered exit 3 on prerequisites and were re-run once those were met: `node scripts/check-plugin-teardown-shape.mjs --self-test` needed a non-shallow clone (`git fetch --unshallow`), 48 cases pass; `pnpm check:dual-build-cjs-loads` needed every `dist/` (`pnpm build`, 119 tasks, exit 0), 116 entry points across 71 packages load. `--ran` at `df1ae02829`: 66 derived, 66 run, 0 NOT-MEASURED, 0 UNRUN. - Outside the derived set: `pnpm check:facade-delegation-only` exit 0 (17 named exceptions); `node scripts/check-facade-delegation-only.mjs --self-test` exit 0 (37 cases); `pnpm lint` exit 0. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_017ihL2fL8RrJDkowuFhXUPG)_ <!-- signed: domain:server#2 · marchtian · session_017ihL2fBJ6xsLWJsnNJGMMx --> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent cadd6aa commit af3451b

6 files changed

Lines changed: 497 additions & 436 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@objectstack/objectql': patch
3+
'@objectstack/spec': patch
4+
---
5+
6+
refactor(objectql): the `ObjectQL#find` and `ObjectQL#findOne` bodies move into the find facet
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
- The bodies of `find` and `findOne` move out of `engine.ts` into `engine-find.ts`, the facet that already holds their read helpers. Each method stays on the class as a one-call stub with its signature and its docblock. Where a body handed the engine itself on (`ql: this` in the before/after hook context), it reads the same engine through the host's `facade` entry.
12+
- No behaviour changes and nothing to do on upgrade. The built declaration files keep every member and every docblock; the source maps move.
13+
- The `query.fields` and `query.top` liveness rows in `@objectstack/spec` now cite `engine-top-level.ts`, where `planFormulaProjection` and `ENGINE_QUERY_SLOTS` are declared, and `engine-find.ts`, where the `find` / `findOne` bodies fold the `top` alias, since `engine.ts` no longer imports those names; the evidence they cite is unchanged.

‎docs/qa/platform-checklist/areas/api-backend.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2264,7 +2264,7 @@
22642264
"packages/formula/src/stdlib.ts#registerStdLib (registerStdLib — the 29 chained registerFunction calls, isoDate / isoDatetime since #22347, plus label(), the macro bindOptionLabel registers (#26608): 30 bare-callable; the receiver methods `can` and `hasCapability`, from bindPermissionPredicate and bindCapabilityPredicate, are outside the count; calendarDayUtc ADR-0053 D1; addMonthsUtc clamp; the floor/ceil #3306 note), (registerNumericCoercions #1928)",
22652265
"packages/formula/src/validate.ts#CEL_STDLIB_FUNCTIONS (the advertised bare-callable list; its docblock tallies the 30 registerStdLib adds and why a receiver-only name such as `can` is never in it)",
22662266
"packages/lint/src/authoring-rules.ts#EXPRESSION_INVALID (the expression-invalid rule the object save door now dispatches on a formula field, #22031) + packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts (the #22019 block: sqrt(record.amount) refused 422 INVALID_METADATA on an active save and on a draft's promotion, nothing lands) + packages/lint/src/runtime-gate.object-formula-writes.test.ts + packages/objectql/src/engine-formula-fault-log.test.ts (the read-path residual: a pre-gate row still reads null, one warn line per object and field)",
2267-
"packages/objectql/src/engine.ts#applyFormulaPlan (applyFormulaPlan — evaluate-fault → null, the silent-null contract; the evaluateFormulaField docblock states the compile-throws vs evaluate-nulls split)",
2267+
"packages/objectql/src/engine-top-level.ts#applyFormulaPlan (applyFormulaPlan — evaluate-fault → null, the silent-null contract; the evaluateFormulaField docblock states the compile-throws vs evaluate-nulls split)",
22682268
"content/docs/data-modeling/formulas.mdx (the advertised catalog the matrix cross-checks)",
22692269
"examples/app-showcase/src/data/objects/field-zoo.object.ts + project.object.ts (the stock live-leg formulas)",
22702270
"ADR-0053 Phase 2 D1 (calendar-day timezone contract)",

0 commit comments

Comments
 (0)