From 95aebe1cebe159cea3440211c0d2c06fcacf0926 Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Thu, 5 Feb 2026 14:47:20 +0800 Subject: [PATCH] Add tombi and plugin JSON schema config (#1062) * Add tombi and plugin JSON schema config * Add tombi lint --- .pre-commit-config.yaml | 2 + .schemas/plugin.schema.json | 138 ++++++++++++++++++++++++++++++ backend/plugin/email/plugin.toml | 4 +- backend/plugin/oauth2/plugin.toml | 8 +- pyproject.toml | 7 ++ 5 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 .schemas/plugin.schema.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a5ae7835..3e766ed0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,8 @@ repos: - repo: https://github.com/tombi-toml/tombi-pre-commit rev: v0.7.26 hooks: + - id: tombi-lint + args: ["--offline"] - id: tombi-format args: ["--offline"] diff --git a/.schemas/plugin.schema.json b/.schemas/plugin.schema.json new file mode 100644 index 00000000..bec10467 --- /dev/null +++ b/.schemas/plugin.schema.json @@ -0,0 +1,138 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "FBA Plugin Manifest Schema", + "description": "JSON Schema for FastAPI Best Architecture plugin.toml files. See: https://fastapi-practices.github.io/fastapi_best_architecture_docs/plugin/dev.html", + + "type": "object", + "required": ["plugin", "app"], + "additionalProperties": false, + + "properties": { + "plugin": { + "type": "object", + "description": "Plugin metadata", + "required": ["summary", "version", "description", "author"], + "additionalProperties": false, + "x-tombi-table-keys-order": "schema", + "properties": { + "icon": { + "type": "string", + "description": "Icon path (plugin repository icon path or URL)" + }, + "summary": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "description": "Brief summary (1-100 characters)" + }, + "version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+$", + "description": "Plugin version (semver format: x.y.z)" + }, + "description": { + "type": "string", + "minLength": 1, + "maxLength": 500, + "description": "Detailed description (1-500 characters)" + }, + "author": { + "type": "string", + "minLength": 1, + "maxLength": 50, + "description": "Plugin author (1-50 characters)" + }, + "tags": { + "type": "array", + "description": "Plugin tags for categorization (will be required in next major version)", + "items": { + "type": "string", + "enum": ["ai", "mcp", "agent", "auth", "storage", "notification", "task", "payment", "other"] + }, + "x-tombi-array-values-order": "ascending" + }, + "database": { + "type": "array", + "description": "Supported databases (will be required in next major version)", + "items": { + "type": "string", + "enum": ["mysql", "postgresql"] + }, + "x-tombi-array-values-order": "ascending" + } + } + }, + + "app": { + "type": "object", + "description": "Application configuration. For app-level plugins: use 'router'. For extend-level plugins: use 'extend'.", + "additionalProperties": false, + "minProperties": 1, + "x-tombi-table-keys-order": "schema", + "properties": { + "extend": { + "type": "string", + "minLength": 1, + "description": "Parent app folder name (for extension-level plugins)" + }, + "router": { + "type": "array", + "minItems": 1, + "description": "Router instances (for application-level plugins)", + "items": { + "type": "string", + "minLength": 1 + }, + "x-tombi-array-values-order": "version-sort" + } + } + }, + + "settings": { + "type": "object", + "description": "Plugin base configuration (hot-pluggable, uppercase keys only)", + "x-tombi-additional-key-label": "SETTING_NAME", + "x-tombi-table-keys-order": "ascending", + "propertyNames": { + "pattern": "^[A-Z][A-Z0-9_]*$" + }, + "additionalProperties": { + "oneOf": [ + { "type": "string" }, + { "type": "number" }, + { "type": "boolean" } + ] + } + }, + + "api": { + "type": "object", + "description": "API endpoint configurations (for extension-level plugins). The key (e.g., 'xxx' in api.xxx) corresponds to the API filename without extension.", + "x-tombi-additional-key-label": "api_filename", + "x-tombi-table-keys-order": "ascending", + "minProperties": 1, + "propertyNames": { + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" + }, + "additionalProperties": { + "type": "object", + "required": ["prefix", "tags"], + "additionalProperties": false, + "x-tombi-table-keys-order": {"properties": "schema"}, + "properties": { + "prefix": { + "type": "string", + "minLength": 1, + "pattern": "^/[a-zA-Z0-9_/-]*$", + "description": "URL prefix for the API (must start with '/', allowed chars: a-z, A-Z, 0-9, _, -, /)" + }, + "tags": { + "type": "string", + "minLength": 1, + "description": "OpenAPI tags for Swagger documentation" + } + } + } + } + } +} diff --git a/backend/plugin/email/plugin.toml b/backend/plugin/email/plugin.toml index 763b6bea..f7b106b5 100644 --- a/backend/plugin/email/plugin.toml +++ b/backend/plugin/email/plugin.toml @@ -10,8 +10,8 @@ database = ["mysql", "postgresql"] router = ["v1"] [settings] +EMAIL_CAPTCHA_EXPIRE_SECONDS = 180 # 3 分钟 +EMAIL_CAPTCHA_REDIS_PREFIX = "fba:email:captcha" EMAIL_HOST = "smtp.qq.com" EMAIL_PORT = 465 EMAIL_SSL = true -EMAIL_CAPTCHA_REDIS_PREFIX = "fba:email:captcha" -EMAIL_CAPTCHA_EXPIRE_SECONDS = 180 # 3 分钟 diff --git a/backend/plugin/oauth2/plugin.toml b/backend/plugin/oauth2/plugin.toml index eb7693fc..58e6b16f 100644 --- a/backend/plugin/oauth2/plugin.toml +++ b/backend/plugin/oauth2/plugin.toml @@ -10,9 +10,9 @@ database = ["mysql", "postgresql"] router = ["v1"] [settings] -OAUTH2_STATE_REDIS_PREFIX = "fba:oauth2:state" -OAUTH2_STATE_EXPIRE_SECONDS = 180 # 3 分钟 +OAUTH2_FRONTEND_BINDING_REDIRECT_URI = "http://localhost:5173/profile" +OAUTH2_FRONTEND_LOGIN_REDIRECT_URI = "http://localhost:5173/oauth2/callback" OAUTH2_GITHUB_REDIRECT_URI = "http://127.0.0.1:8000/api/v1/oauth2/github/callback" OAUTH2_GOOGLE_REDIRECT_URI = "http://127.0.0.1:8000/api/v1/oauth2/google/callback" -OAUTH2_FRONTEND_LOGIN_REDIRECT_URI = "http://localhost:5173/oauth2/callback" -OAUTH2_FRONTEND_BINDING_REDIRECT_URI = "http://localhost:5173/profile" +OAUTH2_STATE_EXPIRE_SECONDS = 180 # 3 分钟 +OAUTH2_STATE_REDIS_PREFIX = "fba:oauth2:state" diff --git a/pyproject.toml b/pyproject.toml index 50cb2294..3ee2fe98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -275,6 +275,13 @@ docstring-code-format = true preview = true quote-style = "single" +[tool.tombi] +toml-version = "v1.1.0" + +[[tool.tombi.schemas]] +path = ".schemas/plugin.schema.json" +include = ["backend/plugin/**/plugin.toml"] + [tool.uv] python-downloads = "manual" default-groups = ["dev", "lint"]