feature:refine
Interactive wizard to configure refinement for a feature — extend models, override services, templates, and hooks from a base feature.
Table of contents
Usage
splent feature:refine <refiner_name>
Example
splent feature:refine splent_feature_notes_tags
Description
This command launches an interactive wizard that:
- Updates contracts of all editable features in the product (so extensible points are current).
- Lists features with extensible points (models, services, templates, hooks, routes).
- Presents extensible points by category with multi-select.
- Generates the
[tool.splent.refinement]section inpyproject.toml. - Scaffolds skeleton code:
models.py— mixin classes (replaces the scaffold’s defaultdb.Model)services.py— replacement service classes (replaces the scaffold’s default service/repository)__init__.py—refine_model()andrefine_service()calls wired upmigrations/env.py— migration scope updated to include base feature tables
- Updates the contract of the refiner feature.
Wizard flow
Step 1: Which feature do you want to refine?
1. auth
1 service(s), 1 model(s), 2 template(s), 4 hook(s), routes
2. notes
1 service(s), 1 model(s), 3 template(s), 1 hook(s), routes
Select: 2
Step 2: What do you want to do?
Models (extend with mixins)
1. Notes
Select: 1
mixin: Notes <- NotesTagsMixin
Services (override with replacement)
1. NotesService
Select: 1
override: NotesService -> NotesServiceWithTags
Step 3: Review
[tool.splent.refinement]
refines = "splent_feature_notes"
...
Write to pyproject.toml and scaffold code? [Y/n]: y
done.
What it generates
pyproject.toml
[tool.splent.refinement]
refines = "splent_feature_notes"
[tool.splent.refinement.extends]
models = [{ target = "Notes", mixin = "NotesTagsMixin" }]
[tool.splent.refinement.overrides]
services = [{ target = "NotesService", replacement = "NotesServiceWithTags" }]
init.py
from splent_framework.blueprints.base_blueprint import create_blueprint
from splent_framework.refinement import refine_model, refine_service
from .models import NotesTagsMixin
from .services import NotesServiceWithTags
notes_tags_bp = create_blueprint(__name__)
def init_feature(app):
refine_model("Notes", NotesTagsMixin)
refine_service(app, "NotesService", NotesServiceWithTags)
migrations/env.py
The wizard updates FEATURE_TABLES to include the base feature’s table, so db:migrate detects add_column operations automatically:
FEATURE_TABLES = {"notes"} # includes base table for mixin columns
Name generation
The wizard generates class names by combining the model/service name with the refiner’s suffix:
| Refiner | Base | Generated mixin | Generated service |
|---|---|---|---|
notes_tags refining notes |
Notes |
NotesTagsMixin |
NotesServiceWithTags |
auth_2fa refining auth |
User |
User2faMixin |
AuthenticationServiceWith2fa |
If the refiner name starts with the base feature name (e.g. notes_tags starts with notes), only the suffix is used (Tags) to avoid repetition.
Requirements
- A product must be selected (
SPLENT_APPset). - The refiner feature must exist at workspace root (editable).
- The base feature must have
[tool.splent.contract.extensible]with at least one extension point.
See also
- feature:contract — Infer and update feature contracts
- feature:xray — View the full composition and refinement map
- Tutorial 6: Extend with refinement — Step-by-step guide