Lowers the barrier for sister sites to build their own plugins.
Generated output satisfies the framework contract out of the box.
CLI command (shopdb/plugins/cli.py):
- `flask plugin new <name> --description "..."` generates a plugin
skeleton under plugins/<name>/. Validates the name against
CONTRIBUTING.md rules (lowercase letters/digits only, no
underscores or hyphens, not in the reserved list) and refuses to
overwrite existing plugins unless --overwrite is passed.
- Output prints the next steps (install, migrate, test).
Scaffolder (shopdb/plugins/scaffolder.py):
- validate_name: enforces the naming rules
- pascal_case: lowercase-to-PascalCase for class names
- scaffold_plugin: copies templates with string.Template
substitution. Three placeholders: $name, $Name, $description.
Files with `model.py` in the path get renamed to <name>.py.
Templates (shopdb/plugins/templates/):
- manifest.json.tmpl: name, version 0.1.0, description, core_version
range >=0.1.0,<1.0.0 (broad enough to survive minor framework bumps)
- plugin.py.tmpl: <Name>Plugin class extending BasePlugin with all
required hooks implemented (meta from manifest, get_blueprint
returning the bp, get_models returning the example model). Includes
on_install hook that seeds the AssetType row.
- models/__init__.py.tmpl + models/model.py.tmpl: Asset extension
table keyed by assetid with one example field. TODO comment marks
it as a placeholder.
- api/__init__.py.tmpl + api/routes.py.tmpl: Blueprint with list and
detail endpoints using the framework's pagination + response helpers.
- schemas/__init__.py.tmpl: marshmallow schema stub.
- tests/__init__.py.tmpl + tests/test_plugin.py.tmpl: smoke tests
asserting plugin loads, get_blueprint returns Blueprint, get_models
returns at least one model.
- README.md.tmpl: one-pager for plugin authors with common edits and
next-step references.
Canary tests (tests/test_plugin_scaffold.py):
- 14 tests asserting the scaffold output passes contract checks.
- Validates name rules (lowercase, reserved, hyphens, digits, etc.)
- Verifies all expected files generated, manifest fields present.
- Loads the generated plugin via PluginLoader (spec_from_file_location
bypasses the real `plugins` package shadowing).
- Asserts subclasses BasePlugin, get_blueprint returns Blueprint,
get_models returns model with __tablename__.
- Module-scoped fixture; cleans up sys.modules + SQLAlchemy metadata
on teardown to avoid cross-test contamination.
Quickstart docs (docs/PLUGIN-QUICKSTART.md):
- 30-minute walkthrough: scaffold -> edit model -> add routes ->
install -> verify -> add hooks. Cross-links to PLUGIN-HOOKS.md and
the ADRs. Includes common-errors table.
Test count: 87 -> 101 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>