@josephyan/qingflow-cli 0.2.0-beta.1000
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/docs/local-agent-install.md +309 -0
- package/entry_point.py +13 -0
- package/npm/bin/qingflow.mjs +5 -0
- package/npm/lib/runtime.mjs +346 -0
- package/npm/scripts/postinstall.mjs +16 -0
- package/package.json +34 -0
- package/pyproject.toml +67 -0
- package/qingflow +15 -0
- package/src/qingflow_mcp/__init__.py +37 -0
- package/src/qingflow_mcp/__main__.py +5 -0
- package/src/qingflow_mcp/backend_client.py +649 -0
- package/src/qingflow_mcp/builder_facade/__init__.py +3 -0
- package/src/qingflow_mcp/builder_facade/models.py +1846 -0
- package/src/qingflow_mcp/builder_facade/service.py +16502 -0
- package/src/qingflow_mcp/cli/__init__.py +1 -0
- package/src/qingflow_mcp/cli/commands/__init__.py +18 -0
- package/src/qingflow_mcp/cli/commands/app.py +40 -0
- package/src/qingflow_mcp/cli/commands/auth.py +112 -0
- package/src/qingflow_mcp/cli/commands/builder.py +539 -0
- package/src/qingflow_mcp/cli/commands/chart.py +18 -0
- package/src/qingflow_mcp/cli/commands/common.py +62 -0
- package/src/qingflow_mcp/cli/commands/imports.py +96 -0
- package/src/qingflow_mcp/cli/commands/portal.py +25 -0
- package/src/qingflow_mcp/cli/commands/record.py +331 -0
- package/src/qingflow_mcp/cli/commands/repo.py +80 -0
- package/src/qingflow_mcp/cli/commands/task.py +141 -0
- package/src/qingflow_mcp/cli/commands/view.py +18 -0
- package/src/qingflow_mcp/cli/commands/workspace.py +110 -0
- package/src/qingflow_mcp/cli/context.py +60 -0
- package/src/qingflow_mcp/cli/formatters.py +573 -0
- package/src/qingflow_mcp/cli/json_io.py +50 -0
- package/src/qingflow_mcp/cli/main.py +186 -0
- package/src/qingflow_mcp/cli/qingflow_login.py +116 -0
- package/src/qingflow_mcp/cli/terminal_ui.py +173 -0
- package/src/qingflow_mcp/config.py +407 -0
- package/src/qingflow_mcp/errors.py +66 -0
- package/src/qingflow_mcp/id_utils.py +49 -0
- package/src/qingflow_mcp/import_store.py +121 -0
- package/src/qingflow_mcp/json_types.py +18 -0
- package/src/qingflow_mcp/list_type_labels.py +76 -0
- package/src/qingflow_mcp/public_surface.py +243 -0
- package/src/qingflow_mcp/repository_store.py +71 -0
- package/src/qingflow_mcp/response_trim.py +841 -0
- package/src/qingflow_mcp/server.py +216 -0
- package/src/qingflow_mcp/server_app_builder.py +543 -0
- package/src/qingflow_mcp/server_app_user.py +386 -0
- package/src/qingflow_mcp/session_store.py +369 -0
- package/src/qingflow_mcp/solution/__init__.py +6 -0
- package/src/qingflow_mcp/solution/build_assembly_store.py +181 -0
- package/src/qingflow_mcp/solution/compiler/__init__.py +282 -0
- package/src/qingflow_mcp/solution/compiler/chart_compiler.py +96 -0
- package/src/qingflow_mcp/solution/compiler/form_compiler.py +495 -0
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +187 -0
- package/src/qingflow_mcp/solution/compiler/navigation_compiler.py +57 -0
- package/src/qingflow_mcp/solution/compiler/package_compiler.py +19 -0
- package/src/qingflow_mcp/solution/compiler/portal_compiler.py +60 -0
- package/src/qingflow_mcp/solution/compiler/view_compiler.py +51 -0
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
- package/src/qingflow_mcp/solution/design_session.py +222 -0
- package/src/qingflow_mcp/solution/design_store.py +100 -0
- package/src/qingflow_mcp/solution/executor.py +2398 -0
- package/src/qingflow_mcp/solution/normalizer.py +23 -0
- package/src/qingflow_mcp/solution/requirements_builder.py +536 -0
- package/src/qingflow_mcp/solution/run_store.py +244 -0
- package/src/qingflow_mcp/solution/spec_models.py +855 -0
- package/src/qingflow_mcp/tools/__init__.py +1 -0
- package/src/qingflow_mcp/tools/ai_builder_tools.py +3449 -0
- package/src/qingflow_mcp/tools/app_tools.py +926 -0
- package/src/qingflow_mcp/tools/approval_tools.py +1062 -0
- package/src/qingflow_mcp/tools/auth_tools.py +1133 -0
- package/src/qingflow_mcp/tools/base.py +281 -0
- package/src/qingflow_mcp/tools/code_block_tools.py +777 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +202 -0
- package/src/qingflow_mcp/tools/directory_tools.py +675 -0
- package/src/qingflow_mcp/tools/feedback_tools.py +238 -0
- package/src/qingflow_mcp/tools/file_tools.py +409 -0
- package/src/qingflow_mcp/tools/import_tools.py +2223 -0
- package/src/qingflow_mcp/tools/navigation_tools.py +210 -0
- package/src/qingflow_mcp/tools/package_tools.py +326 -0
- package/src/qingflow_mcp/tools/portal_tools.py +158 -0
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +374 -0
- package/src/qingflow_mcp/tools/record_tools.py +14291 -0
- package/src/qingflow_mcp/tools/repository_dev_tools.py +552 -0
- package/src/qingflow_mcp/tools/resource_read_tools.py +503 -0
- package/src/qingflow_mcp/tools/role_tools.py +112 -0
- package/src/qingflow_mcp/tools/solution_tools.py +4054 -0
- package/src/qingflow_mcp/tools/task_context_tools.py +2986 -0
- package/src/qingflow_mcp/tools/task_tools.py +889 -0
- package/src/qingflow_mcp/tools/view_tools.py +335 -0
- package/src/qingflow_mcp/tools/workflow_tools.py +376 -0
- package/src/qingflow_mcp/tools/workspace_tools.py +266 -0
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ..context import CliContext
|
|
6
|
+
from .common import load_list_arg, load_object_arg, raise_config_error, require_list_arg
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
10
|
+
parser = subparsers.add_parser("builder", aliases=["build"], help="稳定 builder 命令")
|
|
11
|
+
builder_subparsers = parser.add_subparsers(dest="builder_command", required=True)
|
|
12
|
+
|
|
13
|
+
file_parser = builder_subparsers.add_parser("file", help="builder 侧文件上传")
|
|
14
|
+
file_subparsers = file_parser.add_subparsers(dest="builder_file_command", required=True)
|
|
15
|
+
file_upload_local = file_subparsers.add_parser("upload-local", help="上传本地文件并返回附件值")
|
|
16
|
+
file_upload_local.add_argument("--upload-kind", default="attachment")
|
|
17
|
+
file_upload_local.add_argument("--file-path", required=True)
|
|
18
|
+
file_upload_local.add_argument("--upload-mark")
|
|
19
|
+
file_upload_local.add_argument("--content-type")
|
|
20
|
+
file_upload_local.add_argument("--bucket-type")
|
|
21
|
+
file_upload_local.add_argument("--path-id", type=int)
|
|
22
|
+
file_upload_local.add_argument("--file-related-url")
|
|
23
|
+
file_upload_local.set_defaults(handler=_handle_file_upload_local, format_hint="generic")
|
|
24
|
+
|
|
25
|
+
feedback = builder_subparsers.add_parser("feedback", help="builder 侧反馈提交")
|
|
26
|
+
feedback_subparsers = feedback.add_subparsers(dest="builder_feedback_command", required=True)
|
|
27
|
+
feedback_submit = feedback_subparsers.add_parser("submit", help="提交 builder 能力反馈")
|
|
28
|
+
feedback_submit.add_argument("--category", required=True)
|
|
29
|
+
feedback_submit.add_argument("--title", required=True)
|
|
30
|
+
feedback_submit.add_argument("--description", required=True)
|
|
31
|
+
feedback_submit.add_argument("--expected-behavior")
|
|
32
|
+
feedback_submit.add_argument("--actual-behavior")
|
|
33
|
+
feedback_submit.add_argument("--impact-scope")
|
|
34
|
+
feedback_submit.add_argument("--tool-name")
|
|
35
|
+
feedback_submit.add_argument("--app-key")
|
|
36
|
+
feedback_submit.add_argument("--record-id")
|
|
37
|
+
feedback_submit.add_argument("--workflow-node-id")
|
|
38
|
+
feedback_submit.add_argument("--note")
|
|
39
|
+
feedback_submit.set_defaults(handler=_handle_feedback_submit, format_hint="generic")
|
|
40
|
+
|
|
41
|
+
contract = builder_subparsers.add_parser("contract", help="读取 builder tool 合约")
|
|
42
|
+
contract.add_argument("--tool-name", required=True)
|
|
43
|
+
contract.set_defaults(handler=_handle_contract, format_hint="builder_summary")
|
|
44
|
+
|
|
45
|
+
member = builder_subparsers.add_parser("member", help="成员目录")
|
|
46
|
+
member_subparsers = member.add_subparsers(dest="builder_member_command", required=True)
|
|
47
|
+
member_search = member_subparsers.add_parser("search", help="搜索成员")
|
|
48
|
+
member_search.add_argument("--query", default="")
|
|
49
|
+
member_search.add_argument("--page-num", type=int, default=1)
|
|
50
|
+
member_search.add_argument("--page-size", type=int, default=20)
|
|
51
|
+
member_search.add_argument("--contain-disable", action=argparse.BooleanOptionalAction, default=False)
|
|
52
|
+
member_search.set_defaults(handler=_handle_member_search, format_hint="builder_summary")
|
|
53
|
+
|
|
54
|
+
role = builder_subparsers.add_parser("role", help="角色目录")
|
|
55
|
+
role_subparsers = role.add_subparsers(dest="builder_role_command", required=True)
|
|
56
|
+
role_search = role_subparsers.add_parser("search", help="搜索角色")
|
|
57
|
+
role_search.add_argument("--keyword", default="")
|
|
58
|
+
role_search.add_argument("--page-num", type=int, default=1)
|
|
59
|
+
role_search.add_argument("--page-size", type=int, default=20)
|
|
60
|
+
role_search.set_defaults(handler=_handle_role_search, format_hint="builder_summary")
|
|
61
|
+
|
|
62
|
+
role_create = role_subparsers.add_parser("create", help="创建角色")
|
|
63
|
+
role_create.add_argument("--role-name", required=True)
|
|
64
|
+
role_create.add_argument("--member-uids-file")
|
|
65
|
+
role_create.add_argument("--member-emails-file")
|
|
66
|
+
role_create.add_argument("--member-names-file")
|
|
67
|
+
role_create.add_argument("--role-icon", default="ex-user-outlined")
|
|
68
|
+
role_create.set_defaults(handler=_handle_role_create, format_hint="builder_summary")
|
|
69
|
+
|
|
70
|
+
package = builder_subparsers.add_parser("package", help="应用包")
|
|
71
|
+
package_subparsers = package.add_subparsers(dest="builder_package_command", required=True)
|
|
72
|
+
|
|
73
|
+
solution = builder_subparsers.add_parser("solution", help="解决方案")
|
|
74
|
+
solution_subparsers = solution.add_subparsers(dest="builder_solution_command", required=True)
|
|
75
|
+
solution_install = solution_subparsers.add_parser("install", help="安装解决方案")
|
|
76
|
+
solution_install.add_argument("--solution-key", required=True)
|
|
77
|
+
solution_install.add_argument("--being-copy-data", action=argparse.BooleanOptionalAction, default=True)
|
|
78
|
+
solution_install.add_argument("--solution-source", default="solutionDetail")
|
|
79
|
+
solution_install.set_defaults(handler=_handle_solution_install, format_hint="builder_summary")
|
|
80
|
+
|
|
81
|
+
package_get = package_subparsers.add_parser("get", help="读取应用包详情")
|
|
82
|
+
package_get.add_argument("--package-id", type=int, required=True)
|
|
83
|
+
package_get.set_defaults(handler=_handle_package_get, format_hint="builder_summary")
|
|
84
|
+
|
|
85
|
+
package_apply = package_subparsers.add_parser("apply", help="创建或更新应用包配置")
|
|
86
|
+
package_apply.add_argument("--config-file", required=True)
|
|
87
|
+
package_apply.set_defaults(handler=_handle_package_apply, format_hint="builder_summary")
|
|
88
|
+
|
|
89
|
+
app = builder_subparsers.add_parser("app", help="应用")
|
|
90
|
+
app_subparsers = app.add_subparsers(dest="builder_app_command", required=True)
|
|
91
|
+
|
|
92
|
+
app_resolve = app_subparsers.add_parser("resolve", help="解析应用")
|
|
93
|
+
app_resolve.add_argument("--app-key", default="")
|
|
94
|
+
app_resolve.add_argument("--app-name", default="")
|
|
95
|
+
app_resolve.add_argument("--package-id", type=int)
|
|
96
|
+
app_resolve.set_defaults(handler=_handle_app_resolve, format_hint="builder_summary")
|
|
97
|
+
|
|
98
|
+
app_release_lock = app_subparsers.add_parser("release-edit-lock-if-mine", help="释放当前账号持有的编辑锁")
|
|
99
|
+
app_release_lock.add_argument("--app-key", required=True)
|
|
100
|
+
app_release_lock.add_argument("--lock-owner-email", required=True)
|
|
101
|
+
app_release_lock.add_argument("--lock-owner-name", required=True)
|
|
102
|
+
app_release_lock.set_defaults(handler=_handle_app_release_edit_lock_if_mine, format_hint="builder_summary")
|
|
103
|
+
|
|
104
|
+
app_get = app_subparsers.add_parser("get", help="读取应用配置(字段请使用: builder app get --app-key APP fields)")
|
|
105
|
+
app_get.add_argument(
|
|
106
|
+
"builder_app_get_section",
|
|
107
|
+
nargs="?",
|
|
108
|
+
choices=["summary", "fields", "layout", "views", "flow", "charts"],
|
|
109
|
+
default="summary",
|
|
110
|
+
)
|
|
111
|
+
app_get.add_argument("--app-key", required=True)
|
|
112
|
+
app_get.set_defaults(handler=_handle_app_get, format_hint="builder_summary")
|
|
113
|
+
|
|
114
|
+
app_repair_code_blocks = app_subparsers.add_parser("repair-code-blocks", help="扫描或修复现有代码块配置")
|
|
115
|
+
app_repair_code_blocks.add_argument("--app-key", required=True)
|
|
116
|
+
app_repair_code_blocks.add_argument("--field")
|
|
117
|
+
app_repair_code_blocks.add_argument("--apply", action="store_true")
|
|
118
|
+
app_repair_code_blocks.set_defaults(handler=_handle_app_repair_code_blocks, format_hint="builder_summary")
|
|
119
|
+
|
|
120
|
+
button = builder_subparsers.add_parser("button", help="自定义按钮")
|
|
121
|
+
button_subparsers = button.add_subparsers(dest="builder_button_command", required=True)
|
|
122
|
+
|
|
123
|
+
button_list = button_subparsers.add_parser("list", help="列出自定义按钮")
|
|
124
|
+
button_list.add_argument("--app-key", required=True)
|
|
125
|
+
button_list.set_defaults(handler=_handle_button_list, format_hint="builder_summary")
|
|
126
|
+
|
|
127
|
+
button_get = button_subparsers.add_parser("get", help="读取自定义按钮")
|
|
128
|
+
button_get.add_argument("--app-key", required=True)
|
|
129
|
+
button_get.add_argument("--button-id", type=int, required=True)
|
|
130
|
+
button_get.set_defaults(handler=_handle_button_get, format_hint="builder_summary")
|
|
131
|
+
|
|
132
|
+
button_create = button_subparsers.add_parser("create", help="创建自定义按钮")
|
|
133
|
+
button_create.add_argument("--app-key", required=True)
|
|
134
|
+
button_create.add_argument("--payload-file", required=True)
|
|
135
|
+
button_create.set_defaults(handler=_handle_button_create, format_hint="builder_summary")
|
|
136
|
+
|
|
137
|
+
button_update = button_subparsers.add_parser("update", help="更新自定义按钮")
|
|
138
|
+
button_update.add_argument("--app-key", required=True)
|
|
139
|
+
button_update.add_argument("--button-id", type=int, required=True)
|
|
140
|
+
button_update.add_argument("--payload-file", required=True)
|
|
141
|
+
button_update.set_defaults(handler=_handle_button_update, format_hint="builder_summary")
|
|
142
|
+
|
|
143
|
+
button_delete = button_subparsers.add_parser("delete", help="删除自定义按钮")
|
|
144
|
+
button_delete.add_argument("--app-key", required=True)
|
|
145
|
+
button_delete.add_argument("--button-id", type=int, required=True)
|
|
146
|
+
button_delete.set_defaults(handler=_handle_button_delete, format_hint="builder_summary")
|
|
147
|
+
|
|
148
|
+
portal = builder_subparsers.add_parser("portal", help="门户")
|
|
149
|
+
portal_subparsers = portal.add_subparsers(dest="builder_portal_command", required=True)
|
|
150
|
+
portal_list = portal_subparsers.add_parser("list", help="列出可配置门户")
|
|
151
|
+
portal_list.set_defaults(handler=_handle_portal_list, format_hint="builder_summary")
|
|
152
|
+
|
|
153
|
+
portal_get = portal_subparsers.add_parser("get", help="读取门户详情")
|
|
154
|
+
portal_get.add_argument("--dash-key", required=True)
|
|
155
|
+
portal_get.add_argument("--being-draft", action=argparse.BooleanOptionalAction, default=True)
|
|
156
|
+
portal_get.set_defaults(handler=_handle_portal_get, format_hint="builder_summary")
|
|
157
|
+
|
|
158
|
+
portal_apply = portal_subparsers.add_parser("apply", help="更新门户")
|
|
159
|
+
portal_apply.add_argument("--dash-key", default="")
|
|
160
|
+
portal_apply.add_argument("--dash-name", default="")
|
|
161
|
+
portal_apply.add_argument("--package-id", type=int)
|
|
162
|
+
portal_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
163
|
+
portal_apply.add_argument("--sections-file")
|
|
164
|
+
portal_apply.add_argument("--visibility-file")
|
|
165
|
+
portal_apply.add_argument("--auth-file")
|
|
166
|
+
portal_apply.add_argument("--icon")
|
|
167
|
+
portal_apply.add_argument("--color")
|
|
168
|
+
portal_apply.add_argument("--hide-copyright", action=argparse.BooleanOptionalAction, default=None)
|
|
169
|
+
portal_apply.add_argument("--dash-global-config-file")
|
|
170
|
+
portal_apply.add_argument("--config-file")
|
|
171
|
+
portal_apply.set_defaults(handler=_handle_portal_apply, format_hint="builder_summary")
|
|
172
|
+
|
|
173
|
+
schema_apply = builder_subparsers.add_parser("schema", help="字段搭建")
|
|
174
|
+
schema_apply_subparsers = schema_apply.add_subparsers(dest="builder_schema_command", required=True)
|
|
175
|
+
schema_apply_apply = schema_apply_subparsers.add_parser("apply", help="执行字段变更")
|
|
176
|
+
schema_apply_apply.add_argument("--app-key", default="")
|
|
177
|
+
schema_apply_apply.add_argument("--package-id", type=int)
|
|
178
|
+
schema_apply_apply.add_argument("--app-name", default="")
|
|
179
|
+
schema_apply_apply.add_argument("--app-title", default="")
|
|
180
|
+
schema_apply_apply.add_argument("--icon")
|
|
181
|
+
schema_apply_apply.add_argument("--color")
|
|
182
|
+
schema_apply_apply.add_argument("--visibility-file")
|
|
183
|
+
schema_apply_apply.add_argument("--create-if-missing", action="store_true")
|
|
184
|
+
schema_apply_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
185
|
+
schema_apply_apply.add_argument("--add-fields-file")
|
|
186
|
+
schema_apply_apply.add_argument("--update-fields-file")
|
|
187
|
+
schema_apply_apply.add_argument("--remove-fields-file")
|
|
188
|
+
schema_apply_apply.set_defaults(handler=_handle_schema_apply, format_hint="builder_summary")
|
|
189
|
+
|
|
190
|
+
layout_apply = builder_subparsers.add_parser("layout", help="布局")
|
|
191
|
+
layout_apply_subparsers = layout_apply.add_subparsers(dest="builder_layout_command", required=True)
|
|
192
|
+
layout_apply_apply = layout_apply_subparsers.add_parser("apply", help="执行布局变更")
|
|
193
|
+
layout_apply_apply.add_argument("--app-key", required=True)
|
|
194
|
+
layout_apply_apply.add_argument("--mode", choices=["merge", "replace"], default="merge")
|
|
195
|
+
layout_apply_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
196
|
+
layout_apply_apply.add_argument("--sections-file", required=True)
|
|
197
|
+
layout_apply_apply.set_defaults(handler=_handle_layout_apply, format_hint="builder_summary")
|
|
198
|
+
|
|
199
|
+
views_apply = builder_subparsers.add_parser("views", help="视图")
|
|
200
|
+
views_apply_subparsers = views_apply.add_subparsers(dest="builder_views_command", required=True)
|
|
201
|
+
views_apply_apply = views_apply_subparsers.add_parser("apply", help="执行视图变更")
|
|
202
|
+
views_apply_apply.add_argument("--app-key", required=True)
|
|
203
|
+
views_apply_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
204
|
+
views_apply_apply.add_argument("--upsert-views-file")
|
|
205
|
+
views_apply_apply.add_argument("--remove-views-file")
|
|
206
|
+
views_apply_apply.set_defaults(handler=_handle_views_apply, format_hint="builder_summary")
|
|
207
|
+
|
|
208
|
+
flow_apply = builder_subparsers.add_parser("flow", help="流程")
|
|
209
|
+
flow_apply_subparsers = flow_apply.add_subparsers(dest="builder_flow_command", required=True)
|
|
210
|
+
flow_apply_apply = flow_apply_subparsers.add_parser("apply", help="执行流程变更")
|
|
211
|
+
flow_apply_apply.add_argument("--app-key", required=True)
|
|
212
|
+
flow_apply_apply.add_argument("--mode", choices=["replace"], default="replace")
|
|
213
|
+
flow_apply_apply.add_argument("--publish", action=argparse.BooleanOptionalAction, default=True)
|
|
214
|
+
flow_apply_apply.add_argument("--nodes-file", required=True)
|
|
215
|
+
flow_apply_apply.add_argument("--transitions-file", required=True)
|
|
216
|
+
flow_apply_apply.set_defaults(handler=_handle_flow_apply, format_hint="builder_summary")
|
|
217
|
+
|
|
218
|
+
charts_apply = builder_subparsers.add_parser("charts", help="报表")
|
|
219
|
+
charts_apply_subparsers = charts_apply.add_subparsers(dest="builder_charts_command", required=True)
|
|
220
|
+
charts_apply_apply = charts_apply_subparsers.add_parser("apply", help="执行报表变更")
|
|
221
|
+
charts_apply_apply.add_argument("--app-key", required=True)
|
|
222
|
+
charts_apply_apply.add_argument("--upsert-file")
|
|
223
|
+
charts_apply_apply.add_argument("--remove-chart-ids-file")
|
|
224
|
+
charts_apply_apply.add_argument("--reorder-chart-ids-file")
|
|
225
|
+
charts_apply_apply.set_defaults(handler=_handle_charts_apply, format_hint="builder_summary")
|
|
226
|
+
|
|
227
|
+
publish_verify = builder_subparsers.add_parser("publish", help="发布校验")
|
|
228
|
+
publish_verify_subparsers = publish_verify.add_subparsers(dest="builder_publish_command", required=True)
|
|
229
|
+
publish_verify_verify = publish_verify_subparsers.add_parser("verify", help="校验应用发布")
|
|
230
|
+
publish_verify_verify.add_argument("--app-key", required=True)
|
|
231
|
+
publish_verify_verify.add_argument("--expected-package-id", type=int)
|
|
232
|
+
publish_verify_verify.set_defaults(handler=_handle_publish_verify, format_hint="builder_summary")
|
|
233
|
+
|
|
234
|
+
view = builder_subparsers.add_parser("view", help="视图详情")
|
|
235
|
+
view_subparsers = view.add_subparsers(dest="builder_view_command", required=True)
|
|
236
|
+
view_get = view_subparsers.add_parser("get", help="读取视图详情")
|
|
237
|
+
view_get.add_argument("--view-key", required=True)
|
|
238
|
+
view_get.set_defaults(handler=_handle_view_get, format_hint="builder_summary")
|
|
239
|
+
|
|
240
|
+
chart = builder_subparsers.add_parser("chart", help="报表详情")
|
|
241
|
+
chart_subparsers = chart.add_subparsers(dest="builder_chart_command", required=True)
|
|
242
|
+
chart_get = chart_subparsers.add_parser("get", help="读取报表配置详情")
|
|
243
|
+
chart_get.add_argument("--chart-id", required=True)
|
|
244
|
+
chart_get.set_defaults(handler=_handle_chart_get, format_hint="builder_summary")
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _handle_file_upload_local(args: argparse.Namespace, context: CliContext) -> dict:
|
|
248
|
+
return context.files.file_upload_local(
|
|
249
|
+
profile=args.profile,
|
|
250
|
+
upload_kind=args.upload_kind,
|
|
251
|
+
file_path=args.file_path,
|
|
252
|
+
upload_mark=args.upload_mark,
|
|
253
|
+
content_type=args.content_type,
|
|
254
|
+
bucket_type=args.bucket_type,
|
|
255
|
+
path_id=args.path_id,
|
|
256
|
+
file_related_url=args.file_related_url,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _handle_feedback_submit(args: argparse.Namespace, context: CliContext) -> dict:
|
|
261
|
+
return context.builder_feedback.feedback_submit(
|
|
262
|
+
category=args.category,
|
|
263
|
+
title=args.title,
|
|
264
|
+
description=args.description,
|
|
265
|
+
expected_behavior=args.expected_behavior,
|
|
266
|
+
actual_behavior=args.actual_behavior,
|
|
267
|
+
impact_scope=args.impact_scope,
|
|
268
|
+
tool_name=args.tool_name,
|
|
269
|
+
app_key=args.app_key,
|
|
270
|
+
record_id=args.record_id,
|
|
271
|
+
workflow_node_id=args.workflow_node_id,
|
|
272
|
+
note=args.note,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _handle_contract(args: argparse.Namespace, context: CliContext) -> dict:
|
|
277
|
+
return context.builder.builder_tool_contract(tool_name=args.tool_name)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _handle_member_search(args: argparse.Namespace, context: CliContext) -> dict:
|
|
281
|
+
return context.builder.member_search(
|
|
282
|
+
profile=args.profile,
|
|
283
|
+
query=args.query,
|
|
284
|
+
page_num=args.page_num,
|
|
285
|
+
page_size=args.page_size,
|
|
286
|
+
contain_disable=bool(args.contain_disable),
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _handle_role_search(args: argparse.Namespace, context: CliContext) -> dict:
|
|
291
|
+
return context.builder.role_search(
|
|
292
|
+
profile=args.profile,
|
|
293
|
+
keyword=args.keyword,
|
|
294
|
+
page_num=args.page_num,
|
|
295
|
+
page_size=args.page_size,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _handle_role_create(args: argparse.Namespace, context: CliContext) -> dict:
|
|
300
|
+
return context.builder.role_create(
|
|
301
|
+
profile=args.profile,
|
|
302
|
+
role_name=args.role_name,
|
|
303
|
+
member_uids=load_list_arg(args.member_uids_file, option_name="--member-uids-file"),
|
|
304
|
+
member_emails=load_list_arg(args.member_emails_file, option_name="--member-emails-file"),
|
|
305
|
+
member_names=load_list_arg(args.member_names_file, option_name="--member-names-file"),
|
|
306
|
+
role_icon=args.role_icon,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _handle_solution_install(args: argparse.Namespace, context: CliContext) -> dict:
|
|
311
|
+
return context.builder.solution_install(
|
|
312
|
+
profile=args.profile,
|
|
313
|
+
solution_key=args.solution_key,
|
|
314
|
+
being_copy_data=bool(args.being_copy_data),
|
|
315
|
+
solution_source=args.solution_source,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _handle_package_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
320
|
+
return context.builder.package_get(profile=args.profile, package_id=args.package_id)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _handle_package_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
324
|
+
config = load_object_arg(args.config_file, option_name="--config-file")
|
|
325
|
+
if not isinstance(config, dict):
|
|
326
|
+
raise_config_error("package apply --config-file must contain a JSON object.")
|
|
327
|
+
return context.builder.package_apply(profile=args.profile, **config)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _handle_app_resolve(args: argparse.Namespace, context: CliContext) -> dict:
|
|
331
|
+
has_app_key = bool((args.app_key or "").strip())
|
|
332
|
+
has_app_name = bool((args.app_name or "").strip())
|
|
333
|
+
has_package_id = args.package_id is not None
|
|
334
|
+
if has_app_key and (has_app_name or has_package_id):
|
|
335
|
+
raise_config_error(
|
|
336
|
+
"app resolve accepts exactly one selector mode.",
|
|
337
|
+
fix_hint="Use only `--app-key`, or use `--app-name` together with `--package-id`.",
|
|
338
|
+
)
|
|
339
|
+
if not has_app_key and not (has_app_name and has_package_id):
|
|
340
|
+
raise_config_error(
|
|
341
|
+
"app resolve requires either --app-key, or --app-name together with --package-id.",
|
|
342
|
+
fix_hint="For an existing known app, pass `--app-key`. For package-scoped lookup, pass both `--app-name` and `--package-id`.",
|
|
343
|
+
)
|
|
344
|
+
return context.builder.app_resolve(
|
|
345
|
+
profile=args.profile,
|
|
346
|
+
app_key=args.app_key,
|
|
347
|
+
app_name=args.app_name,
|
|
348
|
+
package_id=args.package_id,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _handle_app_release_edit_lock_if_mine(args: argparse.Namespace, context: CliContext) -> dict:
|
|
353
|
+
return context.builder.app_release_edit_lock_if_mine(
|
|
354
|
+
profile=args.profile,
|
|
355
|
+
app_key=args.app_key,
|
|
356
|
+
lock_owner_email=args.lock_owner_email,
|
|
357
|
+
lock_owner_name=args.lock_owner_name,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _handle_button_list(args: argparse.Namespace, context: CliContext) -> dict:
|
|
362
|
+
return context.builder.app_custom_button_list(profile=args.profile, app_key=args.app_key)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _handle_button_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
366
|
+
return context.builder.app_custom_button_get(profile=args.profile, app_key=args.app_key, button_id=args.button_id)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _handle_button_create(args: argparse.Namespace, context: CliContext) -> dict:
|
|
370
|
+
return context.builder.app_custom_button_create(
|
|
371
|
+
profile=args.profile,
|
|
372
|
+
app_key=args.app_key,
|
|
373
|
+
payload=load_object_arg(args.payload_file, option_name="--payload-file"),
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _handle_button_update(args: argparse.Namespace, context: CliContext) -> dict:
|
|
378
|
+
return context.builder.app_custom_button_update(
|
|
379
|
+
profile=args.profile,
|
|
380
|
+
app_key=args.app_key,
|
|
381
|
+
button_id=args.button_id,
|
|
382
|
+
payload=load_object_arg(args.payload_file, option_name="--payload-file"),
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _handle_button_delete(args: argparse.Namespace, context: CliContext) -> dict:
|
|
387
|
+
return context.builder.app_custom_button_delete(profile=args.profile, app_key=args.app_key, button_id=args.button_id)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def _handle_app_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
391
|
+
handlers = {
|
|
392
|
+
"summary": context.builder.app_get,
|
|
393
|
+
"fields": context.builder.app_get_fields,
|
|
394
|
+
"layout": context.builder.app_get_layout,
|
|
395
|
+
"views": context.builder.app_get_views,
|
|
396
|
+
"flow": context.builder.app_get_flow,
|
|
397
|
+
"charts": context.builder.app_get_charts,
|
|
398
|
+
}
|
|
399
|
+
return handlers[args.builder_app_get_section](profile=args.profile, app_key=args.app_key)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def _handle_app_repair_code_blocks(args: argparse.Namespace, context: CliContext) -> dict:
|
|
403
|
+
return context.builder.app_repair_code_blocks(
|
|
404
|
+
profile=args.profile,
|
|
405
|
+
app_key=args.app_key,
|
|
406
|
+
field=args.field,
|
|
407
|
+
apply=bool(args.apply),
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def _handle_portal_list(args: argparse.Namespace, context: CliContext) -> dict:
|
|
412
|
+
return context.builder.portal_list(profile=args.profile)
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def _handle_portal_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
416
|
+
return context.builder.portal_get(profile=args.profile, dash_key=args.dash_key, being_draft=bool(args.being_draft))
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def _handle_view_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
420
|
+
return context.builder.view_get(profile=args.profile, view_key=args.view_key)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _handle_chart_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
424
|
+
return context.builder.chart_get(profile=args.profile, chart_id=args.chart_id)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def _handle_schema_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
428
|
+
has_app_key = bool((args.app_key or "").strip())
|
|
429
|
+
has_app_name = bool((args.app_name or "").strip())
|
|
430
|
+
has_app_title = bool((args.app_title or "").strip())
|
|
431
|
+
has_package_id = args.package_id is not None
|
|
432
|
+
if has_app_key:
|
|
433
|
+
if args.create_if_missing or has_package_id:
|
|
434
|
+
raise_config_error(
|
|
435
|
+
"schema apply edit mode accepts --app-key and optional --app-name only.",
|
|
436
|
+
fix_hint="For existing apps, use `--app-key` and optionally `--app-name`. For create mode, use `--package-id --app-name --create-if-missing`.",
|
|
437
|
+
)
|
|
438
|
+
else:
|
|
439
|
+
if not args.create_if_missing or not has_package_id or not (has_app_name or has_app_title):
|
|
440
|
+
raise_config_error(
|
|
441
|
+
"schema apply create mode requires --package-id, --app-name, and --create-if-missing.",
|
|
442
|
+
fix_hint="Use `--app-key` for existing apps, or pass `--package-id --app-name --create-if-missing` to create a new app.",
|
|
443
|
+
)
|
|
444
|
+
return context.builder.app_schema_apply(
|
|
445
|
+
profile=args.profile,
|
|
446
|
+
app_key=args.app_key,
|
|
447
|
+
package_id=args.package_id,
|
|
448
|
+
app_name=args.app_name,
|
|
449
|
+
app_title=args.app_title,
|
|
450
|
+
icon=args.icon,
|
|
451
|
+
color=args.color,
|
|
452
|
+
visibility=load_object_arg(args.visibility_file, option_name="--visibility-file"),
|
|
453
|
+
create_if_missing=bool(args.create_if_missing),
|
|
454
|
+
publish=bool(args.publish),
|
|
455
|
+
add_fields=load_list_arg(args.add_fields_file, option_name="--add-fields-file"),
|
|
456
|
+
update_fields=load_list_arg(args.update_fields_file, option_name="--update-fields-file"),
|
|
457
|
+
remove_fields=load_list_arg(args.remove_fields_file, option_name="--remove-fields-file"),
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def _handle_layout_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
462
|
+
return context.builder.app_layout_apply(
|
|
463
|
+
profile=args.profile,
|
|
464
|
+
app_key=args.app_key,
|
|
465
|
+
mode=args.mode,
|
|
466
|
+
publish=bool(args.publish),
|
|
467
|
+
sections=require_list_arg(args.sections_file, option_name="--sections-file"),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def _handle_views_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
472
|
+
return context.builder.app_views_apply(
|
|
473
|
+
profile=args.profile,
|
|
474
|
+
app_key=args.app_key,
|
|
475
|
+
publish=bool(args.publish),
|
|
476
|
+
upsert_views=load_list_arg(args.upsert_views_file, option_name="--upsert-views-file"),
|
|
477
|
+
remove_views=load_list_arg(args.remove_views_file, option_name="--remove-views-file"),
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def _handle_flow_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
482
|
+
return context.builder.app_flow_apply(
|
|
483
|
+
profile=args.profile,
|
|
484
|
+
app_key=args.app_key,
|
|
485
|
+
mode=args.mode,
|
|
486
|
+
publish=bool(args.publish),
|
|
487
|
+
nodes=require_list_arg(args.nodes_file, option_name="--nodes-file"),
|
|
488
|
+
transitions=require_list_arg(args.transitions_file, option_name="--transitions-file"),
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def _handle_charts_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
493
|
+
return context.builder.app_charts_apply(
|
|
494
|
+
profile=args.profile,
|
|
495
|
+
app_key=args.app_key,
|
|
496
|
+
upsert_charts=load_list_arg(args.upsert_file, option_name="--upsert-file"),
|
|
497
|
+
remove_chart_ids=load_list_arg(args.remove_chart_ids_file, option_name="--remove-chart-ids-file"),
|
|
498
|
+
reorder_chart_ids=load_list_arg(args.reorder_chart_ids_file, option_name="--reorder-chart-ids-file"),
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def _handle_portal_apply(args: argparse.Namespace, context: CliContext) -> dict:
|
|
503
|
+
has_dash_key = bool((args.dash_key or "").strip())
|
|
504
|
+
has_dash_name = bool((args.dash_name or "").strip())
|
|
505
|
+
has_package_id = args.package_id is not None
|
|
506
|
+
if has_dash_key and has_package_id:
|
|
507
|
+
raise_config_error(
|
|
508
|
+
"portal apply accepts exactly one selector mode.",
|
|
509
|
+
fix_hint="Use `--dash-key` to update an existing portal, or use `--package-id --dash-name` to create a new portal.",
|
|
510
|
+
)
|
|
511
|
+
if not has_dash_key and not (has_package_id and has_dash_name):
|
|
512
|
+
raise_config_error(
|
|
513
|
+
"portal apply requires either --dash-key, or --package-id together with --dash-name.",
|
|
514
|
+
fix_hint="Use `--dash-key` for an existing portal. For create mode, pass `--package-id --dash-name`.",
|
|
515
|
+
)
|
|
516
|
+
sections = [] if not args.sections_file else require_list_arg(args.sections_file, option_name="--sections-file")
|
|
517
|
+
return context.builder.portal_apply(
|
|
518
|
+
profile=args.profile,
|
|
519
|
+
dash_key=args.dash_key,
|
|
520
|
+
dash_name=args.dash_name,
|
|
521
|
+
package_id=args.package_id,
|
|
522
|
+
publish=bool(args.publish),
|
|
523
|
+
sections=sections,
|
|
524
|
+
visibility=load_object_arg(args.visibility_file, option_name="--visibility-file"),
|
|
525
|
+
auth=load_object_arg(args.auth_file, option_name="--auth-file"),
|
|
526
|
+
icon=args.icon,
|
|
527
|
+
color=args.color,
|
|
528
|
+
hide_copyright=args.hide_copyright,
|
|
529
|
+
dash_global_config=load_object_arg(args.dash_global_config_file, option_name="--dash-global-config-file"),
|
|
530
|
+
config=load_object_arg(args.config_file, option_name="--config-file"),
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _handle_publish_verify(args: argparse.Namespace, context: CliContext) -> dict:
|
|
535
|
+
return context.builder.app_publish_verify(
|
|
536
|
+
profile=args.profile,
|
|
537
|
+
app_key=args.app_key,
|
|
538
|
+
expected_package_id=args.expected_package_id,
|
|
539
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ..context import CliContext
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
9
|
+
parser = subparsers.add_parser("chart", help="报表访问")
|
|
10
|
+
chart_subparsers = parser.add_subparsers(dest="chart_command", required=True)
|
|
11
|
+
|
|
12
|
+
get_parser = chart_subparsers.add_parser("get", help="读取报表数据")
|
|
13
|
+
get_parser.add_argument("--chart-id", required=True)
|
|
14
|
+
get_parser.set_defaults(handler=_handle_get, format_hint="generic")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _handle_get(args: argparse.Namespace, context: CliContext) -> dict:
|
|
18
|
+
return context.resource.chart_get(profile=args.profile, chart_id=args.chart_id)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ...errors import QingflowApiError
|
|
9
|
+
from ..json_io import load_json_list, load_json_object, load_optional_json_list, load_optional_json_object
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_bool_text(value: str) -> bool:
|
|
13
|
+
normalized = value.strip().lower()
|
|
14
|
+
if normalized in {"true", "1", "yes", "y", "on"}:
|
|
15
|
+
return True
|
|
16
|
+
if normalized in {"false", "0", "no", "n", "off"}:
|
|
17
|
+
return False
|
|
18
|
+
raise argparse.ArgumentTypeError("expected one of: true, false, 1, 0, yes, no")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def load_list_arg(path: str | None, *, option_name: str) -> list[Any]:
|
|
22
|
+
return load_optional_json_list(path, option_name=option_name)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def load_object_arg(path: str | None, *, option_name: str) -> dict[str, Any] | None:
|
|
26
|
+
return load_optional_json_object(path, option_name=option_name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def require_list_arg(path: str | None, *, option_name: str) -> list[Any]:
|
|
30
|
+
if not path:
|
|
31
|
+
raise QingflowApiError.config_error(f"{option_name} is required")
|
|
32
|
+
return load_json_list(path, option_name=option_name)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def require_object_arg(path: str | None, *, option_name: str) -> dict[str, Any]:
|
|
36
|
+
if not path:
|
|
37
|
+
raise QingflowApiError.config_error(f"{option_name} is required")
|
|
38
|
+
return load_json_object(path, option_name=option_name)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def read_secret_arg(value: str | None, *, stdin_enabled: bool, label: str) -> str:
|
|
42
|
+
if stdin_enabled:
|
|
43
|
+
secret = sys.stdin.read().strip()
|
|
44
|
+
if secret:
|
|
45
|
+
return secret
|
|
46
|
+
if value:
|
|
47
|
+
return value
|
|
48
|
+
raise QingflowApiError.config_error(f"{label} is required")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def raise_config_error(message: str, *, fix_hint: str) -> None:
|
|
52
|
+
raise RuntimeError(
|
|
53
|
+
json.dumps(
|
|
54
|
+
{
|
|
55
|
+
"category": "config",
|
|
56
|
+
"message": message,
|
|
57
|
+
"error_code": "CONFIG_ERROR",
|
|
58
|
+
"details": {"fix_hint": fix_hint},
|
|
59
|
+
},
|
|
60
|
+
ensure_ascii=False,
|
|
61
|
+
)
|
|
62
|
+
)
|