Implement a "templates" registry similar to sources with GET /templates and GET /templates/{id} endpoints, including ETag support for detail endpoints, caching, filtering, sorting, and automated tests.
graph TD
A[Client Request] --> B{Endpoint}
B -->|GET /templates| C[Templates List Handler]
B -->|GET /templates/{id}| D[Template Detail Handler]
C --> E[Load Templates Config]
D --> E
E --> F{Cache Hit?}
F -->|Yes| G[Return Cached Data]
F -->|No| H[Load from File]
H --> I[Apply Filters]
I --> J[Apply Sorting]
J --> K[Apply Pagination]
K --> L[Update Cache]
L --> M[Return Response]
D --> N[Find Template by ID]
N --> O{Found?}
O -->|No| P[Return 404]
O -->|Yes| Q[Compute ETag]
Q --> R{ETag Match?}
R -->|Yes| S[Return 304]
R -->|No| T[Return Template with ETag]
subgraph Templates System
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
end
subgraph Configuration
U[templates_config.json]
V[TEMPLATES_CONFIG_PATH ENV]
end
H --> U
H --> V
- Create
packages/templates/templates_config.json - Include seed items as specified in the task
- Include
node_id_defaultfield for consistency with sources
- Add loader functions to
app/main.pyfollowing sources pattern - Implement cache with TTL
- Support TEMPLATES_CONFIG_PATH environment variable override
- Create filter functions for channel, locale, status, tag, and query
- Create sort function for template fields
- Create pagination helper
- Create
app/templates_validate.pyfollowing sources_validate.py pattern - Validate required fields: id, name, channel, locale, status, vars, example
- Validate optional fields: tags
- Validate status values: active, paused, deprecated
- Validate vars is a list of strings
- Add endpoint handler to
app/main.py - Support query parameters: channel, locale, status, tag, q, limit, offset, sort
- Apply filters, sorting, and pagination
- Return response with templates list, metadata, and generated_at
- Include rate limit headers
- Add endpoint handler to
app/main.py - Find template by ID
- Compute ETag using existing compute_etag function
- Support If-None-Match header for conditional requests
- Return 304 Not Modified when ETag matches
- Return 404 when template not found
- Include rate limit headers
- Create
apps/action-engine-api/tests/contract/test_templates_contract.py - Test basic response structure and headers
- Test filtering by channel, locale, status, tag, and query
- Test pagination with limit and offset
- Test sorting by various fields
- Test rate limit headers presence
- Create
apps/action-engine-api/tests/contract/test_template_by_id_contract.py - Test basic response structure and headers
- Test ETag header presence
- Test If-None-Match functionality
- Test 404 response for non-existent template
- Test rate limit headers presence
- Create
apps/action-engine-api/tests/unit/test_templates_logic.py - Test filter functions individually
- Test sort function
- Test pagination
- Test cache behavior
- Test environment variable override
- Add templates endpoints to
examples/requests.http - Add templates validation to
scripts/demo.sh - Add templates documentation to
README.md
packages/
templates/
templates_config.json # New file
apps/action-engine-api/
app/
main.py # Add templates loader and endpoints
templates_validate.py # New file for validation
tests/
contract/
test_templates_contract.py # New file
test_template_by_id_contract.py # New file
unit/
test_templates_logic.py # New file
examples/
requests.http # Add templates endpoints
scripts/
demo.sh # Add templates validation
README.md # Add templates documentation
{
"node_id_default": "demo",
"templates": [
{
"id": "rain_flash_sale",
"name": "Rainy Day Flash Sale",
"channel": "social_post",
"locale": "zh-Hant",
"tags": ["rain","promotion","footfall"],
"status": "active",
"vars": ["shop_name","discount_pct","time_window"],
"example": "【{{shop_name}}|雨天限定】{{time_window}} 全品項 {{discount_pct}}% 折扣,外帶再送熱飲!"
}
]
}{
"templates": [...],
"meta": {
"count": <int>,
"limit": <int>,
"offset": <int>,
"filters": {...},
"sort": "<or null>"
},
"generated_at": "<ISO8601>"
}{
"template": {...},
"generated_at": "<ISO8601>"
}- filter_by_channel(templates, channel_filter)
- filter_by_locale(templates, locale_filter)
- filter_by_status(templates, status_filter)
- filter_by_tag(templates, tag_filter)
- filter_by_query(templates, query)
- apply_sort(templates, sort_field) - supports id, name, channel, locale, status with optional "-" prefix
- Verify response structure and required fields
- Verify rate limit headers are present
- Verify filtering works correctly
- Verify pagination works correctly
- Verify sorting works correctly
- Verify ETag functionality for detail endpoint
- Test each filter function in isolation
- Test sort function with various fields and directions
- Test pagination edge cases
- Test cache hit/miss behavior
- Test environment variable override
No new dependencies required. Reuse existing patterns and functions from sources implementation.