draftgo-cli 3.0.1 → 3.0.33
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/LICENSE +21 -0
- package/README.md +73 -124
- package/package.json +21 -8
- package/resources/skill/SKILL.md +62 -89
- package/resources/skill/init/SKILL.md +18 -67
- package/resources/skill/manifest.json +27 -0
- package/resources/skill/pull/SKILL.md +18 -44
- package/resources/skill/push/SKILL.md +30 -247
- package/resources/skill/references/aihub.md +86 -0
- package/resources/skill/references/api-endpoints.md +178 -0
- package/resources/skill/references/api.json +20248 -0
- package/resources/skill/{quickref → references}/app-api.md +44 -14
- package/resources/skill/{core → references}/architecture.md +6 -26
- package/resources/skill/references/chat-sdk.md +201 -0
- package/resources/skill/references/custom-services.md +308 -0
- package/resources/skill/references/data.md +298 -0
- package/resources/skill/references/db-relations.md +227 -0
- package/resources/skill/references/frontend.md +788 -0
- package/resources/skill/references/modules.md +66 -0
- package/resources/skill/references/parallel.md +48 -0
- package/resources/skill/{specs → references}/runtime.md +31 -1
- package/resources/skill/{specs → references}/security.md +3 -3
- package/resources/skill/references/ui-protocol.md +99 -0
- package/resources/skill/scripts/draftgo_delete.py +0 -2
- package/resources/skill/scripts/draftgo_init.py +15 -3
- package/resources/skill/scripts/draftgo_pull.py +154 -87
- package/resources/skill/scripts/draftgo_push.py +440 -183
- package/resources/skill/story/SKILL.md +13 -23
- package/src/cli.js +22 -7
- package/src/commandRegistry.js +34 -0
- package/src/commands/api.js +204 -0
- package/src/commands/autoPush.js +41 -0
- package/src/commands/check.js +27 -17
- package/src/commands/delete.js +6 -4
- package/src/commands/deploy.js +31 -0
- package/src/commands/help.js +41 -28
- package/src/commands/init.js +34 -20
- package/src/commands/local.js +9 -3
- package/src/commands/map.js +18 -7
- package/src/commands/sync.js +11 -4
- package/src/commands/update.js +39 -52
- package/src/commands/verifyUi.js +199 -0
- package/src/index.js +13 -46
- package/src/localdev/compose.js +48 -197
- package/src/localdev/index.js +116 -216
- package/src/localdev/mysqlClient.js +12 -9
- package/src/localdev/services.js +163 -0
- package/src/platforms.js +3 -3
- package/src/projectConfig.js +12 -2
- package/src/projectMap.js +240 -68
- package/src/skill.js +113 -29
- package/src/updateCheck.js +37 -15
- package/resources/skill/core/modules.md +0 -54
- package/resources/skill/practices/anti-patterns.md +0 -70
- package/resources/skill/practices/best-practices.md +0 -41
- package/resources/skill/practices/dev-declaration.md +0 -94
- package/resources/skill/quickref/api-endpoints.md +0 -130
- package/resources/skill/quickref/api.json +0 -17675
- package/resources/skill/quickref/dg-components.md +0 -198
- package/resources/skill/rules/dev-workflow.md +0 -652
- package/resources/skill/rules/frontend.md +0 -210
- package/resources/skill/rules/parallel.md +0 -263
- package/resources/skill/specs/data.md +0 -108
- package/resources/skill/specs/ui-protocol.md +0 -68
- package/src/commands/doctor.js +0 -54
- package/src/commands/new.js +0 -183
- package/src/commands/projectScript.js +0 -37
- /package/resources/skill/{rules → references}/debugging-syntax.md +0 -0
|
@@ -8,7 +8,6 @@ DraftGo Pull Script
|
|
|
8
8
|
python draftgo_pull.py nav [nav_id ...]
|
|
9
9
|
python draftgo_pull.py db_meta [db_meta_id ...]
|
|
10
10
|
python draftgo_pull.py aihub [aihub_id ...]
|
|
11
|
-
python draftgo_pull.py external_apis [api_id ...]
|
|
12
11
|
python draftgo_pull.py system_config [config_key ...]
|
|
13
12
|
python draftgo_pull.py docs [article_id ...]
|
|
14
13
|
python draftgo_pull.py doc_categories [category_id ...]
|
|
@@ -19,7 +18,7 @@ DraftGo Pull Script
|
|
|
19
18
|
"""
|
|
20
19
|
import json, sys
|
|
21
20
|
from pathlib import Path
|
|
22
|
-
import urllib.request, urllib.error
|
|
21
|
+
import urllib.request, urllib.error, urllib.parse
|
|
23
22
|
|
|
24
23
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
25
24
|
|
|
@@ -43,28 +42,18 @@ DEFAULT_ROOT = find_project_root(SCRIPT_DIR)
|
|
|
43
42
|
|
|
44
43
|
# ── 端点映射 ──
|
|
45
44
|
ENDPOINTS = {
|
|
46
|
-
"pages": "/api/pages
|
|
45
|
+
"pages": "/api/pages/",
|
|
47
46
|
"navigations": "/api/navigations",
|
|
48
47
|
"roles": "/api/roles",
|
|
49
|
-
"users": "/api/users
|
|
48
|
+
"users": "/api/users",
|
|
50
49
|
"db_meta": "/api/db-meta",
|
|
51
|
-
"aihub": "/api/aihub
|
|
52
|
-
"external_apis": "/api/external-apis?page=1&page_size=500",
|
|
50
|
+
"aihub": "/api/aihub",
|
|
53
51
|
"system_config": "/api/system/config",
|
|
54
52
|
"doc_categories": "/api/docs/categories?flat=true",
|
|
55
|
-
"docs": "/api/docs/admin/articles
|
|
56
|
-
"custom_scripts": "/api/scripts
|
|
53
|
+
"docs": "/api/docs/admin/articles",
|
|
54
|
+
"custom_scripts": "/api/scripts/",
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
_LANG_EXT = {
|
|
60
|
-
"python": "py", "py": "py",
|
|
61
|
-
"javascript": "js", "js": "js",
|
|
62
|
-
"typescript": "ts", "ts": "ts",
|
|
63
|
-
"shell": "sh", "bash": "sh",
|
|
64
|
-
"go": "go",
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
57
|
# ── 通用工具函数 ──
|
|
69
58
|
|
|
70
59
|
def load_config(root=None):
|
|
@@ -129,7 +118,31 @@ def safe_slug(s):
|
|
|
129
118
|
return str(s).strip("/").replace("/", "_") or "root"
|
|
130
119
|
|
|
131
120
|
|
|
132
|
-
def write_index(folder, items):
|
|
121
|
+
def write_index(folder, items, preserve_existing=False, id_key="id"):
|
|
122
|
+
if preserve_existing:
|
|
123
|
+
index_path = folder / "index.json"
|
|
124
|
+
try:
|
|
125
|
+
existing = json.loads(index_path.read_text(encoding="utf-8"))
|
|
126
|
+
if not isinstance(existing, list):
|
|
127
|
+
existing = []
|
|
128
|
+
except (OSError, json.JSONDecodeError):
|
|
129
|
+
existing = []
|
|
130
|
+
replacements = {
|
|
131
|
+
str(item.get(id_key)): item for item in items if item.get(id_key) is not None
|
|
132
|
+
}
|
|
133
|
+
retained = []
|
|
134
|
+
seen = set()
|
|
135
|
+
for item in existing:
|
|
136
|
+
key = str(item.get(id_key)) if item.get(id_key) is not None else None
|
|
137
|
+
if key in replacements:
|
|
138
|
+
retained.append(replacements[key])
|
|
139
|
+
seen.add(key)
|
|
140
|
+
else:
|
|
141
|
+
retained.append(item)
|
|
142
|
+
items = retained + [
|
|
143
|
+
item for item in items
|
|
144
|
+
if item.get(id_key) is None or str(item.get(id_key)) not in seen
|
|
145
|
+
]
|
|
133
146
|
folder.mkdir(parents=True, exist_ok=True)
|
|
134
147
|
(folder / "index.json").write_text(
|
|
135
148
|
json.dumps(items, ensure_ascii=False, indent=2), encoding="utf-8"
|
|
@@ -138,7 +151,7 @@ def write_index(folder, items):
|
|
|
138
151
|
|
|
139
152
|
# ── 各类型的 explode 逻辑 ──
|
|
140
153
|
|
|
141
|
-
def explode_pages(out_dir, items):
|
|
154
|
+
def explode_pages(out_dir, items, preserve_existing=False):
|
|
142
155
|
index = []
|
|
143
156
|
for p in items:
|
|
144
157
|
pid = p.get("id", "x")
|
|
@@ -148,66 +161,95 @@ def explode_pages(out_dir, items):
|
|
|
148
161
|
meta = {k: v for k, v in p.items() if k != "value"}
|
|
149
162
|
meta["html_file"] = f".draftgo/pages/{fname}"
|
|
150
163
|
index.append(meta)
|
|
151
|
-
write_index(out_dir, index)
|
|
164
|
+
write_index(out_dir, index, preserve_existing)
|
|
152
165
|
return len(index)
|
|
153
166
|
|
|
154
167
|
|
|
155
|
-
def explode_navigations(out_dir, items):
|
|
168
|
+
def explode_navigations(out_dir, items, preserve_existing=False):
|
|
156
169
|
index = []
|
|
157
170
|
for item in items:
|
|
158
171
|
iid = item.get("id", "x")
|
|
159
172
|
name_slug = safe_slug(item.get("code") or item.get("route") or iid)
|
|
160
173
|
fname = f"nav_{iid}_{name_slug}.html"
|
|
161
|
-
|
|
174
|
+
# 列表接口只返回导航元数据。详情拉取失败时不能以空内容覆盖本地导航。
|
|
175
|
+
if isinstance(item.get("html"), str):
|
|
176
|
+
(out_dir / fname).write_text(item["html"], encoding="utf-8")
|
|
177
|
+
else:
|
|
178
|
+
print(
|
|
179
|
+
f" WARN nav_id={iid} 未取得 HTML,保留本地文件: {fname}",
|
|
180
|
+
file=sys.stderr,
|
|
181
|
+
)
|
|
162
182
|
meta = {k: v for k, v in item.items() if k != "html"}
|
|
163
183
|
meta["html_file"] = f".draftgo/navigations/{fname}"
|
|
164
184
|
index.append(meta)
|
|
165
|
-
write_index(out_dir, index)
|
|
185
|
+
write_index(out_dir, index, preserve_existing)
|
|
166
186
|
return len(index)
|
|
167
187
|
|
|
168
188
|
|
|
169
|
-
def explode_docs(out_dir, items):
|
|
189
|
+
def explode_docs(out_dir, items, preserve_existing=False):
|
|
170
190
|
index = []
|
|
171
191
|
for art in items:
|
|
172
192
|
aid = art.get("id", "x")
|
|
173
193
|
slug = safe_slug(art.get("slug") or art.get("title") or aid)
|
|
174
|
-
fname = f"article_{aid}_{slug}.
|
|
194
|
+
fname = f"article_{aid}_{slug}.html"
|
|
175
195
|
content = art.get("content") or ""
|
|
176
196
|
(out_dir / fname).write_text(content, encoding="utf-8")
|
|
177
197
|
meta = {k: v for k, v in art.items() if k != "content"}
|
|
178
198
|
meta["content_file"] = f".draftgo/docs/articles/{fname}"
|
|
179
199
|
index.append(meta)
|
|
180
|
-
write_index(out_dir, index)
|
|
200
|
+
write_index(out_dir, index, preserve_existing)
|
|
181
201
|
return len(index)
|
|
182
202
|
|
|
183
203
|
|
|
184
|
-
def explode_scripts(out_dir, items):
|
|
204
|
+
def explode_scripts(out_dir, items, preserve_existing=False):
|
|
185
205
|
index = []
|
|
186
206
|
for sc in items:
|
|
187
207
|
sid = sc.get("id", "x")
|
|
188
208
|
slug = safe_slug(sc.get("slug") or sc.get("name") or sid)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
209
|
+
fname = f"script_{sid}_{slug}.go"
|
|
210
|
+
# 列表接口不含 code;详情拉取失败时绝不能用空内容覆盖受管源码。
|
|
211
|
+
if "code" in sc:
|
|
212
|
+
(out_dir / fname).write_text(sc["code"], encoding="utf-8")
|
|
213
|
+
else:
|
|
214
|
+
print(f" WARN script_id={sid} 未取得代码,保留本地文件: {fname}", file=sys.stderr)
|
|
215
|
+
meta = {k: v for k, v in sc.items() if k not in ("code", "language")}
|
|
193
216
|
meta["code_file"] = f".draftgo/custom_scripts/{fname}"
|
|
194
217
|
index.append(meta)
|
|
195
|
-
write_index(out_dir, index)
|
|
218
|
+
write_index(out_dir, index, preserve_existing)
|
|
196
219
|
return len(index)
|
|
197
220
|
|
|
198
221
|
|
|
199
222
|
# ── 按类型拉取 ──
|
|
200
223
|
|
|
224
|
+
def select_items(items, ids, id_key, type_name):
|
|
225
|
+
"""筛选指定目标,并拒绝用空结果覆盖现有索引。"""
|
|
226
|
+
if not ids:
|
|
227
|
+
return items
|
|
228
|
+
wanted = [str(value) for value in ids]
|
|
229
|
+
found = {str(item.get(id_key)) for item in items if item.get(id_key) is not None}
|
|
230
|
+
missing = [value for value in wanted if value not in found]
|
|
231
|
+
if missing:
|
|
232
|
+
print(
|
|
233
|
+
f" ERR {type_name} 云端未返回目标 {id_key}: {', '.join(missing)}",
|
|
234
|
+
file=sys.stderr,
|
|
235
|
+
)
|
|
236
|
+
return None
|
|
237
|
+
return [item for item in items if str(item.get(id_key)) in wanted]
|
|
238
|
+
|
|
201
239
|
def pull_pages(server, token, root, ids=None):
|
|
202
240
|
raw = fetch(server, token, ENDPOINTS["pages"])
|
|
203
241
|
if raw is None:
|
|
204
|
-
return
|
|
242
|
+
return None
|
|
205
243
|
items = extract_items(raw)
|
|
206
|
-
|
|
207
|
-
|
|
244
|
+
items = select_items(items, ids, "id", "pages")
|
|
245
|
+
if items is None:
|
|
246
|
+
return None
|
|
247
|
+
if any(not isinstance(p.get("value"), dict) or not isinstance(p["value"].get("html"), str) for p in items):
|
|
248
|
+
print(" ERR pages 响应缺少 HTML,未写入本地缓存", file=sys.stderr)
|
|
249
|
+
return None
|
|
208
250
|
out = root / ".draftgo/pages"
|
|
209
251
|
out.mkdir(parents=True, exist_ok=True)
|
|
210
|
-
count = explode_pages(out, items)
|
|
252
|
+
count = explode_pages(out, items, preserve_existing=bool(ids))
|
|
211
253
|
print(f" OK pages ({count} items)")
|
|
212
254
|
return count
|
|
213
255
|
|
|
@@ -215,13 +257,33 @@ def pull_pages(server, token, root, ids=None):
|
|
|
215
257
|
def pull_navigations(server, token, root, ids=None):
|
|
216
258
|
raw = fetch(server, token, ENDPOINTS["navigations"])
|
|
217
259
|
if raw is None:
|
|
218
|
-
return
|
|
260
|
+
return None
|
|
219
261
|
items = extract_items(raw)
|
|
220
|
-
|
|
221
|
-
|
|
262
|
+
items = select_items(items, ids, "id", "navigations")
|
|
263
|
+
if items is None:
|
|
264
|
+
return None
|
|
265
|
+
hydrated = []
|
|
266
|
+
for item in items:
|
|
267
|
+
code = item.get("code")
|
|
268
|
+
if not code:
|
|
269
|
+
print(
|
|
270
|
+
f" ERR nav_id={item.get('id', '?')} 缺少 code,未写入本地缓存",
|
|
271
|
+
file=sys.stderr,
|
|
272
|
+
)
|
|
273
|
+
return None
|
|
274
|
+
detail = unwrap(fetch(
|
|
275
|
+
server, token, f"/api/navigations/{urllib.parse.quote(str(code), safe='')}"
|
|
276
|
+
))
|
|
277
|
+
if not isinstance(detail, dict) or not isinstance(detail.get("html"), str):
|
|
278
|
+
print(
|
|
279
|
+
f" ERR nav_id={item.get('id', '?')} 未取得 HTML,未写入本地缓存",
|
|
280
|
+
file=sys.stderr,
|
|
281
|
+
)
|
|
282
|
+
return None
|
|
283
|
+
hydrated.append({**item, **detail})
|
|
222
284
|
out = root / ".draftgo/navigations"
|
|
223
285
|
out.mkdir(parents=True, exist_ok=True)
|
|
224
|
-
count = explode_navigations(out,
|
|
286
|
+
count = explode_navigations(out, hydrated, preserve_existing=bool(ids))
|
|
225
287
|
print(f" OK navigations ({count} items)")
|
|
226
288
|
return count
|
|
227
289
|
|
|
@@ -230,50 +292,40 @@ def pull_simple(server, token, root, type_name, ids=None):
|
|
|
230
292
|
"""拉取仅需 index.json 的简单类型(db_meta, aihub, roles, users, system_config)。"""
|
|
231
293
|
raw = fetch(server, token, ENDPOINTS[type_name])
|
|
232
294
|
if raw is None:
|
|
233
|
-
return
|
|
295
|
+
return None
|
|
234
296
|
items = extract_items(raw)
|
|
235
|
-
if
|
|
236
|
-
|
|
237
|
-
|
|
297
|
+
id_key = "config_key" if type_name == "system_config" else "id"
|
|
298
|
+
items = select_items(items, ids, id_key, type_name)
|
|
299
|
+
if items is None:
|
|
300
|
+
return None
|
|
238
301
|
out = root / f".draftgo/{type_name}"
|
|
239
|
-
write_index(out, items)
|
|
302
|
+
write_index(out, items, preserve_existing=bool(ids), id_key=id_key)
|
|
240
303
|
print(f" OK {type_name} ({len(items)} items)")
|
|
241
304
|
return len(items)
|
|
242
305
|
|
|
243
306
|
|
|
244
|
-
def pull_external_apis(server, token, root, ids=None):
|
|
245
|
-
raw = fetch(server, token, ENDPOINTS["external_apis"])
|
|
246
|
-
if raw is None:
|
|
247
|
-
return 0
|
|
248
|
-
items = extract_items(raw)
|
|
249
|
-
if ids:
|
|
250
|
-
items = [it for it in items if str(it.get("id")) in ids]
|
|
251
|
-
hydrated = []
|
|
252
|
-
for it in items:
|
|
253
|
-
api_id = it.get("id")
|
|
254
|
-
detail = unwrap(fetch(server, token, f"/api/external-apis/{api_id}")) if api_id else None
|
|
255
|
-
hydrated.append({**it, **detail} if isinstance(detail, dict) else it)
|
|
256
|
-
out = root / ".draftgo/external_apis"
|
|
257
|
-
write_index(out, hydrated)
|
|
258
|
-
print(f" OK external_apis ({len(hydrated)} items)")
|
|
259
|
-
return len(hydrated)
|
|
260
|
-
|
|
261
|
-
|
|
262
307
|
def pull_docs(server, token, root, ids=None):
|
|
263
308
|
raw = fetch(server, token, ENDPOINTS["docs"])
|
|
264
309
|
if raw is None:
|
|
265
|
-
return
|
|
310
|
+
return None
|
|
266
311
|
items = extract_items(raw)
|
|
267
|
-
|
|
268
|
-
|
|
312
|
+
items = select_items(items, ids, "id", "docs")
|
|
313
|
+
if items is None:
|
|
314
|
+
return None
|
|
269
315
|
hydrated = []
|
|
270
316
|
for it in items:
|
|
271
317
|
aid = it.get("id")
|
|
272
318
|
detail = unwrap(fetch(server, token, f"/api/docs/articles/{aid}")) if aid else None
|
|
273
|
-
|
|
319
|
+
if not isinstance(detail, dict) or not isinstance(detail.get("content"), str):
|
|
320
|
+
print(
|
|
321
|
+
f" ERR article_id={aid or '?'} 未取得正文,未写入本地缓存",
|
|
322
|
+
file=sys.stderr,
|
|
323
|
+
)
|
|
324
|
+
return None
|
|
325
|
+
hydrated.append({**it, **detail})
|
|
274
326
|
out = root / ".draftgo/docs/articles"
|
|
275
327
|
out.mkdir(parents=True, exist_ok=True)
|
|
276
|
-
count = explode_docs(out, hydrated)
|
|
328
|
+
count = explode_docs(out, hydrated, preserve_existing=bool(ids))
|
|
277
329
|
print(f" OK docs ({count} articles)")
|
|
278
330
|
return count
|
|
279
331
|
|
|
@@ -281,12 +333,13 @@ def pull_docs(server, token, root, ids=None):
|
|
|
281
333
|
def pull_doc_categories(server, token, root, ids=None):
|
|
282
334
|
raw = fetch(server, token, ENDPOINTS["doc_categories"])
|
|
283
335
|
if raw is None:
|
|
284
|
-
return
|
|
336
|
+
return None
|
|
285
337
|
items = extract_items(raw)
|
|
286
|
-
|
|
287
|
-
|
|
338
|
+
items = select_items(items, ids, "id", "doc_categories")
|
|
339
|
+
if items is None:
|
|
340
|
+
return None
|
|
288
341
|
out = root / ".draftgo/doc_categories"
|
|
289
|
-
write_index(out, items)
|
|
342
|
+
write_index(out, items, preserve_existing=bool(ids))
|
|
290
343
|
print(f" OK doc_categories ({len(items)} items)")
|
|
291
344
|
return len(items)
|
|
292
345
|
|
|
@@ -294,14 +347,26 @@ def pull_doc_categories(server, token, root, ids=None):
|
|
|
294
347
|
def pull_custom_scripts(server, token, root, ids=None):
|
|
295
348
|
raw = fetch(server, token, ENDPOINTS["custom_scripts"])
|
|
296
349
|
if raw is None:
|
|
297
|
-
return
|
|
350
|
+
return None
|
|
298
351
|
items = extract_items(raw)
|
|
299
|
-
|
|
300
|
-
|
|
352
|
+
items = select_items(items, ids, "id", "custom_scripts")
|
|
353
|
+
if items is None:
|
|
354
|
+
return None
|
|
355
|
+
hydrated = []
|
|
356
|
+
for it in items:
|
|
357
|
+
script_id = it.get("id")
|
|
358
|
+
detail = unwrap(fetch(server, token, f"/api/scripts/{script_id}")) if script_id else None
|
|
359
|
+
if not isinstance(detail, dict) or not isinstance(detail.get("code"), str):
|
|
360
|
+
print(
|
|
361
|
+
f" ERR script_id={script_id or '?'} 未取得代码,未写入本地缓存",
|
|
362
|
+
file=sys.stderr,
|
|
363
|
+
)
|
|
364
|
+
return None
|
|
365
|
+
hydrated.append({**it, **detail})
|
|
301
366
|
out = root / ".draftgo/custom_scripts"
|
|
302
367
|
out.mkdir(parents=True, exist_ok=True)
|
|
303
|
-
count = explode_scripts(out,
|
|
304
|
-
print(f" OK custom_scripts ({count} scripts)")
|
|
368
|
+
count = explode_scripts(out, hydrated, preserve_existing=bool(ids))
|
|
369
|
+
print(f" OK custom_scripts ({count} scripts, code from details)")
|
|
305
370
|
return count
|
|
306
371
|
|
|
307
372
|
|
|
@@ -316,7 +381,6 @@ PULL_HANDLERS = {
|
|
|
316
381
|
"roles": lambda s, t, r, ids=None: pull_simple(s, t, r, "roles", ids),
|
|
317
382
|
"users": lambda s, t, r, ids=None: pull_simple(s, t, r, "users", ids),
|
|
318
383
|
"system_config": lambda s, t, r, ids=None: pull_simple(s, t, r, "system_config", ids),
|
|
319
|
-
"external_apis": pull_external_apis,
|
|
320
384
|
"docs": pull_docs,
|
|
321
385
|
"doc_categories": pull_doc_categories,
|
|
322
386
|
"custom_scripts": pull_custom_scripts,
|
|
@@ -325,14 +389,15 @@ PULL_HANDLERS = {
|
|
|
325
389
|
|
|
326
390
|
def pull_all(server, token, root):
|
|
327
391
|
"""拉取全部类型,供 init 复用。"""
|
|
328
|
-
pull_pages(server, token, root)
|
|
329
|
-
pull_navigations(server, token, root)
|
|
392
|
+
results = [pull_pages(server, token, root), pull_navigations(server, token, root)]
|
|
330
393
|
for t in ("db_meta", "aihub", "roles", "users", "system_config"):
|
|
331
|
-
pull_simple(server, token, root, t)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
394
|
+
results.append(pull_simple(server, token, root, t))
|
|
395
|
+
results.extend([
|
|
396
|
+
pull_doc_categories(server, token, root),
|
|
397
|
+
pull_docs(server, token, root),
|
|
398
|
+
pull_custom_scripts(server, token, root),
|
|
399
|
+
])
|
|
400
|
+
return None if any(result is None for result in results) else results
|
|
336
401
|
|
|
337
402
|
|
|
338
403
|
def main():
|
|
@@ -345,7 +410,8 @@ def main():
|
|
|
345
410
|
root = DEFAULT_ROOT
|
|
346
411
|
|
|
347
412
|
if mode == "--all":
|
|
348
|
-
pull_all(server, token, root)
|
|
413
|
+
if pull_all(server, token, root) is None:
|
|
414
|
+
sys.exit(1)
|
|
349
415
|
return
|
|
350
416
|
|
|
351
417
|
if mode not in PULL_HANDLERS:
|
|
@@ -353,7 +419,8 @@ def main():
|
|
|
353
419
|
sys.exit(1)
|
|
354
420
|
|
|
355
421
|
ids = sys.argv[2:] or None
|
|
356
|
-
PULL_HANDLERS[mode](server, token, root, ids)
|
|
422
|
+
if PULL_HANDLERS[mode](server, token, root, ids) is None:
|
|
423
|
+
sys.exit(1)
|
|
357
424
|
|
|
358
425
|
|
|
359
426
|
if __name__ == "__main__":
|