Bỏ qua để đến nội dung

Ngữ cảnh của template

Khi bạn sinh mã, Restorm truyền toàn bộ thiết kế của bạn cho template dưới dạng một đối tượng ctx. Các mô hình, enum, tuyến của bạn và nhất là ý định của chúng (searchable, PII, cache, và toàn bộ hồ sơ vận hành của mô hình: dung lượng, hồ sơ truy cập, lưu lượng, độ tươi, độ nhạy, thời gian lưu giữ) đều có ở đó — một template đọc chúng để quyết định sinh gì. Không cần một biến cho việc đó: những thông tin bạn đã nhập trong thiết kế đều khả dụng trực tiếp.

Tab Code generation của một thuộc tính: các cờ và biến của nó được template đọc

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

Các tham chiếu được thực hiện theo tên (không bao giờ theo định danh nội bộ): property.enum là tên của enum, property.references.model tên của mô hình được nhắm tới, model.inherits tên của mô hình cha. Trên một mô hình, properties[] liệt kê các thuộc tính riêng của nó (cho việc khai báo kiểu) và allProperties[] các thuộc tính riêng + kế thừa, được làm phẳng (cho một instance đầy đủ: dữ liệu ví dụ, cột SQL, thân yêu cầu).

Các cờ boolean chỉ hiện diện trong ctx khi chúng được bật. Bộ máy kết xuất ở chế độ StrictUndefined: do đó phải kiểm tra sự hiện diện của khóa, không bao giờ kiểm tra giá trị của nó.

{# ✅ đúng — ta kiểm tra sự hiện diện #}
{% if 'searchable' in p %}INDEX({{ p['name'] }}){% endif %}
{# ❌ sai — ném ra lỗi khi cờ vắng mặt #}
{% if p.searchable %}…{% endif %}

Chỉ property.required (boolean) và route.auth (enum) là luôn hiện diện. Các cờ boolean khác thì « hiện diện = đúng »; các trường có giá trị (dung lượng, hồ sơ vận hành, cache…) mang giá trị của chúng khi được điền, và vắng mặt nếu không — cùng quy tắc về sự hiện diện.

Trên một thuộc tínhTrên một mô hìnhTrên một tuyến
readOnly · writeOnly · nullabletimestamps · softDelete (boolean)idempotent · deprecated (boolean)
unique · searchable · immutable · piiHồ sơ vận hành (giá trị): volumetry · accessPattern · traffic · freshness · sensitivity · retentioncacheSeconds (số) · pagination (đối tượng)

Các giá trị của hồ sơ vận hành của một mô hình: 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).

Ví dụ: đưa vào cache các dữ liệu có nhu cầu đọc cao

Section titled “Ví dụ: đưa vào cache các dữ liệu có nhu cầu đọc cao”

Hai trường hợp, tùy theo thông tin đã tồn tại trong thiết kế hay chưa.

a) Thiết kế đã mang sẵn thông tin

Section titled “a) Thiết kế đã mang sẵn thông tin”

Nếu bạn đã điền một thời lượng cache trên một tuyến, nó đến trong route['cacheSeconds']; route['idempotent'] cho bạn biết rằng nó an toàn để đưa vào cache (chỉ đọc):

{% 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) « Nhu cầu đọc cao » là một trường gốc của mô hình

Section titled “b) « Nhu cầu đọc cao » là một trường gốc của mô hình”

Không cần biến: « nhu cầu đọc cao » chính là hồ sơ truy cập của mô hình. Trong các thiết lập của mô hình, nhóm Hồ sơ vận hành, bạn chọn Đọc là chủ đạo — template đọc nó trong model['accessPattern']. Kết hợp nó với model['freshness'] (mức chấp nhận độ tươi) để quyết định có nên đưa vào cache hay không, và trong bao lâu:

{% 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 đã bật ({{ ttl }}s)
{% endif %}
{% endfor %}

Lưu ý phép kiểm tra != 'strong': một mô hình đọc là chủ đạo nhưng có tính nhất quán mạnh thì không nên được đưa vào cache. Đó chính là lợi ích của việc có cả hai ý định cạnh nhau trong thiết kế.

Hãy dành các biến sinh mã cho những gì thiết kế chưa mang sẵn (một thiết lập riêng của template): các ý định nghiệp vụ — dung lượng, hồ sơ truy cập, lưu lượng, độ tươi, độ nhạy, thời gian lưu giữ — là các trường gốc của mô hình.

Ngữ cảnh này được quản lý phiên bản (ctx['contextVersion']) và được mô tả đầy đủ bởi một JSON-Schema được giao trong kho của ứng dụng (docs/contributing/design-codegen-context.schema.json) — hãy sao chép nó vào template của bạn để CI của nó xác thực ngữ cảnh tham chiếu. Một tác nhân AI có được cùng một hợp đồng ngay tức thì qua công cụ MCP get_design_template_contract.