Skip to content

Commit ad24e25

Browse files
dmealingclaude
andcommitted
docs(changelog): the GET /_meta contract; test(csharp): reuse CorpusRoot in MetaEndpointTests
CHANGELOG.md's Unreleased section had no entry for the 19-commit GET /_meta + browser read-model feature. Adds one under Added covering: the per-port effective-canonical-JSON contract; the metaJson/MetaJson/metaJson/meta_json helpers and META_ROUTE_PATH in each of the five ports; that only TypeScript mounts HTTP routes (mountMetaRoute, mountMetaRouteHono) and why; the browser loadMetaModel + MetaRead surface in @metaobjectsdev/runtime-web; and the two widened TypeScript barrels (canonicalSerializeEffective off the metadata root; /constants re-exporting shared/base-types + shared/structural). MetaEndpointTests.LoadExtendsFixture hand-rolled a walk up from AppContext.BaseDirectory to find fixtures/conformance/, duplicating the CorpusRoot helper already in the same test project. Uses CorpusRoot.Path instead. dotnet test MetaObjects.Conformance.Tests: Passed! 1092/1092, compiled clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NrWUxA6euwvnFcwKxcK6A
1 parent d932fce commit ad24e25

2 files changed

Lines changed: 34 additions & 11 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,39 @@ edit (two registered `description` strings) and was ruled a hold, as 1.0.4's was
116116

117117
### Added
118118

119+
- **`GET /_meta` — a per-port metadata endpoint contract, plus a browser read-model that
120+
consumes it.** Every backend can now serve its loaded model as a single
121+
`GET {apiPrefix}/_meta` document: the response body is that port's **effective**
122+
canonical JSON (the super-chain merge already materialized) — the same serialization
123+
each port's metadata conformance corpus already pins, never the raw form, so a browser
124+
reader never has to resolve `extends` itself (per ADR-0039, an own-vs-resolving mistake
125+
there silently drops inherited `@columns`/`@pageSize`/`@sortableDefaultOrder`). Each port
126+
ships a thin, framework-free helper alongside its own `META_ROUTE_PATH` constant
127+
(`"/_meta"`): TypeScript's `metaJson(root)` (`@metaobjectsdev/runtime-ts`), C#'s
128+
`MetaEndpoint.MetaJson(MetaData root)`, Java's `MetaEndpoint.metaJson(MetaData root)`
129+
(reachable from Kotlin through the `metadata-ktx` facade), and Python's `meta_json(root)`.
130+
**Only TypeScript ships an HTTP mount** — `mountMetaRoute` (Fastify) and
131+
`mountMetaRouteHono` (Hono), both in `@metaobjectsdev/runtime-ts`: it is the only port
132+
with a web-bound runtime home, and adding a web-framework dependency to a runtime package
133+
for one endpoint would push that dependency onto every consumer of the package, including
134+
ones with no HTTP surface at all — every other port's helper is mounted by the host.
135+
Mounting is opt-in everywhere; nothing registers the route implicitly, and `/_meta`
136+
should sit behind whatever auth the rest of the API uses, since it discloses the model's
137+
shape (entities, fields, types, validators, layouts — never row data).
138+
139+
On the browser side, `@metaobjectsdev/runtime-web` ships `loadMetaModel()`, a plain
140+
structural reader (no registry, no validation, no `extends` resolution) that turns a
141+
fetched `/_meta` document into the narrow `MetaRead` / `MetaFieldRead` / `MetaLayoutRead`
142+
/ `MetaModelRead` surface the existing `buildGrid()` already consumes — so a grid built
143+
from a live document and one built from a real loaded `MetaObject` produce byte-identical
144+
output, gated by a parity suite that runs `buildGrid()` over both. Two TypeScript barrels
145+
widened to support it: the `@metaobjectsdev/metadata` package root now exports
146+
`canonicalSerializeEffective`, and its browser-safe `/constants` subpath now re-exports
147+
`shared/base-types` and `shared/structural` as well.
148+
149+
See `docs/features/metadata-api.md` for the full contract, per-port code samples, and the
150+
browser-consumption walkthrough.
151+
119152
- **Independent checks and a feature-combination gate (TypeScript, real Postgres).** Every
120153
corpus was green while the first real application found nine defects, each where two
121154
features meet, and two of them were invisible by construction: `meta verify --db` diffs

‎server/csharp/MetaObjects.Conformance.Tests/MetaEndpointTests.cs‎

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,7 @@ private static LoadResult LoadExtendsFixture()
3030
// This fixture has a BaseEntity with inherited fields (id, createdAt)
3131
// and a Subscriber that extends it, allowing us to verify the effective
3232
// serialization materializes the super-chain merge.
33-
// Walk up from AppContext.BaseDirectory to find fixtures/conformance/
34-
string root = System.AppContext.BaseDirectory;
35-
while (!System.IO.Directory.Exists(System.IO.Path.Combine(root, "fixtures", "conformance")))
36-
{
37-
var parent = System.IO.Directory.GetParent(root)?.FullName;
38-
if (parent is null || parent == root)
39-
throw new System.InvalidOperationException("fixtures/conformance not found walking up from " + System.AppContext.BaseDirectory);
40-
root = parent;
41-
}
42-
43-
var fixtureDir = System.IO.Path.Combine(root, "fixtures", "conformance", "extends-abstract-base", "input");
33+
var fixtureDir = System.IO.Path.Combine(CorpusRoot.Path, "extends-abstract-base", "input");
4434
return MetaDataLoader.FromDirectory(fixtureDir);
4535
}
4636
}

0 commit comments

Comments
 (0)