Zum Inhalt springen

Der Kontext des Templates

Wenn Sie Code generieren, übergibt Restorm Ihr gesamtes Design an das Template in Form eines ctx-Objekts. Ihre Modelle, Ihre Enums, Ihre Routen und vor allem ihre Absichten (searchable, PII, cache und das gesamte operative Profil des Modells: Volumen, Zugriffsprofil, Traffic, Aktualität, Sensibilität, Aufbewahrung) sind da — ein Template liest sie, um zu entscheiden, was zu generieren ist. Dafür braucht es keine Variable: die Informationen, die Sie bereits im Design erfasst haben, sind direkt verfügbar.

Der Tab Code generation einer Eigenschaft: ihre Flags und ihre vom Template gelesenen Variablen

ctx
├─ design # name, version, description, basePath, defaultAuth, vars
├─ enums[] # name, description, values[]
├─ models[] # name, description, inherits, identifier, timestamps, softDelete,
│ # volumetry, accessPattern, traffic, freshness, sensitivity,
│ # retention, properties[], allProperties[], examples[], vars
└─ groups[] # name, basePath, versionPrefix, headers[], routes[]
└─ routes[] # method, path, fullPath, params[], body, responses[],
# auth, pagination, cacheSeconds, idempotent, deprecated, vars

Die Referenzen erfolgen über den Namen (niemals über einen internen Bezeichner): property.enum ist der Name des Enums, property.references.model der Name des angezielten Modells, model.inherits der Name des übergeordneten Modells. Auf einem Modell listet properties[] seine eigenen Eigenschaften (für die Deklaration des Typs) und allProperties[] die eigenen + geerbten, abgeflachten Eigenschaften (für eine vollständige Instanz: Beispieldaten, SQL-Spalten, Anfrage-Body).

Die booleschen Flags sind in ctx nur dann vorhanden, wenn sie aktiviert sind. Die Engine rendert in StrictUndefined: man muss also die Präsenz des Schlüssels testen, niemals seinen Wert.

{# ✅ correct — on teste la présence #}
{% if 'searchable' in p %}INDEX({{ p['name'] }}){% endif %}
{# ❌ faux — lève une erreur quand le flag est absent #}
{% if p.searchable %}…{% endif %}

Nur property.required (boolesch) und route.auth (Enumeration) sind immer vorhanden. Die anderen booleschen Flags sind „vorhanden = wahr”; die Felder mit Wert (Volumen, operatives Profil, cache…) tragen ihren Wert, wenn sie ausgefüllt sind, und fehlen andernfalls — dieselbe Präsenzregel.

Auf einer EigenschaftAuf einem ModellAuf einer Route
readOnly · writeOnly · nullabletimestamps · softDelete (boolesch)idempotent · deprecated (boolesch)
unique · searchable · immutable · piiOperatives Profil (Werte): volumetry · accessPattern · traffic · freshness · sensitivity · retentioncacheSeconds (Zahl) · pagination (Objekt)

Die Werte des operativen Profils eines Modells: accessPattern (readHeavy / writeHeavy / balanced / appendOnly), traffic (low / medium / high), freshness (strong / shortCache / longCache), sensitivity (public / internal / confidential / pii), retention (permanent / archivable / ephemeral), volumetry (hundreds / tenThousands / millions).

Beispiel: Daten mit hoher Lesenachfrage cachen

Section titled “Beispiel: Daten mit hoher Lesenachfrage cachen”

Zwei Fälle, je nachdem, ob die Information bereits im Design existiert oder nicht.

Wenn Sie eine Cache-Dauer auf einer Route ausgefüllt haben, kommt sie in route['cacheSeconds'] an; route['idempotent'] sagt Ihnen, dass sie sicher zu cachen ist (schreibgeschützt):

{% for group in ctx['groups'] %}
{% for route in group['routes'] %}
{% if 'cacheSeconds' in route and 'idempotent' in route %}
// {{ route['method'] }} {{ route['fullPath'] }}
app.use("{{ route['fullPath'] }}", cache({{ route['cacheSeconds'] }}));
{% endif %}
{% endfor %}
{% endfor %}

b) „Hohe Lesenachfrage” ist ein natives Feld des Modells

Section titled “b) „Hohe Lesenachfrage” ist ein natives Feld des Modells”

Keine Variable nötig: „hohe Lesenachfrage” ist direkt das Zugriffsprofil des Modells. In den Einstellungen des Modells, Gruppe Operatives Profil, wählen Sie Lesedominant — das Template liest es in model['accessPattern']. Kombinieren Sie es mit model['freshness'] (Toleranz gegenüber der Aktualität), um zu entscheiden, ob und für wie lange gecacht werden soll:

{% for model in ctx['models'] %}
{% if model['accessPattern'] == 'readHeavy' and model['freshness'] != 'strong' %}
{% set ttl = 3600 if model['freshness'] == 'longCache' else 60 %}
registerCache("{{ model['name'] }}", {{ ttl }}); // cache activé ({{ ttl }}s)
{% endif %}
{% endfor %}

Beachten Sie den Test != 'strong': ein lesedominantes Modell, aber mit starker Konsistenz, darf nicht gecacht werden. Das ist genau der Sinn davon, die beiden Absichten im Design nebeneinander zu haben.

Reservieren Sie die Generierungsvariablen für das, was das Design nicht bereits trägt (eine template-eigene Einstellung): die fachlichen Absichten — Volumen, Zugriffsprofil, Traffic, Aktualität, Sensibilität, Aufbewahrung — sind native Felder des Modells.

Dieser Kontext ist versioniert (ctx['contextVersion']) und wird vollständig durch ein JSON-Schema beschrieben, das im Repository der Anwendung geliefert wird (docs/contributing/design-codegen-context.schema.json) — kopieren Sie es in Ihr Template, damit dessen CI den Referenzkontext validiert. Ein KI-Agent erhält denselben Vertrag im laufenden Betrieb über das MCP-Tool get_design_template_contract.