Sari la conținut

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.

Fila Code generation a unei proprietăți: flag-urile și variabilele sale citite de șablon

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

Referinț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).

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 proprietatePe un modelPe o rută
readOnly · writeOnly · nullabletimestamps · softDelete (booleene)idempotent · deprecated (booleene)
unique · searchable · immutable · piiProfil operațional (valori): volumetry · accessPattern · traffic · freshness · sensitivity · retentioncacheSeconds (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.

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.

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.