You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Pre-launch review found the newcomer quickstarts broken as written and ~8 docs
under-claiming shipped features (Java/Kotlin/Python route+filter+payload-VO+output-parser
codegen, Python ObjectManager, C# NuGet publication) while adjacent files said "shipped".
Code was verified solid; only the docs were wrong.
Newcomer-critical (re-ran every corrected snippet for real):
- typescript.md: fixed the flagship "Use" example (real flat path/authorRoutes/Fastify-plugin
shape) + documented the working `meta migrate --from-db ... --apply` init path (baseline
silently no-ops for a new project) + db.ts wiring + fastify/ESM/tsconfig notes.
- python.md: fixed the loader-API "Use" example (real imports + root.children()/get_meta_attr),
the broken `python -m` gen/verify commands (→ metaobjects console-script), the providers
example, @DataClass→BaseModel, pydantic/fastapi + 3.11+ notes, ObjectManager "roadmap"→shipped.
- server/python/README.md (PyPI page): removed the false `migrate`-module + SQLAlchemy claims.
Underclaim/self-contradiction sweep (verified each flip against source):
- README matrix, api-contract.md (self-contradicted 4×), csharp.md (NuGet 0.19.3), java.md,
entities.md, templates-and-payloads.md, migrations-and-drift.md, typescript-client.md,
llms-full.txt, docs/README.md — now accurately reflect the shipped state.
Refs the pre-launch review (.superpowers/sdd/launch-review-*.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeGSV3StPCcJGZNNJ4ZfAb
Copy file name to clipboardExpand all lines: README.md
+9-8Lines changed: 9 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -88,7 +88,7 @@ first-week wedge plan — and `meta init` picks up from there.
88
88
|---|---|---|---|
89
89
| TypeScript | Published to npm at `0.19.3` (the `@metaobjectsdev/*` packages) |[`docs/ports/typescript.md`](docs/ports/typescript.md)|[`server/typescript/`](server/typescript/) · [`client/web/`](client/web/)|
90
90
| Java | Loader + OMDB + render + Maven plugin all shipped; full conformance green |[`docs/ports/java.md`](docs/ports/java.md)|[`server/java/`](server/java/)|
91
-
| Kotlin | Codegen tier on top of Java — 7 generators (entity, Exposed table, relations, payload, validator, Spring config, storedProc); 12 / 12 persistence-conformance |[`docs/ports/kotlin.md`](docs/ports/kotlin.md)|[`server/java/codegen-kotlin/`](server/java/codegen-kotlin/) · [`server/java/metadata-ktx/`](server/java/metadata-ktx/)|
91
+
| Kotlin | Codegen tier on top of Java — 9 generators (entity, Exposed table, relations, payload, output-parser, validator, Spring config, storedProc, Spring controller); 12 / 12 persistence-conformance |[`docs/ports/kotlin.md`](docs/ports/kotlin.md)|[`server/java/codegen-kotlin/`](server/java/codegen-kotlin/) · [`server/java/metadata-ktx/`](server/java/metadata-ktx/)|
92
92
| C# | Loader + conformance + EF Core codegen + render engine + `dotnet meta` CLI all shipped |[`docs/ports/csharp.md`](docs/ports/csharp.md)|[`server/csharp/`](server/csharp/)|
| React / UI client (browser) | Yes (`@metaobjectsdev/react` + `@metaobjectsdev/tanstack`; codegen + runtime)| Consumes TS client via REST | Consumes TS client via REST | Consumes TS client via REST | Consumes TS client via REST |
113
-
| Cross-port REST routes for the client | Generated (`routesFile()` → Fastify) |Hand-write Spring controller per contract|Hand-write Spring-Kotlin / Ktor per contract | Generated (`RoutesGenerator` → ASP.NET Minimal API) |Hand-write FastAPI router per contract|
112
+
| React / Angular UI client (browser) | Yes — React (`@metaobjectsdev/react` + `@metaobjectsdev/tanstack`) and Angular 18 (`@metaobjectsdev/angular`, published at `0.6.0`); both codegen + runtime | Consumes TS client via REST | Consumes TS client via REST | Consumes TS client via REST | Consumes TS client via REST |
113
+
| Cross-port REST routes for the client | Generated (`routesFile()` → Fastify) |Generated (`SpringControllerGenerator` → Spring `@RestController`, incl. filter/sort)|Generated (`KotlinSpringControllerGenerator` → Spring `@RestController`, incl. filter/sort) | Generated (`RoutesGenerator` → ASP.NET Minimal API) |Generated (`router_generator` → FastAPI `APIRouter`, incl. filter/sort)|
114
114
115
115
A "Yes" means the feature is covered by the shared conformance corpora at
116
116
[`fixtures/`](fixtures/) for that port, or by a port-local test of equivalent
117
117
scope. A "partial" means the loader recognizes the metamodel feature but the
118
118
codegen / runtime tier doesn't fully exercise it yet.
119
119
120
-
The React / UI client is TypeScript-only by construction (the browser is
121
-
TS-native) but is**universal** — see
120
+
The React and Angular UI clients are TypeScript-only by construction (the
121
+
browser is TS-native) but are**universal** — see
122
122
[`docs/features/api-contract.md`](docs/features/api-contract.md) for the
123
123
URL grammar + wire format the client speaks, and
124
124
[`docs/ports/typescript-client.md`](docs/ports/typescript-client.md) for
125
-
the consumer-side wiring.
125
+
the consumer-side wiring (React + TanStack, and the
If this list and `ls docs/features/` ever disagree, trust the directory listing —
51
+
this tree is documentation, not the source of truth.
52
+
40
53
## When to read which
41
54
42
55
| You want to … | Read |
@@ -48,7 +61,7 @@ docs/
48
61
| Wire prompt construction (FR-004) |[`features/templates-and-payloads.md`](features/templates-and-payloads.md)|
49
62
| Share a metadata shape across multiple instances (abstracts, `extends:`) |[`features/abstracts-and-inheritance.md`](features/abstracts-and-inheritance.md)|
50
63
| Add a custom metamodel subtype or attribute to a downstream project |[`features/extending-with-providers.md`](features/extending-with-providers.md) + [`recipes/extending-metaobjects-with-providers.md`](recipes/extending-metaobjects-with-providers.md)|
51
-
| Wire the universal browser client (React + TanStack) to any backend |[`ports/typescript-client.md`](ports/typescript-client.md) + [`features/api-contract.md`](features/api-contract.md)|
64
+
| Wire the universal browser client (React + TanStack, or Angular 18) to any backend |[`ports/typescript-client.md`](ports/typescript-client.md) (see [§Angular 18](ports/typescript-client.md#angular-18) for the Angular tier) + [`features/api-contract.md`](features/api-contract.md)|
52
65
| Know which feature is supported in which port today | the capability matrix in the root [`README.md`](../README.md) or the per-port "Capability snapshot" table |
53
66
| See which conformance fixtures gate each feature (and which port passes which) |[`CONFORMANCE.md`](CONFORMANCE.md)|
54
67
| Read the canonical spec (target-agnostic) |[`../spec/`](../spec/)|
the entity-constants file, so the client and the server agree on the
73
73
path segment without hand-coordination.
74
74
75
-
### Filter operators (8)
75
+
### Filter operators (9)
76
76
77
77
Filters use a **bracketed qs** shape: `filter[<field>][<op>]=<value>`.
78
78
A bare value (`filter[<field>]=<value>`) is sugar for `eq`. Multiple
@@ -90,12 +90,12 @@ filters AND together.
90
90
The operator set is gated by field subtype in the generated
91
91
`<Entity>FilterAllowlist`. A request with an operator that the field
92
92
subtype doesn't support → HTTP 400. The operator list is a Tier 1
93
-
cross-port invariant — every port's parser must implement these eight
94
-
and only these eight.
93
+
cross-port invariant — every port's parser must implement these nine
94
+
and only these nine.
95
95
96
96
### TS-only filter extensions (not part of the cross-port contract)
97
97
98
-
The TypeScript runtime parser ships five filter behaviors beyond the eight
98
+
The TypeScript runtime parser ships five filter behaviors beyond the nine
99
99
operators. They are **NOT part of the cross-port REST contract** — the other
100
100
ports (Java, Kotlin, Python, C#) do not implement them, and a relying adopter
101
101
must not assume them on a non-TS backend. They are deliberately deferred until
@@ -191,17 +191,20 @@ retryable / log-only.
191
191
|---|---|---|
192
192
| TypeScript | shipped — `@metaobjectsdev/codegen-ts``routesFile()` → Fastify (`@metaobjectsdev/runtime-ts/drizzle-fastify`) AND `routesFileHono()` → Hono (`@metaobjectsdev/runtime-ts/hono`) | Reference implementation; full filter/sort + `withCount` support. Both flavors emit byte-identical on-the-wire responses for the same metadata (same envelopes, same status codes, same filter operator parser), so consumers can pick the server framework that matches their runtime (Fastify for long-lived Node, Hono for Workers / Bun / edge). |
193
193
| C# | shipped — `MetaObjects.Codegen``RoutesGenerator` → ASP.NET Minimal API |`MapGet` / `MapPost` / `MapPut` / `MapDelete` mounted under `apiPrefix`; full CRUD. |
194
-
| Java | shipped — `metaobjects-codegen-spring``SpringControllerGenerator` + `SpringDtoGenerator` + `SpringRepositoryGenerator` → Spring `@RestController` (Spring Boot 3.x / Spring Web MVC) | One controller per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH + PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Java 21 record DTOs for request/response; a stubbed `<Entity>Repository` interface the consumer implements against their persistence layer (JPA / jOOQ / JDBC). Filter operators (`eq/ne/...`) deferred — see the module's `KNOWN_GAPS.md`. |
195
-
| Kotlin | shipped — `metaobjects-codegen-kotlin``KotlinSpringControllerGenerator` → Spring `@RestController`| One controller per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH+PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Filter operators (`eq/ne/...`) deferred. |
196
-
| Python | shipped — `metaobjects.codegen.generators.router_generator` → FastAPI `APIRouter`| One router per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH+PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Consumer wires the repository via FastAPI `app.dependency_overrides`; the generator emits a `Protocol` interface so the persistence layer (SQLAlchemy / asyncpg / etc.) is the consumer's choice. Filter operators (`eq/ne/...`) deferred — see the module's `KNOWN_GAPS.md`. |
194
+
| Java | shipped — `metaobjects-codegen-spring``SpringControllerGenerator` + `SpringDtoGenerator` + `SpringRepositoryGenerator` → Spring `@RestController` (Spring Boot 3.x / Spring Web MVC) | One controller per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH + PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Java 21 record DTOs for request/response; a stubbed `<Entity>Repository` interface the consumer implements against their persistence layer (JPA / jOOQ / JDBC). Filter operators (`eq/ne/gt/gte/lt/lte/in/like/isNull`) ship via the generated `<Entity>FilterAllowlist` (`SpringFilterAllowlistGenerator`) + the runtime `FilterParser`, wired directly into the list handler. |
195
+
| Kotlin | shipped — `metaobjects-codegen-kotlin``KotlinSpringControllerGenerator` → Spring `@RestController`| One controller per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH+PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Filter operators ship via the generated `<Entity>FilterAllowlist` (`KotlinFilterAllowlistGenerator`) + an inline `parse<Entity>Filter` helper emitted in the controller. |
196
+
| Python | shipped — `metaobjects.codegen.generators.router_generator` → FastAPI `APIRouter`| One router per writable entity (`source.rdb @kind="table"`); 5 CRUD endpoints (GET list / GET by id / POST / PATCH+PUT / DELETE); `?sort`, `?limit/?offset`, `?withCount=1` envelope, 404 + 400 envelopes per the contract. Consumer wires the repository via FastAPI `app.dependency_overrides`; the generator emits a `Protocol` interface so the persistence layer (SQLAlchemy / asyncpg / etc.) is the consumer's choice. Filter operators ship via the generated `<entity>_filter_allowlist.py` (`filter_allowlist_generator.py`) + the shared `filter_parser` helper, wired into the list handler. |
197
197
198
-
## Hand-writing a conforming controller
198
+
## Hand-writing a conforming controller (if you outgrow the generated one)
199
199
200
-
While the planned route-codegen work matures, here is the minimum
201
-
controller needed to make `useAuthors`, `useAuthor`, etc. work against
202
-
each non-TS / non-C# backend. The shape is the same in every language —
203
-
mount five (or six, if you want PUT) routes under `apiPrefix` that
204
-
match the URL grammar above.
200
+
Every port ships a route generator today (see the status table above) —
201
+
you do not need to hand-write a controller to get a conforming API. This
202
+
section is for the rare case where you need a shape the generator
203
+
doesn't cover (a custom auth scheme, a framework the generator doesn't
204
+
target, etc.) and want a hand-rolled controller that still speaks the
205
+
contract. The shape is the same in every language — mount five (or six,
206
+
if you want PUT) routes under `apiPrefix` that match the URL grammar
207
+
above.
205
208
206
209
### Java — Spring `@RestController`
207
210
@@ -303,20 +306,24 @@ into your framework's idiomatic query-builder, gated by the generated
303
306
304
307
## Future direction
305
308
306
-
Cross-port route codegen — for Java (Spring), Kotlin (Spring-Kotlin /
307
-
Ktor), Python (FastAPI), and a browser-side Angular client — is planned
308
-
but not yet specced. The planned FR will track:
309
+
Cross-port route + filter codegen (Java, Kotlin, Python), the shared
310
+
route-shape oracle (`fixtures/api-contract-conformance/`), and a
311
+
browser-side Angular client have all shipped — see "Per-port route
0 commit comments