Repository navigation
feat(metadata): add @collectionName and naming.collections pluralizer across all five ports - #558
Merged
Merged
Conversation
…ng.collections pluralizer Renames the unreleased @dbSetName to @collectionName (no alias) and registers it in every port on object.entity, object.projection and object.report, marked implementedIn csharp: the generated C# context takes it as the DbSet property name. A project chooses the pluralizer an object without one takes its name from with naming.collections in .metaobjects/config.json (standard by default, none, or one the application registers); every port reads the key and refuses an unknown name. The shared fixture object-port-scoped-attr-dbsetname becomes object-collection-name, and object-port-scoped-attr-object-adapter keeps the port-scoped marker covered.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
@dbSetNameattr to@collectionNameonobject.entity,object.projectionandobject.report, with no alias (it was never published). Updatespec/metamodel/object.json, the registry manifest and canonical, the per-port embedded copies, the generated metamodel docs and the TS/C#/Java/Python constants.@objectAdapterstays the one port-scoped attr (["java", "kotlin"]). Conformance fixtures:object-port-scoped-attr-dbsetnamebecomesobject-collection-name, and a newobject-port-scoped-attr-object-adapterfixture covers the port-scoped case.naming.collectionspluralizer (standarddefault,none, or an application-registered one). It is read in the TSsdkconfig and the C#, Java and PythonNeutralConfigloaders, which refuse an unknown pluralizer at config read. Registration entry points areregisterPluralizer(TS, Java),RegisterPluralizer(C#) andregister_pluralizer(Python), alongside the existing column/table naming rules. The C# generated context uses@collectionNamefor the DbSet property name in place of the derived plural (CSharpNaming,DbContextGenerator).collection-naming-config.test.ts,CollectionNameVocabularyTests.cs,CollectionNamingTest.javaandtest_collection_naming.py. UpdateCHANGELOG.md,docs/features/migrations/physical-naming.md,docs/CONFORMANCE.mdand the generated site-reference pages to match.Validation
Risk Assessment
✅ Low: The fix round closed all three round-1 warnings: the TS config reads and carries naming.collections, the C# and Python probe candidates keep the pluralizer, and Java, TS and C# now have tests checked against the shared naming-conformance corpus. The remaining gap, TS cannot register a custom pluralizer from metaobjects.config.ts, is PR 2 scope.
Testing
Drove the TS and Python CLIs and loaders live against disposable local projects. Confirmed valid
naming.collectionsand@collectionNameload. Confirmed bad pluralizer names and misplaced attrs are refused with clear errors. Java and C# were verified by unit and conformance suites only, with no live run; those scenarios are recorded as untested. The full TS server suite did not complete, and Python integration tests cannot collect without pg8000. Those gaps are reported as findings.node dist/bin/meta.js verify --templatesexit 0 in a disposable projectEvidence: Live CLI and Python loader transcripts for naming.collections and @collectionName
Pipeline
Updates from git push no-mistakes
✅ **Intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
server/typescript/packages/sdk/src/config.ts:238- The TypeScript config reader rejectsnaming.collections. The sdknamingzod schema allows onlycolumnsandtablesand is.strict(). A project that sets"naming": { "collections": "none" }therefore fails every Nodemetacommand (gen,migrate,verify) with an unknown-key error. This includes a C# adopter, who must run Nodemeta migratefor schema (ADR-0015).physicalNamingFromConfig(config.ts:315-320) also never copiescollectionsonto the root'sPhysicalNaming, so the newcollectionNameOf(metadata/src/naming.ts:447) always falls back tostandard. Three places claim the key is read in every port: CHANGELOG.md:110 ("Every port registers the attr and reads the key, and refuses an unknown pluralizer when it reads the config"), thenamingtable in docs/features/migrations/physical-naming.md:30, and theregisterPluralizerdocstring in naming.ts:215. Fix: addcollections: z.string().superRefine(n => isRegisteredPluralizer(n) || issue(unknownNamingStrategyMessage("collections", n))).optional()to the schema, carrycollectionsthroughphysicalNamingFromConfig, and add an sdk test that reads the config (acceptsnone, refuses an unknown name). This may have been planned for PR 2, but PR 1's CHANGELOG and docs already state it as shipped.server/csharp/MetaObjects.Codegen/CodegenCli.cs:818- Theverify --codegennaming probe drops the project's pluralizer and miscompares candidates.PhysicalNaming(C# record) andNamingRules(Python dataclass) now includecollectionsin equality, butNamingCandidatesstill buildsnew PhysicalNaming(c, t)withCollections = null. Take a project with"naming": {"collections": "none"}(or an explicit"standard"). The candidate with the same columns and tables asusednow compares unequal and is probed: one wasted regeneration today. Every probe also replacesroot.PhysicalNamingwith a candidate that has lost the configured pluralizer. Once C# codegen readsCollections(PR 3), a probe can match on the pluralizer alone, andNamingDiffersthen prints two identicalnamingblocks instead of saying "regenerate". Same defect in Python at server/python/src/metaobjects/cli.py:2323 (NamingRules(columns=c, tables=t)takes the defaultcollections="standard"). Fix: carry the used pluralizer into each candidate:new PhysicalNaming(c, t) { Collections = used.Collections }andNamingRules(columns=c, tables=t, collections=used.collections).server/java/metadata/src/main/java/com/metaobjects/config/NeutralConfig.java:341- The new Java work has no tests. The intent requires that "Python and Java accept naming.collections", but nothing executes Java'snaming.collectionsread, the unknown-pluralizer refusal inPhysicalNaming.of(columns, tables, collections),NamingStrategies.registerPluralizerand its built-in protection, orstandardPluralize(NamingStrategies.java:103). Python has test_collection_naming.py for the same behavior. Add a Java test like the Python one. Write a temp.metaobjects/config.jsonand read it throughNeutralConfig. Assert thatcollections: "none"reads back and that an absent key givesnull. Assert that"latin"fails with the"naming.collections" names "latin"message. Assert that registeringnonethrows. CheckstandardPluralizeagainst the shared naming-conformance cases (Category→Categories, Address→Addresses, Stats→Stats). Example wrong behavior this would catch: thesuiaalready-plural check is inverted and Address becomes Address. TSregisterPluralizer/pluralizer/collectionNameOf(naming.ts:219-458) and C#CollectionNames.StandardPluralize/Of(CollectionNames.cs:18-45) are also new and have no direct tests.server/csharp/MetaObjects.Codegen/CSharpNaming.cs:374-naming.collectionsdoes nothing yet in any generator. C#DbSetNamestill falls back toPluralize(Pascal(entity.Name))and ignores the configured pluralizer, andCollectionNames.Of/collectionNameOfhave no callers. The CHANGELOG and the new attr description ("Absent, the project's pluralizer derives it") describe the finished behavior. This matches the four-PR plan (PR 3 wires C# codegen), and 1.3.0 is held until all four land, so no action is needed in PR 1. Make sure PR 3 switchesDbSetNametoCollectionNames.Of.server/typescript/packages/metadata/test/object-definition-completeness.test.ts:89- Corrected the comment "@collectionName (implementedIn C# + TypeScript)" to "(implementedIn C#)". The registry marks itimplementedIn: ["csharp"]only.🔧 Fix applied.
3 infos still open:
server/csharp/MetaObjects.Codegen/CSharpNaming.cs:374-naming.collectionsdoes nothing yet in any generator. C#DbSetNamestill falls back toPluralize(Pascal(entity.Name))and ignores the configured pluralizer, andCollectionNames.Of/collectionNameOfhave no callers. The CHANGELOG and the new attr description ("Absent, the project's pluralizer derives it") describe the finished behavior. This matches the four-PR plan (PR 3 wires C# codegen), and 1.3.0 is held until all four land, so no action is needed in PR 1. Make sure PR 3 switchesDbSetNametoCollectionNames.Of.server/typescript/packages/metadata/test/object-definition-completeness.test.ts:89- Corrected the comment "@collectionName (implementedIn C# + TypeScript)" to "(implementedIn C#)". The registry marks itimplementedIn: ["csharp"]only.server/typescript/packages/cli/src/lib/naming-preload.ts:48- A TypeScript project cannot select an application-registered pluralizer through the CLI.namingStrategiesinmetaobjects.config.ts(codegen-ts/src/metaobjects-config.ts:172) has onlycolumnsandtables, soregisterNamingStrategies(cli/src/lib/load-metaobjects-config.ts:577) never registers a pluralizer.registerProjectNamingStrategiesalso reads onlycolumnsandtables. A config withnaming.collections: "my-plural"is refused by the reader on everymetacommand, and only a program that callsregisterPluralizerbefore loading can satisfy it. The built-ins (standard,none) work, and the fix round's TS config read is correct. docs/features/migrations/physical-naming.md says pluralizers register "the same way" as table rules, which is not true for the TS config file. This fits PR 2 (TS codegen): addcollectionstoNamingStrategies,registerNamingStrategiesand the preload check, or narrow the doc sentence for TS.bun testin server/typescript) was killed at the 10-minute background limit with no output, so it was not verified. Touched packages metadata, sdk and cli pass in full. Re-run the full TS server suite in a longer background run, or in per-package chunks.node dist/bin/meta.js verify --templatesexit 0 in a disposable projectscripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsBaseline:scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains(given)bun testin server/typescript/packages/{sdk,metadata}/test/collection-naming-config.test.ts, object-definition-completeness.test.ts, port-scoped-attr.test.tspython3 -m pytest tests/unit/test_collection_naming.py tests/loader/test_port_scoped_attr.pymvn -o -pl metadata test -Dtest=CollectionNamingTest,PortScopedAttrTest(Java surefire reports read: 7 and 4 tests, 0 fail)dotnet test MetaObjects.Codegen.Tests --filter Naming(127 pass)dotnet test MetaObjects.Conformance.Tests(2403 pass, includes CollectionNameVocabularyTests and NamingStrategiesTests)Rebuilt TS CLI:cd server/typescript/packages/cli && bun run buildLive TS CLInode dist/bin/meta.js verify --templateson a disposable project with.metaobjects/config.jsonnaming.collections=none,@collectionNameon an entity: exit 0Live TS CLI on a disposable project with naming.collections=latin: refused with"naming.collections" names "latin", exit 1Live TS CLI on a disposable project with@collectionNameon field.string: refused with ERR_UNKNOWN_ATTR, exit 1Live Python loaderMetaDataLoader.from_directory(..., strict=True)on ok project: loads Stats and Address, no errors; on adv project: ERR_UNKNOWN_ATTRLive Python CLImetaobjectsmain on bad project:naming.collectionslatin refused with same message, exit 2Full regression:bun testin server/typescript/packages/metadata (3970 pass), sdk (443 pass), cli (2006 pass, 2017 ran)Full regression:python3 -m pytest tests/unit tests/loader(746 pass)Full regression:mvn -o -pl metadata test(3337 pass, BUILD SUCCESS)Fullbun testin server/typescript was killed at the 10-minute background limit with no output, so the whole TS server suite is NOT verifiedFull Pythonpyteston tests/integration errors at collection: ModuleNotFoundError pg8000 (environment, not installed)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.