Fix API compatibility and add user/role/permission and asset import/export
This commit is contained in:
73
backend/app/utils/case.py
Normal file
73
backend/app/utils/case.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
Case conversion utilities for API payloads.
|
||||
"""
|
||||
import re
|
||||
from typing import Any, Dict, List
|
||||
|
||||
|
||||
_FIRST_CAP_RE = re.compile(r"(.)([A-Z][a-z]+)")
|
||||
_ALL_CAP_RE = re.compile(r"([a-z0-9])([A-Z])")
|
||||
|
||||
_SPECIAL_ALIASES = {
|
||||
"avatar_url": "avatar",
|
||||
"avatarUrl": "avatar",
|
||||
}
|
||||
|
||||
|
||||
def to_snake(name: str) -> str:
|
||||
"""Convert camelCase/PascalCase to snake_case."""
|
||||
if not isinstance(name, str) or not name:
|
||||
return name
|
||||
if name.lower() == name:
|
||||
return name
|
||||
s1 = _FIRST_CAP_RE.sub(r"\1_\2", name)
|
||||
s2 = _ALL_CAP_RE.sub(r"\1_\2", s1)
|
||||
return s2.lower()
|
||||
|
||||
|
||||
def to_camel(name: str) -> str:
|
||||
"""Convert snake_case to camelCase."""
|
||||
if not isinstance(name, str) or not name:
|
||||
return name
|
||||
if "_" not in name:
|
||||
return name
|
||||
parts = name.split("_")
|
||||
if not parts:
|
||||
return name
|
||||
first = parts[0]
|
||||
rest = "".join(part.capitalize() if part else "_" for part in parts[1:])
|
||||
return first + rest
|
||||
|
||||
|
||||
def convert_keys_to_snake(data: Any) -> Any:
|
||||
"""Recursively convert dict keys to snake_case."""
|
||||
if isinstance(data, list):
|
||||
return [convert_keys_to_snake(item) for item in data]
|
||||
if isinstance(data, dict):
|
||||
converted: Dict[Any, Any] = {}
|
||||
for key, value in data.items():
|
||||
new_key = to_snake(key) if isinstance(key, str) else key
|
||||
converted[new_key] = convert_keys_to_snake(value)
|
||||
return converted
|
||||
return data
|
||||
|
||||
|
||||
def add_camelcase_aliases(data: Any) -> Any:
|
||||
"""Recursively add camelCase aliases for snake_case keys."""
|
||||
if isinstance(data, list):
|
||||
return [add_camelcase_aliases(item) for item in data]
|
||||
if isinstance(data, dict):
|
||||
result: Dict[Any, Any] = {}
|
||||
for key, value in data.items():
|
||||
result[key] = add_camelcase_aliases(value)
|
||||
# Add camelCase aliases without overriding existing keys
|
||||
for key, value in list(result.items()):
|
||||
if isinstance(key, str):
|
||||
camel_key = to_camel(key)
|
||||
if camel_key != key and camel_key not in result:
|
||||
result[camel_key] = value
|
||||
alias_key = _SPECIAL_ALIASES.get(key)
|
||||
if alias_key and alias_key not in result:
|
||||
result[alias_key] = value
|
||||
return result
|
||||
return data
|
||||
Reference in New Issue
Block a user