siluzan-website-cli 1.0.1-beta.2 → 1.0.1-beta.3

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/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) req.write(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
- const text = res.text;
2579
- if (res.status < 200 || res.status >= 300) {
2580
- throw new Error(formatHttpError(res.status, text, { verbose }));
2581
- }
2582
- if (!text.trim()) return null;
2583
- try {
2584
- return parseJsonWithStringIds(text);
2585
- } catch {
2586
- if (verbose) {
2587
- console.error(` \u26A0\uFE0F \u54CD\u5E94\u975E JSON\uFF0C\u539F\u59CB\u5185\u5BB9\uFF1A${redactSensitive(text).slice(0, 200)}`);
2588
- }
2589
- return text;
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 {
@@ -3691,6 +3750,9 @@ function loadConfig() {
3691
3750
  function apiFetch2(url, config, options = {}, verbose = false) {
3692
3751
  return apiFetch(url, config, options, verbose);
3693
3752
  }
3753
+ function apiFetchMultipart2(url, config, payload, verbose = false) {
3754
+ return apiFetchMultipart(url, config, payload, verbose);
3755
+ }
3694
3756
 
3695
3757
  // src/utils/site-url.ts
3696
3758
  function normalizeRegion(raw) {
@@ -3842,6 +3904,57 @@ function register5(program2) {
3842
3904
 
3843
3905
  // src/commands/pages.ts
3844
3906
  import * as fs6 from "fs";
3907
+
3908
+ // src/utils/wp-site.ts
3909
+ async function resolveTarget(opts) {
3910
+ const config = loadConfig();
3911
+ const site = await resolveSite(config, opts);
3912
+ return { config, site, base: trimTrailingSlash(site.url) };
3913
+ }
3914
+ function wpV2(base, path6) {
3915
+ const suffix = path6.startsWith("/") ? path6 : `/${path6}`;
3916
+ return `${base}/wp-json/wp/v2${suffix}`;
3917
+ }
3918
+ async function resolveTypeRestBase(target, typeArg, verbose = false) {
3919
+ const needle = typeArg.trim().toLowerCase();
3920
+ if (!needle) {
3921
+ throw new Error("\u8BF7\u63D0\u4F9B --type\uFF08\u5148 content types \u770B rest_base\uFF09");
3922
+ }
3923
+ const types = await apiFetch2(
3924
+ wpV2(target.base, "/types?context=edit"),
3925
+ target.config,
3926
+ {},
3927
+ verbose
3928
+ );
3929
+ for (const [slug, info] of Object.entries(types || {})) {
3930
+ const restBase = (info.rest_base || slug).toLowerCase();
3931
+ if (slug.toLowerCase() === needle || restBase === needle) {
3932
+ return info.rest_base || slug;
3933
+ }
3934
+ }
3935
+ return typeArg.trim();
3936
+ }
3937
+ async function resolveTaxonomyRestBase(target, taxonomyArg, verbose = false) {
3938
+ const needle = taxonomyArg.trim().toLowerCase();
3939
+ if (!needle) {
3940
+ throw new Error("\u8BF7\u63D0\u4F9B --taxonomy\uFF08\u5982 category\u3001post_tag\uFF09");
3941
+ }
3942
+ const taxes = await apiFetch2(
3943
+ wpV2(target.base, "/taxonomies?context=edit"),
3944
+ target.config,
3945
+ {},
3946
+ verbose
3947
+ );
3948
+ for (const [slug, info] of Object.entries(taxes || {})) {
3949
+ const restBase = (info.rest_base || slug).toLowerCase();
3950
+ if (slug.toLowerCase() === needle || restBase === needle) {
3951
+ return info.rest_base || slug;
3952
+ }
3953
+ }
3954
+ return taxonomyArg.trim();
3955
+ }
3956
+
3957
+ // src/commands/pages.ts
3845
3958
  function pageTitle(page) {
3846
3959
  if (typeof page.title === "string") return page.title;
3847
3960
  return page.title?.rendered ?? "";
@@ -3909,6 +4022,7 @@ async function runPagesList(opts) {
3909
4022
  { key: "id", header: "id" },
3910
4023
  { key: "title", header: "\u6807\u9898" },
3911
4024
  { key: "status", header: "\u72B6\u6001" },
4025
+ { key: "slug", header: "slug" },
3912
4026
  { key: "link", header: "\u94FE\u63A5" }
3913
4027
  ];
3914
4028
  console.log(`
@@ -3919,6 +4033,7 @@ ${site.name} \u9875\u9762\uFF08${pages.length}\uFF09
3919
4033
  id: String(p.id),
3920
4034
  title: pageTitle(p) || "(\u65E0\u6807\u9898)",
3921
4035
  status: p.status ?? "-",
4036
+ slug: p.slug ?? "-",
3922
4037
  link: p.link ?? "-"
3923
4038
  })),
3924
4039
  columns
@@ -3981,6 +4096,103 @@ async function runPagesWrite(mode, opts) {
3981
4096
  console.log(` \u7AD9\u70B9 : ${base}
3982
4097
  `);
3983
4098
  }
4099
+ async function runPagesGet(opts) {
4100
+ const id = Number(opts.id);
4101
+ if (!Number.isFinite(id) || id <= 0) {
4102
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
4103
+ process.exit(1);
4104
+ }
4105
+ const target = await resolveTarget(opts);
4106
+ const page = await apiFetch2(
4107
+ wpV2(target.base, `/pages/${id}?context=edit`),
4108
+ target.config,
4109
+ {},
4110
+ opts.verbose
4111
+ ).catch((e) => {
4112
+ console.error(`
4113
+ \u274C \u83B7\u53D6\u9875\u9762\u5931\u8D25\uFF1A${e.message}
4114
+ `);
4115
+ process.exit(1);
4116
+ });
4117
+ if (opts.json) {
4118
+ console.log(JSON.stringify(page, null, 2));
4119
+ return;
4120
+ }
4121
+ console.log(`
4122
+ \u9875\u9762 #${page.id}`);
4123
+ console.log(` \u6807\u9898 : ${pageTitle(page) || "-"}`);
4124
+ console.log(` \u72B6\u6001 : ${page.status || "-"}`);
4125
+ console.log(` slug : ${page.slug || "-"}`);
4126
+ console.log(` \u94FE\u63A5 : ${page.link || "-"}`);
4127
+ if (page.parent) console.log(` \u7236\u9875 : ${page.parent}`);
4128
+ if (page.featured_media) console.log(` \u7279\u8272\u56FE : ${page.featured_media}`);
4129
+ console.log();
4130
+ }
4131
+ async function runPagesMeta(opts) {
4132
+ const id = Number(opts.id);
4133
+ if (!Number.isFinite(id) || id <= 0) {
4134
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
4135
+ process.exit(1);
4136
+ }
4137
+ const body = {};
4138
+ if (opts.title?.trim()) body.title = opts.title.trim();
4139
+ if (opts.slug?.trim()) body.slug = opts.slug.trim();
4140
+ if (opts.status?.trim()) body.status = opts.status.trim();
4141
+ const parent = Number(opts.parent);
4142
+ if (opts.parent !== void 0 && Number.isFinite(parent)) body.parent = parent;
4143
+ const featured = Number(opts.featuredMedia);
4144
+ if (Number.isFinite(featured) && featured > 0) body.featured_media = featured;
4145
+ if (Object.keys(body).length === 0) {
4146
+ console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\u3002\u6B63\u6587\u8BF7\u7528 pages update\u3002\n");
4147
+ process.exit(1);
4148
+ }
4149
+ const target = await resolveTarget(opts);
4150
+ const page = await apiFetch2(
4151
+ wpV2(target.base, `/pages/${id}`),
4152
+ target.config,
4153
+ { method: "POST", body: JSON.stringify(body) },
4154
+ opts.verbose
4155
+ ).catch((e) => {
4156
+ console.error(`
4157
+ \u274C \u66F4\u65B0\u9875\u9762\u5143\u6570\u636E\u5931\u8D25\uFF1A${e.message}
4158
+ `);
4159
+ process.exit(1);
4160
+ });
4161
+ console.log(`
4162
+ \u2705 \u9875\u9762 #${page.id} \u5143\u6570\u636E\u5DF2\u66F4\u65B0`);
4163
+ console.log(` \u6807\u9898 : ${pageTitle(page) || "-"}`);
4164
+ console.log(` \u72B6\u6001 : ${page.status || "-"}`);
4165
+ console.log(` slug : ${page.slug || "-"}`);
4166
+ if (page.link) console.log(` \u94FE\u63A5 : ${page.link}`);
4167
+ console.log();
4168
+ }
4169
+ async function runPagesTrash(opts) {
4170
+ const id = Number(opts.id);
4171
+ if (!Number.isFinite(id) || id <= 0) {
4172
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
4173
+ process.exit(1);
4174
+ }
4175
+ const target = await resolveTarget(opts);
4176
+ const qs = opts.force ? "?force=true" : "";
4177
+ const page = await apiFetch2(
4178
+ wpV2(target.base, `/pages/${id}${qs}`),
4179
+ target.config,
4180
+ { method: "DELETE" },
4181
+ opts.verbose
4182
+ ).catch((e) => {
4183
+ console.error(`
4184
+ \u274C \u5220\u9664\u9875\u9762\u5931\u8D25\uFF1A${e.message}
4185
+ `);
4186
+ process.exit(1);
4187
+ });
4188
+ console.log(
4189
+ opts.force ? `
4190
+ \u2705 \u5DF2\u6C38\u4E45\u5220\u9664\u9875\u9762 #${id}
4191
+ ` : `
4192
+ \u2705 \u9875\u9762 #${id} \u5DF2\u8FDB\u56DE\u6536\u7AD9\uFF08status=${page.status || "trash"}\uFF09
4193
+ `
4194
+ );
4195
+ }
3984
4196
  function register6(program2) {
3985
4197
  const pages = program2.command("pages").description("WordPress \u9875\u9762\uFF08zionbuilder visual-edit\uFF09");
3986
4198
  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) => {
@@ -3992,12 +4204,29 @@ function register6(program2) {
3992
4204
  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) => {
3993
4205
  await runPagesWrite("update", opts);
3994
4206
  });
4207
+ 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) => {
4208
+ await runPagesGet(opts);
4209
+ });
4210
+ 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) => {
4211
+ await runPagesMeta(opts);
4212
+ });
4213
+ 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) => {
4214
+ await runPagesTrash(opts);
4215
+ });
3995
4216
  }
3996
4217
 
3997
4218
  // src/commands/plugins.ts
3998
4219
  import { readFileSync as readFileSync6, existsSync as existsSync3 } from "fs";
3999
4220
  import { basename as basename2, resolve as resolve2 } from "path";
4000
4221
  var MAX_ZIP_BYTES = 20 * 1024 * 1024;
4222
+ var PROTECTED_PLUGIN_PREFIXES = ["siluzan-helper-plugin", "wp-oauth2"];
4223
+ function isProtectedPlugin(plugin) {
4224
+ const key = pluginKey(plugin);
4225
+ return PROTECTED_PLUGIN_PREFIXES.some((prefix) => key === prefix || key.startsWith(`${prefix}/`));
4226
+ }
4227
+ function wpPluginRestPath(plugin) {
4228
+ return plugin.replace(/\\/g, "/").split("/").filter(Boolean).map((part) => encodeURIComponent(part)).join("/");
4229
+ }
4001
4230
  function pluginName(item) {
4002
4231
  if (typeof item.name === "string") return item.name;
4003
4232
  return item.name?.raw || item.name?.rendered || item.plugin || "";
@@ -4005,7 +4234,7 @@ function pluginName(item) {
4005
4234
  function pluginKey(value) {
4006
4235
  return value.replace(/\\/g, "/").replace(/\.php$/i, "").toLowerCase();
4007
4236
  }
4008
- async function resolveTarget(opts) {
4237
+ async function resolveTarget2(opts) {
4009
4238
  const config = loadConfig();
4010
4239
  const site = await resolveSite(config, opts);
4011
4240
  return { config, site, base: trimTrailingSlash(site.url) };
@@ -4060,7 +4289,7 @@ async function withHelperBootstrap(opts, target, run) {
4060
4289
  }
4061
4290
  }
4062
4291
  async function runPluginsList(opts) {
4063
- const { config, site, base } = await resolveTarget(opts);
4292
+ const { config, site, base } = await resolveTarget2(opts);
4064
4293
  const api = `${base}/wp-json/wp/v2/plugins`;
4065
4294
  let plugins;
4066
4295
  try {
@@ -4156,7 +4385,7 @@ ${site.name} \u5DF2\u88C5\u63D2\u4EF6\uFF08${rows.length}\uFF09
4156
4385
  console.log();
4157
4386
  }
4158
4387
  async function runPluginsCatalog(opts) {
4159
- const target = await resolveTarget(opts);
4388
+ const target = await resolveTarget2(opts);
4160
4389
  const { site, base } = target;
4161
4390
  let res;
4162
4391
  try {
@@ -4225,7 +4454,7 @@ async function runPluginsInstall(opts) {
4225
4454
  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");
4226
4455
  process.exit(1);
4227
4456
  }
4228
- const target = await resolveTarget(opts);
4457
+ const target = await resolveTarget2(opts);
4229
4458
  const { site, base } = target;
4230
4459
  let result;
4231
4460
  try {
@@ -4267,7 +4496,7 @@ async function runPluginsUpdate(opts) {
4267
4496
  console.error("\n\u274C \u8BF7\u63D0\u4F9B --plugin\uFF08\u5148 plugins list \u770B plugin \u5217\uFF09\n");
4268
4497
  process.exit(1);
4269
4498
  }
4270
- const target = await resolveTarget(opts);
4499
+ const target = await resolveTarget2(opts);
4271
4500
  const { site, base } = target;
4272
4501
  const zipPath = opts.zip?.trim() ?? "";
4273
4502
  const body = { plugin };
@@ -4311,7 +4540,7 @@ async function runPluginsUpdate(opts) {
4311
4540
  });
4312
4541
  }
4313
4542
  async function runHelperStatus(opts) {
4314
- const { config, site, base } = await resolveTarget(opts);
4543
+ const { config, site, base } = await resolveTarget2(opts);
4315
4544
  let status;
4316
4545
  try {
4317
4546
  status = await apiFetch2(
@@ -4345,7 +4574,7 @@ ${site.name} helper \u72B6\u6001`);
4345
4574
  `);
4346
4575
  }
4347
4576
  async function runUpdateHelper(opts, fromBootstrap = false) {
4348
- const { config, site, base } = await resolveTarget(opts);
4577
+ const { config, site, base } = await resolveTarget2(opts);
4349
4578
  let result;
4350
4579
  try {
4351
4580
  result = await apiFetch2(
@@ -4372,8 +4601,84 @@ async function runUpdateHelper(opts, fromBootstrap = false) {
4372
4601
  await runHelperStatus({ site: site.guid || opts.site, url: site.url, verbose: opts.verbose });
4373
4602
  }
4374
4603
  }
4604
+ async function findInstalledPlugin(base, config, pluginArg, verbose = false) {
4605
+ const plugins = await apiFetch2(`${base}/wp-json/wp/v2/plugins`, config, {}, verbose);
4606
+ if (!Array.isArray(plugins)) {
4607
+ throw new Error("\u7AD9\u70B9\u8FD4\u56DE\u7684\u63D2\u4EF6\u5217\u8868\u683C\u5F0F\u5F02\u5E38");
4608
+ }
4609
+ const needle = pluginKey(pluginArg);
4610
+ const exact = plugins.find((p) => pluginKey(p.plugin || "") === needle);
4611
+ if (exact?.plugin) return exact;
4612
+ const hits = plugins.filter((p) => {
4613
+ const key = pluginKey(p.plugin || "");
4614
+ return key === needle || key.startsWith(`${needle}/`) || key.endsWith(`/${needle}`);
4615
+ });
4616
+ if (hits.length === 1 && hits[0].plugin) return hits[0];
4617
+ if (hits.length > 1) {
4618
+ const names = hits.map((p) => p.plugin).join("\u3001");
4619
+ throw new Error(`\u300C${pluginArg}\u300D\u5339\u914D\u5230\u591A\u4E2A\u63D2\u4EF6\uFF0C\u8BF7\u6539\u7528\u5B8C\u6574 --plugin\uFF1A${names}`);
4620
+ }
4621
+ throw new Error(`\u7AD9\u70B9\u4E0A\u6CA1\u6709\u63D2\u4EF6\u300C${pluginArg}\u300D\uFF0C\u5148 plugins list \u770B plugin \u5217`);
4622
+ }
4623
+ async function runPluginsUninstall(opts) {
4624
+ const pluginArg = opts.plugin?.trim() ?? "";
4625
+ if (!pluginArg) {
4626
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --plugin\uFF08\u5148 plugins list \u770B plugin \u5217\uFF09\n");
4627
+ process.exit(1);
4628
+ }
4629
+ if (isProtectedPlugin(pluginArg)) {
4630
+ 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");
4631
+ process.exit(1);
4632
+ }
4633
+ const target = await resolveTarget2(opts);
4634
+ const { site, base } = target;
4635
+ let current;
4636
+ try {
4637
+ current = await findInstalledPlugin(base, target.config, pluginArg, opts.verbose);
4638
+ } catch (e) {
4639
+ console.error(`
4640
+ \u274C ${e.message}
4641
+ `);
4642
+ process.exit(1);
4643
+ return;
4644
+ }
4645
+ const plugin = current.plugin || pluginArg;
4646
+ if (isProtectedPlugin(plugin)) {
4647
+ 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");
4648
+ process.exit(1);
4649
+ }
4650
+ const restPath = `${base}/wp-json/wp/v2/plugins/${wpPluginRestPath(plugin)}`;
4651
+ try {
4652
+ if (current.status === "active") {
4653
+ console.log(`\u5148\u505C\u7528 ${plugin} \u2026`);
4654
+ await apiFetch2(
4655
+ restPath,
4656
+ target.config,
4657
+ { method: "POST", body: JSON.stringify({ status: "inactive" }) },
4658
+ opts.verbose
4659
+ );
4660
+ }
4661
+ await apiFetch2(restPath, target.config, { method: "DELETE" }, opts.verbose);
4662
+ } catch (e) {
4663
+ console.error(`
4664
+ \u274C \u5378\u8F7D\u5931\u8D25\uFF1A${e.message}
4665
+ `);
4666
+ process.exit(1);
4667
+ return;
4668
+ }
4669
+ console.log(`
4670
+ \u2705 \u5DF2\u5378\u8F7D ${plugin}`);
4671
+ console.log(` \u7AD9\u70B9 : ${site.name} (${base})
4672
+ `);
4673
+ await runPluginsList({
4674
+ site: site.guid || opts.site,
4675
+ url: site.url,
4676
+ verbose: opts.verbose,
4677
+ exitOnError: false
4678
+ });
4679
+ }
4375
4680
  function register7(program2) {
4376
- const plugins = program2.command("plugins").description("WordPress \u63D2\u4EF6\uFF1A\u5217\u51FA\u3001\u76EE\u5F55\u3001\u5B89\u88C5\u3001\u5347\u7EA7");
4681
+ const plugins = program2.command("plugins").description("WordPress \u63D2\u4EF6\uFF1A\u5217\u51FA\u3001\u76EE\u5F55\u3001\u5B89\u88C5\u3001\u5347\u7EA7\u3001\u5378\u8F7D");
4377
4682
  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) => {
4378
4683
  await runPluginsList(opts);
4379
4684
  });
@@ -4386,6 +4691,9 @@ function register7(program2) {
4386
4691
  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) => {
4387
4692
  await runPluginsUpdate(opts);
4388
4693
  });
4694
+ 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) => {
4695
+ await runPluginsUninstall(opts);
4696
+ });
4389
4697
  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) => {
4390
4698
  await runHelperStatus(opts);
4391
4699
  });
@@ -4394,10 +4702,729 @@ function register7(program2) {
4394
4702
  });
4395
4703
  }
4396
4704
 
4705
+ // src/commands/content.ts
4706
+ import * as fs7 from "fs";
4707
+
4708
+ // src/types/wp-rest.ts
4709
+ function wpRenderedText(value) {
4710
+ if (!value) return "";
4711
+ if (typeof value === "string") return value;
4712
+ return value.raw || value.rendered || "";
4713
+ }
4714
+
4715
+ // src/commands/content.ts
4716
+ function parseIdList(raw) {
4717
+ if (!raw?.trim()) return void 0;
4718
+ return raw.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
4719
+ }
4720
+ function printPost(item, restBase) {
4721
+ console.log(`
4722
+ \u2705 ${restBase} #${item.id}`);
4723
+ console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
4724
+ console.log(` \u72B6\u6001 : ${item.status || "-"}`);
4725
+ console.log(` slug : ${item.slug || "-"}`);
4726
+ if (item.link) console.log(` \u94FE\u63A5 : ${item.link}`);
4727
+ console.log();
4728
+ }
4729
+ async function runContentTypes(opts) {
4730
+ const target = await resolveTarget(opts);
4731
+ let types;
4732
+ try {
4733
+ types = await apiFetch2(
4734
+ wpV2(target.base, "/types?context=edit"),
4735
+ target.config,
4736
+ {},
4737
+ opts.verbose
4738
+ );
4739
+ } catch (e) {
4740
+ console.error(`
4741
+ \u274C \u83B7\u53D6\u5185\u5BB9\u7C7B\u578B\u5931\u8D25\uFF1A${e.message}
4742
+ `);
4743
+ process.exit(1);
4744
+ return;
4745
+ }
4746
+ const rows = Object.entries(types || {}).map(([slug, info]) => ({
4747
+ slug,
4748
+ rest_base: info.rest_base || slug,
4749
+ name: info.name || slug
4750
+ }));
4751
+ if (opts.json) {
4752
+ console.log(JSON.stringify({ site: target.site, types: rows }, null, 2));
4753
+ return;
4754
+ }
4755
+ console.log(`
4756
+ ${target.site.name} \u53EF REST \u7BA1\u7406\u7684\u5185\u5BB9\u7C7B\u578B\uFF08${rows.length}\uFF09
4757
+ `);
4758
+ printCliTable(rows, [
4759
+ { key: "slug", header: "slug" },
4760
+ { key: "rest_base", header: "rest_base\uFF08--type\uFF09" },
4761
+ { key: "name", header: "\u540D\u79F0" }
4762
+ ]);
4763
+ console.log("\n\u9875\u9762\u6B63\u6587\u8BF7\u7528 pages add/update\uFF1B\u5176\u5B83\u7C7B\u578B\u7528 content add --type <rest_base>\n");
4764
+ }
4765
+ async function runContentList(opts) {
4766
+ const typeArg = opts.type?.trim() || "posts";
4767
+ const target = await resolveTarget(opts);
4768
+ let restBase;
4769
+ try {
4770
+ restBase = await resolveTypeRestBase(target, typeArg, opts.verbose);
4771
+ } catch (e) {
4772
+ console.error(`
4773
+ \u274C ${e.message}
4774
+ `);
4775
+ process.exit(1);
4776
+ return;
4777
+ }
4778
+ const status = opts.status?.trim() || "publish,draft,private,pending";
4779
+ const api = wpV2(target.base, `/${restBase}?per_page=100&status=${encodeURIComponent(status)}`);
4780
+ let items;
4781
+ try {
4782
+ items = await apiFetch2(api, target.config, {}, opts.verbose);
4783
+ } catch (e) {
4784
+ console.error(`
4785
+ \u274C \u83B7\u53D6 ${restBase} \u5931\u8D25\uFF1A${e.message}
4786
+ `);
4787
+ process.exit(1);
4788
+ return;
4789
+ }
4790
+ if (!Array.isArray(items)) {
4791
+ console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
4792
+ process.exit(1);
4793
+ }
4794
+ if (opts.json) {
4795
+ console.log(
4796
+ JSON.stringify(
4797
+ {
4798
+ site: { guid: target.site.guid, name: target.site.name, url: target.site.url },
4799
+ type: restBase,
4800
+ total: items.length,
4801
+ items: items.map((p) => ({
4802
+ id: p.id,
4803
+ title: wpRenderedText(p.title),
4804
+ status: p.status ?? "",
4805
+ slug: p.slug ?? "",
4806
+ link: p.link ?? "",
4807
+ modified: p.modified ?? ""
4808
+ }))
4809
+ },
4810
+ null,
4811
+ 2
4812
+ )
4813
+ );
4814
+ return;
4815
+ }
4816
+ if (items.length === 0) {
4817
+ console.log(`
4818
+ ${target.site.name} \u6CA1\u6709 ${restBase}\u3002
4819
+ `);
4820
+ return;
4821
+ }
4822
+ const columns = [
4823
+ { key: "id", header: "id" },
4824
+ { key: "title", header: "\u6807\u9898" },
4825
+ { key: "status", header: "\u72B6\u6001" },
4826
+ { key: "slug", header: "slug" },
4827
+ { key: "link", header: "\u94FE\u63A5" }
4828
+ ];
4829
+ console.log(`
4830
+ ${target.site.name} ${restBase}\uFF08${items.length}\uFF09
4831
+ `);
4832
+ printCliTable(
4833
+ items.map((p) => ({
4834
+ id: String(p.id),
4835
+ title: wpRenderedText(p.title) || "(\u65E0\u6807\u9898)",
4836
+ status: p.status ?? "-",
4837
+ slug: p.slug ?? "-",
4838
+ link: p.link ?? "-"
4839
+ })),
4840
+ columns
4841
+ );
4842
+ console.log();
4843
+ }
4844
+ async function runContentGet(opts) {
4845
+ const id = Number(opts.id);
4846
+ if (!Number.isFinite(id) || id <= 0) {
4847
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B\u6709\u6548 --id\n");
4848
+ process.exit(1);
4849
+ }
4850
+ const target = await resolveTarget(opts);
4851
+ const restBase = await resolveTypeRestBase(target, opts.type?.trim() || "posts", opts.verbose);
4852
+ const item = await apiFetch2(
4853
+ wpV2(target.base, `/${restBase}/${id}?context=edit`),
4854
+ target.config,
4855
+ {},
4856
+ opts.verbose
4857
+ ).catch((e) => {
4858
+ console.error(`
4859
+ \u274C \u83B7\u53D6\u5931\u8D25\uFF1A${e.message}
4860
+ `);
4861
+ process.exit(1);
4862
+ });
4863
+ if (opts.json) {
4864
+ console.log(JSON.stringify(item, null, 2));
4865
+ return;
4866
+ }
4867
+ console.log(`
4868
+ ${restBase} #${item.id}`);
4869
+ console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
4870
+ console.log(` \u72B6\u6001 : ${item.status || "-"}`);
4871
+ console.log(` slug : ${item.slug || "-"}`);
4872
+ console.log(` \u94FE\u63A5 : ${item.link || "-"}`);
4873
+ if (item.featured_media) console.log(` \u7279\u8272\u56FE : ${item.featured_media}`);
4874
+ const excerpt = wpRenderedText(item.excerpt);
4875
+ if (excerpt) console.log(` \u6458\u8981 : ${excerpt.slice(0, 120)}`);
4876
+ console.log();
4877
+ }
4878
+ async function runContentWrite(mode, opts) {
4879
+ const typeArg = opts.type?.trim() || "posts";
4880
+ if (typeArg === "page" || typeArg === "pages") {
4881
+ console.error("\n\u274C \u9875\u9762\u6B63\u6587\u8BF7\u7528 pages add / pages update\uFF08Zion visual-edit\uFF09\u3002");
4882
+ console.error(" \u53EA\u6539 slug/\u72B6\u6001/\u56DE\u6536\u7AD9\u7528 pages meta / pages trash\u3002\n");
4883
+ process.exit(1);
4884
+ }
4885
+ const target = await resolveTarget(opts);
4886
+ const restBase = await resolveTypeRestBase(target, typeArg, opts.verbose);
4887
+ const content = opts.contentFile ? fs7.readFileSync(opts.contentFile, "utf8") : opts.content ?? "";
4888
+ if (mode === "add" && !opts.title?.trim() && !content.trim()) {
4889
+ console.error("\n\u274C \u65B0\u589E\u81F3\u5C11\u8981 --title \u6216 --content / --content-file\n");
4890
+ process.exit(1);
4891
+ }
4892
+ const body = {};
4893
+ if (opts.title?.trim()) body.title = opts.title.trim();
4894
+ if (content.trim()) body.content = content;
4895
+ if (opts.status?.trim()) body.status = opts.status.trim();
4896
+ if (opts.slug?.trim()) body.slug = opts.slug.trim();
4897
+ if (opts.excerpt?.trim()) body.excerpt = opts.excerpt.trim();
4898
+ const featured = Number(opts.featuredMedia);
4899
+ if (Number.isFinite(featured) && featured > 0) body.featured_media = featured;
4900
+ const cats = parseIdList(opts.categories);
4901
+ if (cats) body.categories = cats;
4902
+ const tags = parseIdList(opts.tags);
4903
+ if (tags) body.tags = tags;
4904
+ if (mode === "update") {
4905
+ const id = Number(opts.id);
4906
+ if (!Number.isFinite(id) || id <= 0) {
4907
+ console.error("\n\u274C \u66F4\u65B0\u5FC5\u987B\u63D0\u4F9B --id\uFF08\u5148 content list\uFF09\n");
4908
+ process.exit(1);
4909
+ }
4910
+ if (Object.keys(body).length === 0) {
4911
+ console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\n");
4912
+ process.exit(1);
4913
+ }
4914
+ const item2 = await apiFetch2(
4915
+ wpV2(target.base, `/${restBase}/${id}`),
4916
+ target.config,
4917
+ { method: "POST", body: JSON.stringify(body) },
4918
+ opts.verbose
4919
+ ).catch((e) => {
4920
+ console.error(`
4921
+ \u274C \u66F4\u65B0\u5931\u8D25\uFF1A${e.message}
4922
+ `);
4923
+ process.exit(1);
4924
+ });
4925
+ printPost(item2, restBase);
4926
+ return;
4927
+ }
4928
+ const item = await apiFetch2(
4929
+ wpV2(target.base, `/${restBase}`),
4930
+ target.config,
4931
+ { method: "POST", body: JSON.stringify(body) },
4932
+ opts.verbose
4933
+ ).catch((e) => {
4934
+ console.error(`
4935
+ \u274C \u65B0\u589E\u5931\u8D25\uFF1A${e.message}
4936
+ `);
4937
+ process.exit(1);
4938
+ });
4939
+ printPost(item, restBase);
4940
+ }
4941
+ async function runContentTrash(opts) {
4942
+ const id = Number(opts.id);
4943
+ if (!Number.isFinite(id) || id <= 0) {
4944
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
4945
+ process.exit(1);
4946
+ }
4947
+ const target = await resolveTarget(opts);
4948
+ const restBase = await resolveTypeRestBase(target, opts.type?.trim() || "posts", opts.verbose);
4949
+ const qs = opts.force ? "?force=true" : "";
4950
+ const item = await apiFetch2(
4951
+ wpV2(target.base, `/${restBase}/${id}${qs}`),
4952
+ target.config,
4953
+ { method: "DELETE" },
4954
+ opts.verbose
4955
+ ).catch((e) => {
4956
+ console.error(`
4957
+ \u274C \u5220\u9664\u5931\u8D25\uFF1A${e.message}
4958
+ `);
4959
+ process.exit(1);
4960
+ });
4961
+ console.log(opts.force ? `
4962
+ \u2705 \u5DF2\u6C38\u4E45\u5220\u9664 ${restBase} #${id}
4963
+ ` : `
4964
+ \u2705 \u5DF2\u79FB\u5165\u56DE\u6536\u7AD9 ${restBase} #${id}\uFF08status=${item.status || "trash"}\uFF09
4965
+ `);
4966
+ }
4967
+ function register8(program2) {
4968
+ 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");
4969
+ 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) => {
4970
+ await runContentTypes(opts);
4971
+ });
4972
+ 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) => {
4973
+ await runContentList(opts);
4974
+ });
4975
+ 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) => {
4976
+ await runContentGet(opts);
4977
+ });
4978
+ 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) => {
4979
+ await runContentWrite("add", opts);
4980
+ });
4981
+ 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) => {
4982
+ await runContentWrite("update", opts);
4983
+ });
4984
+ 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) => {
4985
+ await runContentTrash(opts);
4986
+ });
4987
+ }
4988
+
4989
+ // src/commands/media.ts
4990
+ import { existsSync as existsSync4, readFileSync as readFileSync8 } from "fs";
4991
+ import { basename as basename3, extname, resolve as resolve3 } from "path";
4992
+ var MIME_BY_EXT = {
4993
+ ".jpg": "image/jpeg",
4994
+ ".jpeg": "image/jpeg",
4995
+ ".png": "image/png",
4996
+ ".gif": "image/gif",
4997
+ ".webp": "image/webp",
4998
+ ".svg": "image/svg+xml",
4999
+ ".pdf": "application/pdf",
5000
+ ".mp4": "video/mp4",
5001
+ ".zip": "application/zip"
5002
+ };
5003
+ var MAX_MEDIA_BYTES = 20 * 1024 * 1024;
5004
+ function guessMime(filename) {
5005
+ return MIME_BY_EXT[extname(filename).toLowerCase()] || "application/octet-stream";
5006
+ }
5007
+ async function runMediaList(opts) {
5008
+ const target = await resolveTarget(opts);
5009
+ let items;
5010
+ try {
5011
+ items = await apiFetch2(
5012
+ wpV2(target.base, "/media?per_page=50"),
5013
+ target.config,
5014
+ {},
5015
+ opts.verbose
5016
+ );
5017
+ } catch (e) {
5018
+ console.error(`
5019
+ \u274C \u83B7\u53D6\u5A92\u4F53\u5E93\u5931\u8D25\uFF1A${e.message}
5020
+ `);
5021
+ process.exit(1);
5022
+ return;
5023
+ }
5024
+ if (!Array.isArray(items)) {
5025
+ console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u5A92\u4F53\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
5026
+ process.exit(1);
5027
+ }
5028
+ if (opts.json) {
5029
+ console.log(
5030
+ JSON.stringify(
5031
+ {
5032
+ site: { guid: target.site.guid, name: target.site.name, url: target.site.url },
5033
+ total: items.length,
5034
+ items: items.map((m) => ({
5035
+ id: m.id,
5036
+ title: wpRenderedText(m.title),
5037
+ mime: m.mime_type ?? "",
5038
+ url: m.source_url ?? ""
5039
+ }))
5040
+ },
5041
+ null,
5042
+ 2
5043
+ )
5044
+ );
5045
+ return;
5046
+ }
5047
+ if (items.length === 0) {
5048
+ console.log(`
5049
+ ${target.site.name} \u5A92\u4F53\u5E93\u4E3A\u7A7A\u3002
5050
+ `);
5051
+ return;
5052
+ }
5053
+ console.log(`
5054
+ ${target.site.name} \u5A92\u4F53\uFF08\u6700\u8FD1 ${items.length}\uFF09
5055
+ `);
5056
+ printCliTable(
5057
+ items.map((m) => ({
5058
+ id: String(m.id),
5059
+ title: wpRenderedText(m.title) || "-",
5060
+ mime: m.mime_type || "-",
5061
+ url: m.source_url || "-"
5062
+ })),
5063
+ [
5064
+ { key: "id", header: "id" },
5065
+ { key: "title", header: "\u6807\u9898" },
5066
+ { key: "mime", header: "\u7C7B\u578B" },
5067
+ { key: "url", header: "\u5730\u5740" }
5068
+ ]
5069
+ );
5070
+ console.log();
5071
+ }
5072
+ async function runMediaGet(opts) {
5073
+ const id = Number(opts.id);
5074
+ if (!Number.isFinite(id) || id <= 0) {
5075
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
5076
+ process.exit(1);
5077
+ }
5078
+ const target = await resolveTarget(opts);
5079
+ const item = await apiFetch2(
5080
+ wpV2(target.base, `/media/${id}`),
5081
+ target.config,
5082
+ {},
5083
+ opts.verbose
5084
+ ).catch((e) => {
5085
+ console.error(`
5086
+ \u274C \u83B7\u53D6\u5A92\u4F53\u5931\u8D25\uFF1A${e.message}
5087
+ `);
5088
+ process.exit(1);
5089
+ });
5090
+ if (opts.json) {
5091
+ console.log(JSON.stringify(item, null, 2));
5092
+ return;
5093
+ }
5094
+ console.log(`
5095
+ \u5A92\u4F53 #${item.id}`);
5096
+ console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || "-"}`);
5097
+ console.log(` \u7C7B\u578B : ${item.mime_type || "-"}`);
5098
+ console.log(` \u5730\u5740 : ${item.source_url || "-"}`);
5099
+ if (item.alt_text) console.log(` alt : ${item.alt_text}`);
5100
+ console.log();
5101
+ }
5102
+ async function runMediaUpload(opts) {
5103
+ const filePath = opts.file?.trim() ?? "";
5104
+ if (!filePath) {
5105
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --file\n");
5106
+ process.exit(1);
5107
+ }
5108
+ const abs = resolve3(filePath);
5109
+ if (!existsSync4(abs)) {
5110
+ console.error(`
5111
+ \u274C \u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${abs}
5112
+ `);
5113
+ process.exit(1);
5114
+ }
5115
+ const data = readFileSync8(abs);
5116
+ if (data.length > MAX_MEDIA_BYTES) {
5117
+ console.error("\n\u274C \u6587\u4EF6\u8D85\u8FC7 20MB\n");
5118
+ process.exit(1);
5119
+ }
5120
+ const filename = basename3(abs);
5121
+ const target = await resolveTarget(opts);
5122
+ const fields = {};
5123
+ if (opts.title?.trim()) fields.title = opts.title.trim();
5124
+ if (opts.alt?.trim()) fields.alt_text = opts.alt.trim();
5125
+ if (opts.caption?.trim()) fields.caption = opts.caption.trim();
5126
+ let item;
5127
+ try {
5128
+ item = await apiFetchMultipart2(
5129
+ wpV2(target.base, "/media"),
5130
+ target.config,
5131
+ {
5132
+ fields,
5133
+ files: [
5134
+ {
5135
+ field: "file",
5136
+ filename,
5137
+ contentType: guessMime(filename),
5138
+ data
5139
+ }
5140
+ ]
5141
+ },
5142
+ opts.verbose
5143
+ );
5144
+ } catch (e) {
5145
+ console.error(`
5146
+ \u274C \u4E0A\u4F20\u5931\u8D25\uFF1A${e.message}
5147
+ `);
5148
+ process.exit(1);
5149
+ return;
5150
+ }
5151
+ console.log(`
5152
+ \u2705 \u5DF2\u4E0A\u4F20\u5A92\u4F53 #${item.id}`);
5153
+ console.log(` \u5730\u5740 : ${item.source_url || "-"}`);
5154
+ console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || filename}`);
5155
+ console.log();
5156
+ }
5157
+ function register9(program2) {
5158
+ const media = program2.command("media").description("\u5A92\u4F53\u5E93\uFF1A\u5217\u51FA\u3001\u67E5\u770B\u3001\u4E0A\u4F20");
5159
+ 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) => {
5160
+ await runMediaList(opts);
5161
+ });
5162
+ 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) => {
5163
+ await runMediaGet(opts);
5164
+ });
5165
+ 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) => {
5166
+ await runMediaUpload(opts);
5167
+ });
5168
+ }
5169
+
5170
+ // src/commands/terms.ts
5171
+ async function runTermsTaxonomies(opts) {
5172
+ const target = await resolveTarget(opts);
5173
+ let taxes;
5174
+ try {
5175
+ taxes = await apiFetch2(
5176
+ wpV2(target.base, "/taxonomies?context=edit"),
5177
+ target.config,
5178
+ {},
5179
+ opts.verbose
5180
+ );
5181
+ } catch (e) {
5182
+ console.error(`
5183
+ \u274C \u83B7\u53D6\u5206\u7C7B\u6CD5\u5931\u8D25\uFF1A${e.message}
5184
+ `);
5185
+ process.exit(1);
5186
+ return;
5187
+ }
5188
+ const rows = Object.entries(taxes || {}).map(([slug, info]) => ({
5189
+ slug,
5190
+ rest_base: info.rest_base || slug,
5191
+ name: info.name || slug
5192
+ }));
5193
+ if (opts.json) {
5194
+ console.log(JSON.stringify({ site: target.site, taxonomies: rows }, null, 2));
5195
+ return;
5196
+ }
5197
+ console.log(`
5198
+ ${target.site.name} \u5206\u7C7B\u6CD5\uFF08${rows.length}\uFF09
5199
+ `);
5200
+ printCliTable(rows, [
5201
+ { key: "slug", header: "slug" },
5202
+ { key: "rest_base", header: "--taxonomy" },
5203
+ { key: "name", header: "\u540D\u79F0" }
5204
+ ]);
5205
+ console.log();
5206
+ }
5207
+ async function runTermsList(opts) {
5208
+ const target = await resolveTarget(opts);
5209
+ const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
5210
+ let items;
5211
+ try {
5212
+ items = await apiFetch2(
5213
+ wpV2(target.base, `/${restBase}?per_page=100`),
5214
+ target.config,
5215
+ {},
5216
+ opts.verbose
5217
+ );
5218
+ } catch (e) {
5219
+ console.error(`
5220
+ \u274C \u83B7\u53D6 ${restBase} \u5931\u8D25\uFF1A${e.message}
5221
+ `);
5222
+ process.exit(1);
5223
+ return;
5224
+ }
5225
+ if (!Array.isArray(items)) {
5226
+ console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u672F\u8BED\u5217\u8868\u683C\u5F0F\u5F02\u5E38\n");
5227
+ process.exit(1);
5228
+ }
5229
+ if (opts.json) {
5230
+ console.log(JSON.stringify({ taxonomy: restBase, total: items.length, items }, null, 2));
5231
+ return;
5232
+ }
5233
+ if (items.length === 0) {
5234
+ console.log(`
5235
+ \u6CA1\u6709 ${restBase}\u3002
5236
+ `);
5237
+ return;
5238
+ }
5239
+ console.log(`
5240
+ ${target.site.name} ${restBase}\uFF08${items.length}\uFF09
5241
+ `);
5242
+ printCliTable(
5243
+ items.map((t) => ({
5244
+ id: String(t.id),
5245
+ name: t.name || "-",
5246
+ slug: t.slug || "-",
5247
+ count: String(t.count ?? 0)
5248
+ })),
5249
+ [
5250
+ { key: "id", header: "id" },
5251
+ { key: "name", header: "\u540D\u79F0" },
5252
+ { key: "slug", header: "slug" },
5253
+ { key: "count", header: "\u6570\u91CF" }
5254
+ ]
5255
+ );
5256
+ console.log();
5257
+ }
5258
+ async function runTermsAdd(opts) {
5259
+ const name = opts.name?.trim() ?? "";
5260
+ if (!name) {
5261
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --name\n");
5262
+ process.exit(1);
5263
+ }
5264
+ const target = await resolveTarget(opts);
5265
+ const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
5266
+ const body = { name };
5267
+ if (opts.slug?.trim()) body.slug = opts.slug.trim();
5268
+ const parent = Number(opts.parent);
5269
+ if (Number.isFinite(parent) && parent > 0) body.parent = parent;
5270
+ const item = await apiFetch2(
5271
+ wpV2(target.base, `/${restBase}`),
5272
+ target.config,
5273
+ { method: "POST", body: JSON.stringify(body) },
5274
+ opts.verbose
5275
+ ).catch((e) => {
5276
+ console.error(`
5277
+ \u274C \u65B0\u589E\u5931\u8D25\uFF1A${e.message}
5278
+ `);
5279
+ process.exit(1);
5280
+ });
5281
+ console.log(`
5282
+ \u2705 \u5DF2\u65B0\u589E ${restBase} #${item.id} ${item.name || name}
5283
+ `);
5284
+ }
5285
+ async function runTermsUpdate(opts) {
5286
+ const id = Number(opts.id);
5287
+ if (!Number.isFinite(id) || id <= 0) {
5288
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
5289
+ process.exit(1);
5290
+ }
5291
+ const body = {};
5292
+ if (opts.name?.trim()) body.name = opts.name.trim();
5293
+ if (opts.slug?.trim()) body.slug = opts.slug.trim();
5294
+ if (Object.keys(body).length === 0) {
5295
+ console.error("\n\u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\n");
5296
+ process.exit(1);
5297
+ }
5298
+ const target = await resolveTarget(opts);
5299
+ const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
5300
+ const item = await apiFetch2(
5301
+ wpV2(target.base, `/${restBase}/${id}`),
5302
+ target.config,
5303
+ { method: "POST", body: JSON.stringify(body) },
5304
+ opts.verbose
5305
+ ).catch((e) => {
5306
+ console.error(`
5307
+ \u274C \u66F4\u65B0\u5931\u8D25\uFF1A${e.message}
5308
+ `);
5309
+ process.exit(1);
5310
+ });
5311
+ console.log(`
5312
+ \u2705 \u5DF2\u66F4\u65B0 ${restBase} #${item.id} ${item.name || ""}
5313
+ `);
5314
+ }
5315
+ async function runTermsDelete(opts) {
5316
+ const id = Number(opts.id);
5317
+ if (!Number.isFinite(id) || id <= 0) {
5318
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id\n");
5319
+ process.exit(1);
5320
+ }
5321
+ const target = await resolveTarget(opts);
5322
+ const restBase = await resolveTaxonomyRestBase(target, opts.taxonomy || "category", opts.verbose);
5323
+ await apiFetch2(
5324
+ wpV2(target.base, `/${restBase}/${id}?force=true`),
5325
+ target.config,
5326
+ { method: "DELETE" },
5327
+ opts.verbose
5328
+ ).catch((e) => {
5329
+ console.error(`
5330
+ \u274C \u5220\u9664\u5931\u8D25\uFF1A${e.message}
5331
+ `);
5332
+ process.exit(1);
5333
+ });
5334
+ console.log(`
5335
+ \u2705 \u5DF2\u5220\u9664 ${restBase} #${id}
5336
+ `);
5337
+ }
5338
+ function register10(program2) {
5339
+ const terms = program2.command("terms").description("\u5206\u7C7B / \u6807\u7B7E / \u81EA\u5B9A\u4E49\u5206\u7C7B\u6CD5");
5340
+ 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) => {
5341
+ await runTermsTaxonomies(opts);
5342
+ });
5343
+ 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) => {
5344
+ await runTermsList(opts);
5345
+ });
5346
+ 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) => {
5347
+ await runTermsAdd(opts);
5348
+ });
5349
+ 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) => {
5350
+ await runTermsUpdate(opts);
5351
+ });
5352
+ 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) => {
5353
+ await runTermsDelete(opts);
5354
+ });
5355
+ }
5356
+
5357
+ // src/commands/search.ts
5358
+ async function runSearch(opts) {
5359
+ const q = opts.q?.trim() ?? "";
5360
+ if (!q) {
5361
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --q\n");
5362
+ process.exit(1);
5363
+ }
5364
+ const target = await resolveTarget(opts);
5365
+ const params = new URLSearchParams({
5366
+ search: q,
5367
+ per_page: "20"
5368
+ });
5369
+ if (opts.type?.trim()) params.set("subtype", opts.type.trim());
5370
+ let hits;
5371
+ try {
5372
+ hits = await apiFetch2(
5373
+ wpV2(target.base, `/search?${params.toString()}`),
5374
+ target.config,
5375
+ {},
5376
+ opts.verbose
5377
+ );
5378
+ } catch (e) {
5379
+ console.error(`
5380
+ \u274C \u641C\u7D22\u5931\u8D25\uFF1A${e.message}
5381
+ `);
5382
+ process.exit(1);
5383
+ return;
5384
+ }
5385
+ if (!Array.isArray(hits)) {
5386
+ console.error("\n\u274C \u7AD9\u70B9\u8FD4\u56DE\u7684\u641C\u7D22\u7ED3\u679C\u683C\u5F0F\u5F02\u5E38\n");
5387
+ process.exit(1);
5388
+ }
5389
+ if (opts.json) {
5390
+ console.log(JSON.stringify({ q, total: hits.length, hits }, null, 2));
5391
+ return;
5392
+ }
5393
+ if (hits.length === 0) {
5394
+ console.log(`
5395
+ \u6CA1\u6709\u5339\u914D\u300C${q}\u300D\u7684\u7ED3\u679C\u3002
5396
+ `);
5397
+ return;
5398
+ }
5399
+ console.log(`
5400
+ ${target.site.name} \u641C\u7D22\u300C${q}\u300D\uFF08${hits.length}\uFF09
5401
+ `);
5402
+ printCliTable(
5403
+ hits.map((h) => ({
5404
+ id: h.id != null ? String(h.id) : "-",
5405
+ title: h.title || "-",
5406
+ type: [h.type, h.subtype].filter(Boolean).join("/") || "-",
5407
+ url: h.url || "-"
5408
+ })),
5409
+ [
5410
+ { key: "id", header: "id" },
5411
+ { key: "title", header: "\u6807\u9898" },
5412
+ { key: "type", header: "\u7C7B\u578B" },
5413
+ { key: "url", header: "\u94FE\u63A5" }
5414
+ ]
5415
+ );
5416
+ console.log();
5417
+ }
5418
+ function register11(program2) {
5419
+ 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) => {
5420
+ await runSearch(opts);
5421
+ });
5422
+ }
5423
+
4397
5424
  // src/index.ts
4398
5425
  installProcessHandlers();
4399
5426
  var program = new Command();
4400
- program.name("siluzan-website").description("Siluzan WordPress \u7AD9\u70B9\u7BA1\u7406\uFF1A\u5217\u51FA\u7AD9\u70B9\u3001\u65B0\u589E/\u7F16\u8F91\u9875\u9762\u3001\u5B89\u88C5/\u5347\u7EA7\u63D2\u4EF6").version(getCurrentVersion2());
5427
+ program.name("siluzan-website").description("Siluzan WordPress \u7AD9\u70B9\u7BA1\u7406\uFF1A\u7AD9\u70B9\u3001\u9875\u9762\u3001\u6587\u7AE0\u3001\u5A92\u4F53\u3001\u5206\u7C7B\u3001\u63D2\u4EF6").version(getCurrentVersion2());
4401
5428
  var REGISTRARS = [
4402
5429
  register,
4403
5430
  register2,
@@ -4405,6 +5432,10 @@ var REGISTRARS = [
4405
5432
  register4,
4406
5433
  register5,
4407
5434
  register6,
5435
+ register8,
5436
+ register9,
5437
+ register10,
5438
+ register11,
4408
5439
  register7
4409
5440
  ];
4410
5441
  for (const reg of REGISTRARS) reg(program);