- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types) - references/: tool constraints + error handling (self-contained) - scripts/setup.py: one-click install/config/verify - SKILL.md: full command reference + dual-platform install guide - VERSION: 2.1.0 Built from D:/Codespace/sap-cli via scripts/pack_skill.py
244 lines
8.0 KiB
Python
244 lines
8.0 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from sapcli.exceptions import InvalidNameError
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ObjectTypeConfig:
|
|
key: str
|
|
label: str
|
|
obj_uri_template: str
|
|
src_uri_template: str | None
|
|
collection_uri: str
|
|
create_content_type: str
|
|
has_source: bool = True
|
|
|
|
def format_obj_uri(self, name: str, **kwargs: str) -> str:
|
|
return self.obj_uri_template.format(name=name, **kwargs)
|
|
|
|
def format_src_uri(self, name: str, **kwargs: str) -> str | None:
|
|
if self.src_uri_template is None:
|
|
return None
|
|
return self.src_uri_template.format(name=name, **kwargs)
|
|
|
|
def format_collection_uri(self, **kwargs: str) -> str:
|
|
return self.collection_uri.format(**kwargs)
|
|
|
|
|
|
_OBJECT_TYPE_REGISTRY: dict[str, ObjectTypeConfig] = {}
|
|
|
|
|
|
def _register(cfg: ObjectTypeConfig) -> ObjectTypeConfig:
|
|
_OBJECT_TYPE_REGISTRY[cfg.key] = cfg
|
|
return cfg
|
|
|
|
|
|
REPORT = _register(ObjectTypeConfig(
|
|
key="report",
|
|
label="程序(REPORT)",
|
|
obj_uri_template="/sap/bc/adt/programs/programs/{name}",
|
|
src_uri_template="/sap/bc/adt/programs/programs/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/programs/programs",
|
|
create_content_type="application/vnd.sap.adt.programs.programs.v2+xml",
|
|
))
|
|
|
|
CLASS = _register(ObjectTypeConfig(
|
|
key="class",
|
|
label="类(CLASS)",
|
|
obj_uri_template="/sap/bc/adt/oo/classes/{name}",
|
|
src_uri_template="/sap/bc/adt/oo/classes/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/oo/classes",
|
|
create_content_type="application/vnd.sap.adt.oo.classes.v1+xml",
|
|
))
|
|
|
|
FUNCTION = _register(ObjectTypeConfig(
|
|
key="function",
|
|
label="函数模块(FUNCTION)",
|
|
obj_uri_template="/sap/bc/adt/functions/groups/{group}/fmodules/{name}",
|
|
src_uri_template="/sap/bc/adt/functions/groups/{group}/fmodules/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/functions/groups/{group}/fmodules",
|
|
create_content_type="application/vnd.sap.adt.functions.fmodules.v1+xml",
|
|
))
|
|
|
|
FUNCTIONGROUP = _register(ObjectTypeConfig(
|
|
key="functiongroup",
|
|
label="函数组(FUNCTION GROUP)",
|
|
obj_uri_template="/sap/bc/adt/functions/groups/{name}",
|
|
src_uri_template=None,
|
|
collection_uri="/sap/bc/adt/functions/groups",
|
|
create_content_type="application/vnd.sap.adt.functions.groups.v2+xml",
|
|
has_source=False,
|
|
))
|
|
|
|
INTERFACE = _register(ObjectTypeConfig(
|
|
key="interface",
|
|
label="接口(INTERFACE)",
|
|
obj_uri_template="/sap/bc/adt/oo/interfaces/{name}",
|
|
src_uri_template="/sap/bc/adt/oo/interfaces/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/oo/interfaces",
|
|
create_content_type="application/vnd.sap.adt.oo.interfaces.v1+xml",
|
|
))
|
|
|
|
DOMAIN = _register(ObjectTypeConfig(
|
|
key="domain",
|
|
label="域(DOMAIN)",
|
|
obj_uri_template="/sap/bc/adt/ddic/domains/{name}",
|
|
src_uri_template="/sap/bc/adt/ddic/domains/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/ddic/domains",
|
|
create_content_type="application/vnd.sap.adt.domains.v2+xml",
|
|
))
|
|
|
|
DATAELEMENT = _register(ObjectTypeConfig(
|
|
key="dataelement",
|
|
label="数据元素(DATA ELEMENT)",
|
|
obj_uri_template="/sap/bc/adt/ddic/dataelements/{name}",
|
|
src_uri_template="/sap/bc/adt/ddic/dataelements/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/ddic/dataelements",
|
|
create_content_type="application/vnd.sap.adt.dataelements.v2+xml",
|
|
))
|
|
|
|
TABLE = _register(ObjectTypeConfig(
|
|
key="table",
|
|
label="透明表(TABLE)",
|
|
obj_uri_template="/sap/bc/adt/ddic/tables/{name}",
|
|
src_uri_template="/sap/bc/adt/ddic/tables/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/ddic/tables",
|
|
create_content_type="application/vnd.sap.adt.ddic.tables.v1+xml",
|
|
))
|
|
|
|
STRUCTURE = _register(ObjectTypeConfig(
|
|
key="structure",
|
|
label="结构(STRUCTURE)",
|
|
obj_uri_template="/sap/bc/adt/ddic/structures/{name}",
|
|
src_uri_template="/sap/bc/adt/ddic/structures/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/ddic/structures",
|
|
create_content_type="application/vnd.sap.adt.ddic.structures.v1+xml",
|
|
))
|
|
|
|
TABLETYPE = _register(ObjectTypeConfig(
|
|
key="tabletype",
|
|
label="表类型(TABLE TYPE)",
|
|
obj_uri_template="/sap/bc/adt/vit/wb/object_type/ttypda/object_name/{name}",
|
|
src_uri_template=None,
|
|
collection_uri="/sap/bc/adt/ddic/tabletypes",
|
|
create_content_type="application/vnd.sap.adt.ddic.tabletypes.v1+xml",
|
|
has_source=False,
|
|
))
|
|
|
|
INCLUDE = _register(ObjectTypeConfig(
|
|
key="include",
|
|
label="Include程序(INCLUDE)",
|
|
obj_uri_template="/sap/bc/adt/programs/includes/{name}",
|
|
src_uri_template="/sap/bc/adt/programs/includes/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/programs/includes",
|
|
create_content_type="application/vnd.sap.adt.programs.includes.v2+xml",
|
|
))
|
|
|
|
CDSVIEW = _register(ObjectTypeConfig(
|
|
key="cdsview",
|
|
label="CDS视图(CDS VIEW)",
|
|
obj_uri_template="/sap/bc/adt/dds/ddl/sources/{name}",
|
|
src_uri_template="/sap/bc/adt/dds/ddl/sources/{name}/content",
|
|
collection_uri="/sap/bc/adt/dds/ddl/sources",
|
|
create_content_type="text/plain",
|
|
))
|
|
|
|
MESSAGECLASS = _register(ObjectTypeConfig(
|
|
key="messageclass",
|
|
label="消息类(MESSAGE CLASS)",
|
|
obj_uri_template="/sap/bc/adt/oo/t100/messages/classes/{name}",
|
|
src_uri_template=None,
|
|
collection_uri="/sap/bc/adt/oo/t100/messages/classes",
|
|
create_content_type="application/vnd.sap.adt.t100.message.classes.v1+xml",
|
|
has_source=False,
|
|
))
|
|
|
|
VIEW = _register(ObjectTypeConfig(
|
|
key="view",
|
|
label="数据库视图(VIEW)",
|
|
obj_uri_template="/sap/bc/adt/ddic/views/{name}",
|
|
src_uri_template="/sap/bc/adt/ddic/views/{name}/source/main",
|
|
collection_uri="/sap/bc/adt/ddic/views",
|
|
create_content_type="application/vnd.sap.adt.ddic.views.v1+xml",
|
|
))
|
|
|
|
SEARCHHELP = _register(ObjectTypeConfig(
|
|
key="searchhelp",
|
|
label="搜索帮助(SEARCH HELP)",
|
|
obj_uri_template="/sap/bc/adt/ddic/searchhelps/{name}",
|
|
src_uri_template=None,
|
|
collection_uri="/sap/bc/adt/ddic/searchhelps",
|
|
create_content_type="application/vnd.sap.adt.ddic.searchhelps.v1+xml",
|
|
has_source=False,
|
|
))
|
|
|
|
LOCKOBJECT = _register(ObjectTypeConfig(
|
|
key="lockobject",
|
|
label="锁对象(LOCK OBJECT)",
|
|
obj_uri_template="/sap/bc/adt/ddic/lockobjects/{name}",
|
|
src_uri_template=None,
|
|
collection_uri="/sap/bc/adt/ddic/lockobjects",
|
|
create_content_type="application/vnd.sap.adt.ddic.lockobjects.v1+xml",
|
|
has_source=False,
|
|
))
|
|
|
|
|
|
def get_type_config(key: str) -> ObjectTypeConfig:
|
|
if key not in _OBJECT_TYPE_REGISTRY:
|
|
raise ValueError(f"不支持的对象类型: {key}")
|
|
return _OBJECT_TYPE_REGISTRY[key]
|
|
|
|
|
|
def all_type_keys() -> list[str]:
|
|
return list(_OBJECT_TYPE_REGISTRY.keys())
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ParsedName:
|
|
obj_uri: str
|
|
src_uri: str | None
|
|
display_name: str
|
|
file_base: str
|
|
|
|
|
|
def parse_object_name(name: str, obj_type: str) -> ParsedName:
|
|
cfg = get_type_config(obj_type)
|
|
|
|
if obj_type == "function":
|
|
if "/" not in name:
|
|
raise InvalidNameError(
|
|
"function 类型需要'函数组名/函数模块名' 格式,例如: ZGROUP/Z_MY_FUNC"
|
|
)
|
|
group, fm = name.split("/", 1)
|
|
group = group.strip()
|
|
fm = fm.strip()
|
|
if not group or not fm:
|
|
raise InvalidNameError("函数组名和函数模块名不能为空")
|
|
return ParsedName(
|
|
obj_uri=cfg.format_obj_uri(fm.lower(), group=group.lower()),
|
|
src_uri=cfg.format_src_uri(fm.lower(), group=group.lower()),
|
|
display_name=name,
|
|
file_base=fm.lower(),
|
|
)
|
|
|
|
# VIT 端点需要大写名称以返回完整元数据;去掉前导 /
|
|
if obj_type == "tabletype":
|
|
clean = name.lstrip("/")
|
|
name_upper = clean.upper()
|
|
return ParsedName(
|
|
obj_uri=cfg.format_obj_uri(name_upper),
|
|
src_uri=cfg.format_src_uri(name_upper),
|
|
display_name=clean,
|
|
file_base=clean.lower(),
|
|
)
|
|
|
|
name_lower = name.lower()
|
|
return ParsedName(
|
|
obj_uri=cfg.format_obj_uri(name_lower),
|
|
src_uri=cfg.format_src_uri(name_lower),
|
|
display_name=name,
|
|
file_base=name_lower,
|
|
)
|