@cmo-so/cli 0.12.7 → 0.12.8

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.
Files changed (2) hide show
  1. package/dist/cmo.mjs +78 -7
  2. package/package.json +1 -1
package/dist/cmo.mjs CHANGED
@@ -17304,7 +17304,7 @@ var childTools = [
17304
17304
  files[`assets/fonts/${name}`] = btoa(bin);
17305
17305
  let fam = fams.find((x) => x.slug === f.slug);
17306
17306
  const stack = `"${f.family}", ${f.fallback || "sans-serif"}`;
17307
- if (!fam || !fam.fontFamily.includes(`"${f.family}"`)) {
17307
+ if (!fam?.fontFamily.includes(`"${f.family}"`)) {
17308
17308
  const keep = fam ? fams.indexOf(fam) : -1;
17309
17309
  fam = { slug: f.slug, name: f.family, fontFamily: stack, fontFace: [] };
17310
17310
  if (keep >= 0) fams[keep] = fam;
@@ -18123,6 +18123,49 @@ var fullTools = [
18123
18123
  });
18124
18124
  }
18125
18125
  }),
18126
+ tool({
18127
+ name: "wp_term_delete",
18128
+ description: "Delete a category or tag by id. Posts keep their other terms; posts left without a category go to the default category, which can't be deleted. Terms have no trash: the result gives name, slug and description to recreate it with wp_term_save.",
18129
+ parameters: {
18130
+ type: "object",
18131
+ properties: {
18132
+ taxonomy: { type: "string", enum: ["categories", "tags"], description: "Default categories." },
18133
+ id: int2("The term to delete (from wp_terms_list).")
18134
+ },
18135
+ required: ["id"]
18136
+ },
18137
+ group: "site",
18138
+ need: WRITE,
18139
+ risk: "W3",
18140
+ gates: [...GATES],
18141
+ confirm: (a, lang) => say(
18142
+ lang,
18143
+ `Delete the ${a.taxonomy === "tags" ? "tag" : "category"} #${String(a.id)} from your website (posts stay; it can be recreated, not restored).`,
18144
+ `\u522A\u9664\u7DB2\u7AD9\u7684${a.taxonomy === "tags" ? "\u6A19\u7C64" : "\u5206\u985E"} #${String(a.id)}\uFF08\u6587\u7AE0\u4FDD\u7559\uFF1B\u53EF\u91CD\u65B0\u5EFA\u7ACB\uFF0C\u7121\u6CD5\u9084\u539F\uFF09\u3002`
18145
+ ),
18146
+ run: async (ctx, a) => {
18147
+ const site = siteOf(ctx);
18148
+ const tax = a.taxonomy === "tags" ? "tags" : "categories";
18149
+ const id = Number(a.id);
18150
+ if (!Number.isInteger(id) || id <= 0) throw new Error("id: the term id from wp_terms_list.");
18151
+ if (tax === "categories") {
18152
+ const st = await call(site, {
18153
+ path: "/wp/v2/settings",
18154
+ query: { _fields: "default_category" }
18155
+ });
18156
+ if (Number(st.default_category ?? 1) === id)
18157
+ throw new Error("That is the default category; it can't be deleted.");
18158
+ }
18159
+ const before = await call(site, { path: `/wp/v2/${tax}/${id}`, query: { _fields: "id,name,slug,description,count,parent" } });
18160
+ await call(site, { method: "DELETE", path: `/wp/v2/${tax}/${id}`, query: { force: "true" } });
18161
+ return {
18162
+ deleted: true,
18163
+ taxonomy: tax,
18164
+ ...before,
18165
+ undo: `wp_term_save ${tax} name "${before.name}" slug ${before.slug}`
18166
+ };
18167
+ }
18168
+ }),
18126
18169
  tool({
18127
18170
  name: "wp_settings_get",
18128
18171
  description: "The site's general settings: title, tagline, search-engine visibility, language, timezone, date and time formats, start of week, posts per page, homepage and posts page, logo and icon.",
@@ -18208,7 +18251,7 @@ var fullTools = [
18208
18251
  }),
18209
18252
  tool({
18210
18253
  name: "wp_plugin_set",
18211
- description: "Install a plugin from WordPress.org by its slug (e.g. wpforms-lite), and/or activate or deactivate an installed one (plugin id from wp_plugins_list, e.g. akismet/akismet). Plugins can't be deleted from here. Installing runs the plugin's code on the site: only well-known plugins the owner asked for.",
18254
+ description: "Install a plugin from WordPress.org by its slug (e.g. wpforms-lite), and/or activate, deactivate or delete an installed one (plugin id from wp_plugins_list, e.g. akismet/akismet; only an inactive plugin can be deleted, and its settings may go with it). Installing runs the plugin's code on the site: only well-known plugins the owner asked for.",
18212
18255
  parameters: {
18213
18256
  type: "object",
18214
18257
  properties: {
@@ -18216,8 +18259,8 @@ var fullTools = [
18216
18259
  plugin: str2("Installed plugin id (folder/file) to change."),
18217
18260
  status: {
18218
18261
  type: "string",
18219
- enum: ["active", "inactive"],
18220
- description: "Activate or deactivate (after installing, default inactive)."
18262
+ enum: ["active", "inactive", "deleted"],
18263
+ description: "Activate, deactivate (after installing, default inactive), or deleted: remove an inactive plugin's files (deactivate it first; Maggie Press can't be removed here)."
18221
18264
  }
18222
18265
  }
18223
18266
  },
@@ -18229,6 +18272,10 @@ var fullTools = [
18229
18272
  lang,
18230
18273
  `Install the plugin ${q2(a.install, "")} from WordPress.org on your website${a.status === "active" ? " and activate it" : ""}.`,
18231
18274
  `\u5728\u7DB2\u7AD9\u4E0A\u5B89\u88DD WordPress.org \u63D2\u4EF6 ${q2(a.install, "")}${a.status === "active" ? "\u4E26\u555F\u7528" : ""}\u3002`
18275
+ ) : a.status === "deleted" ? say(
18276
+ lang,
18277
+ `Delete the plugin ${q2(a.plugin, "")} from your website (its files are removed; reinstall it from WordPress.org to undo, its settings may be lost).`,
18278
+ `\u5F9E\u7DB2\u7AD9\u522A\u9664\u63D2\u4EF6 ${q2(a.plugin, "")}\uFF08\u6A94\u6848\u6703\u88AB\u79FB\u9664\uFF1B\u53EF\u5F9E WordPress.org \u91CD\u65B0\u5B89\u88DD\uFF0C\u8A2D\u5B9A\u53EF\u80FD\u907A\u5931\uFF09\u3002`
18232
18279
  ) : say(
18233
18280
  lang,
18234
18281
  `${a.status === "active" ? "Activate" : "Deactivate"} the plugin ${q2(a.plugin, "")} on your website.`,
@@ -18249,9 +18296,29 @@ var fullTools = [
18249
18296
  if (!a.plugin || !a.status) throw new Error("Give install (a slug), or plugin and status.");
18250
18297
  if (!/^[a-z0-9._-]+(\/[a-z0-9._-]+)?$/i.test(String(a.plugin)))
18251
18298
  throw new Error("plugin: the id from wp_plugins_list, e.g. akismet/akismet.");
18299
+ const id = String(a.plugin).replace(/\.php$/, "");
18300
+ if (a.status === "deleted") {
18301
+ if (/^maggie-?press\//i.test(id))
18302
+ throw new Error("Maggie Press runs the site's styles; it can't be deleted here.");
18303
+ const cur = await call(site, {
18304
+ path: `/wp/v2/plugins/${id}`,
18305
+ query: { _fields: "plugin,name,version,status" }
18306
+ });
18307
+ if (cur.status !== "inactive")
18308
+ throw new Error(`${cur.name} is ${cur.status}: deactivate it first (status inactive), then delete it.`);
18309
+ await call(site, { method: "DELETE", path: `/wp/v2/plugins/${id}` });
18310
+ const slug = id.split("/")[0];
18311
+ return {
18312
+ deleted: true,
18313
+ plugin: cur.plugin,
18314
+ name: cur.name,
18315
+ version: cur.version,
18316
+ undo: `wp_plugin_set install ${slug}`
18317
+ };
18318
+ }
18252
18319
  return call(site, {
18253
18320
  method: "POST",
18254
- path: `/wp/v2/plugins/${String(a.plugin).replace(/\.php$/, "")}`,
18321
+ path: `/wp/v2/plugins/${id}`,
18255
18322
  query: { _fields: "plugin,name,version,status" },
18256
18323
  body: { status: a.status }
18257
18324
  });
@@ -21699,7 +21766,7 @@ var program = new Command();
21699
21766
  // package.json
21700
21767
  var package_default = {
21701
21768
  name: "@cmo-so/cli",
21702
- version: "0.12.7",
21769
+ version: "0.12.8",
21703
21770
  description: "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
21704
21771
  type: "module",
21705
21772
  license: "MIT",
@@ -32899,6 +32966,9 @@ ${table(r.issues, ["severity", "code", "path", "detail"])}`;
32899
32966
  description: o.description
32900
32967
  })
32901
32968
  );
32969
+ terms.command("delete <id>").option("--tags", "a tag instead of a category").action(
32970
+ (id, o, c) => run(g(c), "wp_term_delete", { taxonomy: o.tags ? "tags" : "categories", id: Number(id) })
32971
+ );
32902
32972
  const settings2 = wp.command("settings").description("the site's general settings");
32903
32973
  settings2.command("get", { isDefault: true }).action((_o, c) => run(g(c), "wp_settings_get", {}));
32904
32974
  settings2.command("set [fields...]").description(
@@ -32909,13 +32979,14 @@ ${table(r.issues, ["severity", "code", "path", "detail"])}`;
32909
32979
  args[k] = /^(true|false)$/.test(v) ? v === "true" : /^\d+$/.test(v) && k !== "title" && k !== "description" ? Number(v) : v;
32910
32980
  await run(g(c), "wp_settings_set", args);
32911
32981
  });
32912
- const plugins = wp.command("plugins").description("plugins: list, install from WordPress.org, activate, deactivate (never delete)");
32982
+ const plugins = wp.command("plugins").description("plugins: list, install from WordPress.org, activate, deactivate, delete (inactive only)");
32913
32983
  plugins.command("ls", { isDefault: true }).action((_o, c) => run(g(c), "wp_plugins_list", {}));
32914
32984
  plugins.command("install <slug>").option("--activate").action(
32915
32985
  (slug, o, c) => run(g(c), "wp_plugin_set", { install: slug, status: o.activate ? "active" : "inactive" })
32916
32986
  );
32917
32987
  plugins.command("activate <plugin>").action((p, _o, c) => run(g(c), "wp_plugin_set", { plugin: p, status: "active" }));
32918
32988
  plugins.command("deactivate <plugin>").action((p, _o, c) => run(g(c), "wp_plugin_set", { plugin: p, status: "inactive" }));
32989
+ plugins.command("delete <plugin>").description("remove an inactive plugin's files (reinstall from WordPress.org to undo)").action((p, _o, c) => run(g(c), "wp_plugin_set", { plugin: p, status: "deleted" }));
32919
32990
  wp.command("api <route>").description("read any allowed WordPress REST route (GET), e.g. /wp/v2/types").option("--query <json>", "query parameters as JSON").action(
32920
32991
  (route, o, c) => run(g(c), "wp_api_read", { route, query: o.query ? JSON.parse(o.query) : void 0 })
32921
32992
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmo-so/cli",
3
- "version": "0.12.7",
3
+ "version": "0.12.8",
4
4
  "description": "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
5
5
  "type": "module",
6
6
  "license": "MIT",