模板的上下文
当您生成代码时,Restorm 会把 您的整个设计 以一个 ctx 对象的形式传给
模板。您的模型、您的枚举、您的路由,尤其是 它们的意图(searchable、PII、
cache,以及模型的整个运行画像:volumetry、accessPattern、traffic、freshness、
sensitivity、retention)都在其中 —— 模板读取它们来决定生成什么。为此不需要一个
变量:您已经在设计中输入的信息可以直接使用。

ctx 的形状
Section titled “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, vars引用通过名称进行(从不通过内部标识符):property.enum 是枚举的名称,
property.references.model 是所指向模型的名称,model.inherits 是父级的名称。
在一个模型上,properties[] 列出它 自有的 属性(用于类型声明),而
allProperties[] 列出 自有 + 继承、被展平的 属性(用于一个完整实例:示例
数据、SQL 列、请求正文)。
读取一个标志:黄金法则
Section titled “读取一个标志:黄金法则”布尔标志 只有在被启用时 才出现在 ctx 中。引擎以 StrictUndefined 渲染:
因此必须 测试键的存在,绝不测试它的值。
{# ✅ 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 %}只有 property.required(布尔)和 route.auth(枚举)始终 存在。其他布尔
标志是「存在 = 真」;带 值 的字段(volumetry、运行画像、cache……)在被填写时
带有它们的值,否则不存在 —— 同样的存在规则。
| 在 属性 上 | 在 模型 上 | 在 路由 上 |
|---|---|---|
readOnly · writeOnly · nullable | timestamps · softDelete(布尔) | idempotent · deprecated(布尔) |
unique · searchable · immutable · pii | 运行画像(值):volumetry · accessPattern · traffic · freshness · sensitivity · retention | cacheSeconds(数字) · pagination(对象) |
一个模型的 运行画像 的值: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)。
示例:缓存读取需求高的数据
Section titled “示例:缓存读取需求高的数据”有两种情况,取决于该信息是否已经存在于设计中。
a) 设计已经带有该信息
Section titled “a) 设计已经带有该信息”如果您在一条路由上填写了一个 缓存时长,它会到达 route['cacheSeconds'];
route['idempotent'] 告诉您它可以安全地缓存(只读):
{% 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)「读取需求高」是模型的一个原生字段
Section titled “b)「读取需求高」是模型的一个原生字段”不需要变量:「读取需求高」直接就是模型的 访问画像。在模型的设置中、运行画像
组里,您选择 Lecture dominante(以读为主)—— 模板在 model['accessPattern'] 中
读取它。把它与 model['freshness'](对新鲜度的容忍度)结合,来决定是否要缓存,
以及缓存多久:
{% 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 %}注意 != 'strong' 这个测试:一个以读为主 但 要求强一致性的模型 不应 被
缓存。这正是把两个意图在设计中并排放置的全部价值所在。
请把生成变量留给设计尚未承载的东西(一个模板自身的 设置):业务意图 —— volumetry、accessPattern、traffic、freshness、sensitivity、 retention —— 是模型的 原生字段。
这个上下文是受版本控制的(ctx['contextVersion']),并由一份随应用程序仓库一起
交付的 JSON-Schema(docs/contributing/design-codegen-context.schema.json)详尽
描述 —— 把它复制到您的模板中,好让它的 CI 验证参考上下文。一个 AI 智能体通过 MCP
工具 get_design_template_contract 即时获得同样的契约。