feature:refine

Interactive wizard to configure refinement for a feature — extend models, override services, templates, and hooks from a base feature.


Table of contents

  1. Usage
    1. Example
  2. Description
  3. Wizard flow
  4. What it generates
    1. pyproject.toml
    2. init.py
    3. migrations/env.py
  5. Name generation
  6. Requirements
  7. See also

Usage

splent feature:refine <refiner_name>

Example

splent feature:refine splent_feature_notes_tags

Description

This command launches an interactive wizard that:

  1. Updates contracts of all editable features in the product (so extensible points are current).
  2. Lists features with extensible points (models, services, templates, hooks, routes).
  3. Presents extensible points by category with multi-select.
  4. Generates the [tool.splent.refinement] section in pyproject.toml.
  5. Scaffolds skeleton code:
    • models.py — mixin classes (replaces the scaffold’s default db.Model)
    • services.py — replacement service classes (replaces the scaffold’s default service/repository)
    • __init__.pyrefine_model() and refine_service() calls wired up
    • migrations/env.py — migration scope updated to include base feature tables
  6. 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_APP set).
  • 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


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es