Skip to content

Commit d0852dd

Browse files
refactor(metadata-protocol): move the row-less expanded view read and the own-name container expansion out of protocol.ts into protocol-view-expansion-names.ts (#25467 cut 22) (#26449)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"} --> _Requested by **Leehom** · [project thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1X7JKgiM29GUcitRvoGGj5BU)_ Part of #25467 Clause-②: no Metadata-protocol: none Ruling-ref: 6270097840 Cut 22 of the `protocol.ts` split (#24586 ruling A, recorded in `6270097840`). Cuts 1–21 landed as #25494, #25518, #25538, #25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797, #25939, #25972, #26014, #26104, #26168, #26264, #26317, #26350, #26366 and #26404. The claim is `6432922305`. The scope is the cut 22 proposal of the cut 21 report (`6432160640`), which the server seat approved in its dispatch order, with the order's condition that the read-seam census stays at 82 with an identical list. Both members passed the AST screen and the census trial, and both moved unedited. Two `ObjectStackProtocolImplementation` members move unedited into a new module, `packages/metadata-protocol/src/protocol-view-expansion-names.ts` (#23050 shape B): - `resolveRowlessExpandedView`: the by-name read's answer for a view name that no stored row holds but a stored view container expands (#21442). It is the list read's own answer by construction: the same rows, parse, expansion and selection (#21967). - `expandUnderOwnName`: the expansion of a container on another package's object under the container's own name (#21334, #21980). `protocol.ts` loses 39 net lines (29,193 to 29,154). The cut is move-only, and the card stays open for later cuts. Branch `claude/project-thread-ybjm3h` is the harness-pinned branch for this thread. It was restarted from `main` `9a0108cdc2` after cut 21 merged. It names no issue, so the claim comment is the identity record. It holds the move commit `c2087b4c49` and the merge of `main` (`95673433d1`). That merge touches no file of `packages/metadata-protocol/`: the package's `src/` tree is `ac8309b0` at the move commit and at the merge. ## Serial with the file's in-flight PRs Measured just before this PR was opened, against the merged head `95673433d1`: of the 20 open PRs, **none edits `protocol.ts`** and none names either member. Two touch `packages/metadata-protocol/src/` test files: **#26337** (3 files) and **#26138** (7 files). Each was checked with `git merge-tree`: both are clean against this head and against `origin/main` alone. No open PR edits the new module. ## The order's screen (private statics, `new Error(`, the read-seam census) Both members passed: - **No private-static read.** The AST walk found no access on the `ObjectStackProtocolImplementation` identifier and none on `this.constructor`. - **No error constructed.** Neither body has `new Error(`, so no `PRODUCERS` row is owed. - **Read-seam census** (added to the screen after cut 21). Each member was moved alone to a scratch module in a clean worktree and `check-durability-degradation-log-level --list` re-run: 82 read seams and an identical list for each. The real cut measures the same; see "The durability `--list`". ## What moves | Member | Base line | Visibility | Body lines | AST tokens (params + return + body) | |---|---|---|---|---| | `resolveRowlessExpandedView` | `:10306` | private async | 27 | 232 | | `expandUnderOwnName` | `:18159` | private | 28 | 297 | ## The shape (#23050 shape B, as cuts 1–21 apply it) - **The class keeps both members.** Each keeps its name, docblock, signature and position. Each body now delegates, marked `[#25467 cut 22]`. - **Typing.** `ViewExpansionNamesHost` types each of its six members as the class member itself (`ObjectStackProtocolImplementation['…']`). Each function types its `this` as the `Pick` of the members it reads. Each stub annotates its literal as `ThisParameterType<typeof fn>`. No member changes visibility. - **Members read, measured by AST walk** (property and element accesses on `this`, with `as` casts, parentheses and `!` stripped, and bare `this` checked too). All are methods, each handed over as a closure `(...a) => this.x(...a)`: - `resolveRowlessExpandedView` reads `readActiveOverlayRows`, `rethrowUnlessMetadataStoreUnprovisioned`, `namesWithOwnStoredRow`, `expandStoredViewContainers` and `storedOverlayEntries`. Three of these are themselves cut 16 stubs, so the call reaches `protocol-stored-overlay-reads.ts` through the class, as before. `expandStoredViewContainers` is generic (`<E …>`); its closure is contextually typed by the class member, and `tsc` accepts it with no annotation. - `expandUnderOwnName` reads `isShippedByAnotherPackage`. - **Every caller still calls the class method.** There are four `this.resolveRowlessExpandedView(` sites (`:11041`, `:11556`, `:22145`, `:27291` at base) and one `this.expandUnderOwnName(` site (`:18008`, inside `expandRuntimeViewContainer`). None changes. ## Module-level declarations, by reader Measured by an AST walk over each body's identifiers, against `protocol.ts`'s top-level declarations and import bindings (property names excluded): | Name | Where `protocol.ts` has it | Other readers in `protocol.ts` | What this cut does | |---|---|---|---| | `RowlessExpandedView` | non-exported interface, `:6254` | yes (2) | gains `export` in place; the new module imports it as a type | | `servedViewExpansion` | non-exported generic function, `:2872` | yes (2) | gains `export` in place; the new module imports it from `./protocol.js` | | `PLURAL_TO_SINGULAR` | the `@objectstack/spec/shared` import | yes (59) | stays; the new module imports it from there too | | `expandViewContainer` | the `@objectstack/spec/ui` import | yes (2) | stays; imported from there too | `index.ts` names its exports one by one, so the two in-place `export`s do not reach the published surface (cuts 8, 11, 18 and 19 did the same). The one new statement in `protocol.ts` is the import of the new module. ## The durability `--list` `check-durability-degradation-log-level` exits 0 at both ends with identical output: `82 read seam(s)` at both ends, the order's condition. Its `--list` is **identical once `[@:][0-9]+` is stripped** (158 lines, and no entry changes file). No entry of the base `--list` names either member. `resolveRowlessExpandedView`'s `try` guards `this.readActiveOverlayRows(...)`, which is already a cut 16 stub, and the gate did not count it as a read seam at base either. Its `catch` rethrows through `rethrowUnlessMetadataStoreUnprovisioned` (#5532), unedited. On the merged tree the verdict still reads `82 read seam(s)`. ## The published `.d.ts` The series bar is ruling `6348891160`: sorted-union identity, measured first, with raw identity reported when it holds. **Both hold for this cut.** Base `9a0108cdc2` and head `c2087b4c49` were built with `pnpm --filter @objectstack/metadata-protocol build` against one dependency tree. The closure was built at head by a full `pnpm build` (118/118). For the base build, the package's `src/` was swapped tree-only to base and restored from `HEAD` under a trap. Afterwards `git diff HEAD` was empty, `git status` was clean, and both touched blobs equalled `HEAD`'s. - **Normalised sha256** (the ruling's bar): `0a7694d518b570981c5cdcbcdd8fcb2dec9f1c7d74a7287299fe9e19e32a4183` at both ends, on `dist/index.d.ts` and `dist/index.d.cts`. The normaliser sorted 80 string-literal union runs. **Sorted-union identity holds.** - **Raw sha256**: `059fa1189ac13c65c36d3718584495bebaa48cc545e1526adb37cd95ef7dfaa3` at both ends, 777,645 bytes. **Raw identity holds.** - **Again on the merged tree** `95673433d1` (closure rebuilt by a full `pnpm build`, 118/118): the same raw and normalised sha256 and the same `index.js`/`index.cjs` hashes as the pre-merge head. - **The two builds differ where they should.** - `index.js` hashes `dbff5f6c5cde69ca…` at base and `14cc3ee05da5713f…` at head (`index.cjs` `919b8129becaf027…` → `c75e50d7513a93c9…`). - Each function's `.call(host` site occurs 0 times in the base bundles and once in the head bundles (ESM and CJS alike), and each `function NAME(` declaration goes 0 → 1. - **Positive control** on the head tree. `private` was dropped from `expandUnderOwnName` on disk (restored from `HEAD` under a trap) and the package rebuilt. Both `.d.ts` files move to `796c09174d25bb97…` (normalised `9f5a865eb21c4211…`, which differs from the bar's `0a7694d5…`) and print `expandUnderOwnName(type: string, object: string, container: Record<string, any>, ownPackageId: string | undefined): Record<string, unknown>[];`. So the bar can see a change on these members. - **Export tables.** The ESM and CJS bundles, loaded at runtime from the package, each export the same 78 names at base and head. The sorted list hashes to `9f18a0177ac736ed…` on all of them. None of the moved functions, `ViewExpansionNamesHost`, `servedViewExpansion` or `RowlessExpandedView` appears. No changeset: `skip-changeset`, per ruling `6348891160`. ## Proof of move-only **Bodies, by AST token.** The compare reads the TypeScript compiler's AST leaf tokens, with JSDoc skipped, over the parameters (less the added `this`), the return type and the body. It compares base `protocol.ts` at `9a0108cdc2` against the head module: ``` resolveRowlessExpandedView: base tokens 232, head tokens 232, differ 0, text-equal(ws-collapsed, comments incl.) true expandUnderOwnName: base tokens 297, head tokens 297, differ 0, text-equal(ws-collapsed, comments incl.) true TOTAL tokens=529 differ=0 members=2 CLASS members base=301 head=301 order-same=true byte-identical=299 stubs-with-identical-docblock+signature=2 other=[] TOP base=250 head=251 byte-identical=248 ``` The two top-level statements that are not byte-identical are `servedViewExpansion` and `RowlessExpandedView`, which gained `export` and nothing else. **Negative controls**, one per member, each one token changed in an in-memory copy of the head module: ``` MUTATED … "!== 'view') return undefined" -> "=== 'view') return undefined" resolveRowlessExpandedView: base tokens 232, head tokens 232, differ 1, text-equal(ws-collapsed, comments incl.) false expandUnderOwnName: base tokens 297, head tokens 297, differ 0, text-equal(ws-collapsed, comments incl.) true MUTATED … "item.name = under;" -> "item.name = ownName;" resolveRowlessExpandedView: base tokens 232, head tokens 232, differ 0, text-equal(ws-collapsed, comments incl.) true expandUnderOwnName: base tokens 297, head tokens 297, differ 1, text-equal(ws-collapsed, comments incl.) false ``` - **Class side.** There are 301 members at base and at head, in the same order. The 299 that did not move are byte-identical to base, leading comments included. Both stubs sit at their base positions and keep their docblocks and signatures byte-identical. - **Top level of `protocol.ts`.** Of the 250 base statements, 248 are byte-identical, leading comments included; the other two gained `export`. Head adds one statement, the new module's import. - **Size.** +143 / −57 over 2 files, 200 changed lines (the proposal's estimate was 200–260). `protocol-view-expansion-names.ts` has 125 lines. ## Readers of the moved lines The tests and scripts that read `protocol.ts` by path (33 files that name `protocol.ts` and call `readFileSync`) were grepped for both member names and for the bodies' text: `servedViewExpansion`, `RowlessExpandedView`, `expandViewContainer(`, `standInRows`, `underIsShipped`, `bareSpelled`. So were the test files in `packages/`, `docs/qa/` and the `@objectstack/spec` liveness ledgers. - **By path: none reads the moved bodies.** No by-path reader matches any of those strings. - **No test names either member.** The behaviour is driven through the class by the view-container expansion tests in the package suite, which pass at both ends. - **The liveness ledgers.** No row points at either member. Carried forward: `manifest.json`'s `dependencies` row → `protocol.ts#resolveWritePackageScope` (cut 19) and `seed.json` → `protocol.ts#applySeedBodies` (cut 14) still quote lines that moved to a seam module. `check:liveness` checks only that the `#symbol` is named in the file, and both stubs keep it. Re-pointing them is a `packages/spec/**` edit, outside this card. - **ADR anchors.** `check-adr-anchors` gives identical output at both ends (1,876 decision letters, 59,344 citations across 8,385 files). Neither body nor the new header cites an ADR. - **Engine-double contract** (`check-engine-double-contract`): exits 0 at both ends. The `updateData`/`deleteData` seams keep their entries at new line numbers (13898 → 13882, 13923 → 13907). `productionFiles` is 3,764 at base and 3,766 at head: the new file, and the gitignored `packages/spec/src/migrations/registry.ts` the spec build writes in the head tree (as in cuts 20 and 21). - **Identical output at both ends:** `check-adr-anchors`, `check-adr-symbol-anchors`, `check-system-context-census`, `check-tenant-audit-census`, `check-query-options-erasure-ratchet`, `check-filter-alias-parity` and `check-durability-degradation-log-level`. `check-nul-bytes` differs only in the scanned file count, +1. The base-end readings were taken in a clean detached worktree at `9a0108cdc2`. ## Verification - `tsc --noEmit` in `packages/metadata-protocol` exits 0 at head and on the merged tree. - `pnpm exec eslint --no-inline-config packages/metadata-protocol` exits 0 with no output (the whole touched package, with the root `lint` script's flags). - **`packages/metadata-protocol` suite**, base and head, compared per test name and status. Each leg ran vitest `--maxWorkers=2` with the JSON reporter under the shared verify lock. - Base `9a0108cdc2`: 21,584 tests (21,565 passed, 0 failed, 19 skipped), 271 files. - Head `c2087b4c49`: 21,584 tests (21,565 passed, 0 failed, 19 skipped), 271 files. - None lost, none added, none changed status. The base leg is the package `src/` swapped tree-only from `9a0108cdc2` (the new module removed) and restored from `HEAD` under a trap. - The merged head `95673433d1` gives the same 21,584 tests, per test identical to the pre-merge head (0 lost, 0 added, 0 changed). - `check-platform-checklist --changed-from origin/main` (merged tree): OK. 1 anchored file is in the change set, 29 anchors were judged, and 0 were lost. - **Governed surface.** `check-governed-merges --branch claude/project-thread-ybjm3h` finds 0 of 2 paths in the register (13 surfaces), so the PR is NOT governed. It has 200 changed lines, under the 3,000-line human-merge bar. - **Derived gates.** `dispatch-gates --commands --repo objectstack-ai/objectstack` derives 46 gates on 2 changed paths from the merged tree `95673433d1`, with no stale-tree warning; all 46 exit 0 after the full `pnpm build` (118/118). `dispatch-gates --ran`: 46 derived, 46 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. When this PR was opened, `main` was one commit past the merge (`ui/packages/app-shell` and a changeset), with no stale-tree warning. - `check-durability-degradation-log-level --list` on the merged tree: `82 read seam(s)`, the list identical to the pre-merge head's. ## Carry-forward These stay in `protocol.ts`: - **The read-seam members** (cut 21): a member named in a `protocol.ts` read-seam entry of `check-durability-degradation-log-level --list`, as guarded wrapper or guarding member, stays until the gate follows imported wrappers or a ruling accepts the loss. The census trial on this base measured `findEnvironmentRows` 82 → 66, `packagelessAddress` → 78, `findServedOverlayRow` → 79, and `foldStoredCollection`, `applyObjectRegistryMutation`, `unmanagedImportCollisions`, `rollBackUnmanagedImport`, `readRevertableCommit` and `storedFlowBindingAgrees` → 81. `rethrowUnlessMetadataStoreUnprovisioned` cannot move at all: moved alone, the gate exits 1 and finds 3 read seams. - Public members whose return type is inferred. - The bodies kept by a reader: `probeRecord`, `getMetaItemCached`, `findReferencesToMeta`, `refuseUnmintableMetaType`, `metaTypeNamespaceExists`, `viewContainerNameCollisionRefusal` with `overlaidShippedContainerViewNames`, `reportPageRequiresAbsentAtLoad`, the 7 `applyRegistryWriteThrough` callers, `readCodeLayerForCarryForward` and `ensureObjectStorage`. - The private-static readers: `refusePackagedBaseRemoval`, `packagedBaseRefusal`, `runPublishSideEffects`, `promoteDraftForPublish`, `publishPackageDrafts` and `discardPackageDrafts`. - The field writers: `warnClosureReadUnavailable`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 21a13f1 commit d0852dd

2 files changed

Lines changed: 143 additions & 57 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* [#25467 cut 22] Two view-container expansion members of
5+
* `ObjectStackProtocolImplementation`, moved out of `protocol.ts` whole: the
6+
* by-name read's answer for a view name no stored row holds but a stored
7+
* container expands (`resolveRowlessExpandedView`, #21442/#21967: the list
8+
* read's own rows, parse, expansion and selection), and the expansion of a
9+
* container on another package's object under the container's own name
10+
* (`expandUnderOwnName`, #21334).
11+
*
12+
* A MOVE, not a redesign. Each function below is the body of the
13+
* `ObjectStackProtocolImplementation` method of the same name as it stood,
14+
* re-indented one level and otherwise unedited: the same reads in the same
15+
* order, the same `#5532` discrimination, the same selection, and the same
16+
* names given to the expanded items.
17+
*
18+
* ## How the moved bodies reach the class
19+
*
20+
* The shape #23050 set for `rest-server.ts` (its `data-action-routes.ts`
21+
* header carries the full reasoning), as `protocol-batch-data.ts` applies it.
22+
* The class keeps both methods — the published `dist/*.d.ts` lists their
23+
* names, docblocks and declared signatures — and each body is one literal of
24+
* exactly the {@link ViewExpansionNamesHost} members it reads, each handed
25+
* over as a closure, plus a `.call`. Every other reader of either method
26+
* keeps calling the class method.
27+
*
28+
* What the bodies read of `protocol.ts`'s own module-level declarations they
29+
* import from it; what they import from elsewhere, they import from where
30+
* `protocol.ts` imported it. Nothing re-exports this module, so the published
31+
* surface does not move.
32+
*/
33+
34+
import { PLURAL_TO_SINGULAR } from '@objectstack/spec/shared';
35+
import { expandViewContainer } from '@objectstack/spec/ui';
36+
import type { ObjectStackProtocolImplementation, RowlessExpandedView } from './protocol.js';
37+
import { servedViewExpansion } from './protocol.js';
38+
39+
/**
40+
* The `ObjectStackProtocolImplementation` members the functions below read —
41+
* every one of them, and no other; a function's `this` is the `Pick` of the
42+
* members it reads. Each is typed AS the class member (an indexed access on
43+
* the class), so a change to a member's signature on the class is a change
44+
* here too, and naming a member the class does not have is a compile error.
45+
*/
46+
export interface ViewExpansionNamesHost {
47+
readonly expandStoredViewContainers: ObjectStackProtocolImplementation['expandStoredViewContainers'];
48+
readonly isShippedByAnotherPackage: ObjectStackProtocolImplementation['isShippedByAnotherPackage'];
49+
readonly namesWithOwnStoredRow: ObjectStackProtocolImplementation['namesWithOwnStoredRow'];
50+
readonly readActiveOverlayRows: ObjectStackProtocolImplementation['readActiveOverlayRows'];
51+
readonly rethrowUnlessMetadataStoreUnprovisioned: ObjectStackProtocolImplementation['rethrowUnlessMetadataStoreUnprovisioned'];
52+
readonly storedOverlayEntries: ObjectStackProtocolImplementation['storedOverlayEntries'];
53+
}
54+
55+
/** The body of `ObjectStackProtocolImplementation#resolveRowlessExpandedView`; the method's docblock there is its contract. */
56+
export async function resolveRowlessExpandedView(
57+
this: Pick<ViewExpansionNamesHost, 'expandStoredViewContainers' | 'namesWithOwnStoredRow' | 'readActiveOverlayRows' | 'rethrowUnlessMetadataStoreUnprovisioned' | 'storedOverlayEntries'>,
58+
request: { type: string; name: string; packageId?: string },
59+
): Promise<RowlessExpandedView | undefined> {
60+
if ((PLURAL_TO_SINGULAR[request.type] ?? request.type) !== 'view') return undefined;
61+
let records: any[] = [];
62+
// [#21967] Naming a package, the package-less rows in scope stand in,
63+
// read as the list scoped to that package reads them (the
64+
// package-agnostic read, filtered back to the package-less rows).
65+
let standInRows: any[] = [];
66+
try {
67+
records = await this.readActiveOverlayRows(
68+
{ type: request.type, ...(request.packageId ? { packageId: request.packageId } : {}) },
69+
);
70+
if (request.packageId) {
71+
standInRows = (await this.readActiveOverlayRows({ type: request.type }))
72+
.filter((row) => (row?.package_id ?? null) === null);
73+
}
74+
} catch (error) {
75+
// [#5532] The list read's rule: only an unprovisioned store means
76+
// "no rows". Any other failure is not answered as "nothing expands
77+
// this name".
78+
this.rethrowUnlessMetadataStoreUnprovisioned(error, 'sys_metadata');
79+
}
80+
const rows = [...records, ...standInRows];
81+
if (this.namesWithOwnStoredRow(rows, request.packageId).has(request.name)) return undefined;
82+
return servedViewExpansion(
83+
this.expandStoredViewContainers(request.type, this.storedOverlayEntries(request, rows)),
84+
request.name,
85+
request.packageId,
86+
);
87+
}
88+
89+
/** The body of `ObjectStackProtocolImplementation#expandUnderOwnName`; the method's docblock there is its contract. */
90+
export function expandUnderOwnName(
91+
this: Pick<ViewExpansionNamesHost, 'isShippedByAnotherPackage'>,
92+
type: string,
93+
object: string,
94+
container: Record<string, any>,
95+
ownPackageId: string | undefined,
96+
): Record<string, unknown>[] {
97+
const ownName = typeof container.name === 'string' && container.name !== '' ? container.name : undefined;
98+
if (ownName === undefined) return [];
99+
const under = `${object}.${ownName}`;
100+
const expandAt = under;
101+
const list = container.list;
102+
const bare = !!list && typeof list === 'object' && !(typeof list.name === 'string' && list.name !== '');
103+
const source = bare ? { ...container, list: { ...list, name: ownName } } : container;
104+
const bareSpelled = `${expandAt}.${ownName}`;
105+
const underIsShipped = this.isShippedByAnotherPackage(type, under, ownPackageId);
106+
return expandViewContainer(expandAt, source).map((vi) => {
107+
const item: Record<string, any> = { ...vi, object };
108+
const name = String(item.name);
109+
const fromBare = bare
110+
&& item.viewKind === 'list'
111+
&& item.config?.name === ownName
112+
&& name.startsWith(bareSpelled)
113+
&& /^(_\d+)?$/.test(name.slice(bareSpelled.length));
114+
if (fromBare) {
115+
const authored = { ...item.config };
116+
delete authored.name;
117+
item.config = authored;
118+
if (!underIsShipped) {
119+
item.name = under;
120+
delete item._diagnostics;
121+
}
122+
}
123+
return item;
124+
});
125+
}

‎packages/metadata-protocol/src/protocol.ts‎

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ import { resolveWritePackageScope } from './protocol-write-package-scope.js';
408408
import { readItemFromMetadataService } from './protocol-metadata-service-read.js';
409409
// [#25467 cut 21] The boot report of the stored overlay rows no read serves because they overlay sealed managed content.
410410
import { reportSealedOverlayRows } from './protocol-sealed-overlay-report.js';
411+
// [#25467 cut 22] A row-less view name's expansion for the by-name read, and a container's expansion under its own name.
412+
import { expandUnderOwnName, resolveRowlessExpandedView } from './protocol-view-expansion-names.js';
411413

412414
/**
413415
* Canonical Zod schema per metadata type lives in
@@ -2869,7 +2871,7 @@ export function addressPackages(packageId: string | undefined): ReadonlyArray<st
28692871
* stored copy of a container displaced another package's item of each name
28702872
* the copy expands, a withdrawn public form included.
28712873
*/
2872-
function servedViewExpansion<E extends { packageId: string | undefined }>(
2874+
export function servedViewExpansion<E extends { packageId: string | undefined }>(
28732875
expansions: ReadonlyArray<{ item: Record<string, unknown>; container: E }>,
28742876
name: string,
28752877
packageId: string | undefined,
@@ -6251,7 +6253,7 @@ export interface StoredOverlayEntry {
62516253
* list read serves under the name, and the stored container row it derives
62526254
* from.
62536255
*/
6254-
interface RowlessExpandedView {
6256+
export interface RowlessExpandedView {
62556257
item: Record<string, unknown>;
62566258
container: StoredOverlayEntry;
62576259
}
@@ -10306,33 +10308,15 @@ export class ObjectStackProtocolImplementation implements
1030610308
private async resolveRowlessExpandedView(
1030710309
request: { type: string; name: string; packageId?: string },
1030810310
): Promise<RowlessExpandedView | undefined> {
10309-
if ((PLURAL_TO_SINGULAR[request.type] ?? request.type) !== 'view') return undefined;
10310-
let records: any[] = [];
10311-
// [#21967] Naming a package, the package-less rows in scope stand in,
10312-
// read as the list scoped to that package reads them (the
10313-
// package-agnostic read, filtered back to the package-less rows).
10314-
let standInRows: any[] = [];
10315-
try {
10316-
records = await this.readActiveOverlayRows(
10317-
{ type: request.type, ...(request.packageId ? { packageId: request.packageId } : {}) },
10318-
);
10319-
if (request.packageId) {
10320-
standInRows = (await this.readActiveOverlayRows({ type: request.type }))
10321-
.filter((row) => (row?.package_id ?? null) === null);
10322-
}
10323-
} catch (error) {
10324-
// [#5532] The list read's rule: only an unprovisioned store means
10325-
// "no rows". Any other failure is not answered as "nothing expands
10326-
// this name".
10327-
this.rethrowUnlessMetadataStoreUnprovisioned(error, 'sys_metadata');
10328-
}
10329-
const rows = [...records, ...standInRows];
10330-
if (this.namesWithOwnStoredRow(rows, request.packageId).has(request.name)) return undefined;
10331-
return servedViewExpansion(
10332-
this.expandStoredViewContainers(request.type, this.storedOverlayEntries(request, rows)),
10333-
request.name,
10334-
request.packageId,
10335-
);
10311+
// [#25467 cut 22] The body moved to `protocol-view-expansion-names.ts` (see `ViewExpansionNamesHost`).
10312+
const host: ThisParameterType<typeof resolveRowlessExpandedView> = {
10313+
expandStoredViewContainers: (...a) => this.expandStoredViewContainers(...a),
10314+
namesWithOwnStoredRow: (...a) => this.namesWithOwnStoredRow(...a),
10315+
readActiveOverlayRows: (...a) => this.readActiveOverlayRows(...a),
10316+
rethrowUnlessMetadataStoreUnprovisioned: (...a) => this.rethrowUnlessMetadataStoreUnprovisioned(...a),
10317+
storedOverlayEntries: (...a) => this.storedOverlayEntries(...a),
10318+
};
10319+
return resolveRowlessExpandedView.call(host, request);
1033610320
}
1033710321

1033810322
/**
@@ -18162,34 +18146,11 @@ export class ObjectStackProtocolImplementation implements
1816218146
container: Record<string, any>,
1816318147
ownPackageId: string | undefined,
1816418148
): Record<string, unknown>[] {
18165-
const ownName = typeof container.name === 'string' && container.name !== '' ? container.name : undefined;
18166-
if (ownName === undefined) return [];
18167-
const under = `${object}.${ownName}`;
18168-
const expandAt = under;
18169-
const list = container.list;
18170-
const bare = !!list && typeof list === 'object' && !(typeof list.name === 'string' && list.name !== '');
18171-
const source = bare ? { ...container, list: { ...list, name: ownName } } : container;
18172-
const bareSpelled = `${expandAt}.${ownName}`;
18173-
const underIsShipped = this.isShippedByAnotherPackage(type, under, ownPackageId);
18174-
return expandViewContainer(expandAt, source).map((vi) => {
18175-
const item: Record<string, any> = { ...vi, object };
18176-
const name = String(item.name);
18177-
const fromBare = bare
18178-
&& item.viewKind === 'list'
18179-
&& item.config?.name === ownName
18180-
&& name.startsWith(bareSpelled)
18181-
&& /^(_\d+)?$/.test(name.slice(bareSpelled.length));
18182-
if (fromBare) {
18183-
const authored = { ...item.config };
18184-
delete authored.name;
18185-
item.config = authored;
18186-
if (!underIsShipped) {
18187-
item.name = under;
18188-
delete item._diagnostics;
18189-
}
18190-
}
18191-
return item;
18192-
});
18149+
// [#25467 cut 22] The body moved to `protocol-view-expansion-names.ts` (see `ViewExpansionNamesHost`).
18150+
const host: ThisParameterType<typeof expandUnderOwnName> = {
18151+
isShippedByAnotherPackage: (...a) => this.isShippedByAnotherPackage(...a),
18152+
};
18153+
return expandUnderOwnName.call(host, type, object, container, ownPackageId);
1819318154
}
1819418155

1819518156
/**

0 commit comments

Comments
 (0)