Skip to content

Commit 197aeeb

Browse files
dmealingclaude
andcommitted
test(codegen-ts): template-codegen conformance corpus + TS gate
Cross-port corpus: spec.json (perEntity/perPackage/perModel) over metadata/ resolving templates/ → byte-identical expected/. The TS gate runs it in a hermetic tmp projectRoot (copies templates/) so runGen's .gen-state merge base never lands in the committed corpus; a corpus .gitignore guards .metaobjects/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky
1 parent adca13d commit 197aeeb

12 files changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.metaobjects/
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# template-codegen conformance corpus
2+
3+
Cross-port gate for the declarative Mustache template generator (SP-1).
4+
5+
Every port runs `spec.json` (a list of `{ name, template, scope, outputPattern }`
6+
generators) over `metadata/meta.shop.json`, resolving templates from `templates/`,
7+
and must produce output **byte-identical** to `expected/`.
8+
9+
The corpus exercises all three built-in scopes:
10+
11+
- **`perEntity`** (`entity.mustache``<Name>.txt`) — the neutral per-entity data
12+
dict: fields (name/type/required/isArray/maxLength), and Order's `product`
13+
relationship.
14+
- **`perPackage`** (`package.mustache``<package>/_package.txt`) — one file per
15+
package, listing its entities.
16+
- **`perModel`** (`model.mustache``_model.txt`) — one file for the whole model.
17+
18+
The render engine is already byte-equal across ports (`fixtures/render-conformance/`);
19+
this corpus gates the *new* surface: the structural data dict, the scope names
20+
(`perEntity`/`perPackage`/`perModel`), and the output-pattern grammar
21+
(`{name}`/`{Name}`/`{package}`).
22+
23+
Regenerate `expected/` after an intentional change to the data dict or scope walks
24+
by pointing the generator at the `expected/` directory and committing the result
25+
(see each port's conformance test).
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Order (shop)
2+
- id: long
3+
- productId: long
4+
rel product -> Product (one)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Product (shop)
2+
- id: long
3+
- name: string required maxLength=120
4+
- status: enum
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
model:
2+
shop: Product Order
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package shop: Product Order
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"metadata.root": {
3+
"package": "shop",
4+
"children": [
5+
{
6+
"object.entity": {
7+
"name": "Product",
8+
"children": [
9+
{ "source.rdb": { "@table": "products" } },
10+
{ "field.long": { "name": "id" } },
11+
{ "field.string": { "name": "name", "@required": true, "@maxLength": 120 } },
12+
{ "field.enum": { "name": "status", "@values": ["ACTIVE", "ARCHIVED"] } },
13+
{ "identity.primary": { "name": "primary", "@fields": ["id"], "@generation": "increment" } }
14+
]
15+
}
16+
},
17+
{
18+
"object.entity": {
19+
"name": "Order",
20+
"children": [
21+
{ "source.rdb": { "@table": "orders" } },
22+
{ "field.long": { "name": "id" } },
23+
{ "field.long": { "name": "productId" } },
24+
{ "identity.primary": { "name": "primary", "@fields": ["id"], "@generation": "increment" } },
25+
{ "relationship.association": { "name": "product", "@cardinality": "one", "@objectRef": "Product" } }
26+
]
27+
}
28+
}
29+
]
30+
}
31+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"generators": [
3+
{ "name": "ent", "template": "entity", "scope": "perEntity", "outputPattern": "{name}.txt" },
4+
{ "name": "pkg", "template": "package", "scope": "perPackage", "outputPattern": "{package}/_package.txt" },
5+
{ "name": "mdl", "template": "model", "scope": "perModel", "outputPattern": "_model.txt" }
6+
]
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// {{name}} ({{package}})
2+
{{#fields}}- {{name}}: {{type}}{{#isArray}}[]{{/isArray}}{{#required}} required{{/required}}{{#maxLength}} maxLength={{maxLength}}{{/maxLength}}
3+
{{/fields}}
4+
{{#relationships}}rel {{name}} -> {{targetRef}} ({{cardinality}})
5+
{{/relationships}}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
model:
2+
{{#packages}} {{package}}: {{#entities}}{{name}} {{/entities}}
3+
{{/packages}}

0 commit comments

Comments
 (0)