Repository navigation
MetaObjects 1.0.13
npm 1.0.13 (all 14 @metaobjectsdev/* packages in lockstep), PyPI 1.0.13, NuGet 1.0.13 and
Maven Central 8.0.13. metamodelVersion stays 1.0. Gated by a private 1.0.13-rc.1 build of the
release commit on the adopter estate (rc-gate.sh 7/7) and a full local CI run (--strict-toolchains)
on that commit. Read "Upgrade impact" below if any entity name is already plural — its REST path
and generated names change.
Fixed
-
Cross-port: an already-plural entity name no longer doubles in generated API/code-surface
names.ProgramPurchaseStatsused to come outProgramPurchaseStatsesin the REST
collection path, generated hook/query/finder/list function names, and DbSet/collection
names — a real adopter shipped six such URLs. Every port's pluralizer now treats a word
ending in "s" as already-plural UNLESS the character before that final "s" is one of
s/u/i/a (soStats/Settings/Series/News/Analytics/Photosstay unchanged, while
Status/Address/Bonus/Alias/Gas/Analysiskeep pluralizing exactly as before —
the heuristic's one documented miss isLens→Lens, correct pluralLenses).Upgrade impact — read before regenerating. If any entity name in your model is
already a plural noun (Stats,Settings,Series, and the like):- The REST collection path changes.
/program_purchase_statsesbecomes
/program_purchase_stats. A client still calling the old doubled URL gets a plain
404, not a redirect — update callers before or alongside the regen. - Generated hook, query, finder, and list function/method names change too
(useProgramPurchaseStatses→useProgramPurchaseStats,listProgramPurchaseStatses
→listProgramPurchaseStats, the C# DbSet property, the Java/Python finder/router
names). Any hand-written code importing or calling the OLD doubled symbol fails to
compile (TS/C#/Kotlin) or import (Python) after you regenerate — grep for the old
spelling across your own code, not just generated output. - There is no per-entity override for a route or generated hook/finder/list name.
TypeScript'svariableNameFromEntity/CollectionNameOptions.overridesrenames only
the Drizzle collection VARIABLE — it does not touch the REST path or any hook/query/
finder/list name. If the new spelling is wrong for your API, the fix is to rename the
entity itself; there is no config knob that renames only the generated surface. - Default PHYSICAL table and column names do NOT change. The fallback used when
metadata declares no explicit physical name is explicitly frozen at the old
suffix-only rule in every port (a new, separately-named, byte-for-byte-preserved
function where the two pluralizers were previously the same one) —meta migrate
proposes no rename for an already-plural entity you didn't touch. - Two entities in one generation run whose names now land on the same API-surface
collection name is a GENERATION ERROR, not a silent collision.Address+Addresses
(orOrder+Orders) both resolve to/addresses//ordersonce an already-plural
name stops doubling — before this fix they did not collide (Addressesdoubled to
addresseses). Every port now refuses such a model outright, before any generator
runs, naming both entities and the colliding name; rename one entity to proceed. New
cross-port fixture corpusfixtures/naming-conformance/carries both the already-plural
cases and the expected-collision cases, run by every port.
Fixing the doubling also surfaced two further, narrower defects it was incidentally
masking: a TypeScript already-plural entity's generated Drizzle collection variable name
could collide with its own singular row variable in the same statement (const [x] = await db.insert(x)..., a TDZ compile error) — the colliding local variable now gets a
Rowsuffix only in that exact case; and a C# already-plural entity's ownDbSet
property name could collide with its own entity TYPE name insideOnModelCreating(C#
resolves a bare same-named reference to the DbSet member before the type, the same
shadowing class as the pre-existingAddress/Addressescross-entity hazard) — the
TPH-discriminator and int-backed-enum nested-type references are nowglobal::-qualified
when, and only when, the owning entity's name is itself already-plural. - The REST collection path changes.
-
Kotlin: two pre-existing generated-controller compile defects, found extending the
exposedApi=1controller-tier compile check. Both were excluded (not fixed) when that
check landed; both are fixed now, forexposedApi=0andexposedApi=1alike, with no
exclusions left. (1) A filterablefield.inetcolumn's generated filter dispatch emitted
ordering operators (gt/gte/lt/lte) thatjava.net.InetAddresscannot satisfy (it is
notComparable) — the per-field operator gate now derives from the same
com.metaobjects.query.FilterOpssingle source of truth the generated<Entity>FilterAllowlist
already reads, so the controller can no longer emit an operator the allowlist itself would
refuse to admit. (2) Thefield.string @dbColumnType=uuidphysical escape hatch bound a
nativeColumn<UUID>on the generated Exposed table while the generated entity/controller
assumedString(per ADR-0037, the escape hatch is physical-only) — a mismatch on every
filter comparison and the PATCH bind. The table now binds aColumn<String>instead (a new
package-shareduuidString(...)extension that persists through the native Postgresuuid
type while converting only at the Kotlin-value boundary), agreeing with the entity/controller
and with how every other port treats the same escape hatch. A newexposedApi=0controller-
tier compile test (integration-tests-kotlin) closes the matching gap on the default/stable
output path, which nothing had compiled over the full shared fitness corpus before.