siluzan-website-cli 1.0.1-beta.1 → 1.0.1-beta.10
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 +30 -4
- package/dist/index.js +2791 -236
- package/dist/skill/SKILL.md +47 -19
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/content.md +39 -0
- package/dist/skill/references/media.md +11 -0
- package/dist/skill/references/pages.md +12 -0
- package/dist/skill/references/plugins.md +66 -15
- package/dist/skill/references/provision.md +104 -0
- package/dist/skill/references/search.md +12 -0
- package/dist/skill/references/sites.md +8 -3
- package/dist/skill/references/terms.md +14 -0
- package/dist/skill/references/zasp-recommender.md +256 -0
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1960,6 +1960,7 @@ import * as fs from "fs";
|
|
|
1960
1960
|
import * as path from "path";
|
|
1961
1961
|
import * as os from "os";
|
|
1962
1962
|
import lockfile from "proper-lockfile";
|
|
1963
|
+
import { randomBytes } from "crypto";
|
|
1963
1964
|
import * as https from "https";
|
|
1964
1965
|
import * as http from "http";
|
|
1965
1966
|
import * as zlib from "zlib";
|
|
@@ -2460,7 +2461,13 @@ function rawRequest(url, options) {
|
|
|
2460
2461
|
}
|
|
2461
2462
|
reject(err);
|
|
2462
2463
|
});
|
|
2463
|
-
if (options.body)
|
|
2464
|
+
if (options.body !== void 0) {
|
|
2465
|
+
const payload = typeof options.body === "string" ? Buffer.from(options.body) : options.body;
|
|
2466
|
+
if (!headers["Content-Length"] && !headers["content-length"]) {
|
|
2467
|
+
req.setHeader("Content-Length", payload.length);
|
|
2468
|
+
}
|
|
2469
|
+
req.write(payload);
|
|
2470
|
+
}
|
|
2464
2471
|
req.end();
|
|
2465
2472
|
});
|
|
2466
2473
|
}
|
|
@@ -2557,6 +2564,54 @@ function formatHttpError(status, rawBody, opts) {
|
|
|
2557
2564
|
function buildAuthHeaders(config) {
|
|
2558
2565
|
return buildSiluzanAuthHeaders(config);
|
|
2559
2566
|
}
|
|
2567
|
+
function buildMultipartBody(fields, files) {
|
|
2568
|
+
const boundary = `----SiluzanForm${randomBytes(16).toString("hex")}`;
|
|
2569
|
+
const chunks = [];
|
|
2570
|
+
for (const [name, value] of Object.entries(fields)) {
|
|
2571
|
+
chunks.push(
|
|
2572
|
+
Buffer.from(
|
|
2573
|
+
`--${boundary}\r
|
|
2574
|
+
Content-Disposition: form-data; name="${name}"\r
|
|
2575
|
+
\r
|
|
2576
|
+
${value}\r
|
|
2577
|
+
`
|
|
2578
|
+
)
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
for (const file of files) {
|
|
2582
|
+
chunks.push(
|
|
2583
|
+
Buffer.from(
|
|
2584
|
+
`--${boundary}\r
|
|
2585
|
+
Content-Disposition: form-data; name="${file.field}"; filename="${file.filename}"\r
|
|
2586
|
+
Content-Type: ${file.contentType}\r
|
|
2587
|
+
\r
|
|
2588
|
+
`
|
|
2589
|
+
)
|
|
2590
|
+
);
|
|
2591
|
+
chunks.push(file.data);
|
|
2592
|
+
chunks.push(Buffer.from("\r\n"));
|
|
2593
|
+
}
|
|
2594
|
+
chunks.push(Buffer.from(`--${boundary}--\r
|
|
2595
|
+
`));
|
|
2596
|
+
return {
|
|
2597
|
+
body: Buffer.concat(chunks),
|
|
2598
|
+
contentType: `multipart/form-data; boundary=${boundary}`
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
async function parseApiResponse(status, text, verbose) {
|
|
2602
|
+
if (status < 200 || status >= 300) {
|
|
2603
|
+
throw new Error(formatHttpError(status, text, { verbose }));
|
|
2604
|
+
}
|
|
2605
|
+
if (!text.trim()) return null;
|
|
2606
|
+
try {
|
|
2607
|
+
return parseJsonWithStringIds(text);
|
|
2608
|
+
} catch {
|
|
2609
|
+
if (verbose) {
|
|
2610
|
+
console.error(` \u26A0\uFE0F \u54CD\u5E94\u975E JSON\uFF0C\u539F\u59CB\u5185\u5BB9\uFF1A${redactSensitive(text).slice(0, 200)}`);
|
|
2611
|
+
}
|
|
2612
|
+
return text;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2560
2615
|
async function apiFetch(url, config, options = {}, verbose = false) {
|
|
2561
2616
|
const method = options.method ?? "GET";
|
|
2562
2617
|
const reqHeaders = {
|
|
@@ -2575,19 +2630,23 @@ async function apiFetch(url, config, options = {}, verbose = false) {
|
|
|
2575
2630
|
headers: reqHeaders,
|
|
2576
2631
|
body
|
|
2577
2632
|
});
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2633
|
+
return parseApiResponse(res.status, res.text, verbose);
|
|
2634
|
+
}
|
|
2635
|
+
async function apiFetchMultipart(url, config, payload, verbose = false) {
|
|
2636
|
+
const packed = buildMultipartBody(payload.fields ?? {}, payload.files);
|
|
2637
|
+
const reqHeaders = {
|
|
2638
|
+
"Content-Type": packed.contentType,
|
|
2639
|
+
"Accept-Language": "zh-CN",
|
|
2640
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
2641
|
+
...buildAuthHeaders(config),
|
|
2642
|
+
Datapermission: config.dataPermission ?? ""
|
|
2643
|
+
};
|
|
2644
|
+
const res = await rawRequest(url, {
|
|
2645
|
+
method: "POST",
|
|
2646
|
+
headers: reqHeaders,
|
|
2647
|
+
body: packed.body
|
|
2648
|
+
});
|
|
2649
|
+
return parseApiResponse(res.status, res.text, verbose);
|
|
2591
2650
|
}
|
|
2592
2651
|
function getCurrentVersion(importMetaUrl) {
|
|
2593
2652
|
try {
|
|
@@ -3258,7 +3317,9 @@ import { spawnSync } from "child_process";
|
|
|
3258
3317
|
var BUILD_ENV = "test";
|
|
3259
3318
|
var DEFAULT_API_BASE = "https://api-ci.siluzan.com";
|
|
3260
3319
|
var DEFAULT_CSO_BASE = "https://cso-ci.siluzan.com";
|
|
3320
|
+
var DEFAULT_CSO_PLUGIN_API = "https://cso-api-ci.siluzan.com";
|
|
3261
3321
|
var DEFAULT_WEB_BASE = "https://www-ci.siluzan.com";
|
|
3322
|
+
var DEFAULT_SITEMAN_BASE = "https://api-ussiteman-ci.mysiluzan.com";
|
|
3262
3323
|
var DEFAULT_SITE_STAGE = "ci";
|
|
3263
3324
|
|
|
3264
3325
|
// src/utils/version.ts
|
|
@@ -3668,6 +3729,7 @@ function loadConfig() {
|
|
|
3668
3729
|
}
|
|
3669
3730
|
const apiBaseUrl = process.env.SILUZAN_WEBSITE_API_BASE ?? DEFAULT_API_BASE;
|
|
3670
3731
|
const csoBaseUrl = process.env.SILUZAN_CSO_BASE ?? DEFAULT_CSO_BASE;
|
|
3732
|
+
const csoPluginApiBaseUrl = process.env.SILUZAN_CSO_PLUGIN_API ?? DEFAULT_CSO_PLUGIN_API;
|
|
3671
3733
|
const apiErr = validateBaseUrl(apiBaseUrl);
|
|
3672
3734
|
if (apiErr) {
|
|
3673
3735
|
console.error(`
|
|
@@ -3680,9 +3742,16 @@ function loadConfig() {
|
|
|
3680
3742
|
\u274C csoBaseUrl \u4E0D\u5408\u6CD5\uFF1A${csoErr}`);
|
|
3681
3743
|
process.exit(1);
|
|
3682
3744
|
}
|
|
3745
|
+
const pluginApiErr = validateBaseUrl(csoPluginApiBaseUrl);
|
|
3746
|
+
if (pluginApiErr) {
|
|
3747
|
+
console.error(`
|
|
3748
|
+
\u274C csoPluginApiBaseUrl \u4E0D\u5408\u6CD5\uFF1A${pluginApiErr}`);
|
|
3749
|
+
process.exit(1);
|
|
3750
|
+
}
|
|
3683
3751
|
return {
|
|
3684
3752
|
apiBaseUrl,
|
|
3685
3753
|
csoBaseUrl,
|
|
3754
|
+
csoPluginApiBaseUrl,
|
|
3686
3755
|
authToken: "",
|
|
3687
3756
|
apiKey,
|
|
3688
3757
|
dataPermission: process.env.SILUZAN_DATA_PERMISSION ?? shared.dataPermission
|
|
@@ -3691,6 +3760,9 @@ function loadConfig() {
|
|
|
3691
3760
|
function apiFetch2(url, config, options = {}, verbose = false) {
|
|
3692
3761
|
return apiFetch(url, config, options, verbose);
|
|
3693
3762
|
}
|
|
3763
|
+
function apiFetchMultipart2(url, config, payload, verbose = false) {
|
|
3764
|
+
return apiFetchMultipart(url, config, payload, verbose);
|
|
3765
|
+
}
|
|
3694
3766
|
|
|
3695
3767
|
// src/utils/site-url.ts
|
|
3696
3768
|
function normalizeRegion(raw) {
|
|
@@ -3834,256 +3906,2202 @@ async function runSitesList(options) {
|
|
|
3834
3906
|
console.log("\n\u540E\u7EED\uFF1Asiluzan-website pages list --site <guid>\n");
|
|
3835
3907
|
}
|
|
3836
3908
|
function register5(program2) {
|
|
3837
|
-
const sites = program2.command("sites").description("WordPress \u7AD9\u70B9\u67E5\u8BE2");
|
|
3909
|
+
const sites = program2.command("sites").description("WordPress \u7AD9\u70B9\u67E5\u8BE2\u4E0E\u5F00\u901A");
|
|
3838
3910
|
sites.command("list").description("\u5217\u51FA\u5F53\u524D\u8D26\u53F7\u4E0B\u7684 WordPress \u7AD9\u70B9").option("-q, --query <keyword>", "\u6309\u540D\u79F0\u641C\u7D22").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
3839
3911
|
await runSitesList(opts);
|
|
3840
3912
|
});
|
|
3913
|
+
sites.command("create").description("\u805A\u5408\u521B\u5EFA\u7AD9\u70B9\uFF08website-provision\uFF0C\u5199\u64CD\u4F5C\uFF0CAgent \u987B\u5148\u83B7\u7528\u6237\u786E\u8BA4\uFF09").option("--name <advertiserName>", "\u7AD9\u70B9\u540D\u79F0").option("--region <US|CN>", "\u533A\u57DF", "US").option("--package <packageId>", "\u5957\u9910 ID").option("--template <siteTemplateId>", "\u6A21\u677F ID").option("--site-lang <lang>", "\u524D\u53F0\u8BED\u8A00\uFF0C\u5982 en_US / zh_CN").option("--admin-lang <lang>", "\u540E\u53F0\u8BED\u8A00").option("--bill <packageBillId>", "\u5DF2\u4ED8\u8D26\u5355\u53F7\uFF08\u4ED8\u8D39\u8DEF\u5F84\uFF1B\u8BD5\u7528\u53EF\u4E0D\u4F20\uFF09").option("--wait", "\u521B\u5EFA\u540E\u8F6E\u8BE2\u81F3 Online", false).option("--timeout <seconds>", "wait \u8D85\u65F6\u79D2\u6570", "600").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
3914
|
+
await runSitesCreate(opts);
|
|
3915
|
+
});
|
|
3916
|
+
sites.command("status").description("\u67E5\u8BE2\u5EFA\u7AD9\u72B6\u6001\uFF08website-provision\uFF09").option("--site <siteGuid>", "\u7AD9\u70B9 guid").option("--region <US|CN>", "\u533A\u57DF", "US").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
3917
|
+
await runSitesStatus(opts);
|
|
3918
|
+
});
|
|
3919
|
+
sites.command("bind").description("\u8D26\u53F7\u6302\u63A5\u8865\u507F\uFF08SiteMan \u5DF2\u6210\u529F\u4F46 list \u4E0D\u53EF\u89C1\u65F6\uFF09").option("--site <siteGuid>", "\u7AD9\u70B9 guid").option("--region <US|CN>", "\u533A\u57DF", "US").option("--name <advertiserName>", "\u7AD9\u70B9\u540D\u79F0\uFF08\u7528\u4E8E\u67E5\u627E/\u521B\u5EFA Mag\uFF09").option("--mag <magKey>", "\u5DF2\u6709 Mag Key\uFF08\u53EF\u9009\uFF09").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
3920
|
+
await runSitesBind(opts);
|
|
3921
|
+
});
|
|
3841
3922
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
import * as fs6 from "fs";
|
|
3845
|
-
function pageTitle(page) {
|
|
3846
|
-
if (typeof page.title === "string") return page.title;
|
|
3847
|
-
return page.title?.rendered ?? "";
|
|
3923
|
+
function asRecordLocal(value) {
|
|
3924
|
+
return value && typeof value === "object" ? value : null;
|
|
3848
3925
|
}
|
|
3849
|
-
function
|
|
3850
|
-
if (
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
} catch (e) {
|
|
3854
|
-
console.error(`
|
|
3855
|
-
\u274C \u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 ${filePath}\uFF1A${e.message}
|
|
3856
|
-
`);
|
|
3857
|
-
process.exit(1);
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
return inline ?? "";
|
|
3926
|
+
function readStr2(obj, key) {
|
|
3927
|
+
if (!obj) return "";
|
|
3928
|
+
const v = obj[key];
|
|
3929
|
+
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
3861
3930
|
}
|
|
3862
|
-
async function
|
|
3931
|
+
async function runSitesCreate(opts) {
|
|
3932
|
+
const name = opts.name?.trim();
|
|
3933
|
+
const packageId = opts.package?.trim();
|
|
3934
|
+
const templateId = opts.template?.trim();
|
|
3935
|
+
const region = (opts.region || "US").trim();
|
|
3936
|
+
const siteLang = opts.siteLang?.trim() || (region.toUpperCase() === "CN" ? "zh_CN" : "en_US");
|
|
3937
|
+
const adminLang = opts.adminLang?.trim() || siteLang;
|
|
3938
|
+
if (!name || !packageId || !templateId) {
|
|
3939
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --name --package --template\uFF08\u4EE5\u53CA\u53EF\u9009 --bill / --region / --site-lang / --admin-lang\uFF09\n");
|
|
3940
|
+
process.exit(1);
|
|
3941
|
+
}
|
|
3942
|
+
console.log("\n\u5373\u5C06\u521B\u5EFA WordPress \u7AD9\u70B9\uFF08\u4E3B\u7AD9 website-provision\uFF0C\u4E0D\u53EF\u76F2\u76EE\u91CD\u8BD5\uFF09\uFF1A");
|
|
3943
|
+
console.log(` name : ${name}`);
|
|
3944
|
+
console.log(` region : ${region}`);
|
|
3945
|
+
console.log(` packageId : ${packageId}`);
|
|
3946
|
+
console.log(` templateId : ${templateId}`);
|
|
3947
|
+
console.log(` siteLang : ${siteLang}`);
|
|
3948
|
+
console.log(` adminLang : ${adminLang}`);
|
|
3949
|
+
console.log(` billId : ${opts.bill?.trim() || "(\u8BD5\u7528)"}`);
|
|
3863
3950
|
const config = loadConfig();
|
|
3864
|
-
const
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3951
|
+
const body = {
|
|
3952
|
+
advertiserName: name,
|
|
3953
|
+
region,
|
|
3954
|
+
packageId,
|
|
3955
|
+
siteTemplateId: templateId,
|
|
3956
|
+
siteLang,
|
|
3957
|
+
adminLang,
|
|
3958
|
+
packageBillId: opts.bill?.trim() || void 0
|
|
3959
|
+
};
|
|
3960
|
+
const url = `${config.apiBaseUrl}/website-provision/sites`;
|
|
3961
|
+
let raw;
|
|
3868
3962
|
try {
|
|
3869
|
-
|
|
3963
|
+
raw = await apiFetch2(
|
|
3964
|
+
url,
|
|
3965
|
+
config,
|
|
3966
|
+
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
|
|
3967
|
+
opts.verbose
|
|
3968
|
+
);
|
|
3870
3969
|
} catch (e) {
|
|
3871
3970
|
console.error(`
|
|
3872
|
-
\u274C \
|
|
3873
|
-
console.error(` \u7AD9\u70B9\uFF1A${base}`);
|
|
3971
|
+
\u274C \u521B\u5EFA\u7AD9\u70B9\u5931\u8D25\uFF1A${e.message}`);
|
|
3874
3972
|
process.exit(1);
|
|
3875
3973
|
return;
|
|
3876
3974
|
}
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3975
|
+
const obj = asRecordLocal(raw);
|
|
3976
|
+
const siteGuid = readStr2(obj, "siteGuid") || readStr2(obj, "SiteGuid");
|
|
3977
|
+
const bound = obj?.bound === true || obj?.Bound === true;
|
|
3978
|
+
const code = readStr2(obj, "code") || readStr2(obj, "Code") || "ok";
|
|
3881
3979
|
if (opts.json) {
|
|
3882
|
-
console.log(
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
2
|
|
3898
|
-
)
|
|
3899
|
-
);
|
|
3900
|
-
return;
|
|
3980
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
3981
|
+
} else {
|
|
3982
|
+
console.log(code === "site_created_unbound" ? "\n\u26A0\uFE0F \u7AD9\u70B9\u5DF2\u521B\u5EFA\u4F46\u8D26\u53F7\u6302\u63A5\u672A\u5B8C\u6210\n" : "\n\u2705 \u7AD9\u70B9\u521B\u5EFA\u8BF7\u6C42\u5DF2\u53D7\u7406\n");
|
|
3983
|
+
console.log(` siteGuid : ${siteGuid}`);
|
|
3984
|
+
console.log(` region : ${readStr2(obj, "region") || region}`);
|
|
3985
|
+
console.log(` state : ${readStr2(obj, "state") || readStr2(obj, "State") || "-"}`);
|
|
3986
|
+
console.log(` platformUrl : ${readStr2(obj, "platformUrl") || readStr2(obj, "PlatformUrl") || "-"}`);
|
|
3987
|
+
console.log(` bound : ${bound}`);
|
|
3988
|
+
console.log(` magKey : ${readStr2(obj, "magKey") || readStr2(obj, "MagKey") || "-"}`);
|
|
3989
|
+
console.log(` code : ${code}`);
|
|
3990
|
+
if (code === "site_created_unbound") {
|
|
3991
|
+
console.log(`
|
|
3992
|
+
\u8865\u507F\uFF1Asiluzan-website sites bind --site ${siteGuid} --region ${region} --name "${name}"
|
|
3993
|
+
`);
|
|
3994
|
+
}
|
|
3901
3995
|
}
|
|
3902
|
-
if (
|
|
3996
|
+
if (opts.wait && siteGuid) {
|
|
3997
|
+
await pollUntilOnline(config, siteGuid, region, Number(opts.timeout) || 600, opts.verbose);
|
|
3998
|
+
} else if (siteGuid && !opts.json) {
|
|
3903
3999
|
console.log(`
|
|
3904
|
-
\
|
|
4000
|
+
\u8F6E\u8BE2\u72B6\u6001\uFF1Asiluzan-website sites status --site ${siteGuid} --region ${region}`);
|
|
4001
|
+
console.log(`\u5217\u8868\u6838\u5BF9\uFF1Asiluzan-website sites list -q ${siteGuid}
|
|
3905
4002
|
`);
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
async function runSitesStatus(opts) {
|
|
4006
|
+
const siteGuid = opts.site?.trim();
|
|
4007
|
+
const region = (opts.region || "US").trim();
|
|
4008
|
+
if (!siteGuid) {
|
|
4009
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --site <siteGuid>\n");
|
|
4010
|
+
process.exit(1);
|
|
4011
|
+
}
|
|
4012
|
+
const config = loadConfig();
|
|
4013
|
+
const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(region)}/${encodeURIComponent(siteGuid)}/status`;
|
|
4014
|
+
let raw;
|
|
4015
|
+
try {
|
|
4016
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4017
|
+
} catch (e) {
|
|
4018
|
+
console.error(`
|
|
4019
|
+
\u274C \u67E5\u8BE2\u72B6\u6001\u5931\u8D25\uFF1A${e.message}`);
|
|
4020
|
+
process.exit(1);
|
|
3906
4021
|
return;
|
|
3907
4022
|
}
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
console.log(`
|
|
3915
|
-
|
|
3916
|
-
`);
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
id: String(p.id),
|
|
3920
|
-
title: pageTitle(p) || "(\u65E0\u6807\u9898)",
|
|
3921
|
-
status: p.status ?? "-",
|
|
3922
|
-
link: p.link ?? "-"
|
|
3923
|
-
})),
|
|
3924
|
-
columns
|
|
3925
|
-
);
|
|
4023
|
+
if (opts.json) {
|
|
4024
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
4025
|
+
return;
|
|
4026
|
+
}
|
|
4027
|
+
const obj = asRecordLocal(raw);
|
|
4028
|
+
console.log("\n\u5EFA\u7AD9\u72B6\u6001\n");
|
|
4029
|
+
console.log(` siteGuid : ${readStr2(obj, "siteGuid") || siteGuid}`);
|
|
4030
|
+
console.log(` region : ${readStr2(obj, "region") || region}`);
|
|
4031
|
+
console.log(` statusCode : ${String(obj?.statusCode ?? obj?.StatusCode ?? "-")}`);
|
|
4032
|
+
console.log(` online : ${String(obj?.online ?? obj?.Online ?? "-")}`);
|
|
4033
|
+
console.log(` url : ${readStr2(obj, "url") || readStr2(obj, "Url") || "-"}`);
|
|
3926
4034
|
console.log();
|
|
3927
4035
|
}
|
|
3928
|
-
async function
|
|
3929
|
-
const
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
const title = opts.title?.trim() ?? "";
|
|
3933
|
-
const content = readTextOption(opts.content, opts.contentFile);
|
|
3934
|
-
if (mode === "add" && !title) {
|
|
3935
|
-
console.error("\n\u274C \u65B0\u589E\u9875\u9762\u5FC5\u987B\u63D0\u4F9B --title\n");
|
|
4036
|
+
async function runSitesBind(opts) {
|
|
4037
|
+
const siteGuid = opts.site?.trim();
|
|
4038
|
+
if (!siteGuid) {
|
|
4039
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --site <siteGuid>\n");
|
|
3936
4040
|
process.exit(1);
|
|
3937
4041
|
}
|
|
3938
|
-
if (!
|
|
3939
|
-
console.error("\n\u274C \u8BF7\
|
|
4042
|
+
if (!opts.name?.trim() && !opts.mag?.trim()) {
|
|
4043
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --name <advertiserName> \u6216 --mag <magKey>\n");
|
|
3940
4044
|
process.exit(1);
|
|
3941
4045
|
}
|
|
4046
|
+
const config = loadConfig();
|
|
3942
4047
|
const body = {
|
|
3943
|
-
|
|
3944
|
-
|
|
4048
|
+
region: opts.region || "US",
|
|
4049
|
+
advertiserName: opts.name?.trim(),
|
|
4050
|
+
magKey: opts.mag?.trim()
|
|
3945
4051
|
};
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
if (css) body._custom_css = css;
|
|
3949
|
-
const js = readTextOption(opts.js, opts.jsFile);
|
|
3950
|
-
if (js) body._custom_javascript = js;
|
|
3951
|
-
if (mode === "add") body.post_type = opts.postType?.trim() || "page";
|
|
3952
|
-
const api = mode === "add" ? `${base}/wp-json/zionbuilder/v1/pages/add-visual-edit` : `${base}/wp-json/zionbuilder/v1/pages/${opts.id}/save-visual-edit`;
|
|
3953
|
-
if (mode === "update" && !opts.id) {
|
|
3954
|
-
console.error("\n\u274C \u66F4\u65B0\u9875\u9762\u5FC5\u987B\u63D0\u4F9B --id\uFF08\u5148 pages list \u67E5 id\uFF09\n");
|
|
3955
|
-
process.exit(1);
|
|
3956
|
-
}
|
|
3957
|
-
let result;
|
|
4052
|
+
const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(siteGuid)}/bind`;
|
|
4053
|
+
let raw;
|
|
3958
4054
|
try {
|
|
3959
|
-
|
|
3960
|
-
|
|
4055
|
+
raw = await apiFetch2(
|
|
4056
|
+
url,
|
|
3961
4057
|
config,
|
|
3962
|
-
{ method: "POST", body: JSON.stringify(body) },
|
|
4058
|
+
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
|
|
3963
4059
|
opts.verbose
|
|
3964
4060
|
);
|
|
3965
4061
|
} catch (e) {
|
|
3966
4062
|
console.error(`
|
|
3967
|
-
\u274C
|
|
3968
|
-
`);
|
|
4063
|
+
\u274C \u6302\u63A5\u5931\u8D25\uFF1A${e.message}`);
|
|
3969
4064
|
process.exit(1);
|
|
3970
4065
|
return;
|
|
3971
4066
|
}
|
|
3972
|
-
if (
|
|
3973
|
-
console.
|
|
3974
|
-
|
|
3975
|
-
`);
|
|
3976
|
-
process.exit(1);
|
|
4067
|
+
if (opts.json) {
|
|
4068
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
4069
|
+
return;
|
|
3977
4070
|
}
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
console.log(`
|
|
3982
|
-
`);
|
|
4071
|
+
const obj = asRecordLocal(raw);
|
|
4072
|
+
console.log("\n\u2705 \u6302\u63A5\u5B8C\u6210\n");
|
|
4073
|
+
console.log(` siteGuid : ${readStr2(obj, "siteGuid") || siteGuid}`);
|
|
4074
|
+
console.log(` bound : ${String(obj?.bound ?? true)}`);
|
|
4075
|
+
console.log(` magKey : ${readStr2(obj, "magKey") || "-"}`);
|
|
4076
|
+
console.log("\n\u8BF7\u518D\u8DD1 siluzan-website sites list \u6838\u5BF9\u3002\n");
|
|
3983
4077
|
}
|
|
3984
|
-
function
|
|
3985
|
-
const
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
4078
|
+
async function pollUntilOnline(config, siteGuid, region, timeoutSec, verbose) {
|
|
4079
|
+
const deadline = Date.now() + timeoutSec * 1e3;
|
|
4080
|
+
console.log(`
|
|
4081
|
+
\u7B49\u5F85\u7AD9\u70B9 Online\uFF08\u6700\u957F ${timeoutSec}s\uFF09\u2026`);
|
|
4082
|
+
while (Date.now() < deadline) {
|
|
4083
|
+
try {
|
|
4084
|
+
const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(region)}/${encodeURIComponent(siteGuid)}/status`;
|
|
4085
|
+
const raw = await apiFetch2(url, config, {}, verbose);
|
|
4086
|
+
const obj = asRecordLocal(raw);
|
|
4087
|
+
const online = Boolean(obj?.online ?? obj?.Online);
|
|
4088
|
+
const code = obj?.statusCode ?? obj?.StatusCode;
|
|
4089
|
+
process.stdout.write(` statusCode=${code} online=${online}
|
|
4090
|
+
`);
|
|
4091
|
+
if (online) {
|
|
4092
|
+
console.log("\n\u2705 \u7AD9\u70B9\u5DF2\u53EF\u8BBF\u95EE\uFF08Online\uFF09\n");
|
|
4093
|
+
return;
|
|
4094
|
+
}
|
|
4095
|
+
} catch (e) {
|
|
4096
|
+
process.stdout.write(` \u8F6E\u8BE2\u5F02\u5E38\uFF1A${e.message}
|
|
4097
|
+
`);
|
|
4098
|
+
}
|
|
4099
|
+
await new Promise((r) => setTimeout(r, 1e4));
|
|
4100
|
+
}
|
|
4101
|
+
console.error("\n\u26A0\uFE0F \u7B49\u5F85\u8D85\u65F6\uFF0C\u7AD9\u70B9\u53EF\u80FD\u4ECD\u5728\u521B\u5EFA\u4E2D\u3002\u8BF7\u7A0D\u540E siluzan-website sites status \u518D\u67E5\u3002\n");
|
|
3995
4102
|
}
|
|
3996
4103
|
|
|
3997
|
-
// src/commands/
|
|
3998
|
-
function
|
|
3999
|
-
|
|
4000
|
-
return item.name?.raw || item.name?.rendered || item.plugin || "";
|
|
4104
|
+
// src/commands/packages.ts
|
|
4105
|
+
function asRecord2(value) {
|
|
4106
|
+
return value && typeof value === "object" ? value : null;
|
|
4001
4107
|
}
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
const
|
|
4005
|
-
return
|
|
4108
|
+
function readString2(obj, key) {
|
|
4109
|
+
if (!obj) return "";
|
|
4110
|
+
const v = obj[key];
|
|
4111
|
+
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
4006
4112
|
}
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4113
|
+
function unwrapList(raw) {
|
|
4114
|
+
if (Array.isArray(raw)) {
|
|
4115
|
+
return raw.map(asRecord2).filter((x) => Boolean(x));
|
|
4116
|
+
}
|
|
4117
|
+
const obj = asRecord2(raw);
|
|
4118
|
+
if (!obj) return [];
|
|
4119
|
+
if (Array.isArray(obj.data)) {
|
|
4120
|
+
return obj.data.map(asRecord2).filter((x) => Boolean(x));
|
|
4121
|
+
}
|
|
4122
|
+
return [];
|
|
4123
|
+
}
|
|
4124
|
+
async function runPackagesList(opts) {
|
|
4125
|
+
const config = loadConfig();
|
|
4126
|
+
const url = `${config.apiBaseUrl}/website-provision/packages`;
|
|
4127
|
+
let raw;
|
|
4011
4128
|
try {
|
|
4012
|
-
|
|
4129
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4013
4130
|
} catch (e) {
|
|
4014
4131
|
console.error(`
|
|
4015
|
-
\u274C \u83B7\u53D6\
|
|
4016
|
-
|
|
4132
|
+
\u274C \u83B7\u53D6\u5957\u9910\u5217\u8868\u5931\u8D25\uFF1A${e.message}`);
|
|
4133
|
+
if (!opts.verbose) console.error(" \u52A0 --verbose \u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF");
|
|
4017
4134
|
process.exit(1);
|
|
4018
4135
|
return;
|
|
4019
4136
|
}
|
|
4020
|
-
|
|
4021
|
-
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u63D2\u4EF6\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
4022
|
-
process.exit(1);
|
|
4023
|
-
}
|
|
4137
|
+
const list = unwrapList(raw);
|
|
4024
4138
|
if (opts.json) {
|
|
4025
|
-
console.log(
|
|
4026
|
-
JSON.stringify(
|
|
4027
|
-
{
|
|
4028
|
-
site: { guid: site.guid, name: site.name, url: site.url },
|
|
4029
|
-
total: plugins.length,
|
|
4030
|
-
plugins: plugins.map((p) => ({
|
|
4031
|
-
plugin: p.plugin ?? "",
|
|
4032
|
-
name: pluginName(p),
|
|
4033
|
-
status: p.status ?? "",
|
|
4034
|
-
version: p.version ?? ""
|
|
4035
|
-
}))
|
|
4036
|
-
},
|
|
4037
|
-
null,
|
|
4038
|
-
2
|
|
4039
|
-
)
|
|
4040
|
-
);
|
|
4139
|
+
console.log(JSON.stringify({ total: list.length, packages: list }, null, 2));
|
|
4041
4140
|
return;
|
|
4042
4141
|
}
|
|
4043
|
-
if (
|
|
4044
|
-
console.log(
|
|
4045
|
-
\u7AD9\u70B9 ${site.name} \u672A\u8FD4\u56DE\u63D2\u4EF6\u3002
|
|
4046
|
-
`);
|
|
4142
|
+
if (list.length === 0) {
|
|
4143
|
+
console.log("\n\u6682\u65E0\u53EF\u7528\u5957\u9910\u3002\n");
|
|
4047
4144
|
return;
|
|
4048
4145
|
}
|
|
4049
4146
|
const columns = [
|
|
4050
|
-
{ key: "
|
|
4051
|
-
{ key: "
|
|
4052
|
-
{ key: "
|
|
4053
|
-
{ key: "
|
|
4147
|
+
{ key: "packageId", header: "packageId" },
|
|
4148
|
+
{ key: "packageName", header: "\u540D\u79F0" },
|
|
4149
|
+
{ key: "monthUsd", header: "\u6708\u4ED8(USD)" },
|
|
4150
|
+
{ key: "yearUsd", header: "\u5E74\u4ED8\u6708\u4EF7(USD)" },
|
|
4151
|
+
{ key: "enabled", header: "\u542F\u7528" },
|
|
4152
|
+
{ key: "sunset", header: "\u4E0B\u67B6" }
|
|
4054
4153
|
];
|
|
4154
|
+
const rows = list.map((p) => ({
|
|
4155
|
+
packageId: readString2(p, "packageId") || readString2(p, "PackageId"),
|
|
4156
|
+
packageName: readString2(p, "packageName") || readString2(p, "PackageName"),
|
|
4157
|
+
monthUsd: readString2(p, "monthPriceUSD") || readString2(p, "MonthPriceUSD") || "-",
|
|
4158
|
+
yearUsd: readString2(p, "yearlyPriceUSD") || readString2(p, "YearlyPriceUSD") || "-",
|
|
4159
|
+
enabled: String(p.enabled ?? p.Enabled ?? "-"),
|
|
4160
|
+
sunset: String(p.sunset ?? p.Sunset ?? "-")
|
|
4161
|
+
}));
|
|
4055
4162
|
console.log(`
|
|
4056
|
-
|
|
4163
|
+
\u5957\u9910\u5217\u8868\uFF08\u5171 ${list.length} \u4E2A\uFF09
|
|
4057
4164
|
`);
|
|
4058
|
-
printCliTable(
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4165
|
+
printCliTable(rows, columns);
|
|
4166
|
+
console.log("\n\u4E0B\u4E00\u6B65\uFF1Asiluzan-website templates list --package <packageId>\n");
|
|
4167
|
+
}
|
|
4168
|
+
function register6(program2) {
|
|
4169
|
+
const packages = program2.command("packages").description("\u5EFA\u7AD9\u5957\u9910\uFF08website-provision\uFF09");
|
|
4170
|
+
packages.command("list").description("\u5217\u51FA\u53EF\u552E\u5957\u9910").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4171
|
+
await runPackagesList(opts);
|
|
4172
|
+
});
|
|
4173
|
+
}
|
|
4174
|
+
|
|
4175
|
+
// src/commands/templates.ts
|
|
4176
|
+
import fs6 from "fs";
|
|
4177
|
+
import path6 from "path";
|
|
4178
|
+
function resolveJsonOutFile(jsonOut) {
|
|
4179
|
+
const raw = jsonOut.trim();
|
|
4180
|
+
if (!raw) {
|
|
4181
|
+
throw new Error("--json-out \u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4182
|
+
}
|
|
4183
|
+
const abs = path6.resolve(raw);
|
|
4184
|
+
if (abs.toLowerCase().endsWith(".json")) {
|
|
4185
|
+
fs6.mkdirSync(path6.dirname(abs), { recursive: true });
|
|
4186
|
+
return abs;
|
|
4187
|
+
}
|
|
4188
|
+
fs6.mkdirSync(abs, { recursive: true });
|
|
4189
|
+
return path6.join(abs, "template-catalog.json");
|
|
4190
|
+
}
|
|
4191
|
+
function slimCatalogGroups(groups) {
|
|
4192
|
+
return groups.map((g) => {
|
|
4193
|
+
const templates = Array.isArray(g.templates) ? g.templates : [];
|
|
4194
|
+
return {
|
|
4195
|
+
packageId: readString3(g, "packageId") || readString3(g, "PackageId"),
|
|
4196
|
+
packageName: readString3(g, "packageName") || readString3(g, "PackageName"),
|
|
4197
|
+
monthPriceUSD: g.monthPriceUSD ?? g.MonthPriceUSD ?? "-",
|
|
4198
|
+
yearlyPriceUSD: g.yearlyPriceUSD ?? g.YearlyPriceUSD ?? "-",
|
|
4199
|
+
templates: templates.map((item) => {
|
|
4200
|
+
const t = asRecord3(item) ?? {};
|
|
4201
|
+
const p = pickPreviewFields(t);
|
|
4202
|
+
return {
|
|
4203
|
+
siteTemplateId: p.id,
|
|
4204
|
+
name: p.name,
|
|
4205
|
+
industry: p.industry,
|
|
4206
|
+
coverUrl: p.coverUrl,
|
|
4207
|
+
previewUrl: p.previewUrl,
|
|
4208
|
+
hotTag: Boolean(t.hotTag ?? t.HotTag),
|
|
4209
|
+
newTag: Boolean(t.newTag ?? t.NewTag)
|
|
4210
|
+
};
|
|
4211
|
+
})
|
|
4212
|
+
};
|
|
4213
|
+
});
|
|
4214
|
+
}
|
|
4215
|
+
function asRecord3(value) {
|
|
4216
|
+
return value && typeof value === "object" ? value : null;
|
|
4217
|
+
}
|
|
4218
|
+
function readString3(obj, key) {
|
|
4219
|
+
if (!obj) return "";
|
|
4220
|
+
const v = obj[key];
|
|
4221
|
+
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
4222
|
+
}
|
|
4223
|
+
function unwrapList2(raw) {
|
|
4224
|
+
if (Array.isArray(raw)) {
|
|
4225
|
+
return raw.map(asRecord3).filter((x) => Boolean(x));
|
|
4226
|
+
}
|
|
4227
|
+
const obj = asRecord3(raw);
|
|
4228
|
+
if (!obj) return [];
|
|
4229
|
+
if (Array.isArray(obj.data)) {
|
|
4230
|
+
return obj.data.map(asRecord3).filter((x) => Boolean(x));
|
|
4231
|
+
}
|
|
4232
|
+
if (Array.isArray(obj.items)) {
|
|
4233
|
+
return obj.items.map(asRecord3).filter((x) => Boolean(x));
|
|
4234
|
+
}
|
|
4235
|
+
return [];
|
|
4236
|
+
}
|
|
4237
|
+
function siteManBase() {
|
|
4238
|
+
return (process.env.SILUZAN_SITEMAN_BASE ?? DEFAULT_SITEMAN_BASE).replace(/\/+$/, "");
|
|
4239
|
+
}
|
|
4240
|
+
function enrichTemplatePreview(t) {
|
|
4241
|
+
const out = { ...t };
|
|
4242
|
+
const base = siteManBase();
|
|
4243
|
+
const coverId = readString3(t, "cover") || readString3(t, "Cover");
|
|
4244
|
+
const imageId = readString3(t, "image") || readString3(t, "Image");
|
|
4245
|
+
if (!readString3(t, "coverUrl") && coverId) out.coverUrl = `${base}/api/Attachments/${coverId}`;
|
|
4246
|
+
if (!readString3(t, "imageUrl") && imageId) out.imageUrl = `${base}/api/Attachments/${imageId}`;
|
|
4247
|
+
const colors = Array.isArray(t.colors) ? t.colors : Array.isArray(t.Colors) ? t.Colors : [];
|
|
4248
|
+
const first = asRecord3(colors[0]);
|
|
4249
|
+
const preview = readString3(first, "colorSchemePreview") || readString3(first, "ColorSchemePreview");
|
|
4250
|
+
if (!readString3(t, "previewUrl") && preview) out.previewUrl = preview;
|
|
4251
|
+
const colorPreviewId = readString3(first, "colorPreview") || readString3(first, "ColorPreview");
|
|
4252
|
+
if (!readString3(t, "colorPreviewUrl") && colorPreviewId) {
|
|
4253
|
+
out.colorPreviewUrl = `${base}/api/Attachments/${colorPreviewId}`;
|
|
4254
|
+
}
|
|
4255
|
+
return out;
|
|
4256
|
+
}
|
|
4257
|
+
function templateBelongsToPackage(t, packageId) {
|
|
4258
|
+
const packages = readString3(t, "packages") || readString3(t, "Packages");
|
|
4259
|
+
if (!packages) return false;
|
|
4260
|
+
if (packages.toLowerCase().includes(`|${packageId.toLowerCase()}|`)) return true;
|
|
4261
|
+
return packages.split(/[|,;]/).map((s) => s.trim()).some((p) => p.toLowerCase() === packageId.toLowerCase());
|
|
4262
|
+
}
|
|
4263
|
+
function pickPreviewFields(t) {
|
|
4264
|
+
const e = enrichTemplatePreview(t);
|
|
4265
|
+
return {
|
|
4266
|
+
id: readString3(e, "siteTemplateId") || readString3(e, "SiteTemplateId"),
|
|
4267
|
+
name: readString3(e, "name") || readString3(e, "Name"),
|
|
4268
|
+
industry: readString3(e, "industrys") || readString3(e, "Industrys") || "-",
|
|
4269
|
+
coverUrl: readString3(e, "coverUrl") || readString3(e, "CoverUrl") || "",
|
|
4270
|
+
previewUrl: readString3(e, "previewUrl") || readString3(e, "PreviewUrl") || "",
|
|
4271
|
+
hot: String(e.hotTag ?? e.HotTag ?? "-"),
|
|
4272
|
+
neu: String(e.newTag ?? e.NewTag ?? "-"),
|
|
4273
|
+
version: readString3(e, "version") || readString3(e, "Version") || "-"
|
|
4274
|
+
};
|
|
4275
|
+
}
|
|
4276
|
+
async function composeCatalogLocally(config, verbose) {
|
|
4277
|
+
const [pkgRaw, tplRaw] = await Promise.all([
|
|
4278
|
+
apiFetch2(`${config.apiBaseUrl}/website-provision/packages`, config, {}, verbose),
|
|
4279
|
+
apiFetch2(
|
|
4280
|
+
`${config.apiBaseUrl}/website-provision/templates?pageSize=500&pageIndex=1`,
|
|
4281
|
+
config,
|
|
4282
|
+
{},
|
|
4283
|
+
verbose
|
|
4284
|
+
)
|
|
4285
|
+
]);
|
|
4286
|
+
const packages = unwrapList2(pkgRaw).filter((p) => !(p.sunset === true || p.Sunset === true));
|
|
4287
|
+
const templates = unwrapList2(tplRaw).map(enrichTemplatePreview);
|
|
4288
|
+
const groups = packages.map((p) => {
|
|
4289
|
+
const packageId = readString3(p, "packageId") || readString3(p, "PackageId");
|
|
4290
|
+
const matched = templates.filter((t) => templateBelongsToPackage(t, packageId));
|
|
4291
|
+
return {
|
|
4292
|
+
packageId,
|
|
4293
|
+
packageName: readString3(p, "packageName") || readString3(p, "PackageName"),
|
|
4294
|
+
monthPriceUSD: p.monthPriceUSD ?? p.MonthPriceUSD,
|
|
4295
|
+
yearlyPriceUSD: p.yearlyPriceUSD ?? p.YearlyPriceUSD,
|
|
4296
|
+
templates: matched,
|
|
4297
|
+
templateCount: matched.length
|
|
4298
|
+
};
|
|
4299
|
+
});
|
|
4300
|
+
return {
|
|
4301
|
+
packages,
|
|
4302
|
+
groups,
|
|
4303
|
+
totalTemplates: templates.length,
|
|
4304
|
+
source: "cli-fallback"
|
|
4305
|
+
};
|
|
4306
|
+
}
|
|
4307
|
+
async function runTemplatesList(opts) {
|
|
4308
|
+
const config = loadConfig();
|
|
4309
|
+
const params = new URLSearchParams({ pageSize: "100", pageIndex: "1" });
|
|
4310
|
+
if (opts.package) params.set("package", opts.package);
|
|
4311
|
+
if (opts.industry) params.set("industry", opts.industry);
|
|
4312
|
+
if (opts.keyword) params.set("keyword", opts.keyword);
|
|
4313
|
+
const url = `${config.apiBaseUrl}/website-provision/templates?${params.toString()}`;
|
|
4314
|
+
let raw;
|
|
4315
|
+
try {
|
|
4316
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4317
|
+
} catch (e) {
|
|
4318
|
+
console.error(`
|
|
4319
|
+
\u274C \u83B7\u53D6\u6A21\u677F\u5217\u8868\u5931\u8D25\uFF1A${e.message}`);
|
|
4320
|
+
if (!opts.verbose) console.error(" \u52A0 --verbose \u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF");
|
|
4321
|
+
process.exit(1);
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
const list = unwrapList2(raw).map(enrichTemplatePreview);
|
|
4325
|
+
if (opts.json) {
|
|
4326
|
+
console.log(JSON.stringify({ total: list.length, templates: list }, null, 2));
|
|
4327
|
+
return;
|
|
4328
|
+
}
|
|
4329
|
+
if (list.length === 0) {
|
|
4330
|
+
console.log("\n\u6682\u65E0\u5339\u914D\u6A21\u677F\u3002\u8BF7\u68C0\u67E5 --package \u662F\u5426\u6B63\u786E\u3002\n");
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
const columns = [
|
|
4334
|
+
{ key: "id", header: "siteTemplateId" },
|
|
4335
|
+
{ key: "name", header: "\u540D\u79F0" },
|
|
4336
|
+
{ key: "industry", header: "\u884C\u4E1A" },
|
|
4337
|
+
{ key: "preview", header: "\u9884\u89C8" },
|
|
4338
|
+
{ key: "hot", header: "\u70ED\u95E8" },
|
|
4339
|
+
{ key: "neu", header: "\u65B0\u54C1" }
|
|
4340
|
+
];
|
|
4341
|
+
const rows = list.map((t) => {
|
|
4342
|
+
const p = pickPreviewFields(t);
|
|
4343
|
+
return {
|
|
4344
|
+
id: p.id,
|
|
4345
|
+
name: p.name,
|
|
4346
|
+
industry: p.industry,
|
|
4347
|
+
preview: p.previewUrl || (p.coverUrl ? "(\u6709\u5C01\u9762)" : "-"),
|
|
4348
|
+
hot: p.hot,
|
|
4349
|
+
neu: p.neu
|
|
4350
|
+
};
|
|
4351
|
+
});
|
|
4352
|
+
console.log(`
|
|
4353
|
+
\u6A21\u677F\u5217\u8868\uFF08\u5171 ${list.length} \u4E2A\uFF09
|
|
4354
|
+
`);
|
|
4355
|
+
printCliTable(rows, columns);
|
|
4356
|
+
console.log("\n\u6A21\u677F\u76EE\u5F55\uFF1Asiluzan-website templates catalog");
|
|
4357
|
+
console.log("\u8BE6\u60C5\uFF1Asiluzan-website templates get --id <siteTemplateId>\n");
|
|
4358
|
+
}
|
|
4359
|
+
async function runTemplatesCatalog(opts) {
|
|
4360
|
+
const config = loadConfig();
|
|
4361
|
+
const url = `${config.apiBaseUrl}/website-provision/template-catalog`;
|
|
4362
|
+
let raw;
|
|
4363
|
+
let usedFallback = false;
|
|
4364
|
+
try {
|
|
4365
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4366
|
+
} catch (e) {
|
|
4367
|
+
const msg = e.message || "";
|
|
4368
|
+
if (/HTTP 404/.test(msg)) {
|
|
4369
|
+
console.error("\u2139\uFE0F \u4E3B\u7AD9\u5C1A\u672A\u90E8\u7F72 template-catalog\uFF0C\u6539\u7528 packages+templates \u672C\u5730\u62FC\u88C5\u76EE\u5F55\u2026");
|
|
4370
|
+
try {
|
|
4371
|
+
raw = await composeCatalogLocally(config, opts.verbose);
|
|
4372
|
+
usedFallback = true;
|
|
4373
|
+
} catch (e2) {
|
|
4374
|
+
console.error(`
|
|
4375
|
+
\u274C \u62FC\u88C5\u6A21\u677F\u76EE\u5F55\u5931\u8D25\uFF1A${e2.message}`);
|
|
4376
|
+
process.exit(1);
|
|
4377
|
+
return;
|
|
4378
|
+
}
|
|
4379
|
+
} else {
|
|
4380
|
+
console.error(`
|
|
4381
|
+
\u274C \u83B7\u53D6\u6A21\u677F\u76EE\u5F55\u5931\u8D25\uFF1A${msg}`);
|
|
4382
|
+
if (!opts.verbose) console.error(" \u52A0 --verbose \u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF");
|
|
4383
|
+
process.exit(1);
|
|
4384
|
+
return;
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
const root = asRecord3(raw);
|
|
4388
|
+
let groups = (Array.isArray(root?.groups) ? root.groups : []).map(asRecord3).filter((x) => Boolean(x)).map((g) => ({
|
|
4389
|
+
...g,
|
|
4390
|
+
templates: Array.isArray(g.templates) ? g.templates.map((t) => enrichTemplatePreview(asRecord3(t) ?? {})) : []
|
|
4391
|
+
}));
|
|
4392
|
+
if (opts.package?.trim()) {
|
|
4393
|
+
const pkg = opts.package.trim();
|
|
4394
|
+
groups = groups.filter((g) => readString3(g, "packageId") === pkg);
|
|
4395
|
+
}
|
|
4396
|
+
const slimGroups = slimCatalogGroups(groups);
|
|
4397
|
+
const totalTemplates = Number(root?.totalTemplates) || slimGroups.reduce(
|
|
4398
|
+
(n, g) => n + (Array.isArray(g.templates) ? g.templates.length : 0),
|
|
4399
|
+
0
|
|
4400
|
+
);
|
|
4401
|
+
const source = usedFallback ? "cli-fallback" : root?.source ?? "api";
|
|
4402
|
+
const payload = {
|
|
4403
|
+
totalGroups: slimGroups.length,
|
|
4404
|
+
totalTemplates,
|
|
4405
|
+
source,
|
|
4406
|
+
groups: slimGroups
|
|
4407
|
+
};
|
|
4408
|
+
if (opts.jsonOut?.trim()) {
|
|
4409
|
+
const outFile = resolveJsonOutFile(opts.jsonOut);
|
|
4410
|
+
fs6.writeFileSync(outFile, JSON.stringify(payload, null, 2), "utf8");
|
|
4411
|
+
console.log(
|
|
4412
|
+
JSON.stringify({
|
|
4413
|
+
ok: true,
|
|
4414
|
+
path: outFile,
|
|
4415
|
+
totalGroups: payload.totalGroups,
|
|
4416
|
+
totalTemplates: payload.totalTemplates,
|
|
4417
|
+
source: payload.source,
|
|
4418
|
+
next: "present_website_templates(groups_path=<path>)"
|
|
4419
|
+
})
|
|
4420
|
+
);
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
if (!opts.table) {
|
|
4424
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
for (const g of groups) {
|
|
4428
|
+
const pkgId = readString3(g, "packageId");
|
|
4429
|
+
const pkgName = readString3(g, "packageName") || pkgId;
|
|
4430
|
+
const templates = Array.isArray(g.templates) ? g.templates : [];
|
|
4431
|
+
console.log(`
|
|
4432
|
+
## ${pkgName} (${pkgId}) \u2014 ${templates.length} \u4E2A\u6A21\u677F
|
|
4433
|
+
`);
|
|
4434
|
+
const columns = [
|
|
4435
|
+
{ key: "id", header: "siteTemplateId" },
|
|
4436
|
+
{ key: "name", header: "\u540D\u79F0" },
|
|
4437
|
+
{ key: "industry", header: "\u884C\u4E1A" },
|
|
4438
|
+
{ key: "preview", header: "\u9884\u89C8URL" }
|
|
4439
|
+
];
|
|
4440
|
+
const rows = templates.map((item) => {
|
|
4441
|
+
const t = asRecord3(item) ?? {};
|
|
4442
|
+
const p = pickPreviewFields(t);
|
|
4443
|
+
return { id: p.id, name: p.name, industry: p.industry, preview: p.previewUrl || "-" };
|
|
4444
|
+
});
|
|
4445
|
+
printCliTable(rows, columns);
|
|
4446
|
+
}
|
|
4447
|
+
console.log();
|
|
4448
|
+
}
|
|
4449
|
+
async function runTemplatesGet(opts) {
|
|
4450
|
+
const id = opts.id?.trim();
|
|
4451
|
+
if (!id) {
|
|
4452
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id <siteTemplateId>\n");
|
|
4453
|
+
process.exit(1);
|
|
4454
|
+
}
|
|
4455
|
+
const config = loadConfig();
|
|
4456
|
+
const url = `${config.apiBaseUrl}/website-provision/templates/${encodeURIComponent(id)}`;
|
|
4457
|
+
let raw;
|
|
4458
|
+
try {
|
|
4459
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4460
|
+
} catch (e) {
|
|
4461
|
+
console.error(`
|
|
4462
|
+
\u274C \u83B7\u53D6\u6A21\u677F\u8BE6\u60C5\u5931\u8D25\uFF1A${e.message}`);
|
|
4463
|
+
process.exit(1);
|
|
4464
|
+
return;
|
|
4465
|
+
}
|
|
4466
|
+
const enriched = enrichTemplatePreview(asRecord3(raw) ?? {});
|
|
4467
|
+
if (opts.json) {
|
|
4468
|
+
console.log(JSON.stringify(enriched, null, 2));
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
const p = pickPreviewFields(enriched);
|
|
4472
|
+
console.log("\n\u6A21\u677F\u8BE6\u60C5\n");
|
|
4473
|
+
console.log(` siteTemplateId : ${p.id || id}`);
|
|
4474
|
+
console.log(` name : ${p.name}`);
|
|
4475
|
+
console.log(` description : ${readString3(enriched, "description") || readString3(enriched, "Description") || "-"}`);
|
|
4476
|
+
console.log(` industrys : ${p.industry}`);
|
|
4477
|
+
console.log(` version : ${p.version}`);
|
|
4478
|
+
console.log(` hasTheme : ${String(enriched.hasTheme ?? "-")}`);
|
|
4479
|
+
console.log(` coverUrl : ${p.coverUrl || "-"}`);
|
|
4480
|
+
console.log(` previewUrl : ${p.previewUrl || "-"}`);
|
|
4481
|
+
if (p.coverUrl) console.log(`
|
|
4482
|
+
`);
|
|
4483
|
+
console.log("\n\uFF08\u5B89\u88C5\u5305\u5730\u5740\u5DF2\u8131\u654F\uFF0C\u4E0D\u4F1A\u8F93\u51FA\uFF09\n");
|
|
4484
|
+
}
|
|
4485
|
+
function register7(program2) {
|
|
4486
|
+
const templates = program2.command("templates").description("\u5EFA\u7AD9\u6A21\u677F\uFF08website-provision\uFF09");
|
|
4487
|
+
templates.command("catalog").description("\u5957\u9910+\u6A21\u677F\u76EE\u5F55 JSON\uFF08\u4F9B DeerFlow present_website_templates\uFF1B\u5F00\u7AD9\u7B2C\u4E00\u6B65\uFF09").option("--package <packageId>", "\u53EA\u8FD4\u56DE\u67D0\u4E00\u5957\u9910").option("--json", "\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u5DF2\u662F JSON\uFF0C\u4FDD\u7559\u517C\u5BB9\uFF09", false).option("--json-out <path>", "\u843D\u76D8 template-catalog.json\uFF08\u76EE\u5F55\u6216 *.json\uFF09\uFF1Bstdout \u4EC5\u4E00\u884C\u6458\u8981").option("--table", "\u7EC8\u7AEF\u8868\u683C\u8F93\u51FA\uFF08\u8C03\u8BD5\u7528\uFF09", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4488
|
+
await runTemplatesCatalog({
|
|
4489
|
+
package: opts.package,
|
|
4490
|
+
json: true,
|
|
4491
|
+
table: opts.table,
|
|
4492
|
+
jsonOut: opts.jsonOut,
|
|
4493
|
+
verbose: opts.verbose
|
|
4494
|
+
});
|
|
4495
|
+
});
|
|
4496
|
+
templates.command("list").description("\u6309\u5957\u9910\u7B49\u6761\u4EF6\u5217\u51FA\u6A21\u677F").option("--package <packageId>", "\u5957\u9910 ID \u8FC7\u6EE4").option("--industry <industry>", "\u884C\u4E1A\u8FC7\u6EE4").option("--keyword <keyword>", "\u5173\u952E\u8BCD").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4497
|
+
await runTemplatesList(opts);
|
|
4498
|
+
});
|
|
4499
|
+
templates.command("get").description("\u6A21\u677F\u8BE6\u60C5\uFF08\u4E0D\u542B\u5B89\u88C5\u5305 URI\uFF09").option("--id <siteTemplateId>", "\u6A21\u677F ID").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4500
|
+
await runTemplatesGet(opts);
|
|
4501
|
+
});
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
// src/commands/trial.ts
|
|
4505
|
+
function asRecord4(value) {
|
|
4506
|
+
return value && typeof value === "object" ? value : null;
|
|
4507
|
+
}
|
|
4508
|
+
async function runTrialStatus(opts) {
|
|
4509
|
+
const config = loadConfig();
|
|
4510
|
+
const url = `${config.apiBaseUrl}/website-provision/trial-count`;
|
|
4511
|
+
let raw;
|
|
4512
|
+
try {
|
|
4513
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4514
|
+
} catch (e) {
|
|
4515
|
+
console.error(`
|
|
4516
|
+
\u274C \u83B7\u53D6\u8BD5\u7528\u6B21\u6570\u5931\u8D25\uFF1A${e.message}`);
|
|
4517
|
+
process.exit(1);
|
|
4518
|
+
return;
|
|
4519
|
+
}
|
|
4520
|
+
if (opts.json) {
|
|
4521
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
const obj = asRecord4(raw);
|
|
4525
|
+
const used = Number(obj?.used ?? obj?.Used ?? 0);
|
|
4526
|
+
const limit = Number(obj?.limit ?? obj?.Limit ?? 3);
|
|
4527
|
+
const remaining = Number(obj?.remaining ?? obj?.Remaining ?? Math.max(0, limit - used));
|
|
4528
|
+
console.log("\n\u8BD5\u7528\u5EFA\u7AD9\u989D\u5EA6\n");
|
|
4529
|
+
console.log(` \u5DF2\u7528 : ${used}`);
|
|
4530
|
+
console.log(` \u4E0A\u9650 : ${limit}`);
|
|
4531
|
+
console.log(` \u5269\u4F59 : ${remaining}`);
|
|
4532
|
+
console.log();
|
|
4533
|
+
}
|
|
4534
|
+
function register8(program2) {
|
|
4535
|
+
const trial = program2.command("trial").description("\u8BD5\u7528\u5EFA\u7AD9\u989D\u5EA6\uFF08website-provision\uFF09");
|
|
4536
|
+
trial.command("status").description("\u67E5\u770B\u5F53\u524D\u8D26\u53F7\u8BD5\u7528\u5DF2\u7528\u6B21\u6570\u4E0E\u4E0A\u9650").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4537
|
+
await runTrialStatus(opts);
|
|
4538
|
+
});
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4541
|
+
// src/commands/bills.ts
|
|
4542
|
+
function asRecord5(value) {
|
|
4543
|
+
return value && typeof value === "object" ? value : null;
|
|
4544
|
+
}
|
|
4545
|
+
function readString4(obj, key) {
|
|
4546
|
+
if (!obj) return "";
|
|
4547
|
+
const v = obj[key];
|
|
4548
|
+
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
4549
|
+
}
|
|
4550
|
+
async function runBillsCreate(opts) {
|
|
4551
|
+
const packageId = opts.package?.trim();
|
|
4552
|
+
if (!packageId) {
|
|
4553
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --package <packageId>\n");
|
|
4554
|
+
process.exit(1);
|
|
4555
|
+
}
|
|
4556
|
+
const config = loadConfig();
|
|
4557
|
+
const body = {
|
|
4558
|
+
packageId,
|
|
4559
|
+
payChannel: opts.channel || "Monthly",
|
|
4560
|
+
currency: opts.currency || "USD",
|
|
4561
|
+
successUrl: opts.successUrl || "",
|
|
4562
|
+
cancelUrl: opts.cancelUrl || ""
|
|
4563
|
+
};
|
|
4564
|
+
console.log("\n\u5373\u5C06\u521B\u5EFA\u5957\u9910\u8D26\u5355\uFF08\u4E0D\u4F1A\u81EA\u52A8\u6263\u6B3E\uFF0C\u7528\u6237\u9700\u6253\u5F00\u6536\u94F6\u53F0\u5B8C\u6210\u652F\u4ED8\uFF09\uFF1A");
|
|
4565
|
+
console.log(` packageId : ${body.packageId}`);
|
|
4566
|
+
console.log(` payChannel : ${body.payChannel}`);
|
|
4567
|
+
console.log(` currency : ${body.currency}`);
|
|
4568
|
+
const url = `${config.apiBaseUrl}/website-provision/bills`;
|
|
4569
|
+
let raw;
|
|
4570
|
+
try {
|
|
4571
|
+
raw = await apiFetch2(
|
|
4572
|
+
url,
|
|
4573
|
+
config,
|
|
4574
|
+
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
|
|
4575
|
+
opts.verbose
|
|
4576
|
+
);
|
|
4577
|
+
} catch (e) {
|
|
4578
|
+
console.error(`
|
|
4579
|
+
\u274C \u521B\u5EFA\u8D26\u5355\u5931\u8D25\uFF1A${e.message}`);
|
|
4580
|
+
process.exit(1);
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4583
|
+
if (opts.json) {
|
|
4584
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
4585
|
+
return;
|
|
4586
|
+
}
|
|
4587
|
+
const obj = asRecord5(raw);
|
|
4588
|
+
const billId = readString4(obj, "billId") || readString4(obj, "BillId");
|
|
4589
|
+
const checkoutUrl = readString4(obj, "checkoutUrl") || readString4(obj, "CheckoutUrl");
|
|
4590
|
+
console.log("\n\u2705 \u8D26\u5355\u5DF2\u521B\u5EFA\n");
|
|
4591
|
+
console.log(` billId : ${billId}`);
|
|
4592
|
+
console.log(` state : ${readString4(obj, "state") || readString4(obj, "State") || "-"}`);
|
|
4593
|
+
console.log(` checkoutUrl : ${checkoutUrl || "(\u65E0\uFF0C\u8BF7\u68C0\u67E5 Stripe \u914D\u7F6E)"}`);
|
|
4594
|
+
console.log("\n\u8BF7\u5C06\u6536\u94F6\u53F0\u94FE\u63A5\u53D1\u7ED9\u7528\u6237\u5B8C\u6210\u652F\u4ED8\uFF0C\u7136\u540E\uFF1A");
|
|
4595
|
+
console.log(` siluzan-website bills get --id ${billId}`);
|
|
4596
|
+
console.log(` \u652F\u4ED8\u6210\u529F\u540E\u521B\u5EFA\u7AD9\u70B9\u65F6\u5E26 --bill ${billId}
|
|
4597
|
+
`);
|
|
4598
|
+
}
|
|
4599
|
+
async function runBillsGet(opts) {
|
|
4600
|
+
const id = opts.id?.trim();
|
|
4601
|
+
if (!id) {
|
|
4602
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id <billId>\n");
|
|
4603
|
+
process.exit(1);
|
|
4604
|
+
}
|
|
4605
|
+
const config = loadConfig();
|
|
4606
|
+
const url = `${config.apiBaseUrl}/website-provision/bills/${encodeURIComponent(id)}`;
|
|
4607
|
+
let raw;
|
|
4608
|
+
try {
|
|
4609
|
+
raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
4610
|
+
} catch (e) {
|
|
4611
|
+
console.error(`
|
|
4612
|
+
\u274C \u67E5\u8BE2\u8D26\u5355\u5931\u8D25\uFF1A${e.message}`);
|
|
4613
|
+
process.exit(1);
|
|
4614
|
+
return;
|
|
4615
|
+
}
|
|
4616
|
+
if (opts.json) {
|
|
4617
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
4618
|
+
return;
|
|
4619
|
+
}
|
|
4620
|
+
const obj = asRecord5(raw);
|
|
4621
|
+
console.log("\n\u8D26\u5355\u72B6\u6001\n");
|
|
4622
|
+
console.log(` billId : ${readString4(obj, "billId") || id}`);
|
|
4623
|
+
console.log(` state : ${readString4(obj, "state") || readString4(obj, "State")}`);
|
|
4624
|
+
console.log(` paid : ${String(obj?.paid ?? obj?.Paid ?? "-")}`);
|
|
4625
|
+
console.log(` packageId : ${readString4(obj, "packageId") || readString4(obj, "PackageId") || "-"}`);
|
|
4626
|
+
console.log(` siteId : ${readString4(obj, "siteId") || readString4(obj, "SiteId") || "(\u672A\u7ED1\u5B9A)"}`);
|
|
4627
|
+
console.log();
|
|
4628
|
+
}
|
|
4629
|
+
function register9(program2) {
|
|
4630
|
+
const bills = program2.command("bills").description("\u5EFA\u7AD9\u5957\u9910\u8D26\u5355 / \u652F\u4ED8\uFF08website-provision\uFF09");
|
|
4631
|
+
bills.command("create").description("\u521B\u5EFA\u5957\u9910\u8D26\u5355\u5E76\u8FD4\u56DE\u6536\u94F6\u53F0 URL\uFF08\u5199\u64CD\u4F5C\uFF0CAgent \u987B\u5148\u83B7\u7528\u6237\u786E\u8BA4\uFF09").option("--package <packageId>", "\u5957\u9910 ID").option("--channel <Monthly|Yearly>", "\u4ED8\u8D39\u5468\u671F", "Monthly").option("--currency <code>", "\u5E01\u79CD", "USD").option("--success-url <url>", "\u652F\u4ED8\u6210\u529F\u56DE\u8DF3 URL").option("--cancel-url <url>", "\u652F\u4ED8\u53D6\u6D88\u56DE\u8DF3 URL").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4632
|
+
await runBillsCreate(opts);
|
|
4633
|
+
});
|
|
4634
|
+
bills.command("get").description("\u67E5\u8BE2\u8D26\u5355\u652F\u4ED8\u4E0E\u7ED1\u5B9A\u72B6\u6001").option("--id <billId>", "\u8D26\u5355\u53F7").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4635
|
+
await runBillsGet(opts);
|
|
4636
|
+
});
|
|
4637
|
+
}
|
|
4638
|
+
|
|
4639
|
+
// src/commands/pages.ts
|
|
4640
|
+
import * as fs7 from "fs";
|
|
4641
|
+
|
|
4642
|
+
// src/utils/wp-site.ts
|
|
4643
|
+
async function resolveTarget(opts) {
|
|
4644
|
+
const config = loadConfig();
|
|
4645
|
+
const site = await resolveSite(config, opts);
|
|
4646
|
+
return { config, site, base: trimTrailingSlash(site.url) };
|
|
4647
|
+
}
|
|
4648
|
+
function wpV2(base, path7) {
|
|
4649
|
+
const suffix = path7.startsWith("/") ? path7 : `/${path7}`;
|
|
4650
|
+
return `${base}/wp-json/wp/v2${suffix}`;
|
|
4651
|
+
}
|
|
4652
|
+
async function resolveTypeRestBase(target, typeArg, verbose = false) {
|
|
4653
|
+
const needle = typeArg.trim().toLowerCase();
|
|
4654
|
+
if (!needle) {
|
|
4655
|
+
throw new Error("\u8BF7\u63D0\u4F9B --type\uFF08\u5148 content types \u770B rest_base\uFF09");
|
|
4656
|
+
}
|
|
4657
|
+
const types = await apiFetch2(
|
|
4658
|
+
wpV2(target.base, "/types?context=edit"),
|
|
4659
|
+
target.config,
|
|
4660
|
+
{},
|
|
4661
|
+
verbose
|
|
4662
|
+
);
|
|
4663
|
+
for (const [slug, info] of Object.entries(types || {})) {
|
|
4664
|
+
const restBase = (info.rest_base || slug).toLowerCase();
|
|
4665
|
+
if (slug.toLowerCase() === needle || restBase === needle) {
|
|
4666
|
+
return info.rest_base || slug;
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
return typeArg.trim();
|
|
4670
|
+
}
|
|
4671
|
+
async function resolveTaxonomyRestBase(target, taxonomyArg, verbose = false) {
|
|
4672
|
+
const needle = taxonomyArg.trim().toLowerCase();
|
|
4673
|
+
if (!needle) {
|
|
4674
|
+
throw new Error("\u8BF7\u63D0\u4F9B --taxonomy\uFF08\u5982 category\u3001post_tag\uFF09");
|
|
4675
|
+
}
|
|
4676
|
+
const taxes = await apiFetch2(
|
|
4677
|
+
wpV2(target.base, "/taxonomies?context=edit"),
|
|
4678
|
+
target.config,
|
|
4679
|
+
{},
|
|
4680
|
+
verbose
|
|
4681
|
+
);
|
|
4682
|
+
for (const [slug, info] of Object.entries(taxes || {})) {
|
|
4683
|
+
const restBase = (info.rest_base || slug).toLowerCase();
|
|
4684
|
+
if (slug.toLowerCase() === needle || restBase === needle) {
|
|
4685
|
+
return info.rest_base || slug;
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
return taxonomyArg.trim();
|
|
4689
|
+
}
|
|
4690
|
+
|
|
4691
|
+
// src/commands/pages.ts
|
|
4692
|
+
function pageTitle(page) {
|
|
4693
|
+
if (typeof page.title === "string") return page.title;
|
|
4694
|
+
return page.title?.rendered ?? "";
|
|
4695
|
+
}
|
|
4696
|
+
function readTextOption(inline, filePath) {
|
|
4697
|
+
if (filePath) {
|
|
4698
|
+
try {
|
|
4699
|
+
return fs7.readFileSync(filePath, "utf8");
|
|
4700
|
+
} catch (e) {
|
|
4701
|
+
console.error(`
|
|
4702
|
+
\u274C \u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 ${filePath}\uFF1A${e.message}
|
|
4703
|
+
`);
|
|
4704
|
+
process.exit(1);
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
return inline ?? "";
|
|
4708
|
+
}
|
|
4709
|
+
async function runPagesList(opts) {
|
|
4710
|
+
const config = loadConfig();
|
|
4711
|
+
const site = await resolveSite(config, opts);
|
|
4712
|
+
const base = trimTrailingSlash(site.url);
|
|
4713
|
+
const api = `${base}/wp-json/wp/v2/pages?per_page=100&status=publish,draft,private,pending`;
|
|
4714
|
+
let pages;
|
|
4715
|
+
try {
|
|
4716
|
+
pages = await apiFetch2(api, config, {}, opts.verbose);
|
|
4717
|
+
} catch (e) {
|
|
4718
|
+
console.error(`
|
|
4719
|
+
\u274C \u83B7\u53D6\u9875\u9762\u5931\u8D25\uFF1A${e.message}`);
|
|
4720
|
+
console.error(` \u7AD9\u70B9\uFF1A${base}`);
|
|
4721
|
+
process.exit(1);
|
|
4722
|
+
return;
|
|
4723
|
+
}
|
|
4724
|
+
if (!Array.isArray(pages)) {
|
|
4725
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u9875\u9762\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
4726
|
+
process.exit(1);
|
|
4727
|
+
}
|
|
4728
|
+
if (opts.json) {
|
|
4729
|
+
console.log(
|
|
4730
|
+
JSON.stringify(
|
|
4731
|
+
{
|
|
4732
|
+
site: { guid: site.guid, name: site.name, url: site.url },
|
|
4733
|
+
total: pages.length,
|
|
4734
|
+
pages: pages.map((p) => ({
|
|
4735
|
+
id: p.id,
|
|
4736
|
+
title: pageTitle(p),
|
|
4737
|
+
slug: p.slug ?? "",
|
|
4738
|
+
status: p.status ?? "",
|
|
4739
|
+
link: p.link ?? "",
|
|
4740
|
+
modified: p.modified ?? ""
|
|
4741
|
+
}))
|
|
4742
|
+
},
|
|
4743
|
+
null,
|
|
4744
|
+
2
|
|
4745
|
+
)
|
|
4746
|
+
);
|
|
4747
|
+
return;
|
|
4748
|
+
}
|
|
4749
|
+
if (pages.length === 0) {
|
|
4750
|
+
console.log(`
|
|
4751
|
+
\u7AD9\u70B9 ${site.name} \u6682\u65E0\u9875\u9762\u3002\u53EF\u7528 pages add \u65B0\u589E\u3002
|
|
4752
|
+
`);
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4755
|
+
const columns = [
|
|
4756
|
+
{ key: "id", header: "id" },
|
|
4757
|
+
{ key: "title", header: "\u6807\u9898" },
|
|
4758
|
+
{ key: "status", header: "\u72B6\u6001" },
|
|
4759
|
+
{ key: "slug", header: "slug" },
|
|
4760
|
+
{ key: "link", header: "\u94FE\u63A5" }
|
|
4761
|
+
];
|
|
4762
|
+
console.log(`
|
|
4763
|
+
${site.name} \u9875\u9762\uFF08${pages.length}\uFF09
|
|
4764
|
+
`);
|
|
4765
|
+
printCliTable(
|
|
4766
|
+
pages.map((p) => ({
|
|
4767
|
+
id: String(p.id),
|
|
4768
|
+
title: pageTitle(p) || "(\u65E0\u6807\u9898)",
|
|
4769
|
+
status: p.status ?? "-",
|
|
4770
|
+
slug: p.slug ?? "-",
|
|
4771
|
+
link: p.link ?? "-"
|
|
4772
|
+
})),
|
|
4773
|
+
columns
|
|
4774
|
+
);
|
|
4775
|
+
console.log();
|
|
4776
|
+
}
|
|
4777
|
+
async function runPagesWrite(mode, opts) {
|
|
4778
|
+
const config = loadConfig();
|
|
4779
|
+
const site = await resolveSite(config, opts);
|
|
4780
|
+
const base = trimTrailingSlash(site.url);
|
|
4781
|
+
const title = opts.title?.trim() ?? "";
|
|
4782
|
+
const content = readTextOption(opts.content, opts.contentFile);
|
|
4783
|
+
if (mode === "add" && !title) {
|
|
4784
|
+
console.error("\n\u274C \u65B0\u589E\u9875\u9762\u5FC5\u987B\u63D0\u4F9B --title\n");
|
|
4785
|
+
process.exit(1);
|
|
4786
|
+
}
|
|
4787
|
+
if (!content.trim()) {
|
|
4788
|
+
console.error("\n\u274C \u8BF7\u7528 --content \u6216 --content-file \u63D0\u4F9B HTML \u6B63\u6587\n");
|
|
4789
|
+
process.exit(1);
|
|
4790
|
+
}
|
|
4791
|
+
const body = {
|
|
4792
|
+
content,
|
|
4793
|
+
import_mode: "preserve"
|
|
4794
|
+
};
|
|
4795
|
+
if (title) body.title = title;
|
|
4796
|
+
const css = readTextOption(opts.css, opts.cssFile);
|
|
4797
|
+
if (css) body._custom_css = css;
|
|
4798
|
+
const js = readTextOption(opts.js, opts.jsFile);
|
|
4799
|
+
if (js) body._custom_javascript = js;
|
|
4800
|
+
if (mode === "add") body.post_type = opts.postType?.trim() || "page";
|
|
4801
|
+
const api = mode === "add" ? `${base}/wp-json/zionbuilder/v1/pages/add-visual-edit` : `${base}/wp-json/zionbuilder/v1/pages/${opts.id}/save-visual-edit`;
|
|
4802
|
+
if (mode === "update" && !opts.id) {
|
|
4803
|
+
console.error("\n\u274C \u66F4\u65B0\u9875\u9762\u5FC5\u987B\u63D0\u4F9B --id\uFF08\u5148 pages list \u67E5 id\uFF09\n");
|
|
4804
|
+
process.exit(1);
|
|
4805
|
+
}
|
|
4806
|
+
let result;
|
|
4807
|
+
try {
|
|
4808
|
+
result = await apiFetch2(
|
|
4809
|
+
api,
|
|
4810
|
+
config,
|
|
4811
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
4812
|
+
opts.verbose
|
|
4813
|
+
);
|
|
4814
|
+
} catch (e) {
|
|
4815
|
+
console.error(`
|
|
4816
|
+
\u274C ${mode === "add" ? "\u65B0\u589E" : "\u66F4\u65B0"}\u9875\u9762\u5931\u8D25\uFF1A${e.message}
|
|
4817
|
+
`);
|
|
4818
|
+
process.exit(1);
|
|
4819
|
+
return;
|
|
4820
|
+
}
|
|
4821
|
+
if (result.error || result.success === false) {
|
|
4822
|
+
console.error(`
|
|
4823
|
+
\u274C ${result.error || result.message || "\u7AD9\u70B9\u62D2\u7EDD\u4FDD\u5B58"}
|
|
4824
|
+
`);
|
|
4825
|
+
process.exit(1);
|
|
4826
|
+
}
|
|
4827
|
+
console.log(mode === "add" ? "\n\u2705 \u9875\u9762\u5DF2\u521B\u5EFA" : "\n\u2705 \u9875\u9762\u5DF2\u66F4\u65B0");
|
|
4828
|
+
if (result.post_id) console.log(` post_id : ${result.post_id}`);
|
|
4829
|
+
if (result.url) console.log(` url : ${result.url}`);
|
|
4830
|
+
console.log(` \u7AD9\u70B9 : ${base}
|
|
4831
|
+
`);
|
|
4832
|
+
}
|
|
4833
|
+
async function runPagesGet(opts) {
|
|
4834
|
+
const id = Number(opts.id);
|
|
4835
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
4836
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
4837
|
+
process.exit(1);
|
|
4838
|
+
}
|
|
4839
|
+
const target = await resolveTarget(opts);
|
|
4840
|
+
const page = await apiFetch2(
|
|
4841
|
+
wpV2(target.base, `/pages/${id}?context=edit`),
|
|
4842
|
+
target.config,
|
|
4843
|
+
{},
|
|
4844
|
+
opts.verbose
|
|
4845
|
+
).catch((e) => {
|
|
4846
|
+
console.error(`
|
|
4847
|
+
\u274C \u83B7\u53D6\u9875\u9762\u5931\u8D25\uFF1A${e.message}
|
|
4848
|
+
`);
|
|
4849
|
+
process.exit(1);
|
|
4850
|
+
});
|
|
4851
|
+
if (opts.json) {
|
|
4852
|
+
console.log(JSON.stringify(page, null, 2));
|
|
4853
|
+
return;
|
|
4854
|
+
}
|
|
4855
|
+
console.log(`
|
|
4856
|
+
\u9875\u9762 #${page.id}`);
|
|
4857
|
+
console.log(` \u6807\u9898 : ${pageTitle(page) || "-"}`);
|
|
4858
|
+
console.log(` \u72B6\u6001 : ${page.status || "-"}`);
|
|
4859
|
+
console.log(` slug : ${page.slug || "-"}`);
|
|
4860
|
+
console.log(` \u94FE\u63A5 : ${page.link || "-"}`);
|
|
4861
|
+
if (page.parent) console.log(` \u7236\u9875 : ${page.parent}`);
|
|
4862
|
+
if (page.featured_media) console.log(` \u7279\u8272\u56FE : ${page.featured_media}`);
|
|
4863
|
+
console.log();
|
|
4864
|
+
}
|
|
4865
|
+
async function runPagesMeta(opts) {
|
|
4866
|
+
const id = Number(opts.id);
|
|
4867
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
4868
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
4869
|
+
process.exit(1);
|
|
4870
|
+
}
|
|
4871
|
+
const body = {};
|
|
4872
|
+
if (opts.title?.trim()) body.title = opts.title.trim();
|
|
4873
|
+
if (opts.slug?.trim()) body.slug = opts.slug.trim();
|
|
4874
|
+
if (opts.status?.trim()) body.status = opts.status.trim();
|
|
4875
|
+
const parent = Number(opts.parent);
|
|
4876
|
+
if (opts.parent !== void 0 && Number.isFinite(parent)) body.parent = parent;
|
|
4877
|
+
const featured = Number(opts.featuredMedia);
|
|
4878
|
+
if (Number.isFinite(featured) && featured > 0) body.featured_media = featured;
|
|
4879
|
+
if (Object.keys(body).length === 0) {
|
|
4880
|
+
console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\u3002\u6B63\u6587\u8BF7\u7528 pages update\u3002\n");
|
|
4881
|
+
process.exit(1);
|
|
4882
|
+
}
|
|
4883
|
+
const target = await resolveTarget(opts);
|
|
4884
|
+
const page = await apiFetch2(
|
|
4885
|
+
wpV2(target.base, `/pages/${id}`),
|
|
4886
|
+
target.config,
|
|
4887
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
4888
|
+
opts.verbose
|
|
4889
|
+
).catch((e) => {
|
|
4890
|
+
console.error(`
|
|
4891
|
+
\u274C \u66F4\u65B0\u9875\u9762\u5143\u6570\u636E\u5931\u8D25\uFF1A${e.message}
|
|
4892
|
+
`);
|
|
4893
|
+
process.exit(1);
|
|
4894
|
+
});
|
|
4895
|
+
console.log(`
|
|
4896
|
+
\u2705 \u9875\u9762 #${page.id} \u5143\u6570\u636E\u5DF2\u66F4\u65B0`);
|
|
4897
|
+
console.log(` \u6807\u9898 : ${pageTitle(page) || "-"}`);
|
|
4898
|
+
console.log(` \u72B6\u6001 : ${page.status || "-"}`);
|
|
4899
|
+
console.log(` slug : ${page.slug || "-"}`);
|
|
4900
|
+
if (page.link) console.log(` \u94FE\u63A5 : ${page.link}`);
|
|
4901
|
+
console.log();
|
|
4902
|
+
}
|
|
4903
|
+
async function runPagesTrash(opts) {
|
|
4904
|
+
const id = Number(opts.id);
|
|
4905
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
4906
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
4907
|
+
process.exit(1);
|
|
4908
|
+
}
|
|
4909
|
+
const target = await resolveTarget(opts);
|
|
4910
|
+
const qs = opts.force ? "?force=true" : "";
|
|
4911
|
+
const page = await apiFetch2(
|
|
4912
|
+
wpV2(target.base, `/pages/${id}${qs}`),
|
|
4913
|
+
target.config,
|
|
4914
|
+
{ method: "DELETE" },
|
|
4915
|
+
opts.verbose
|
|
4916
|
+
).catch((e) => {
|
|
4917
|
+
console.error(`
|
|
4918
|
+
\u274C \u5220\u9664\u9875\u9762\u5931\u8D25\uFF1A${e.message}
|
|
4919
|
+
`);
|
|
4920
|
+
process.exit(1);
|
|
4921
|
+
});
|
|
4922
|
+
console.log(
|
|
4923
|
+
opts.force ? `
|
|
4924
|
+
\u2705 \u5DF2\u6C38\u4E45\u5220\u9664\u9875\u9762 #${id}
|
|
4925
|
+
` : `
|
|
4926
|
+
\u2705 \u9875\u9762 #${id} \u5DF2\u8FDB\u56DE\u6536\u7AD9\uFF08status=${page.status || "trash"}\uFF09
|
|
4927
|
+
`
|
|
4928
|
+
);
|
|
4929
|
+
}
|
|
4930
|
+
function register10(program2) {
|
|
4931
|
+
const pages = program2.command("pages").description("WordPress \u9875\u9762\uFF08zionbuilder visual-edit\uFF09");
|
|
4932
|
+
pages.command("list").description("\u5217\u51FA\u7AD9\u70B9\u9875\u9762").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740\uFF08\u8DF3\u8FC7 all-sites\uFF09").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4933
|
+
await runPagesList(opts);
|
|
4934
|
+
});
|
|
4935
|
+
pages.command("add").description("\u7528 HTML \u65B0\u589E\u9875\u9762\uFF08\u8D70 add-visual-edit\uFF0C\u4F1A\u76F4\u63A5\u53D1\u5E03\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("-t, --title <title>", "\u9875\u9762\u6807\u9898").option("-c, --content <html>", "HTML \u6B63\u6587").option("--content-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 HTML \u6B63\u6587").option("--css <css>", "\u9644\u52A0 CSS").option("--css-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 CSS").option("--js <js>", "\u9644\u52A0 JS").option("--js-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 JS").option("--post-type <type>", "\u6587\u7AE0\u7C7B\u578B\uFF0C\u9ED8\u8BA4 page", "page").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4936
|
+
await runPagesWrite("add", opts);
|
|
4937
|
+
});
|
|
4938
|
+
pages.command("update").description("\u7528 HTML \u8986\u76D6\u5DF2\u6709\u9875\u9762\uFF08\u8D70 save-visual-edit\uFF0C\u4F1A\u76F4\u63A5\u53D1\u5E03\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--id <id>", "\u9875\u9762 ID").option("-t, --title <title>", "\u65B0\u6807\u9898\uFF08\u53EF\u7701\u7565\uFF09").option("-c, --content <html>", "HTML \u6B63\u6587").option("--content-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 HTML \u6B63\u6587").option("--css <css>", "\u9644\u52A0 CSS").option("--css-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 CSS").option("--js <js>", "\u9644\u52A0 JS").option("--js-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 JS").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4939
|
+
await runPagesWrite("update", opts);
|
|
4940
|
+
});
|
|
4941
|
+
pages.command("get").description("\u67E5\u770B\u5355\u4E2A\u9875\u9762\u7684\u5143\u6570\u636E").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--id <id>", "\u9875\u9762 ID").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4942
|
+
await runPagesGet(opts);
|
|
4943
|
+
});
|
|
4944
|
+
pages.command("meta").description("\u6539\u9875\u9762 slug / \u72B6\u6001 / \u7236\u9875 / \u7279\u8272\u56FE\uFF08\u4E0D\u6539 Zion \u6B63\u6587\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--id <id>", "\u9875\u9762 ID").option("-t, --title <title>", "\u6807\u9898").option("--slug <slug>", "\u522B\u540D").option("--status <status>", "publish / draft / private / pending").option("--parent <id>", "\u7236\u9875\u9762 ID\uFF0C0 \u8868\u793A\u53D6\u6D88").option("--featured-media <id>", "\u7279\u8272\u56FE\u5A92\u4F53 ID").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4945
|
+
await runPagesMeta(opts);
|
|
4946
|
+
});
|
|
4947
|
+
pages.command("trash").description("\u9875\u9762\u8FDB\u56DE\u6536\u7AD9\uFF1B\u52A0 --force \u6C38\u4E45\u5220\u9664").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--id <id>", "\u9875\u9762 ID").option("--force", "\u6C38\u4E45\u5220\u9664", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
4948
|
+
await runPagesTrash(opts);
|
|
4949
|
+
});
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4952
|
+
// src/commands/plugins.ts
|
|
4953
|
+
import { readFileSync as readFileSync7, existsSync as existsSync3 } from "fs";
|
|
4954
|
+
import { basename as basename2, resolve as resolve2 } from "path";
|
|
4955
|
+
|
|
4956
|
+
// src/utils/wp-plugin-catalog.ts
|
|
4957
|
+
import * as http2 from "http";
|
|
4958
|
+
import * as https2 from "https";
|
|
4959
|
+
function trimSlash(url) {
|
|
4960
|
+
return url.replace(/\/+$/, "");
|
|
4961
|
+
}
|
|
4962
|
+
function pluginApiBases(config) {
|
|
4963
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4964
|
+
const out = [];
|
|
4965
|
+
for (const raw of [config.csoPluginApiBaseUrl, config.csoBaseUrl]) {
|
|
4966
|
+
const base = trimSlash(raw || "");
|
|
4967
|
+
if (!base || seen.has(base)) continue;
|
|
4968
|
+
seen.add(base);
|
|
4969
|
+
out.push(base);
|
|
4970
|
+
}
|
|
4971
|
+
return out;
|
|
4972
|
+
}
|
|
4973
|
+
function isNetworkish(err) {
|
|
4974
|
+
const msg = err.message || "";
|
|
4975
|
+
return /fetch failed|ENOTFOUND|ECONNREFUSED|ETIMEDOUT|ECONNRESET|EPROTO|TLS|socket disconnected|certificate|HTTP 5\d\d/i.test(
|
|
4976
|
+
msg
|
|
4977
|
+
);
|
|
4978
|
+
}
|
|
4979
|
+
function compareVersion(a, b) {
|
|
4980
|
+
const pa = a.split(".").map((p) => Number(p) || 0);
|
|
4981
|
+
const pb = b.split(".").map((p) => Number(p) || 0);
|
|
4982
|
+
const n = Math.max(pa.length, pb.length);
|
|
4983
|
+
for (let i = 0; i < n; i++) {
|
|
4984
|
+
const da = pa[i] ?? 0;
|
|
4985
|
+
const db = pb[i] ?? 0;
|
|
4986
|
+
if (da !== db) return da - db;
|
|
4987
|
+
}
|
|
4988
|
+
return 0;
|
|
4989
|
+
}
|
|
4990
|
+
function versionFromPath(path7, filename) {
|
|
4991
|
+
const parts = path7.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
4992
|
+
if (parts.length >= 2) return parts[1];
|
|
4993
|
+
const m = filename.match(/\.((?:\d+\.)*\d+)\.zip$/i);
|
|
4994
|
+
return m?.[1] ?? "";
|
|
4995
|
+
}
|
|
4996
|
+
function collectZips(nodes, out = []) {
|
|
4997
|
+
for (const node of nodes || []) {
|
|
4998
|
+
if (!node.isDirectory && /\.zip$/i.test(node.name || "") && node.url) {
|
|
4999
|
+
out.push(node);
|
|
5000
|
+
}
|
|
5001
|
+
if (node.children?.length) collectZips(node.children, out);
|
|
5002
|
+
}
|
|
5003
|
+
return out;
|
|
5004
|
+
}
|
|
5005
|
+
function flattenOfficialPlugins(items) {
|
|
5006
|
+
const best = /* @__PURE__ */ new Map();
|
|
5007
|
+
for (const zip of collectZips(items)) {
|
|
5008
|
+
const path7 = (zip.path || "").replace(/\\/g, "/");
|
|
5009
|
+
const filename = zip.name || path7.split("/").pop() || "";
|
|
5010
|
+
const slug = path7.split("/").filter(Boolean)[0] || filename.replace(/\.zip$/i, "");
|
|
5011
|
+
if (!slug) continue;
|
|
5012
|
+
const candidate = {
|
|
5013
|
+
slug,
|
|
5014
|
+
version: versionFromPath(path7, filename),
|
|
5015
|
+
filename,
|
|
5016
|
+
path: path7,
|
|
5017
|
+
size: Number(zip.size) || 0,
|
|
5018
|
+
url: zip.url || "",
|
|
5019
|
+
lastModified: zip.lastModified || ""
|
|
5020
|
+
};
|
|
5021
|
+
const prev = best.get(slug);
|
|
5022
|
+
if (!prev || compareVersion(candidate.version, prev.version) > 0) {
|
|
5023
|
+
best.set(slug, candidate);
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
return [...best.values()].sort((a, b) => a.slug.localeCompare(b.slug));
|
|
5027
|
+
}
|
|
5028
|
+
async function fetchOfficialPluginList(config, opts = {}) {
|
|
5029
|
+
const params = new URLSearchParams();
|
|
5030
|
+
if (opts.prefix?.trim()) params.set("prefix", opts.prefix.trim());
|
|
5031
|
+
const qs = params.toString();
|
|
5032
|
+
const path7 = `/cso/v1/wp-plugin/list${qs ? `?${qs}` : ""}`;
|
|
5033
|
+
const bases = pluginApiBases(config);
|
|
5034
|
+
let lastErr;
|
|
5035
|
+
for (let i = 0; i < bases.length; i++) {
|
|
5036
|
+
const url = `${bases[i]}${path7}`;
|
|
5037
|
+
try {
|
|
5038
|
+
const raw = await apiFetch2(url, config, {}, opts.verbose);
|
|
5039
|
+
const code = raw.code;
|
|
5040
|
+
if (code !== void 0 && code !== 1) {
|
|
5041
|
+
throw new Error(raw.message || `\u76EE\u5F55\u63A5\u53E3\u8FD4\u56DE code=${code}`);
|
|
5042
|
+
}
|
|
5043
|
+
const data = raw.data || {};
|
|
5044
|
+
return {
|
|
5045
|
+
container: data.container || "wp-plugins",
|
|
5046
|
+
items: flattenOfficialPlugins(data.items)
|
|
5047
|
+
};
|
|
5048
|
+
} catch (e) {
|
|
5049
|
+
lastErr = e;
|
|
5050
|
+
if (i < bases.length - 1 && isNetworkish(lastErr)) {
|
|
5051
|
+
console.log(`\u76EE\u5F55\u63A5\u53E3 ${bases[i]} \u4E0D\u53EF\u8FBE\uFF0C\u6539\u8D70 ${bases[i + 1]} \u2026`);
|
|
5052
|
+
continue;
|
|
5053
|
+
}
|
|
5054
|
+
throw lastErr;
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
throw lastErr || new Error("\u76EE\u5F55\u63A5\u53E3\u4E0D\u53EF\u7528");
|
|
5058
|
+
}
|
|
5059
|
+
async function findOfficialPlugin(config, slugOrPlugin, verbose = false) {
|
|
5060
|
+
const needle = slugOrPlugin.replace(/\\/g, "/").replace(/\.php$/i, "").toLowerCase();
|
|
5061
|
+
if (!needle) return null;
|
|
5062
|
+
const { items } = await fetchOfficialPluginList(config, { verbose });
|
|
5063
|
+
return items.find((p) => p.slug.toLowerCase() === needle) || items.find((p) => needle === p.slug.toLowerCase() || needle.startsWith(`${p.slug.toLowerCase()}/`)) || null;
|
|
5064
|
+
}
|
|
5065
|
+
function downloadOfficialZip(url) {
|
|
5066
|
+
return new Promise((resolve4, reject) => {
|
|
5067
|
+
let parsed;
|
|
5068
|
+
try {
|
|
5069
|
+
parsed = new URL(url);
|
|
5070
|
+
} catch {
|
|
5071
|
+
reject(new Error("\u76EE\u5F55\u5305\u5730\u5740\u4E0D\u5408\u6CD5"));
|
|
5072
|
+
return;
|
|
5073
|
+
}
|
|
5074
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
5075
|
+
reject(new Error("\u76EE\u5F55\u5305\u5730\u5740\u5FC5\u987B\u662F http(s)"));
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
const transport = parsed.protocol === "https:" ? https2 : http2;
|
|
5079
|
+
const req = transport.get(url, { timeout: 12e4 }, (res) => {
|
|
5080
|
+
const status = res.statusCode ?? 0;
|
|
5081
|
+
if (status >= 300 && status < 400 && res.headers.location) {
|
|
5082
|
+
res.resume();
|
|
5083
|
+
downloadOfficialZip(res.headers.location).then(resolve4, reject);
|
|
5084
|
+
return;
|
|
5085
|
+
}
|
|
5086
|
+
if (status < 200 || status >= 300) {
|
|
5087
|
+
res.resume();
|
|
5088
|
+
reject(new Error(`\u4E0B\u8F7D\u76EE\u5F55\u5305\u5931\u8D25\uFF1AHTTP ${status}`));
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
const chunks = [];
|
|
5092
|
+
let size = 0;
|
|
5093
|
+
res.on("data", (chunk) => {
|
|
5094
|
+
size += chunk.length;
|
|
5095
|
+
if (size > 40 * 1024 * 1024) {
|
|
5096
|
+
res.destroy();
|
|
5097
|
+
reject(new Error("\u76EE\u5F55\u5305\u8D85\u8FC7 40MB"));
|
|
5098
|
+
return;
|
|
5099
|
+
}
|
|
5100
|
+
chunks.push(chunk);
|
|
5101
|
+
});
|
|
5102
|
+
res.on("end", () => resolve4(Buffer.concat(chunks)));
|
|
5103
|
+
res.on("error", reject);
|
|
5104
|
+
});
|
|
5105
|
+
req.on("timeout", () => {
|
|
5106
|
+
req.destroy();
|
|
5107
|
+
reject(new Error("\u4E0B\u8F7D\u76EE\u5F55\u5305\u8D85\u65F6"));
|
|
5108
|
+
});
|
|
5109
|
+
req.on("error", reject);
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5113
|
+
// src/commands/zasp.ts
|
|
5114
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
5115
|
+
var SECRET_KEY = /api_key|password|token|secret|private_key/i;
|
|
5116
|
+
function zaspUrl(base, path7) {
|
|
5117
|
+
const suffix = path7.startsWith("/") ? path7 : `/${path7}`;
|
|
5118
|
+
return `${base}/wp-json/zasp-b2b/v2${suffix}`;
|
|
5119
|
+
}
|
|
5120
|
+
function explainZaspError(err) {
|
|
5121
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5122
|
+
if (/404|rest_no_route|not found/i.test(msg)) {
|
|
5123
|
+
return `${msg}
|
|
5124
|
+
\u7AD9\u70B9\u53EF\u80FD\u6CA1\u88C5 zasp-smart-recommender\uFF0C\u6216\u7248\u672C\u592A\u65E7\u3001\u6CA1\u6709\u7BA1\u7406 REST\u3002
|
|
5125
|
+
\u5148 \`plugins list\`\uFF0C\u518D \`plugins catalog\` / \`install --slug zasp-smart-recommender\`\uFF0C
|
|
5126
|
+
\u6216 \`update --plugin zasp-smart-recommender/zasp-smart-recommender\``;
|
|
5127
|
+
}
|
|
5128
|
+
return msg;
|
|
5129
|
+
}
|
|
5130
|
+
function redactSecrets(value) {
|
|
5131
|
+
if (Array.isArray(value)) return value.map(redactSecrets);
|
|
5132
|
+
if (value && typeof value === "object") {
|
|
5133
|
+
const out = {};
|
|
5134
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
5135
|
+
if (SECRET_KEY.test(key) && typeof nested === "string" && nested) {
|
|
5136
|
+
out[key] = "***";
|
|
5137
|
+
} else {
|
|
5138
|
+
out[key] = redactSecrets(nested);
|
|
5139
|
+
}
|
|
5140
|
+
}
|
|
5141
|
+
return out;
|
|
5142
|
+
}
|
|
5143
|
+
return value;
|
|
5144
|
+
}
|
|
5145
|
+
function printJson(data) {
|
|
5146
|
+
console.log(JSON.stringify(redactSecrets(data), null, 2));
|
|
5147
|
+
}
|
|
5148
|
+
function collectPair(value, acc) {
|
|
5149
|
+
acc.push(value);
|
|
5150
|
+
return acc;
|
|
5151
|
+
}
|
|
5152
|
+
function coerceSetValue(raw) {
|
|
5153
|
+
if (raw === "true") return true;
|
|
5154
|
+
if (raw === "false") return false;
|
|
5155
|
+
if (raw === "null") return null;
|
|
5156
|
+
if (/^-?\d+$/.test(raw)) return Number(raw);
|
|
5157
|
+
if (/^-?\d+\.\d+$/.test(raw)) return Number(raw);
|
|
5158
|
+
return raw;
|
|
5159
|
+
}
|
|
5160
|
+
function parseSetPairs(pairs) {
|
|
5161
|
+
const body = {};
|
|
5162
|
+
for (const raw of pairs ?? []) {
|
|
5163
|
+
const eq = raw.indexOf("=");
|
|
5164
|
+
if (eq <= 0) {
|
|
5165
|
+
throw new Error(`--set \u683C\u5F0F\u5E94\u4E3A key=value\uFF0C\u6536\u5230\uFF1A${raw}`);
|
|
5166
|
+
}
|
|
5167
|
+
const key = raw.slice(0, eq).trim();
|
|
5168
|
+
if (!key) {
|
|
5169
|
+
throw new Error(`--set \u7F3A\u5C11\u5B57\u6BB5\u540D\uFF1A${raw}`);
|
|
5170
|
+
}
|
|
5171
|
+
body[key] = coerceSetValue(raw.slice(eq + 1));
|
|
5172
|
+
}
|
|
5173
|
+
return body;
|
|
5174
|
+
}
|
|
5175
|
+
function parseBodyJson(inline, filePath) {
|
|
5176
|
+
const raw = filePath ? readFileSync6(filePath, "utf8") : inline;
|
|
5177
|
+
if (!raw?.trim()) return {};
|
|
5178
|
+
const parsed = JSON.parse(raw);
|
|
5179
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
5180
|
+
throw new Error("--body / --body-file \u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
5181
|
+
}
|
|
5182
|
+
return parsed;
|
|
5183
|
+
}
|
|
5184
|
+
async function zaspFetch(opts, path7, init = {}) {
|
|
5185
|
+
const target = await resolveTarget(opts);
|
|
5186
|
+
try {
|
|
5187
|
+
const data = await apiFetch2(zaspUrl(target.base, path7), target.config, init, opts.verbose);
|
|
5188
|
+
return { data, siteName: target.site.name, base: target.base };
|
|
5189
|
+
} catch (e) {
|
|
5190
|
+
throw new Error(explainZaspError(e));
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
async function runZaspSettings(opts) {
|
|
5194
|
+
let pack;
|
|
5195
|
+
try {
|
|
5196
|
+
pack = await zaspFetch(opts, "/settings");
|
|
5197
|
+
} catch (e) {
|
|
5198
|
+
console.error(`
|
|
5199
|
+
\u274C \u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A${e.message}
|
|
5200
|
+
`);
|
|
5201
|
+
process.exit(1);
|
|
5202
|
+
return;
|
|
5203
|
+
}
|
|
5204
|
+
if (opts.json) {
|
|
5205
|
+
printJson({ site: pack.siteName, url: pack.base, ...pack.data });
|
|
5206
|
+
return;
|
|
5207
|
+
}
|
|
5208
|
+
const settings = pack.data.settings ?? {};
|
|
5209
|
+
const runtime = pack.data.runtime ?? {};
|
|
5210
|
+
console.log(`
|
|
5211
|
+
${pack.siteName} AI \u63A8\u8350\u914D\u7F6E (${pack.base})
|
|
5212
|
+
`);
|
|
5213
|
+
printCliTable(
|
|
5214
|
+
[
|
|
5215
|
+
{ k: "ai_provider", v: String(settings.ai_provider ?? "-") },
|
|
5216
|
+
{ k: "vector_provider", v: String(settings.vector_provider ?? "-") },
|
|
5217
|
+
{ k: "related_enabled", v: String(settings.related_enabled ?? "-") },
|
|
5218
|
+
{ k: "related_limit", v: String(settings.related_limit ?? "-") },
|
|
5219
|
+
{ k: "auto_sync", v: String(settings.auto_sync ?? "-") },
|
|
5220
|
+
{ k: "has_ai_api_key", v: String(settings.has_ai_api_key ?? "-") },
|
|
5221
|
+
{ k: "has_vector_api_key", v: String(settings.has_vector_api_key ?? "-") },
|
|
5222
|
+
{ k: "has_vector_embed_api_key", v: String(settings.has_vector_embed_api_key ?? "-") },
|
|
5223
|
+
{ k: "runtime.ai_configured", v: String(runtime.ai_configured ?? "-") },
|
|
5224
|
+
{ k: "runtime.vector_configured", v: String(runtime.vector_configured ?? "-") },
|
|
5225
|
+
{ k: "runtime.vector_site_id", v: String(runtime.vector_site_id ?? "-") },
|
|
5226
|
+
{ k: "runtime.retrieval_mode", v: String(runtime.retrieval_mode ?? "-") }
|
|
5227
|
+
],
|
|
5228
|
+
[
|
|
5229
|
+
{ key: "k", header: "\u5B57\u6BB5" },
|
|
5230
|
+
{ key: "v", header: "\u503C" }
|
|
5231
|
+
]
|
|
5232
|
+
);
|
|
5233
|
+
const sync = runtime.sync_state;
|
|
5234
|
+
if (sync?.error) {
|
|
5235
|
+
console.log(`
|
|
5236
|
+
\u4E0A\u6B21\u540C\u6B65\u5931\u8D25\uFF1A${String(sync.error)}`);
|
|
5237
|
+
}
|
|
5238
|
+
console.log("\n\u5B8C\u6574\u5B57\u6BB5\u7528 --json\uFF1B\u5B57\u6BB5\u5B57\u5178\u7528 `zasp schema`\u3002\n");
|
|
5239
|
+
}
|
|
5240
|
+
async function runZaspSchema(opts) {
|
|
5241
|
+
let pack;
|
|
5242
|
+
try {
|
|
5243
|
+
pack = await zaspFetch(opts, "/settings/schema");
|
|
5244
|
+
} catch (e) {
|
|
5245
|
+
console.error(`
|
|
5246
|
+
\u274C \u8BFB\u53D6\u5B57\u6BB5\u5B57\u5178\u5931\u8D25\uFF1A${e.message}
|
|
5247
|
+
`);
|
|
5248
|
+
process.exit(1);
|
|
5249
|
+
return;
|
|
5250
|
+
}
|
|
5251
|
+
if (opts.json) {
|
|
5252
|
+
printJson(pack.data);
|
|
5253
|
+
return;
|
|
5254
|
+
}
|
|
5255
|
+
console.log(`
|
|
5256
|
+
${pack.siteName} \u5B57\u6BB5\u5B57\u5178
|
|
5257
|
+
`);
|
|
5258
|
+
printJson(pack.data);
|
|
5259
|
+
console.log();
|
|
5260
|
+
}
|
|
5261
|
+
async function runZaspSet(opts) {
|
|
5262
|
+
let patch;
|
|
5263
|
+
try {
|
|
5264
|
+
patch = {
|
|
5265
|
+
...parseBodyJson(opts.body, opts.bodyFile),
|
|
5266
|
+
...parseSetPairs(opts.set)
|
|
5267
|
+
};
|
|
5268
|
+
} catch (e) {
|
|
5269
|
+
console.error(`
|
|
5270
|
+
\u274C ${e.message}
|
|
5271
|
+
`);
|
|
5272
|
+
process.exit(1);
|
|
5273
|
+
return;
|
|
5274
|
+
}
|
|
5275
|
+
if (opts.clearAiKey) patch.clear_ai_key = true;
|
|
5276
|
+
if (opts.clearVectorKey) patch.clear_vector_key = true;
|
|
5277
|
+
if (opts.clearVectorEmbedKey) patch.clear_vector_embed_key = true;
|
|
5278
|
+
if (Object.keys(patch).length === 0) {
|
|
5279
|
+
console.error(`
|
|
5280
|
+
\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\u3002\u7528 --set key=value\uFF0C\u6216 --body '{"related_enabled":1}'
|
|
5281
|
+
`);
|
|
5282
|
+
process.exit(1);
|
|
5283
|
+
}
|
|
5284
|
+
let pack;
|
|
5285
|
+
try {
|
|
5286
|
+
pack = await zaspFetch(opts, "/settings", {
|
|
5287
|
+
method: "PATCH",
|
|
5288
|
+
body: JSON.stringify(patch)
|
|
5289
|
+
});
|
|
5290
|
+
} catch (e) {
|
|
5291
|
+
console.error(`
|
|
5292
|
+
\u274C \u66F4\u65B0\u914D\u7F6E\u5931\u8D25\uFF1A${e.message}
|
|
5293
|
+
`);
|
|
5294
|
+
process.exit(1);
|
|
5295
|
+
return;
|
|
5296
|
+
}
|
|
5297
|
+
const changed = Object.keys(patch).filter((k) => !SECRET_KEY.test(k) && !k.startsWith("clear_"));
|
|
5298
|
+
console.log(`
|
|
5299
|
+
\u2705 \u5DF2\u66F4\u65B0 ${pack.siteName} \u7684 AI \u63A8\u8350\u914D\u7F6E`);
|
|
5300
|
+
if (changed.length) console.log(` \u5B57\u6BB5\uFF1A${changed.join(", ")}`);
|
|
5301
|
+
if (opts.clearAiKey || opts.clearVectorKey || opts.clearVectorEmbedKey) {
|
|
5302
|
+
console.log(" \u5DF2\u6309\u5F00\u5173\u6E05\u7A7A\u5BF9\u5E94\u5BC6\u94A5\uFF08\u660E\u6587\u4E0D\u4F1A\u56DE\u663E\uFF09");
|
|
5303
|
+
}
|
|
5304
|
+
console.log(` \u7AD9\u70B9\uFF1A${pack.base}
|
|
5305
|
+
`);
|
|
5306
|
+
if (opts.json) {
|
|
5307
|
+
printJson(pack.data);
|
|
5308
|
+
return;
|
|
5309
|
+
}
|
|
5310
|
+
const settings = pack.data.settings ?? {};
|
|
5311
|
+
const runtime = pack.data.runtime ?? {};
|
|
5312
|
+
console.log(
|
|
5313
|
+
` ai_provider=${String(settings.ai_provider ?? "-")} vector_provider=${String(settings.vector_provider ?? "-")} ai_configured=${String(runtime.ai_configured ?? "-")} vector_configured=${String(runtime.vector_configured ?? "-")}`
|
|
5314
|
+
);
|
|
5315
|
+
console.log(" \u6539\u4E86\u5411\u91CF\u540E\u7AEF\u7684\u8BDD\uFF0C\u63A5\u7740\u8DD1 `zasp sync`\uFF1B\u53EA\u6539\u76F8\u5173\u63A8\u8350 / custom AI \u4E00\u822C\u4E0D\u7528\u3002\n");
|
|
5316
|
+
}
|
|
5317
|
+
async function runZaspSync(opts) {
|
|
5318
|
+
let pack;
|
|
5319
|
+
try {
|
|
5320
|
+
pack = await zaspFetch(opts, "/sync", { method: "POST" });
|
|
5321
|
+
} catch (e) {
|
|
5322
|
+
console.error(`
|
|
5323
|
+
\u274C \u540C\u6B65\u5931\u8D25\uFF1A${e.message}
|
|
5324
|
+
`);
|
|
5325
|
+
process.exit(1);
|
|
5326
|
+
return;
|
|
5327
|
+
}
|
|
5328
|
+
if (opts.json) {
|
|
5329
|
+
printJson(pack.data);
|
|
5330
|
+
return;
|
|
5331
|
+
}
|
|
5332
|
+
if (pack.data.ok) {
|
|
5333
|
+
console.log(`
|
|
5334
|
+
\u2705 ${pack.siteName} \u5168\u91CF\u540C\u6B65\u5B8C\u6210\uFF0C\u5199\u5165 ${pack.data.count ?? 0} \u6761
|
|
5335
|
+
`);
|
|
5336
|
+
return;
|
|
5337
|
+
}
|
|
5338
|
+
console.error(`
|
|
5339
|
+
\u274C \u540C\u6B65\u672A\u5B8C\u6210\uFF1A${pack.data.error || "\u672A\u77E5\u9519\u8BEF"}`);
|
|
5340
|
+
console.error(" \u5148\u4FEE Collection / key / \u7EF4\u5EA6\uFF0C\u518D `zasp set`\uFF0C\u518D `zasp sync`\n");
|
|
5341
|
+
process.exit(1);
|
|
5342
|
+
}
|
|
5343
|
+
async function runZaspStatus(opts) {
|
|
5344
|
+
let pack;
|
|
5345
|
+
try {
|
|
5346
|
+
pack = await zaspFetch(opts, "/status");
|
|
5347
|
+
} catch (e) {
|
|
5348
|
+
console.error(`
|
|
5349
|
+
\u274C \u8BFB\u53D6\u72B6\u6001\u5931\u8D25\uFF1A${e.message}
|
|
5350
|
+
`);
|
|
5351
|
+
process.exit(1);
|
|
5352
|
+
return;
|
|
5353
|
+
}
|
|
5354
|
+
if (opts.json) {
|
|
5355
|
+
printJson({ site: pack.siteName, url: pack.base, ...pack.data });
|
|
5356
|
+
return;
|
|
5357
|
+
}
|
|
5358
|
+
const counts = pack.data.source_counts ?? {};
|
|
5359
|
+
console.log(`
|
|
5360
|
+
${pack.siteName} AI \u63A8\u8350\u72B6\u6001 (${pack.base})
|
|
5361
|
+
`);
|
|
5362
|
+
printCliTable(
|
|
5363
|
+
[
|
|
5364
|
+
{ k: "ready", v: String(pack.data.ready ?? pack.data.status ?? "-") },
|
|
5365
|
+
{ k: "ai_configured", v: String(pack.data.ai_configured ?? "-") },
|
|
5366
|
+
{ k: "vector_configured", v: String(pack.data.vector_configured ?? "-") },
|
|
5367
|
+
{ k: "vector_site_id", v: String(pack.data.vector_site_id ?? "-") },
|
|
5368
|
+
{ k: "mode", v: String(pack.data.mode ?? "-") },
|
|
5369
|
+
{ k: "version", v: String(pack.data.version ?? "-") },
|
|
5370
|
+
{ k: "documents", v: String(counts.documents ?? "-") },
|
|
5371
|
+
{ k: "products", v: String(counts.products ?? "-") }
|
|
5372
|
+
],
|
|
5373
|
+
[
|
|
5374
|
+
{ key: "k", header: "\u5B57\u6BB5" },
|
|
5375
|
+
{ key: "v", header: "\u503C" }
|
|
5376
|
+
]
|
|
5377
|
+
);
|
|
5378
|
+
console.log();
|
|
5379
|
+
}
|
|
5380
|
+
async function runZaspDiagnostics(opts) {
|
|
5381
|
+
let pack;
|
|
5382
|
+
try {
|
|
5383
|
+
pack = await zaspFetch(opts, "/diagnostics");
|
|
5384
|
+
} catch (e) {
|
|
5385
|
+
console.error(`
|
|
5386
|
+
\u274C \u8BCA\u65AD\u5931\u8D25\uFF1A${e.message}
|
|
5387
|
+
`);
|
|
5388
|
+
process.exit(1);
|
|
5389
|
+
return;
|
|
5390
|
+
}
|
|
5391
|
+
console.log(`
|
|
5392
|
+
${pack.siteName} \u8BCA\u65AD
|
|
5393
|
+
`);
|
|
5394
|
+
printJson(pack.data);
|
|
5395
|
+
console.log();
|
|
5396
|
+
}
|
|
5397
|
+
async function runZaspRecommend(opts) {
|
|
5398
|
+
const placement = opts.placement?.trim() || "assistant";
|
|
5399
|
+
const limit = Number(opts.limit ?? 5);
|
|
5400
|
+
const pageId = Number(opts.pageId ?? 0);
|
|
5401
|
+
if (!Number.isFinite(limit) || limit < 1) {
|
|
5402
|
+
console.error("\n\u274C --limit \u5FC5\u987B\u662F\u6B63\u6574\u6570\n");
|
|
5403
|
+
process.exit(1);
|
|
5404
|
+
}
|
|
5405
|
+
if (placement === "related_products" && (!Number.isFinite(pageId) || pageId <= 0)) {
|
|
5406
|
+
console.error("\n\u274C \u9875\u9762\u76F8\u5173\u63A8\u8350\u5FC5\u987B\u63D0\u4F9B\u6709\u6548\u5546\u54C1 --page-id\n");
|
|
5407
|
+
process.exit(1);
|
|
5408
|
+
}
|
|
5409
|
+
const body = {
|
|
5410
|
+
query: opts.query?.trim() ?? "",
|
|
5411
|
+
placement,
|
|
5412
|
+
limit,
|
|
5413
|
+
page_id: Number.isFinite(pageId) ? pageId : 0,
|
|
5414
|
+
constraints: {},
|
|
5415
|
+
session: { seen: [], interest: {} }
|
|
5416
|
+
};
|
|
5417
|
+
let pack;
|
|
5418
|
+
try {
|
|
5419
|
+
pack = await zaspFetch(opts, "/recommend", {
|
|
5420
|
+
method: "POST",
|
|
5421
|
+
body: JSON.stringify(body)
|
|
5422
|
+
});
|
|
5423
|
+
} catch (e) {
|
|
5424
|
+
console.error(`
|
|
5425
|
+
\u274C \u8BD5\u63A8\u5931\u8D25\uFF1A${e.message}
|
|
5426
|
+
`);
|
|
5427
|
+
process.exit(1);
|
|
5428
|
+
return;
|
|
5429
|
+
}
|
|
5430
|
+
if (opts.json) {
|
|
5431
|
+
printJson(pack.data);
|
|
5432
|
+
return;
|
|
5433
|
+
}
|
|
5434
|
+
const items = pack.data.items ?? [];
|
|
5435
|
+
console.log(`
|
|
5436
|
+
${pack.siteName} \u8BD5\u63A8 status=${pack.data.status ?? "-"} mode=${pack.data.mode ?? "-"}`);
|
|
5437
|
+
if (items.length === 0) {
|
|
5438
|
+
console.log("\u6CA1\u6709\u5339\u914D\u7ED3\u679C\u3002\n");
|
|
5439
|
+
return;
|
|
5440
|
+
}
|
|
5441
|
+
printCliTable(
|
|
5442
|
+
items.map((item) => ({
|
|
5443
|
+
id: item.id != null ? String(item.id) : "-",
|
|
5444
|
+
title: item.title || "-",
|
|
5445
|
+
type: item.type || "-",
|
|
5446
|
+
score: item.score != null ? String(item.score) : "-",
|
|
5447
|
+
url: item.url || "-"
|
|
5448
|
+
})),
|
|
5449
|
+
[
|
|
5450
|
+
{ key: "id", header: "id" },
|
|
5451
|
+
{ key: "title", header: "\u6807\u9898" },
|
|
5452
|
+
{ key: "type", header: "\u7C7B\u578B" },
|
|
5453
|
+
{ key: "score", header: "\u5206" },
|
|
5454
|
+
{ key: "url", header: "\u94FE\u63A5" }
|
|
5455
|
+
]
|
|
5456
|
+
);
|
|
5457
|
+
console.log();
|
|
5458
|
+
}
|
|
5459
|
+
function hintZaspIfNeeded(pluginOrSlug) {
|
|
5460
|
+
if (!pluginOrSlug.toLowerCase().includes("zasp-smart-recommender")) return;
|
|
5461
|
+
console.log(" \u63A5\u4E0B\u6765\u7528 `siluzan-website zasp settings / set / sync` \u914D\u7F6E AI \u63A8\u8350\uFF08\u89C1 references/zasp-recommender.md\uFF09\n");
|
|
5462
|
+
}
|
|
5463
|
+
function register11(program2) {
|
|
5464
|
+
const zasp = program2.command("zasp").description("zasp-smart-recommender\uFF08AI \u63A8\u8350\uFF09\u914D\u7F6E\u4E0E\u9A8C\u6536\uFF0C\u8D70\u7AD9\u70B9 /wp-json/zasp-b2b/v2");
|
|
5465
|
+
zasp.command("settings").description("\u67E5\u770B\u5F53\u524D AI \u63A8\u8350\u914D\u7F6E\uFF08GET /settings\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA\u5B8C\u6574 JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5466
|
+
await runZaspSettings(opts);
|
|
5467
|
+
});
|
|
5468
|
+
zasp.command("schema").description("\u67E5\u770B\u53EF\u5199\u5B57\u6BB5\u5B57\u5178\uFF08GET /settings/schema\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5469
|
+
await runZaspSchema(opts);
|
|
5470
|
+
});
|
|
5471
|
+
zasp.command("set").description("\u53EA\u6539\u8981\u6539\u7684\u5B57\u6BB5\uFF08PATCH /settings\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--body <json>", "PATCH JSON \u5BF9\u8C61\uFF0C\u53EA\u542B\u8981\u6539\u7684\u5B57\u6BB5").option("--body-file <file>", "\u4ECE\u6587\u4EF6\u8BFB PATCH JSON").option("--set <key=value>", "\u5355\u4E2A\u5B57\u6BB5\uFF0C\u53EF\u91CD\u590D", collectPair, []).option("--clear-ai-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684 AI Key", false).option("--clear-vector-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684\u5411\u91CF\u5E93 Key", false).option("--clear-vector-embed-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684 Embedding Key", false).option("--json", "\u8F93\u51FA\u66F4\u65B0\u540E\u7684\u5B8C\u6574 JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5472
|
+
await runZaspSet(opts);
|
|
5473
|
+
});
|
|
5474
|
+
zasp.command("sync").description("\u5168\u91CF\u540C\u6B65\u5546\u54C1\u5230\u5411\u91CF\u5E93\uFF08POST /sync\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5475
|
+
await runZaspSync(opts);
|
|
5476
|
+
});
|
|
5477
|
+
zasp.command("status").description("\u516C\u5F00\u9A8C\u6536\uFF1Aready / \u662F\u5426\u914D\u597D\uFF08GET /status\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5478
|
+
await runZaspStatus(opts);
|
|
5479
|
+
});
|
|
5480
|
+
zasp.command("diagnostics").description("\u7BA1\u7406\u5458\u6DF1\u67E5\uFF08GET /diagnostics\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5481
|
+
await runZaspDiagnostics(opts);
|
|
5482
|
+
});
|
|
5483
|
+
zasp.command("recommend").description("\u524D\u53F0\u8BD5\u63A8\u4E00\u6761\uFF08POST /recommend\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--query <q>", "\u68C0\u7D22\u8BCD\uFF1B\u76F8\u5173\u63A8\u8350\u53EF\u7559\u7A7A").option("--placement <p>", "assistant \u6216 related_products", "assistant").option("--limit <n>", "\u6761\u6570", "5").option("--page-id <id>", "related_products \u65F6\u7684\u5546\u54C1\u9875 ID", "0").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5484
|
+
await runZaspRecommend(opts);
|
|
5485
|
+
});
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
// src/commands/plugins.ts
|
|
5489
|
+
var MAX_ZIP_BYTES = 40 * 1024 * 1024;
|
|
5490
|
+
var PROTECTED_PLUGIN_PREFIXES = ["siluzan-helper-plugin", "wp-oauth2"];
|
|
5491
|
+
function isProtectedPlugin(plugin) {
|
|
5492
|
+
const key = pluginKey(plugin);
|
|
5493
|
+
return PROTECTED_PLUGIN_PREFIXES.some((prefix) => key === prefix || key.startsWith(`${prefix}/`));
|
|
5494
|
+
}
|
|
5495
|
+
function wpPluginRestPath(plugin) {
|
|
5496
|
+
return plugin.replace(/\\/g, "/").split("/").filter(Boolean).map((part) => encodeURIComponent(part)).join("/");
|
|
5497
|
+
}
|
|
5498
|
+
function pluginName(item) {
|
|
5499
|
+
if (typeof item.name === "string") return item.name;
|
|
5500
|
+
return item.name?.raw || item.name?.rendered || item.plugin || "";
|
|
5501
|
+
}
|
|
5502
|
+
function pluginKey(value) {
|
|
5503
|
+
return value.replace(/\\/g, "/").replace(/\.php$/i, "").toLowerCase();
|
|
5504
|
+
}
|
|
5505
|
+
function formatBytes(n) {
|
|
5506
|
+
if (!n) return "-";
|
|
5507
|
+
if (n < 1024) return `${n} B`;
|
|
5508
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
5509
|
+
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
5510
|
+
}
|
|
5511
|
+
async function resolveTarget2(opts) {
|
|
5512
|
+
const config = loadConfig();
|
|
5513
|
+
const site = await resolveSite(config, opts);
|
|
5514
|
+
return { config, site, base: trimTrailingSlash(site.url) };
|
|
5515
|
+
}
|
|
5516
|
+
function isRouteMissing(err) {
|
|
5517
|
+
const msg = err.message || "";
|
|
5518
|
+
return /HTTP 404/.test(msg) && /No route was found|rest_no_route/i.test(msg);
|
|
5519
|
+
}
|
|
5520
|
+
function readZipPayload(zipPath) {
|
|
5521
|
+
const abs = resolve2(zipPath);
|
|
5522
|
+
if (!existsSync3(abs)) {
|
|
5523
|
+
console.error(`
|
|
5524
|
+
\u274C zip \u4E0D\u5B58\u5728\uFF1A${abs}
|
|
5525
|
+
`);
|
|
5526
|
+
process.exit(1);
|
|
5527
|
+
}
|
|
5528
|
+
const buf = readFileSync7(abs);
|
|
5529
|
+
if (buf.length > MAX_ZIP_BYTES) {
|
|
5530
|
+
console.error("\n\u274C zip \u8D85\u8FC7 20MB\uFF0C\u8BF7\u6362\u66F4\u5C0F\u7684\u5305\n");
|
|
5531
|
+
process.exit(1);
|
|
5532
|
+
}
|
|
5533
|
+
return {
|
|
5534
|
+
filename: basename2(abs),
|
|
5535
|
+
zip_base64: buf.toString("base64")
|
|
5536
|
+
};
|
|
5537
|
+
}
|
|
5538
|
+
function printActionResult(result, site, base, okTitle) {
|
|
5539
|
+
if (!result.success) {
|
|
5540
|
+
console.error(`
|
|
5541
|
+
\u274C ${result.message || "\u7AD9\u70B9\u62D2\u7EDD\u4E86\u8FD9\u6B21\u64CD\u4F5C"}`);
|
|
5542
|
+
if (result.code) console.error(` code : ${result.code}`);
|
|
5543
|
+
process.exit(1);
|
|
5544
|
+
}
|
|
5545
|
+
console.log(result.already ? "\n\u2705 \u63D2\u4EF6\u5DF2\u5728\u7AD9\u70B9\u4E0A\uFF08\u5DF2\u542F\u7528\uFF09" : `
|
|
5546
|
+
\u2705 ${okTitle}`);
|
|
5547
|
+
if (result.plugin) console.log(` plugin : ${result.plugin}`);
|
|
5548
|
+
if (result.version) console.log(` \u7248\u672C : ${result.version}`);
|
|
5549
|
+
if (result.zip) console.log(` zip : ${result.zip}`);
|
|
5550
|
+
if (result.message) console.log(` \u8BF4\u660E : ${result.message}`);
|
|
5551
|
+
console.log(` \u7AD9\u70B9 : ${site.name} (${base})
|
|
5552
|
+
`);
|
|
5553
|
+
}
|
|
5554
|
+
async function withHelperBootstrap(opts, target, run) {
|
|
5555
|
+
try {
|
|
5556
|
+
return await run();
|
|
5557
|
+
} catch (e) {
|
|
5558
|
+
const err = e;
|
|
5559
|
+
if (!isRouteMissing(err)) throw err;
|
|
5560
|
+
console.log("\u7AD9\u70B9 helper REST \u4E0D\u53EF\u7528\uFF0C\u5148\u4ECE\u955C\u50CF\u672C\u5730 zip \u5347\u7EA7 helper\u2026");
|
|
5561
|
+
await runUpdateHelper({ ...opts, site: target.site.guid || opts.site, url: target.site.url }, true);
|
|
5562
|
+
return await run();
|
|
5563
|
+
}
|
|
5564
|
+
}
|
|
5565
|
+
async function runPluginsList(opts) {
|
|
5566
|
+
const { config, site, base } = await resolveTarget2(opts);
|
|
5567
|
+
const api = `${base}/wp-json/wp/v2/plugins`;
|
|
5568
|
+
let plugins;
|
|
5569
|
+
try {
|
|
5570
|
+
plugins = await apiFetch2(api, config, {}, opts.verbose);
|
|
5571
|
+
} catch (e) {
|
|
5572
|
+
const msg = e.message || "";
|
|
5573
|
+
console.error(`
|
|
5574
|
+
\u274C \u83B7\u53D6\u5DF2\u88C5\u63D2\u4EF6\u5931\u8D25\uFF1A${msg}`);
|
|
5575
|
+
if (/HTTP 401/.test(msg)) {
|
|
5576
|
+
console.error(" \u7AD9\u70B9 oauth2 \u8FC7\u65E7\u6216\u4E0D\u8BA4 API Key\uFF0C\u9700\u8981\u5148\u505A SiteMan \u955C\u50CF\u5347\u7EA7\u3002\n");
|
|
5577
|
+
}
|
|
5578
|
+
if (opts.exitOnError === false) return;
|
|
5579
|
+
process.exit(1);
|
|
5580
|
+
return;
|
|
5581
|
+
}
|
|
5582
|
+
if (!Array.isArray(plugins)) {
|
|
5583
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u63D2\u4EF6\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
5584
|
+
if (opts.exitOnError === false) return;
|
|
5585
|
+
process.exit(1);
|
|
5586
|
+
}
|
|
5587
|
+
let official = [];
|
|
5588
|
+
try {
|
|
5589
|
+
official = (await fetchOfficialPluginList(config, { verbose: opts.verbose })).items;
|
|
5590
|
+
} catch {
|
|
5591
|
+
}
|
|
5592
|
+
const officialBySlug = new Map(official.map((item) => [item.slug.toLowerCase(), item]));
|
|
5593
|
+
const rows = plugins.map((p) => {
|
|
5594
|
+
const plugin = p.plugin ?? "";
|
|
5595
|
+
const slug = pluginKey(plugin).split("/")[0];
|
|
5596
|
+
const hit = officialBySlug.get(slug);
|
|
5597
|
+
return {
|
|
5598
|
+
plugin,
|
|
5599
|
+
name: pluginName(p),
|
|
5600
|
+
status: p.status ?? "",
|
|
5601
|
+
version: p.version ?? "",
|
|
5602
|
+
updateSource: hit ? "catalog" : "none",
|
|
5603
|
+
catalogVersion: hit?.version ?? ""
|
|
5604
|
+
};
|
|
5605
|
+
});
|
|
5606
|
+
if (opts.json) {
|
|
5607
|
+
console.log(
|
|
5608
|
+
JSON.stringify(
|
|
5609
|
+
{
|
|
5610
|
+
site: { guid: site.guid, name: site.name, url: site.url },
|
|
5611
|
+
total: rows.length,
|
|
5612
|
+
plugins: rows
|
|
5613
|
+
},
|
|
5614
|
+
null,
|
|
5615
|
+
2
|
|
5616
|
+
)
|
|
5617
|
+
);
|
|
5618
|
+
return;
|
|
5619
|
+
}
|
|
5620
|
+
if (rows.length === 0) {
|
|
5621
|
+
console.log(`
|
|
5622
|
+
\u7AD9\u70B9 ${site.name} \u672A\u8FD4\u56DE\u63D2\u4EF6\u3002
|
|
5623
|
+
`);
|
|
5624
|
+
return;
|
|
5625
|
+
}
|
|
5626
|
+
const columns = [
|
|
5627
|
+
{ key: "plugin", header: "plugin" },
|
|
5628
|
+
{ key: "name", header: "\u540D\u79F0" },
|
|
5629
|
+
{ key: "status", header: "\u72B6\u6001" },
|
|
5630
|
+
{ key: "version", header: "\u7248\u672C" },
|
|
5631
|
+
{ key: "updateSource", header: "\u66F4\u65B0\u6E90" },
|
|
5632
|
+
{ key: "catalogVersion", header: "\u76EE\u5F55\u7248\u672C" }
|
|
5633
|
+
];
|
|
5634
|
+
console.log(`
|
|
5635
|
+
${site.name} \u5DF2\u88C5\u63D2\u4EF6\uFF08${rows.length}\uFF09
|
|
5636
|
+
`);
|
|
5637
|
+
printCliTable(
|
|
5638
|
+
rows.map((r) => ({
|
|
5639
|
+
plugin: r.plugin || "-",
|
|
5640
|
+
name: r.name || "-",
|
|
5641
|
+
status: r.status || "-",
|
|
5642
|
+
version: r.version || "-",
|
|
5643
|
+
updateSource: r.updateSource,
|
|
5644
|
+
catalogVersion: r.catalogVersion || "-"
|
|
5645
|
+
})),
|
|
4065
5646
|
columns
|
|
4066
5647
|
);
|
|
4067
5648
|
console.log();
|
|
4068
5649
|
}
|
|
4069
5650
|
async function runPluginsCatalog(opts) {
|
|
4070
|
-
const
|
|
4071
|
-
|
|
4072
|
-
|
|
5651
|
+
const config = loadConfig();
|
|
5652
|
+
let pack;
|
|
5653
|
+
try {
|
|
5654
|
+
pack = await fetchOfficialPluginList(config, { prefix: opts.prefix, verbose: opts.verbose });
|
|
5655
|
+
} catch (e) {
|
|
5656
|
+
console.error(`
|
|
5657
|
+
\u274C \u83B7\u53D6\u63D2\u4EF6\u76EE\u5F55\u5931\u8D25\uFF1A${e.message}
|
|
5658
|
+
`);
|
|
5659
|
+
process.exit(1);
|
|
5660
|
+
return;
|
|
5661
|
+
}
|
|
5662
|
+
const installedBySlug = /* @__PURE__ */ new Map();
|
|
5663
|
+
if (opts.site || opts.url) {
|
|
5664
|
+
try {
|
|
5665
|
+
const target = await resolveTarget2(opts);
|
|
5666
|
+
const plugins = await apiFetch2(
|
|
5667
|
+
`${target.base}/wp-json/wp/v2/plugins`,
|
|
5668
|
+
target.config,
|
|
5669
|
+
{},
|
|
5670
|
+
opts.verbose
|
|
5671
|
+
);
|
|
5672
|
+
if (Array.isArray(plugins)) {
|
|
5673
|
+
for (const p of plugins) {
|
|
5674
|
+
const slug = pluginKey(p.plugin || "").split("/")[0];
|
|
5675
|
+
if (slug) installedBySlug.set(slug, { version: p.version || "", status: p.status || "" });
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5678
|
+
} catch {
|
|
5679
|
+
}
|
|
5680
|
+
}
|
|
5681
|
+
const rows = pack.items.map((p) => {
|
|
5682
|
+
const onSite = installedBySlug.get(p.slug.toLowerCase());
|
|
5683
|
+
return {
|
|
5684
|
+
slug: p.slug,
|
|
5685
|
+
version: p.version,
|
|
5686
|
+
size: formatBytes(p.size),
|
|
5687
|
+
installed: onSite ? "yes" : opts.site || opts.url ? "no" : "-",
|
|
5688
|
+
filename: p.filename
|
|
5689
|
+
};
|
|
5690
|
+
});
|
|
5691
|
+
if (opts.json) {
|
|
5692
|
+
console.log(
|
|
5693
|
+
JSON.stringify({ container: pack.container, total: pack.items.length, items: pack.items }, null, 2)
|
|
5694
|
+
);
|
|
5695
|
+
return;
|
|
5696
|
+
}
|
|
5697
|
+
if (rows.length === 0) {
|
|
5698
|
+
console.log("\n\u5B98\u65B9\u63D2\u4EF6\u76EE\u5F55\u4E3A\u7A7A\u3002\n");
|
|
5699
|
+
return;
|
|
5700
|
+
}
|
|
5701
|
+
console.log(`
|
|
5702
|
+
\u5B98\u65B9\u63D2\u4EF6\u76EE\u5F55 ${pack.container}\uFF08${rows.length}\uFF09
|
|
5703
|
+
`);
|
|
5704
|
+
printCliTable(rows, [
|
|
5705
|
+
{ key: "slug", header: "slug" },
|
|
5706
|
+
{ key: "version", header: "\u76EE\u5F55\u7248\u672C" },
|
|
5707
|
+
{ key: "size", header: "\u5927\u5C0F" },
|
|
5708
|
+
{ key: "installed", header: "\u672C\u7AD9\u5DF2\u88C5" },
|
|
5709
|
+
{ key: "filename", header: "zip" }
|
|
5710
|
+
]);
|
|
5711
|
+
console.log("\n\u5B89\u88C5\uFF1Asiluzan-website plugins install --site <guid> --slug <slug>\n");
|
|
5712
|
+
}
|
|
5713
|
+
async function installOfficialZip(target, official, verbose = false) {
|
|
5714
|
+
if (official.size > MAX_ZIP_BYTES) {
|
|
5715
|
+
throw new Error(`\u76EE\u5F55\u5305 ${official.filename} \u8D85\u8FC7 40MB`);
|
|
5716
|
+
}
|
|
5717
|
+
console.log(`\u4ECE\u5B98\u65B9\u76EE\u5F55\u4E0B\u8F7D ${official.slug} ${official.version} \u2026`);
|
|
5718
|
+
const buf = await downloadOfficialZip(official.url);
|
|
5719
|
+
if (buf.length > MAX_ZIP_BYTES) {
|
|
5720
|
+
throw new Error(`\u76EE\u5F55\u5305 ${official.filename} \u8D85\u8FC7 40MB`);
|
|
5721
|
+
}
|
|
5722
|
+
return apiFetch2(
|
|
5723
|
+
`${target.base}/wp-json/siluzan-helper/v1/plugins/install-zip`,
|
|
5724
|
+
target.config,
|
|
5725
|
+
{
|
|
5726
|
+
method: "POST",
|
|
5727
|
+
body: JSON.stringify({
|
|
5728
|
+
filename: official.filename,
|
|
5729
|
+
zip_base64: buf.toString("base64")
|
|
5730
|
+
})
|
|
5731
|
+
},
|
|
5732
|
+
verbose
|
|
5733
|
+
);
|
|
5734
|
+
}
|
|
5735
|
+
async function runPluginsInstall(opts) {
|
|
5736
|
+
const slug = opts.slug?.trim() ?? "";
|
|
5737
|
+
const zipPath = opts.zip?.trim() ?? "";
|
|
5738
|
+
if (slug && zipPath || !slug && !zipPath) {
|
|
5739
|
+
console.error("\n\u274C \u76EE\u5F55\u63D2\u4EF6\u7528 --slug\uFF0C\u5916\u90E8\u63D2\u4EF6\u7528 --zip\uFF0C\u4E24\u8005\u53EA\u4F20\u4E00\u4E2A\n");
|
|
5740
|
+
process.exit(1);
|
|
5741
|
+
}
|
|
5742
|
+
const target = await resolveTarget2(opts);
|
|
5743
|
+
const { site, base } = target;
|
|
5744
|
+
let result;
|
|
5745
|
+
try {
|
|
5746
|
+
result = await withHelperBootstrap(opts, target, async () => {
|
|
5747
|
+
if (slug) {
|
|
5748
|
+
const official = await findOfficialPlugin(target.config, slug, opts.verbose);
|
|
5749
|
+
if (official) {
|
|
5750
|
+
return installOfficialZip(target, official, opts.verbose);
|
|
5751
|
+
}
|
|
5752
|
+
return apiFetch2(
|
|
5753
|
+
`${base}/wp-json/siluzan-helper/v1/plugins/install`,
|
|
5754
|
+
target.config,
|
|
5755
|
+
{ method: "POST", body: JSON.stringify({ slug }) },
|
|
5756
|
+
opts.verbose
|
|
5757
|
+
);
|
|
5758
|
+
}
|
|
5759
|
+
const zip = readZipPayload(zipPath);
|
|
5760
|
+
return apiFetch2(
|
|
5761
|
+
`${base}/wp-json/siluzan-helper/v1/plugins/install-zip`,
|
|
5762
|
+
target.config,
|
|
5763
|
+
{ method: "POST", body: JSON.stringify(zip) },
|
|
5764
|
+
opts.verbose
|
|
5765
|
+
);
|
|
5766
|
+
});
|
|
5767
|
+
} catch (e) {
|
|
5768
|
+
console.error(`
|
|
5769
|
+
\u274C \u5B89\u88C5\u5931\u8D25\uFF1A${e.message}
|
|
5770
|
+
`);
|
|
5771
|
+
process.exit(1);
|
|
5772
|
+
return;
|
|
5773
|
+
}
|
|
5774
|
+
printActionResult(result, site, base, "\u63D2\u4EF6\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
|
|
5775
|
+
hintZaspIfNeeded(`${result.plugin || ""} ${slug} ${zipPath}`);
|
|
5776
|
+
await runPluginsList({
|
|
5777
|
+
site: site.guid || opts.site,
|
|
5778
|
+
url: site.url,
|
|
5779
|
+
verbose: opts.verbose,
|
|
5780
|
+
exitOnError: false
|
|
5781
|
+
});
|
|
5782
|
+
}
|
|
5783
|
+
async function runPluginsUpdate(opts) {
|
|
5784
|
+
const plugin = opts.plugin?.trim() ?? "";
|
|
5785
|
+
if (!plugin) {
|
|
5786
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --plugin\uFF08\u5148 plugins list \u770B plugin \u5217\uFF09\n");
|
|
5787
|
+
process.exit(1);
|
|
5788
|
+
}
|
|
5789
|
+
const target = await resolveTarget2(opts);
|
|
5790
|
+
const { site, base } = target;
|
|
5791
|
+
const zipPath = opts.zip?.trim() ?? "";
|
|
5792
|
+
const body = { plugin };
|
|
5793
|
+
if (zipPath) {
|
|
5794
|
+
const zip = readZipPayload(zipPath);
|
|
5795
|
+
body.zip_base64 = zip.zip_base64;
|
|
5796
|
+
body.filename = zip.filename;
|
|
5797
|
+
}
|
|
5798
|
+
let result;
|
|
5799
|
+
try {
|
|
5800
|
+
result = await withHelperBootstrap(opts, target, async () => {
|
|
5801
|
+
if (!zipPath) {
|
|
5802
|
+
const official = await findOfficialPlugin(target.config, plugin, opts.verbose);
|
|
5803
|
+
if (official) {
|
|
5804
|
+
return installOfficialZip(target, official, opts.verbose);
|
|
5805
|
+
}
|
|
5806
|
+
}
|
|
5807
|
+
return apiFetch2(
|
|
5808
|
+
`${base}/wp-json/siluzan-helper/v1/plugins/update`,
|
|
5809
|
+
target.config,
|
|
5810
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
5811
|
+
opts.verbose
|
|
5812
|
+
);
|
|
5813
|
+
});
|
|
5814
|
+
} catch (e) {
|
|
5815
|
+
const msg = e.message || "";
|
|
5816
|
+
if (/HTTP 409/.test(msg) && /no_package/i.test(msg)) {
|
|
5817
|
+
console.error(`
|
|
5818
|
+
\u274C ${msg}`);
|
|
5819
|
+
console.error(" \u76EE\u5F55\u548C WordPress.org \u90FD\u6CA1\u6709\u5B89\u88C5\u5305\u3002\u5916\u90E8\u63D2\u4EF6\u8BF7\u5E26 --zip \u518D\u5347\u7EA7\u3002\n");
|
|
5820
|
+
process.exit(1);
|
|
5821
|
+
}
|
|
5822
|
+
console.error(`
|
|
5823
|
+
\u274C \u5347\u7EA7\u5931\u8D25\uFF1A${msg}
|
|
5824
|
+
`);
|
|
5825
|
+
process.exit(1);
|
|
5826
|
+
return;
|
|
5827
|
+
}
|
|
5828
|
+
printActionResult(result, site, base, "\u63D2\u4EF6\u5DF2\u5347\u7EA7");
|
|
5829
|
+
hintZaspIfNeeded(`${result.plugin || ""} ${plugin}`);
|
|
5830
|
+
await runPluginsList({
|
|
5831
|
+
site: site.guid || opts.site,
|
|
5832
|
+
url: site.url,
|
|
5833
|
+
verbose: opts.verbose,
|
|
5834
|
+
exitOnError: false
|
|
5835
|
+
});
|
|
5836
|
+
}
|
|
5837
|
+
async function runHelperStatus(opts) {
|
|
5838
|
+
const { config, site, base } = await resolveTarget2(opts);
|
|
5839
|
+
let status;
|
|
5840
|
+
try {
|
|
5841
|
+
status = await apiFetch2(
|
|
5842
|
+
`${base}/wp-json/wposso/v1/helper/status`,
|
|
5843
|
+
config,
|
|
5844
|
+
{},
|
|
5845
|
+
opts.verbose
|
|
5846
|
+
);
|
|
5847
|
+
} catch (e) {
|
|
5848
|
+
const msg = e.message || "";
|
|
5849
|
+
console.error(`
|
|
5850
|
+
\u274C \u65E0\u6CD5\u8BFB\u53D6 helper \u72B6\u6001\uFF1A${msg}`);
|
|
5851
|
+
if (isRouteMissing(e) || /HTTP 404/.test(msg)) {
|
|
5852
|
+
console.error(" \u7AD9\u70B9 oauth2 \u8FD8\u6CA1\u6709\u5F15\u5BFC\u5347\u7EA7\u63A5\u53E3\uFF0C\u9700\u8981\u5148\u505A SiteMan \u955C\u50CF\u5347\u7EA7\u3002\n");
|
|
5853
|
+
}
|
|
5854
|
+
process.exit(1);
|
|
5855
|
+
return;
|
|
5856
|
+
}
|
|
5857
|
+
if (opts.json) {
|
|
5858
|
+
console.log(JSON.stringify({ site: { guid: site.guid, name: site.name, url: site.url }, ...status }, null, 2));
|
|
5859
|
+
return;
|
|
5860
|
+
}
|
|
5861
|
+
console.log(`
|
|
5862
|
+
${site.name} helper \u72B6\u6001`);
|
|
5863
|
+
console.log(` \u5DF2\u5B89\u88C5 : ${status.helper_installed ? "yes" : "no"}`);
|
|
5864
|
+
console.log(` \u5DF2\u542F\u7528 : ${status.helper_active ? "yes" : "no"}`);
|
|
5865
|
+
console.log(` \u7248\u672C : ${status.helper_version || "-"}`);
|
|
5866
|
+
console.log(` helper REST: ${status.helper_rest_available ? "yes" : "no"}`);
|
|
5867
|
+
console.log(` \u955C\u50CF zip : ${status.bootstrap_zip || "-"}`);
|
|
5868
|
+
console.log(` \u53EF\u5F15\u5BFC\u5347\u7EA7 : ${status.can_upgrade ? "yes" : "no"}
|
|
5869
|
+
`);
|
|
5870
|
+
}
|
|
5871
|
+
async function runUpdateHelper(opts, fromBootstrap = false) {
|
|
5872
|
+
const { config, site, base } = await resolveTarget2(opts);
|
|
5873
|
+
let result;
|
|
5874
|
+
try {
|
|
5875
|
+
result = await apiFetch2(
|
|
5876
|
+
`${base}/wp-json/wposso/v1/helper/upgrade`,
|
|
5877
|
+
config,
|
|
5878
|
+
{ method: "POST", body: JSON.stringify({}) },
|
|
5879
|
+
opts.verbose
|
|
5880
|
+
);
|
|
5881
|
+
} catch (e) {
|
|
5882
|
+
const msg = e.message || "";
|
|
5883
|
+
console.error(`
|
|
5884
|
+
\u274C helper \u5347\u7EA7\u5931\u8D25\uFF1A${msg}`);
|
|
5885
|
+
if (isRouteMissing(e)) {
|
|
5886
|
+
console.error(" \u7AD9\u70B9 oauth2 \u8FD8\u6CA1\u6709\u5F15\u5BFC\u5347\u7EA7\u63A5\u53E3\uFF0C\u9700\u8981\u5148\u505A SiteMan \u955C\u50CF\u5347\u7EA7\u3002");
|
|
5887
|
+
} else if (/HTTP 409/.test(msg)) {
|
|
5888
|
+
console.error(" \u5F53\u524D\u955C\u50CF\u91CC\u6CA1\u6709 siluzan-helper-plugin.1.0.*.zip\u3002");
|
|
5889
|
+
}
|
|
5890
|
+
console.error();
|
|
5891
|
+
process.exit(1);
|
|
5892
|
+
return;
|
|
5893
|
+
}
|
|
5894
|
+
printActionResult(result, site, base, "helper \u5DF2\u4ECE\u955C\u50CF\u672C\u5730 zip \u5347\u7EA7");
|
|
5895
|
+
if (!fromBootstrap) {
|
|
5896
|
+
await runHelperStatus({ site: site.guid || opts.site, url: site.url, verbose: opts.verbose });
|
|
5897
|
+
}
|
|
5898
|
+
}
|
|
5899
|
+
async function findInstalledPlugin(base, config, pluginArg, verbose = false) {
|
|
5900
|
+
const plugins = await apiFetch2(`${base}/wp-json/wp/v2/plugins`, config, {}, verbose);
|
|
5901
|
+
if (!Array.isArray(plugins)) {
|
|
5902
|
+
throw new Error("\u7AD9\u70B9\u8FD4\u56DE\u7684\u63D2\u4EF6\u5217\u8868\u683C\u5F0F\u5F02\u5E38");
|
|
5903
|
+
}
|
|
5904
|
+
const needle = pluginKey(pluginArg);
|
|
5905
|
+
const exact = plugins.find((p) => pluginKey(p.plugin || "") === needle);
|
|
5906
|
+
if (exact?.plugin) return exact;
|
|
5907
|
+
const hits = plugins.filter((p) => {
|
|
5908
|
+
const key = pluginKey(p.plugin || "");
|
|
5909
|
+
return key === needle || key.startsWith(`${needle}/`) || key.endsWith(`/${needle}`);
|
|
5910
|
+
});
|
|
5911
|
+
if (hits.length === 1 && hits[0].plugin) return hits[0];
|
|
5912
|
+
if (hits.length > 1) {
|
|
5913
|
+
const names = hits.map((p) => p.plugin).join("\u3001");
|
|
5914
|
+
throw new Error(`\u300C${pluginArg}\u300D\u5339\u914D\u5230\u591A\u4E2A\u63D2\u4EF6\uFF0C\u8BF7\u6539\u7528\u5B8C\u6574 --plugin\uFF1A${names}`);
|
|
5915
|
+
}
|
|
5916
|
+
throw new Error(`\u7AD9\u70B9\u4E0A\u6CA1\u6709\u63D2\u4EF6\u300C${pluginArg}\u300D\uFF0C\u5148 plugins list \u770B plugin \u5217`);
|
|
5917
|
+
}
|
|
5918
|
+
async function runPluginsUninstall(opts) {
|
|
5919
|
+
const pluginArg = opts.plugin?.trim() ?? "";
|
|
5920
|
+
if (!pluginArg) {
|
|
5921
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --plugin\uFF08\u5148 plugins list \u770B plugin \u5217\uFF09\n");
|
|
5922
|
+
process.exit(1);
|
|
5923
|
+
}
|
|
5924
|
+
if (isProtectedPlugin(pluginArg)) {
|
|
5925
|
+
console.error("\n\u274C \u4E0D\u80FD\u5378\u8F7D siluzan-helper-plugin \u6216 wp-oauth2\uFF0C\u5378\u6389\u540E\u7AD9\u70B9\u65E0\u6CD5\u518D\u7528 Skill \u7BA1\u7406\u3002\n");
|
|
5926
|
+
process.exit(1);
|
|
5927
|
+
}
|
|
5928
|
+
const target = await resolveTarget2(opts);
|
|
5929
|
+
const { site, base } = target;
|
|
5930
|
+
let current;
|
|
5931
|
+
try {
|
|
5932
|
+
current = await findInstalledPlugin(base, target.config, pluginArg, opts.verbose);
|
|
5933
|
+
} catch (e) {
|
|
5934
|
+
console.error(`
|
|
5935
|
+
\u274C ${e.message}
|
|
5936
|
+
`);
|
|
5937
|
+
process.exit(1);
|
|
5938
|
+
return;
|
|
5939
|
+
}
|
|
5940
|
+
const plugin = current.plugin || pluginArg;
|
|
5941
|
+
if (isProtectedPlugin(plugin)) {
|
|
5942
|
+
console.error("\n\u274C \u4E0D\u80FD\u5378\u8F7D siluzan-helper-plugin \u6216 wp-oauth2\uFF0C\u5378\u6389\u540E\u7AD9\u70B9\u65E0\u6CD5\u518D\u7528 Skill \u7BA1\u7406\u3002\n");
|
|
5943
|
+
process.exit(1);
|
|
5944
|
+
}
|
|
5945
|
+
const restPath = `${base}/wp-json/wp/v2/plugins/${wpPluginRestPath(plugin)}`;
|
|
5946
|
+
try {
|
|
5947
|
+
if (current.status === "active") {
|
|
5948
|
+
console.log(`\u5148\u505C\u7528 ${plugin} \u2026`);
|
|
5949
|
+
await apiFetch2(
|
|
5950
|
+
restPath,
|
|
5951
|
+
target.config,
|
|
5952
|
+
{ method: "POST", body: JSON.stringify({ status: "inactive" }) },
|
|
5953
|
+
opts.verbose
|
|
5954
|
+
);
|
|
5955
|
+
}
|
|
5956
|
+
await apiFetch2(restPath, target.config, { method: "DELETE" }, opts.verbose);
|
|
5957
|
+
} catch (e) {
|
|
5958
|
+
console.error(`
|
|
5959
|
+
\u274C \u5378\u8F7D\u5931\u8D25\uFF1A${e.message}
|
|
5960
|
+
`);
|
|
5961
|
+
process.exit(1);
|
|
5962
|
+
return;
|
|
5963
|
+
}
|
|
5964
|
+
console.log(`
|
|
5965
|
+
\u2705 \u5DF2\u5378\u8F7D ${plugin}`);
|
|
5966
|
+
console.log(` \u7AD9\u70B9 : ${site.name} (${base})
|
|
5967
|
+
`);
|
|
5968
|
+
await runPluginsList({
|
|
5969
|
+
site: site.guid || opts.site,
|
|
5970
|
+
url: site.url,
|
|
5971
|
+
verbose: opts.verbose,
|
|
5972
|
+
exitOnError: false
|
|
5973
|
+
});
|
|
5974
|
+
}
|
|
5975
|
+
function register12(program2) {
|
|
5976
|
+
const plugins = program2.command("plugins").description("WordPress \u63D2\u4EF6\uFF1A\u5217\u51FA\u3001\u76EE\u5F55\u3001\u5B89\u88C5\u3001\u5347\u7EA7\u3001\u5378\u8F7D");
|
|
5977
|
+
plugins.command("list").description("\u5217\u51FA\u7AD9\u70B9\u5DF2\u5B89\u88C5\u7684\u5168\u90E8\u63D2\u4EF6").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5978
|
+
await runPluginsList(opts);
|
|
5979
|
+
});
|
|
5980
|
+
plugins.command("catalog").description("\u5217\u51FA\u5B98\u65B9\u63D2\u4EF6\u76EE\u5F55\uFF08sammk8s / wp-plugins\uFF0C\u4E0D\u4F9D\u8D56\u7AD9\u70B9\uFF09").option("-s, --site <guidOrName>", "\u53EF\u9009\uFF0C\u5BF9\u7167\u8BE5\u7AD9\u662F\u5426\u5DF2\u88C5").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--prefix <prefix>", "\u53EA\u5217\u67D0\u4E2A\u76EE\u5F55\uFF0C\u5982 zasp-smart-recommender/").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5981
|
+
await runPluginsCatalog(opts);
|
|
5982
|
+
});
|
|
5983
|
+
plugins.command("install").description("\u5B89\u88C5\u5E76\u542F\u7528\u63D2\u4EF6\uFF1A\u5B98\u65B9\u76EE\u5F55\u7528 --slug\uFF0C\u5916\u90E8\u7528 --zip").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--slug <slug>", "\u4E1D\u8DEF\u8D5E\u76EE\u5F55\u4E2D\u7684 slug \u6216 plugin \u8DEF\u5F84").option("--zip <file>", "\u5916\u90E8\u63D2\u4EF6 zip\uFF08\u6839\u76EE\u5F55\u5FC5\u987B\u662F\u63D2\u4EF6\u76EE\u5F55\uFF09").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5984
|
+
await runPluginsInstall(opts);
|
|
5985
|
+
});
|
|
5986
|
+
plugins.command("update").description("\u5347\u7EA7\u5DF2\u88C5\u63D2\u4EF6\uFF1A\u6709\u76EE\u5F55/\u5B98\u65B9\u5305\u5219\u4E0D\u7528 zip\uFF0C\u5916\u90E8\u63D2\u4EF6\u5E26 --zip").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--plugin <plugin>", "\u5DF2\u88C5\u63D2\u4EF6\u8DEF\u5F84\uFF0C\u5982 theme-manage/theme-manage").option("--zip <file>", "\u5916\u90E8\u63D2\u4EF6\u5347\u7EA7\u5305").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5987
|
+
await runPluginsUpdate(opts);
|
|
5988
|
+
});
|
|
5989
|
+
plugins.command("uninstall").description("\u5378\u8F7D\u5DF2\u88C5\u63D2\u4EF6\uFF08\u5148\u505C\u7528\u518D\u5220\u9664\uFF1Bhelper / oauth2 \u4E0D\u5141\u8BB8\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--plugin <plugin>", "\u5DF2\u88C5\u63D2\u4EF6\u8DEF\u5F84\uFF0C\u5982 dummy-e2e-plugin/dummy-e2e-plugin").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5990
|
+
await runPluginsUninstall(opts);
|
|
5991
|
+
});
|
|
5992
|
+
plugins.command("helper-status").description("\u67E5\u770B\u7AD9\u70B9 helper \u4E0E\u955C\u50CF\u672C\u5730 zip").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5993
|
+
await runHelperStatus(opts);
|
|
5994
|
+
});
|
|
5995
|
+
plugins.command("update-helper").description("\u7528\u955C\u50CF\u91CC\u7684 siluzan-helper-plugin.1.0.*.zip \u5347\u7EA7 helper\uFF08\u5199\u64CD\u4F5C\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
5996
|
+
await runUpdateHelper(opts);
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
|
|
6000
|
+
// src/commands/content.ts
|
|
6001
|
+
import * as fs8 from "fs";
|
|
6002
|
+
|
|
6003
|
+
// src/types/wp-rest.ts
|
|
6004
|
+
function wpRenderedText(value) {
|
|
6005
|
+
if (!value) return "";
|
|
6006
|
+
if (typeof value === "string") return value;
|
|
6007
|
+
return value.raw || value.rendered || "";
|
|
6008
|
+
}
|
|
6009
|
+
|
|
6010
|
+
// src/commands/content.ts
|
|
6011
|
+
function parseIdList(raw) {
|
|
6012
|
+
if (!raw?.trim()) return void 0;
|
|
6013
|
+
return raw.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
6014
|
+
}
|
|
6015
|
+
function printPost(item, restBase) {
|
|
6016
|
+
console.log(`
|
|
6017
|
+
\u2705 ${restBase} #${item.id}`);
|
|
6018
|
+
console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
|
|
6019
|
+
console.log(` \u72B6\u6001 : ${item.status || "-"}`);
|
|
6020
|
+
console.log(` slug : ${item.slug || "-"}`);
|
|
6021
|
+
if (item.link) console.log(` \u94FE\u63A5 : ${item.link}`);
|
|
6022
|
+
console.log();
|
|
6023
|
+
}
|
|
6024
|
+
async function runContentTypes(opts) {
|
|
6025
|
+
const target = await resolveTarget(opts);
|
|
6026
|
+
let types;
|
|
6027
|
+
try {
|
|
6028
|
+
types = await apiFetch2(
|
|
6029
|
+
wpV2(target.base, "/types?context=edit"),
|
|
6030
|
+
target.config,
|
|
6031
|
+
{},
|
|
6032
|
+
opts.verbose
|
|
6033
|
+
);
|
|
6034
|
+
} catch (e) {
|
|
6035
|
+
console.error(`
|
|
6036
|
+
\u274C \u83B7\u53D6\u5185\u5BB9\u7C7B\u578B\u5931\u8D25\uFF1A${e.message}
|
|
6037
|
+
`);
|
|
6038
|
+
process.exit(1);
|
|
6039
|
+
return;
|
|
6040
|
+
}
|
|
6041
|
+
const rows = Object.entries(types || {}).map(([slug, info]) => ({
|
|
6042
|
+
slug,
|
|
6043
|
+
rest_base: info.rest_base || slug,
|
|
6044
|
+
name: info.name || slug
|
|
6045
|
+
}));
|
|
6046
|
+
if (opts.json) {
|
|
6047
|
+
console.log(JSON.stringify({ site: target.site, types: rows }, null, 2));
|
|
6048
|
+
return;
|
|
6049
|
+
}
|
|
6050
|
+
console.log(`
|
|
6051
|
+
${target.site.name} \u53EF REST \u7BA1\u7406\u7684\u5185\u5BB9\u7C7B\u578B\uFF08${rows.length}\uFF09
|
|
6052
|
+
`);
|
|
6053
|
+
printCliTable(rows, [
|
|
6054
|
+
{ key: "slug", header: "slug" },
|
|
6055
|
+
{ key: "rest_base", header: "rest_base\uFF08--type\uFF09" },
|
|
6056
|
+
{ key: "name", header: "\u540D\u79F0" }
|
|
6057
|
+
]);
|
|
6058
|
+
console.log("\n\u9875\u9762\u6B63\u6587\u8BF7\u7528 pages add/update\uFF1B\u5176\u5B83\u7C7B\u578B\u7528 content add --type <rest_base>\n");
|
|
6059
|
+
}
|
|
6060
|
+
async function runContentList(opts) {
|
|
6061
|
+
const typeArg = opts.type?.trim() || "posts";
|
|
6062
|
+
const target = await resolveTarget(opts);
|
|
6063
|
+
let restBase;
|
|
6064
|
+
try {
|
|
6065
|
+
restBase = await resolveTypeRestBase(target, typeArg, opts.verbose);
|
|
6066
|
+
} catch (e) {
|
|
6067
|
+
console.error(`
|
|
6068
|
+
\u274C ${e.message}
|
|
6069
|
+
`);
|
|
6070
|
+
process.exit(1);
|
|
6071
|
+
return;
|
|
6072
|
+
}
|
|
6073
|
+
const status = opts.status?.trim() || "publish,draft,private,pending";
|
|
6074
|
+
const api = wpV2(target.base, `/${restBase}?per_page=100&status=${encodeURIComponent(status)}`);
|
|
6075
|
+
let items;
|
|
4073
6076
|
try {
|
|
4074
|
-
|
|
6077
|
+
items = await apiFetch2(api, target.config, {}, opts.verbose);
|
|
4075
6078
|
} catch (e) {
|
|
4076
6079
|
console.error(`
|
|
4077
|
-
\u274C \u83B7\u53D6\
|
|
4078
|
-
|
|
6080
|
+
\u274C \u83B7\u53D6 ${restBase} \u5931\u8D25\uFF1A${e.message}
|
|
6081
|
+
`);
|
|
4079
6082
|
process.exit(1);
|
|
4080
6083
|
return;
|
|
4081
6084
|
}
|
|
4082
|
-
|
|
6085
|
+
if (!Array.isArray(items)) {
|
|
6086
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
6087
|
+
process.exit(1);
|
|
6088
|
+
}
|
|
4083
6089
|
if (opts.json) {
|
|
4084
6090
|
console.log(
|
|
4085
6091
|
JSON.stringify(
|
|
4086
|
-
{
|
|
6092
|
+
{
|
|
6093
|
+
site: { guid: target.site.guid, name: target.site.name, url: target.site.url },
|
|
6094
|
+
type: restBase,
|
|
6095
|
+
total: items.length,
|
|
6096
|
+
items: items.map((p) => ({
|
|
6097
|
+
id: p.id,
|
|
6098
|
+
title: wpRenderedText(p.title),
|
|
6099
|
+
status: p.status ?? "",
|
|
6100
|
+
slug: p.slug ?? "",
|
|
6101
|
+
link: p.link ?? "",
|
|
6102
|
+
modified: p.modified ?? ""
|
|
6103
|
+
}))
|
|
6104
|
+
},
|
|
4087
6105
|
null,
|
|
4088
6106
|
2
|
|
4089
6107
|
)
|
|
@@ -4092,96 +6110,633 @@ async function runPluginsCatalog(opts) {
|
|
|
4092
6110
|
}
|
|
4093
6111
|
if (items.length === 0) {
|
|
4094
6112
|
console.log(`
|
|
4095
|
-
|
|
6113
|
+
${target.site.name} \u6CA1\u6709 ${restBase}\u3002
|
|
4096
6114
|
`);
|
|
4097
6115
|
return;
|
|
4098
6116
|
}
|
|
4099
6117
|
const columns = [
|
|
6118
|
+
{ key: "id", header: "id" },
|
|
6119
|
+
{ key: "title", header: "\u6807\u9898" },
|
|
6120
|
+
{ key: "status", header: "\u72B6\u6001" },
|
|
4100
6121
|
{ key: "slug", header: "slug" },
|
|
4101
|
-
{ key: "
|
|
4102
|
-
{ key: "new_version", header: "\u76EE\u5F55\u7248\u672C" },
|
|
4103
|
-
{ key: "installed", header: "\u5DF2\u88C5" },
|
|
4104
|
-
{ key: "active", header: "\u542F\u7528" }
|
|
6122
|
+
{ key: "link", header: "\u94FE\u63A5" }
|
|
4105
6123
|
];
|
|
4106
6124
|
console.log(`
|
|
4107
|
-
${site.name} \
|
|
6125
|
+
${target.site.name} ${restBase}\uFF08${items.length}\uFF09
|
|
4108
6126
|
`);
|
|
4109
6127
|
printCliTable(
|
|
4110
6128
|
items.map((p) => ({
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
6129
|
+
id: String(p.id),
|
|
6130
|
+
title: wpRenderedText(p.title) || "(\u65E0\u6807\u9898)",
|
|
6131
|
+
status: p.status ?? "-",
|
|
6132
|
+
slug: p.slug ?? "-",
|
|
6133
|
+
link: p.link ?? "-"
|
|
4116
6134
|
})),
|
|
4117
6135
|
columns
|
|
4118
6136
|
);
|
|
4119
|
-
console.log(
|
|
6137
|
+
console.log();
|
|
4120
6138
|
}
|
|
4121
|
-
async function
|
|
4122
|
-
const
|
|
4123
|
-
if (!
|
|
4124
|
-
console.error("\n\u274C \u8BF7\u63D0\u4F9B
|
|
6139
|
+
async function runContentGet(opts) {
|
|
6140
|
+
const id = Number(opts.id);
|
|
6141
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6142
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B\u6709\u6548 --id\n");
|
|
4125
6143
|
process.exit(1);
|
|
4126
6144
|
}
|
|
4127
|
-
const
|
|
4128
|
-
const
|
|
4129
|
-
|
|
6145
|
+
const target = await resolveTarget(opts);
|
|
6146
|
+
const restBase = await resolveTypeRestBase(target, opts.type?.trim() || "posts", opts.verbose);
|
|
6147
|
+
const item = await apiFetch2(
|
|
6148
|
+
wpV2(target.base, `/${restBase}/${id}?context=edit`),
|
|
6149
|
+
target.config,
|
|
6150
|
+
{},
|
|
6151
|
+
opts.verbose
|
|
6152
|
+
).catch((e) => {
|
|
6153
|
+
console.error(`
|
|
6154
|
+
\u274C \u83B7\u53D6\u5931\u8D25\uFF1A${e.message}
|
|
6155
|
+
`);
|
|
6156
|
+
process.exit(1);
|
|
6157
|
+
});
|
|
6158
|
+
if (opts.json) {
|
|
6159
|
+
console.log(JSON.stringify(item, null, 2));
|
|
6160
|
+
return;
|
|
6161
|
+
}
|
|
6162
|
+
console.log(`
|
|
6163
|
+
${restBase} #${item.id}`);
|
|
6164
|
+
console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
|
|
6165
|
+
console.log(` \u72B6\u6001 : ${item.status || "-"}`);
|
|
6166
|
+
console.log(` slug : ${item.slug || "-"}`);
|
|
6167
|
+
console.log(` \u94FE\u63A5 : ${item.link || "-"}`);
|
|
6168
|
+
if (item.featured_media) console.log(` \u7279\u8272\u56FE : ${item.featured_media}`);
|
|
6169
|
+
const excerpt = wpRenderedText(item.excerpt);
|
|
6170
|
+
if (excerpt) console.log(` \u6458\u8981 : ${excerpt.slice(0, 120)}`);
|
|
6171
|
+
console.log();
|
|
6172
|
+
}
|
|
6173
|
+
async function runContentWrite(mode, opts) {
|
|
6174
|
+
const typeArg = opts.type?.trim() || "posts";
|
|
6175
|
+
if (typeArg === "page" || typeArg === "pages") {
|
|
6176
|
+
console.error("\n\u274C \u9875\u9762\u6B63\u6587\u8BF7\u7528 pages add / pages update\uFF08Zion visual-edit\uFF09\u3002");
|
|
6177
|
+
console.error(" \u53EA\u6539 slug/\u72B6\u6001/\u56DE\u6536\u7AD9\u7528 pages meta / pages trash\u3002\n");
|
|
6178
|
+
process.exit(1);
|
|
6179
|
+
}
|
|
6180
|
+
const target = await resolveTarget(opts);
|
|
6181
|
+
const restBase = await resolveTypeRestBase(target, typeArg, opts.verbose);
|
|
6182
|
+
const content = opts.contentFile ? fs8.readFileSync(opts.contentFile, "utf8") : opts.content ?? "";
|
|
6183
|
+
if (mode === "add" && !opts.title?.trim() && !content.trim()) {
|
|
6184
|
+
console.error("\n\u274C \u65B0\u589E\u81F3\u5C11\u8981 --title \u6216 --content / --content-file\n");
|
|
6185
|
+
process.exit(1);
|
|
6186
|
+
}
|
|
6187
|
+
const body = {};
|
|
6188
|
+
if (opts.title?.trim()) body.title = opts.title.trim();
|
|
6189
|
+
if (content.trim()) body.content = content;
|
|
6190
|
+
if (opts.status?.trim()) body.status = opts.status.trim();
|
|
6191
|
+
if (opts.slug?.trim()) body.slug = opts.slug.trim();
|
|
6192
|
+
if (opts.excerpt?.trim()) body.excerpt = opts.excerpt.trim();
|
|
6193
|
+
const featured = Number(opts.featuredMedia);
|
|
6194
|
+
if (Number.isFinite(featured) && featured > 0) body.featured_media = featured;
|
|
6195
|
+
const cats = parseIdList(opts.categories);
|
|
6196
|
+
if (cats) body.categories = cats;
|
|
6197
|
+
const tags = parseIdList(opts.tags);
|
|
6198
|
+
if (tags) body.tags = tags;
|
|
6199
|
+
if (mode === "update") {
|
|
6200
|
+
const id = Number(opts.id);
|
|
6201
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6202
|
+
console.error("\n\u274C \u66F4\u65B0\u5FC5\u987B\u63D0\u4F9B --id\uFF08\u5148 content list\uFF09\n");
|
|
6203
|
+
process.exit(1);
|
|
6204
|
+
}
|
|
6205
|
+
if (Object.keys(body).length === 0) {
|
|
6206
|
+
console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\n");
|
|
6207
|
+
process.exit(1);
|
|
6208
|
+
}
|
|
6209
|
+
const item2 = await apiFetch2(
|
|
6210
|
+
wpV2(target.base, `/${restBase}/${id}`),
|
|
6211
|
+
target.config,
|
|
6212
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
6213
|
+
opts.verbose
|
|
6214
|
+
).catch((e) => {
|
|
6215
|
+
console.error(`
|
|
6216
|
+
\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${e.message}
|
|
6217
|
+
`);
|
|
6218
|
+
process.exit(1);
|
|
6219
|
+
});
|
|
6220
|
+
printPost(item2, restBase);
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
const item = await apiFetch2(
|
|
6224
|
+
wpV2(target.base, `/${restBase}`),
|
|
6225
|
+
target.config,
|
|
6226
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
6227
|
+
opts.verbose
|
|
6228
|
+
).catch((e) => {
|
|
6229
|
+
console.error(`
|
|
6230
|
+
\u274C \u65B0\u589E\u5931\u8D25\uFF1A${e.message}
|
|
6231
|
+
`);
|
|
6232
|
+
process.exit(1);
|
|
6233
|
+
});
|
|
6234
|
+
printPost(item, restBase);
|
|
6235
|
+
}
|
|
6236
|
+
async function runContentTrash(opts) {
|
|
6237
|
+
const id = Number(opts.id);
|
|
6238
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6239
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
6240
|
+
process.exit(1);
|
|
6241
|
+
}
|
|
6242
|
+
const target = await resolveTarget(opts);
|
|
6243
|
+
const restBase = await resolveTypeRestBase(target, opts.type?.trim() || "posts", opts.verbose);
|
|
6244
|
+
const qs = opts.force ? "?force=true" : "";
|
|
6245
|
+
const item = await apiFetch2(
|
|
6246
|
+
wpV2(target.base, `/${restBase}/${id}${qs}`),
|
|
6247
|
+
target.config,
|
|
6248
|
+
{ method: "DELETE" },
|
|
6249
|
+
opts.verbose
|
|
6250
|
+
).catch((e) => {
|
|
6251
|
+
console.error(`
|
|
6252
|
+
\u274C \u5220\u9664\u5931\u8D25\uFF1A${e.message}
|
|
6253
|
+
`);
|
|
6254
|
+
process.exit(1);
|
|
6255
|
+
});
|
|
6256
|
+
console.log(opts.force ? `
|
|
6257
|
+
\u2705 \u5DF2\u6C38\u4E45\u5220\u9664 ${restBase} #${id}
|
|
6258
|
+
` : `
|
|
6259
|
+
\u2705 \u5DF2\u79FB\u5165\u56DE\u6536\u7AD9 ${restBase} #${id}\uFF08status=${item.status || "trash"}\uFF09
|
|
6260
|
+
`);
|
|
6261
|
+
}
|
|
6262
|
+
function register13(program2) {
|
|
6263
|
+
const content = program2.command("content").description("\u901A\u7528\u5185\u5BB9\uFF1A\u6587\u7AE0/\u4EA7\u54C1\u7B49 REST \u7C7B\u578B\uFF08\u9875\u9762\u6B63\u6587\u8BF7\u7528 pages\uFF09");
|
|
6264
|
+
content.command("types").description("\u5217\u51FA\u7AD9\u70B9\u53EF REST \u7BA1\u7406\u7684\u5185\u5BB9\u7C7B\u578B").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6265
|
+
await runContentTypes(opts);
|
|
6266
|
+
});
|
|
6267
|
+
content.command("list").description("\u5217\u51FA\u67D0\u4E00\u7C7B\u578B\u7684\u5185\u5BB9").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--type <restBase>", "\u7C7B\u578B rest_base\uFF0C\u9ED8\u8BA4 posts", "posts").option("--status <status>", "\u72B6\u6001\uFF0C\u9017\u53F7\u5206\u9694", "publish,draft,private,pending").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6268
|
+
await runContentList(opts);
|
|
6269
|
+
});
|
|
6270
|
+
content.command("get").description("\u67E5\u770B\u5355\u6761\u5185\u5BB9").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--type <restBase>", "\u7C7B\u578B rest_base\uFF0C\u9ED8\u8BA4 posts", "posts").requiredOption("--id <id>", "\u5185\u5BB9 ID").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6271
|
+
await runContentGet(opts);
|
|
6272
|
+
});
|
|
6273
|
+
content.command("add").description("\u65B0\u589E\u6587\u7AE0\u6216\u5176\u5B83 CPT\uFF08\u4E0D\u8981\u7528\u6765\u52A0 Zion \u9875\u9762\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--type <restBase>", "\u7C7B\u578B rest_base\uFF0C\u9ED8\u8BA4 posts", "posts").option("-t, --title <title>", "\u6807\u9898").option("-c, --content <html>", "\u6B63\u6587 HTML").option("--content-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u6B63\u6587").option("--status <status>", "publish / draft / private", "draft").option("--slug <slug>", "\u522B\u540D").option("--excerpt <text>", "\u6458\u8981").option("--featured-media <id>", "\u7279\u8272\u56FE\u5A92\u4F53 ID").option("--categories <ids>", "\u5206\u7C7B ID\uFF0C\u9017\u53F7\u5206\u9694").option("--tags <ids>", "\u6807\u7B7E ID\uFF0C\u9017\u53F7\u5206\u9694").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6274
|
+
await runContentWrite("add", opts);
|
|
6275
|
+
});
|
|
6276
|
+
content.command("update").description("\u66F4\u65B0\u5DF2\u6709\u5185\u5BB9\u5B57\u6BB5").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--type <restBase>", "\u7C7B\u578B rest_base\uFF0C\u9ED8\u8BA4 posts", "posts").requiredOption("--id <id>", "\u5185\u5BB9 ID").option("-t, --title <title>", "\u6807\u9898").option("-c, --content <html>", "\u6B63\u6587 HTML").option("--content-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u6B63\u6587").option("--status <status>", "publish / draft / private / pending").option("--slug <slug>", "\u522B\u540D").option("--excerpt <text>", "\u6458\u8981").option("--featured-media <id>", "\u7279\u8272\u56FE\u5A92\u4F53 ID").option("--categories <ids>", "\u5206\u7C7B ID\uFF0C\u9017\u53F7\u5206\u9694").option("--tags <ids>", "\u6807\u7B7E ID\uFF0C\u9017\u53F7\u5206\u9694").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6277
|
+
await runContentWrite("update", opts);
|
|
6278
|
+
});
|
|
6279
|
+
content.command("trash").description("\u79FB\u5165\u56DE\u6536\u7AD9\uFF1B\u52A0 --force \u6C38\u4E45\u5220\u9664").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--type <restBase>", "\u7C7B\u578B rest_base\uFF0C\u9ED8\u8BA4 posts", "posts").requiredOption("--id <id>", "\u5185\u5BB9 ID").option("--force", "\u6C38\u4E45\u5220\u9664", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6280
|
+
await runContentTrash(opts);
|
|
6281
|
+
});
|
|
6282
|
+
}
|
|
6283
|
+
|
|
6284
|
+
// src/commands/media.ts
|
|
6285
|
+
import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
|
|
6286
|
+
import { basename as basename3, extname, resolve as resolve3 } from "path";
|
|
6287
|
+
var MIME_BY_EXT = {
|
|
6288
|
+
".jpg": "image/jpeg",
|
|
6289
|
+
".jpeg": "image/jpeg",
|
|
6290
|
+
".png": "image/png",
|
|
6291
|
+
".gif": "image/gif",
|
|
6292
|
+
".webp": "image/webp",
|
|
6293
|
+
".svg": "image/svg+xml",
|
|
6294
|
+
".pdf": "application/pdf",
|
|
6295
|
+
".mp4": "video/mp4",
|
|
6296
|
+
".zip": "application/zip"
|
|
6297
|
+
};
|
|
6298
|
+
var MAX_MEDIA_BYTES = 20 * 1024 * 1024;
|
|
6299
|
+
function guessMime(filename) {
|
|
6300
|
+
return MIME_BY_EXT[extname(filename).toLowerCase()] || "application/octet-stream";
|
|
6301
|
+
}
|
|
6302
|
+
async function runMediaList(opts) {
|
|
6303
|
+
const target = await resolveTarget(opts);
|
|
6304
|
+
let items;
|
|
4130
6305
|
try {
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
config,
|
|
4134
|
-
{
|
|
6306
|
+
items = await apiFetch2(
|
|
6307
|
+
wpV2(target.base, "/media?per_page=50"),
|
|
6308
|
+
target.config,
|
|
6309
|
+
{},
|
|
4135
6310
|
opts.verbose
|
|
4136
6311
|
);
|
|
4137
6312
|
} catch (e) {
|
|
4138
6313
|
console.error(`
|
|
4139
|
-
\u274C \
|
|
6314
|
+
\u274C \u83B7\u53D6\u5A92\u4F53\u5E93\u5931\u8D25\uFF1A${e.message}
|
|
4140
6315
|
`);
|
|
4141
6316
|
process.exit(1);
|
|
4142
6317
|
return;
|
|
4143
6318
|
}
|
|
4144
|
-
if (!
|
|
6319
|
+
if (!Array.isArray(items)) {
|
|
6320
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u5A92\u4F53\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
6321
|
+
process.exit(1);
|
|
6322
|
+
}
|
|
6323
|
+
if (opts.json) {
|
|
6324
|
+
console.log(
|
|
6325
|
+
JSON.stringify(
|
|
6326
|
+
{
|
|
6327
|
+
site: { guid: target.site.guid, name: target.site.name, url: target.site.url },
|
|
6328
|
+
total: items.length,
|
|
6329
|
+
items: items.map((m) => ({
|
|
6330
|
+
id: m.id,
|
|
6331
|
+
title: wpRenderedText(m.title),
|
|
6332
|
+
mime: m.mime_type ?? "",
|
|
6333
|
+
url: m.source_url ?? ""
|
|
6334
|
+
}))
|
|
6335
|
+
},
|
|
6336
|
+
null,
|
|
6337
|
+
2
|
|
6338
|
+
)
|
|
6339
|
+
);
|
|
6340
|
+
return;
|
|
6341
|
+
}
|
|
6342
|
+
if (items.length === 0) {
|
|
6343
|
+
console.log(`
|
|
6344
|
+
${target.site.name} \u5A92\u4F53\u5E93\u4E3A\u7A7A\u3002
|
|
6345
|
+
`);
|
|
6346
|
+
return;
|
|
6347
|
+
}
|
|
6348
|
+
console.log(`
|
|
6349
|
+
${target.site.name} \u5A92\u4F53\uFF08\u6700\u8FD1 ${items.length}\uFF09
|
|
6350
|
+
`);
|
|
6351
|
+
printCliTable(
|
|
6352
|
+
items.map((m) => ({
|
|
6353
|
+
id: String(m.id),
|
|
6354
|
+
title: wpRenderedText(m.title) || "-",
|
|
6355
|
+
mime: m.mime_type || "-",
|
|
6356
|
+
url: m.source_url || "-"
|
|
6357
|
+
})),
|
|
6358
|
+
[
|
|
6359
|
+
{ key: "id", header: "id" },
|
|
6360
|
+
{ key: "title", header: "\u6807\u9898" },
|
|
6361
|
+
{ key: "mime", header: "\u7C7B\u578B" },
|
|
6362
|
+
{ key: "url", header: "\u5730\u5740" }
|
|
6363
|
+
]
|
|
6364
|
+
);
|
|
6365
|
+
console.log();
|
|
6366
|
+
}
|
|
6367
|
+
async function runMediaGet(opts) {
|
|
6368
|
+
const id = Number(opts.id);
|
|
6369
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6370
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
6371
|
+
process.exit(1);
|
|
6372
|
+
}
|
|
6373
|
+
const target = await resolveTarget(opts);
|
|
6374
|
+
const item = await apiFetch2(
|
|
6375
|
+
wpV2(target.base, `/media/${id}`),
|
|
6376
|
+
target.config,
|
|
6377
|
+
{},
|
|
6378
|
+
opts.verbose
|
|
6379
|
+
).catch((e) => {
|
|
4145
6380
|
console.error(`
|
|
4146
|
-
\u274C
|
|
6381
|
+
\u274C \u83B7\u53D6\u5A92\u4F53\u5931\u8D25\uFF1A${e.message}
|
|
4147
6382
|
`);
|
|
4148
6383
|
process.exit(1);
|
|
6384
|
+
});
|
|
6385
|
+
if (opts.json) {
|
|
6386
|
+
console.log(JSON.stringify(item, null, 2));
|
|
6387
|
+
return;
|
|
6388
|
+
}
|
|
6389
|
+
console.log(`
|
|
6390
|
+
\u5A92\u4F53 #${item.id}`);
|
|
6391
|
+
console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
|
|
6392
|
+
console.log(` \u7C7B\u578B : ${item.mime_type || "-"}`);
|
|
6393
|
+
console.log(` \u5730\u5740 : ${item.source_url || "-"}`);
|
|
6394
|
+
if (item.alt_text) console.log(` alt : ${item.alt_text}`);
|
|
6395
|
+
console.log();
|
|
6396
|
+
}
|
|
6397
|
+
async function runMediaUpload(opts) {
|
|
6398
|
+
const filePath = opts.file?.trim() ?? "";
|
|
6399
|
+
if (!filePath) {
|
|
6400
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --file\n");
|
|
6401
|
+
process.exit(1);
|
|
4149
6402
|
}
|
|
4150
|
-
|
|
4151
|
-
if (
|
|
4152
|
-
|
|
4153
|
-
|
|
6403
|
+
const abs = resolve3(filePath);
|
|
6404
|
+
if (!existsSync4(abs)) {
|
|
6405
|
+
console.error(`
|
|
6406
|
+
\u274C \u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${abs}
|
|
4154
6407
|
`);
|
|
6408
|
+
process.exit(1);
|
|
6409
|
+
}
|
|
6410
|
+
const data = readFileSync9(abs);
|
|
6411
|
+
if (data.length > MAX_MEDIA_BYTES) {
|
|
6412
|
+
console.error("\n\u274C \u6587\u4EF6\u8D85\u8FC7 20MB\n");
|
|
6413
|
+
process.exit(1);
|
|
6414
|
+
}
|
|
6415
|
+
const filename = basename3(abs);
|
|
6416
|
+
const target = await resolveTarget(opts);
|
|
6417
|
+
const fields = {};
|
|
6418
|
+
if (opts.title?.trim()) fields.title = opts.title.trim();
|
|
6419
|
+
if (opts.alt?.trim()) fields.alt_text = opts.alt.trim();
|
|
6420
|
+
if (opts.caption?.trim()) fields.caption = opts.caption.trim();
|
|
6421
|
+
let item;
|
|
4155
6422
|
try {
|
|
4156
|
-
await
|
|
4157
|
-
|
|
6423
|
+
item = await apiFetchMultipart2(
|
|
6424
|
+
wpV2(target.base, "/media"),
|
|
6425
|
+
target.config,
|
|
6426
|
+
{
|
|
6427
|
+
fields,
|
|
6428
|
+
files: [
|
|
6429
|
+
{
|
|
6430
|
+
field: "file",
|
|
6431
|
+
filename,
|
|
6432
|
+
contentType: guessMime(filename),
|
|
6433
|
+
data
|
|
6434
|
+
}
|
|
6435
|
+
]
|
|
6436
|
+
},
|
|
6437
|
+
opts.verbose
|
|
6438
|
+
);
|
|
6439
|
+
} catch (e) {
|
|
6440
|
+
console.error(`
|
|
6441
|
+
\u274C \u4E0A\u4F20\u5931\u8D25\uFF1A${e.message}
|
|
6442
|
+
`);
|
|
6443
|
+
process.exit(1);
|
|
6444
|
+
return;
|
|
4158
6445
|
}
|
|
6446
|
+
console.log(`
|
|
6447
|
+
\u2705 \u5DF2\u4E0A\u4F20\u5A92\u4F53 #${item.id}`);
|
|
6448
|
+
console.log(` \u5730\u5740 : ${item.source_url || "-"}`);
|
|
6449
|
+
console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || filename}`);
|
|
6450
|
+
console.log();
|
|
4159
6451
|
}
|
|
4160
|
-
function
|
|
4161
|
-
const
|
|
4162
|
-
|
|
4163
|
-
await
|
|
6452
|
+
function register14(program2) {
|
|
6453
|
+
const media = program2.command("media").description("\u5A92\u4F53\u5E93\uFF1A\u5217\u51FA\u3001\u67E5\u770B\u3001\u4E0A\u4F20");
|
|
6454
|
+
media.command("list").description("\u5217\u51FA\u5A92\u4F53\u5E93\uFF08\u6700\u8FD1 50 \u6761\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6455
|
+
await runMediaList(opts);
|
|
4164
6456
|
});
|
|
4165
|
-
|
|
4166
|
-
await
|
|
6457
|
+
media.command("get").description("\u67E5\u770B\u5355\u4E2A\u5A92\u4F53").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--id <id>", "\u5A92\u4F53 ID").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6458
|
+
await runMediaGet(opts);
|
|
4167
6459
|
});
|
|
4168
|
-
|
|
4169
|
-
await
|
|
6460
|
+
media.command("upload").description("\u4E0A\u4F20\u672C\u5730\u6587\u4EF6\u5230\u5A92\u4F53\u5E93\uFF08\u5199\u64CD\u4F5C\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("--file <path>", "\u672C\u5730\u6587\u4EF6\u8DEF\u5F84").option("-t, --title <title>", "\u5A92\u4F53\u6807\u9898").option("--alt <text>", "\u56FE\u7247 alt").option("--caption <text>", "\u8BF4\u660E").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6461
|
+
await runMediaUpload(opts);
|
|
6462
|
+
});
|
|
6463
|
+
}
|
|
6464
|
+
|
|
6465
|
+
// src/commands/terms.ts
|
|
6466
|
+
async function runTermsTaxonomies(opts) {
|
|
6467
|
+
const target = await resolveTarget(opts);
|
|
6468
|
+
let taxes;
|
|
6469
|
+
try {
|
|
6470
|
+
taxes = await apiFetch2(
|
|
6471
|
+
wpV2(target.base, "/taxonomies?context=edit"),
|
|
6472
|
+
target.config,
|
|
6473
|
+
{},
|
|
6474
|
+
opts.verbose
|
|
6475
|
+
);
|
|
6476
|
+
} catch (e) {
|
|
6477
|
+
console.error(`
|
|
6478
|
+
\u274C \u83B7\u53D6\u5206\u7C7B\u6CD5\u5931\u8D25\uFF1A${e.message}
|
|
6479
|
+
`);
|
|
6480
|
+
process.exit(1);
|
|
6481
|
+
return;
|
|
6482
|
+
}
|
|
6483
|
+
const rows = Object.entries(taxes || {}).map(([slug, info]) => ({
|
|
6484
|
+
slug,
|
|
6485
|
+
rest_base: info.rest_base || slug,
|
|
6486
|
+
name: info.name || slug
|
|
6487
|
+
}));
|
|
6488
|
+
if (opts.json) {
|
|
6489
|
+
console.log(JSON.stringify({ site: target.site, taxonomies: rows }, null, 2));
|
|
6490
|
+
return;
|
|
6491
|
+
}
|
|
6492
|
+
console.log(`
|
|
6493
|
+
${target.site.name} \u5206\u7C7B\u6CD5\uFF08${rows.length}\uFF09
|
|
6494
|
+
`);
|
|
6495
|
+
printCliTable(rows, [
|
|
6496
|
+
{ key: "slug", header: "slug" },
|
|
6497
|
+
{ key: "rest_base", header: "--taxonomy" },
|
|
6498
|
+
{ key: "name", header: "\u540D\u79F0" }
|
|
6499
|
+
]);
|
|
6500
|
+
console.log();
|
|
6501
|
+
}
|
|
6502
|
+
async function runTermsList(opts) {
|
|
6503
|
+
const target = await resolveTarget(opts);
|
|
6504
|
+
const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
|
|
6505
|
+
let items;
|
|
6506
|
+
try {
|
|
6507
|
+
items = await apiFetch2(
|
|
6508
|
+
wpV2(target.base, `/${restBase}?per_page=100`),
|
|
6509
|
+
target.config,
|
|
6510
|
+
{},
|
|
6511
|
+
opts.verbose
|
|
6512
|
+
);
|
|
6513
|
+
} catch (e) {
|
|
6514
|
+
console.error(`
|
|
6515
|
+
\u274C \u83B7\u53D6 ${restBase} \u5931\u8D25\uFF1A${e.message}
|
|
6516
|
+
`);
|
|
6517
|
+
process.exit(1);
|
|
6518
|
+
return;
|
|
6519
|
+
}
|
|
6520
|
+
if (!Array.isArray(items)) {
|
|
6521
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u672F\u8BED\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
|
|
6522
|
+
process.exit(1);
|
|
6523
|
+
}
|
|
6524
|
+
if (opts.json) {
|
|
6525
|
+
console.log(JSON.stringify({ taxonomy: restBase, total: items.length, items }, null, 2));
|
|
6526
|
+
return;
|
|
6527
|
+
}
|
|
6528
|
+
if (items.length === 0) {
|
|
6529
|
+
console.log(`
|
|
6530
|
+
\u6CA1\u6709 ${restBase}\u3002
|
|
6531
|
+
`);
|
|
6532
|
+
return;
|
|
6533
|
+
}
|
|
6534
|
+
console.log(`
|
|
6535
|
+
${target.site.name} ${restBase}\uFF08${items.length}\uFF09
|
|
6536
|
+
`);
|
|
6537
|
+
printCliTable(
|
|
6538
|
+
items.map((t) => ({
|
|
6539
|
+
id: String(t.id),
|
|
6540
|
+
name: t.name || "-",
|
|
6541
|
+
slug: t.slug || "-",
|
|
6542
|
+
count: String(t.count ?? 0)
|
|
6543
|
+
})),
|
|
6544
|
+
[
|
|
6545
|
+
{ key: "id", header: "id" },
|
|
6546
|
+
{ key: "name", header: "\u540D\u79F0" },
|
|
6547
|
+
{ key: "slug", header: "slug" },
|
|
6548
|
+
{ key: "count", header: "\u6570\u91CF" }
|
|
6549
|
+
]
|
|
6550
|
+
);
|
|
6551
|
+
console.log();
|
|
6552
|
+
}
|
|
6553
|
+
async function runTermsAdd(opts) {
|
|
6554
|
+
const name = opts.name?.trim() ?? "";
|
|
6555
|
+
if (!name) {
|
|
6556
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --name\n");
|
|
6557
|
+
process.exit(1);
|
|
6558
|
+
}
|
|
6559
|
+
const target = await resolveTarget(opts);
|
|
6560
|
+
const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
|
|
6561
|
+
const body = { name };
|
|
6562
|
+
if (opts.slug?.trim()) body.slug = opts.slug.trim();
|
|
6563
|
+
const parent = Number(opts.parent);
|
|
6564
|
+
if (Number.isFinite(parent) && parent > 0) body.parent = parent;
|
|
6565
|
+
const item = await apiFetch2(
|
|
6566
|
+
wpV2(target.base, `/${restBase}`),
|
|
6567
|
+
target.config,
|
|
6568
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
6569
|
+
opts.verbose
|
|
6570
|
+
).catch((e) => {
|
|
6571
|
+
console.error(`
|
|
6572
|
+
\u274C \u65B0\u589E\u5931\u8D25\uFF1A${e.message}
|
|
6573
|
+
`);
|
|
6574
|
+
process.exit(1);
|
|
6575
|
+
});
|
|
6576
|
+
console.log(`
|
|
6577
|
+
\u2705 \u5DF2\u65B0\u589E ${restBase} #${item.id} ${item.name || name}
|
|
6578
|
+
`);
|
|
6579
|
+
}
|
|
6580
|
+
async function runTermsUpdate(opts) {
|
|
6581
|
+
const id = Number(opts.id);
|
|
6582
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6583
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
6584
|
+
process.exit(1);
|
|
6585
|
+
}
|
|
6586
|
+
const body = {};
|
|
6587
|
+
if (opts.name?.trim()) body.name = opts.name.trim();
|
|
6588
|
+
if (opts.slug?.trim()) body.slug = opts.slug.trim();
|
|
6589
|
+
if (Object.keys(body).length === 0) {
|
|
6590
|
+
console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\n");
|
|
6591
|
+
process.exit(1);
|
|
6592
|
+
}
|
|
6593
|
+
const target = await resolveTarget(opts);
|
|
6594
|
+
const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
|
|
6595
|
+
const item = await apiFetch2(
|
|
6596
|
+
wpV2(target.base, `/${restBase}/${id}`),
|
|
6597
|
+
target.config,
|
|
6598
|
+
{ method: "POST", body: JSON.stringify(body) },
|
|
6599
|
+
opts.verbose
|
|
6600
|
+
).catch((e) => {
|
|
6601
|
+
console.error(`
|
|
6602
|
+
\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${e.message}
|
|
6603
|
+
`);
|
|
6604
|
+
process.exit(1);
|
|
6605
|
+
});
|
|
6606
|
+
console.log(`
|
|
6607
|
+
\u2705 \u5DF2\u66F4\u65B0 ${restBase} #${item.id} ${item.name || ""}
|
|
6608
|
+
`);
|
|
6609
|
+
}
|
|
6610
|
+
async function runTermsDelete(opts) {
|
|
6611
|
+
const id = Number(opts.id);
|
|
6612
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
6613
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
|
|
6614
|
+
process.exit(1);
|
|
6615
|
+
}
|
|
6616
|
+
const target = await resolveTarget(opts);
|
|
6617
|
+
const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
|
|
6618
|
+
await apiFetch2(
|
|
6619
|
+
wpV2(target.base, `/${restBase}/${id}?force=true`),
|
|
6620
|
+
target.config,
|
|
6621
|
+
{ method: "DELETE" },
|
|
6622
|
+
opts.verbose
|
|
6623
|
+
).catch((e) => {
|
|
6624
|
+
console.error(`
|
|
6625
|
+
\u274C \u5220\u9664\u5931\u8D25\uFF1A${e.message}
|
|
6626
|
+
`);
|
|
6627
|
+
process.exit(1);
|
|
6628
|
+
});
|
|
6629
|
+
console.log(`
|
|
6630
|
+
\u2705 \u5DF2\u5220\u9664 ${restBase} #${id}
|
|
6631
|
+
`);
|
|
6632
|
+
}
|
|
6633
|
+
function register15(program2) {
|
|
6634
|
+
const terms = program2.command("terms").description("\u5206\u7C7B / \u6807\u7B7E / \u81EA\u5B9A\u4E49\u5206\u7C7B\u6CD5");
|
|
6635
|
+
terms.command("taxonomies").description("\u5217\u51FA\u5206\u7C7B\u6CD5").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6636
|
+
await runTermsTaxonomies(opts);
|
|
6637
|
+
});
|
|
6638
|
+
terms.command("list").description("\u5217\u51FA\u67D0\u5206\u7C7B\u6CD5\u4E0B\u7684\u672F\u8BED").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--taxonomy <slug>", "category / post_tag / \u5176\u5B83 rest_base", "category").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6639
|
+
await runTermsList(opts);
|
|
6640
|
+
});
|
|
6641
|
+
terms.command("add").description("\u65B0\u589E\u672F\u8BED\uFF08\u5199\u64CD\u4F5C\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--taxonomy <slug>", "\u9ED8\u8BA4 category", "category").requiredOption("-n, --name <name>", "\u540D\u79F0").option("--slug <slug>", "\u522B\u540D").option("--parent <id>", "\u7236\u7EA7 ID").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6642
|
+
await runTermsAdd(opts);
|
|
6643
|
+
});
|
|
6644
|
+
terms.command("update").description("\u66F4\u65B0\u672F\u8BED\uFF08\u5199\u64CD\u4F5C\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--taxonomy <slug>", "\u9ED8\u8BA4 category", "category").requiredOption("--id <id>", "\u672F\u8BED ID").option("-n, --name <name>", "\u540D\u79F0").option("--slug <slug>", "\u522B\u540D").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6645
|
+
await runTermsUpdate(opts);
|
|
6646
|
+
});
|
|
6647
|
+
terms.command("delete").description("\u5220\u9664\u672F\u8BED\uFF08\u5199\u64CD\u4F5C\uFF0C\u4E0D\u53EF\u8FDB\u56DE\u6536\u7AD9\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--taxonomy <slug>", "\u9ED8\u8BA4 category", "category").requiredOption("--id <id>", "\u672F\u8BED ID").option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6648
|
+
await runTermsDelete(opts);
|
|
6649
|
+
});
|
|
6650
|
+
}
|
|
6651
|
+
|
|
6652
|
+
// src/commands/search.ts
|
|
6653
|
+
async function runSearch(opts) {
|
|
6654
|
+
const q = opts.q?.trim() ?? "";
|
|
6655
|
+
if (!q) {
|
|
6656
|
+
console.error("\n\u274C \u8BF7\u63D0\u4F9B --q\n");
|
|
6657
|
+
process.exit(1);
|
|
6658
|
+
}
|
|
6659
|
+
const target = await resolveTarget(opts);
|
|
6660
|
+
const params = new URLSearchParams({
|
|
6661
|
+
search: q,
|
|
6662
|
+
per_page: "20"
|
|
6663
|
+
});
|
|
6664
|
+
if (opts.type?.trim()) params.set("subtype", opts.type.trim());
|
|
6665
|
+
let hits;
|
|
6666
|
+
try {
|
|
6667
|
+
hits = await apiFetch2(
|
|
6668
|
+
wpV2(target.base, `/search?${params.toString()}`),
|
|
6669
|
+
target.config,
|
|
6670
|
+
{},
|
|
6671
|
+
opts.verbose
|
|
6672
|
+
);
|
|
6673
|
+
} catch (e) {
|
|
6674
|
+
console.error(`
|
|
6675
|
+
\u274C \u641C\u7D22\u5931\u8D25\uFF1A${e.message}
|
|
6676
|
+
`);
|
|
6677
|
+
process.exit(1);
|
|
6678
|
+
return;
|
|
6679
|
+
}
|
|
6680
|
+
if (!Array.isArray(hits)) {
|
|
6681
|
+
console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u641C\u7D22\u7ED3\u679C\u683C\u5F0F\u5F02\u5E38\n");
|
|
6682
|
+
process.exit(1);
|
|
6683
|
+
}
|
|
6684
|
+
if (opts.json) {
|
|
6685
|
+
console.log(JSON.stringify({ q, total: hits.length, hits }, null, 2));
|
|
6686
|
+
return;
|
|
6687
|
+
}
|
|
6688
|
+
if (hits.length === 0) {
|
|
6689
|
+
console.log(`
|
|
6690
|
+
\u6CA1\u6709\u5339\u914D\u300C${q}\u300D\u7684\u7ED3\u679C\u3002
|
|
6691
|
+
`);
|
|
6692
|
+
return;
|
|
6693
|
+
}
|
|
6694
|
+
console.log(`
|
|
6695
|
+
${target.site.name} \u641C\u7D22\u300C${q}\u300D\uFF08${hits.length}\uFF09
|
|
6696
|
+
`);
|
|
6697
|
+
printCliTable(
|
|
6698
|
+
hits.map((h) => ({
|
|
6699
|
+
id: h.id != null ? String(h.id) : "-",
|
|
6700
|
+
title: h.title || "-",
|
|
6701
|
+
type: [h.type, h.subtype].filter(Boolean).join("/") || "-",
|
|
6702
|
+
url: h.url || "-"
|
|
6703
|
+
})),
|
|
6704
|
+
[
|
|
6705
|
+
{ key: "id", header: "id" },
|
|
6706
|
+
{ key: "title", header: "\u6807\u9898" },
|
|
6707
|
+
{ key: "type", header: "\u7C7B\u578B" },
|
|
6708
|
+
{ key: "url", header: "\u94FE\u63A5" }
|
|
6709
|
+
]
|
|
6710
|
+
);
|
|
6711
|
+
console.log();
|
|
6712
|
+
}
|
|
6713
|
+
function register16(program2) {
|
|
6714
|
+
program2.command("search").description("\u5168\u7AD9\u641C\u7D22\uFF08\u9875\u9762/\u6587\u7AE0/\u5A92\u4F53\u7B49\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("-q, --q <keyword>", "\u5173\u952E\u8BCD").option("--type <subtype>", "\u9650\u5B9A rest \u5B50\u7C7B\u578B\uFF0C\u5982 page / post").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
|
|
6715
|
+
await runSearch(opts);
|
|
4170
6716
|
});
|
|
4171
6717
|
}
|
|
4172
6718
|
|
|
4173
6719
|
// src/index.ts
|
|
4174
6720
|
installProcessHandlers();
|
|
4175
6721
|
var program = new Command();
|
|
4176
|
-
program.name("siluzan-website").description("Siluzan WordPress
|
|
6722
|
+
program.name("siluzan-website").description("Siluzan WordPress\uFF1A\u5F00\u901A\u5EFA\u7AD9\u3001\u7AD9\u70B9\u3001\u9875\u9762\u3001\u6587\u7AE0\u3001\u5A92\u4F53\u3001\u5206\u7C7B\u3001\u63D2\u4EF6\u3001AI \u63A8\u8350").version(getCurrentVersion2());
|
|
4177
6723
|
var REGISTRARS = [
|
|
4178
6724
|
register,
|
|
4179
6725
|
register2,
|
|
4180
6726
|
register3,
|
|
4181
6727
|
register4,
|
|
4182
|
-
register5,
|
|
4183
6728
|
register6,
|
|
4184
|
-
register7
|
|
6729
|
+
register7,
|
|
6730
|
+
register8,
|
|
6731
|
+
register9,
|
|
6732
|
+
register5,
|
|
6733
|
+
register10,
|
|
6734
|
+
register13,
|
|
6735
|
+
register14,
|
|
6736
|
+
register15,
|
|
6737
|
+
register16,
|
|
6738
|
+
register12,
|
|
6739
|
+
register11
|
|
4185
6740
|
];
|
|
4186
6741
|
for (const reg of REGISTRARS) reg(program);
|
|
4187
6742
|
program.parse();
|