Contextul șablonului
Când generați cod, Restorm transmite întregul dumneavoastră design șablonului sub
forma unui obiect ctx. Modelele, enum-urile, rutele și mai ales
intențiile lor (searchable, PII, cache, și întregul profil operațional al
modelului: volumetrie, profil de acces, trafic, prospețime, sensibilitate, retenție)
sunt acolo — un șablon le citește pentru a decide ce să genereze. Nu este nevoie de o
variabilă pentru asta: informațiile pe care le-ați introdus deja în design
sunt direct disponibile.

Forma lui ctx
Section titled “Forma lui ctx”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, varsReferințele se fac prin nume (niciodată prin identificator intern):
property.enum este numele enum-ului, property.references.model numele
modelului vizat, model.inherits numele părintelui. Pe un model, properties[]
listează proprietățile sale proprii (pentru declararea tipului) și
allProperties[] proprietățile proprii + moștenite, aplatizate (pentru o
instanță completă: date de exemplu, coloane SQL, corp de cerere).
Citirea unui flag: regula de aur
Section titled “Citirea unui flag: regula de aur”Flag-urile booleene sunt prezente în ctx doar când sunt activate.
Motorul randează în StrictUndefined: trebuie deci testată prezența
cheii, niciodată valoarea sa.
{# ✅ corect — se testează prezența #}{% if 'searchable' in p %}INDEX({{ p['name'] }}){% endif %}
{# ❌ greșit — ridică o eroare când flag-ul este absent #}{% if p.searchable %}…{% endif %}Doar property.required (boolean) și route.auth (enumerare) sunt
întotdeauna prezente. Celelalte flag-uri booleene sunt «prezent = adevărat»; câmpurile
cu valoare (volumetrie, profil operațional, cache…) poartă
valoarea lor când sunt completate, și sunt absente altfel — aceeași regulă de
prezență.
| Pe o proprietate | Pe un model | Pe o rută |
|---|---|---|
readOnly · writeOnly · nullable | timestamps · softDelete (booleene) | idempotent · deprecated (booleene) |
unique · searchable · immutable · pii | Profil operațional (valori): volumetry · accessPattern · traffic · freshness · sensitivity · retention | cacheSeconds (număr) · pagination (obiect) |
Valorile profilului operațional al unui model: 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).
Exemplu: punerea în cache a datelor cu cerere mare la citire
Section titled “Exemplu: punerea în cache a datelor cu cerere mare la citire”Două cazuri, după cum informația există deja în design sau nu.
a) Designul poartă deja informația
Section titled “a) Designul poartă deja informația”Dacă ați completat o durată de cache pe o rută, ea sosește în
route['cacheSeconds']; route['idempotent'] vă spune că este sigură pentru
punerea în cache (doar citire):
{% 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) «Cerere mare la citire» este un câmp nativ al modelului
Section titled “b) «Cerere mare la citire» este un câmp nativ al modelului”Nu este nevoie de variabilă: «cerere mare la citire» este direct profilul
de acces al modelului. În setările modelului, grupul Profil operațional,
alegeți Citire dominantă — șablonul îl citește în
model['accessPattern']. Combinați-l cu model['freshness'] (toleranța la
prospețime) pentru a decide dacă trebuie pus în cache, și pentru cât timp:
{% 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 activat ({{ ttl }}s){% endif %}{% endfor %}Observați testul != 'strong': un model cu citire dominantă dar cu
consistență puternică nu trebuie pus în cache. Acesta este tot interesul de a avea
cele două intenții una lângă alta în design.
Rezervați variabilele de generare pentru ceea ce designul nu poartă deja (o setare proprie șablonului): intențiile de business — volumetrie, profil de acces, trafic, prospețime, sensibilitate, retenție — sunt câmpuri native ale modelului.
Contractul complet
Section titled “Contractul complet”Acest context este versionat (ctx['contextVersion']) și descris exhaustiv de
un JSON-Schema livrat în depozitul aplicației
(docs/contributing/design-codegen-context.schema.json) — copiați-l în
șablonul dumneavoastră pentru ca CI-ul său să valideze contextul de referință. Un agent IA obține
același contract din mers prin instrumentul MCP get_design_template_contract.