@mx-space/cli 0.4.0 → 0.4.1

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 CHANGED
@@ -19,9 +19,11 @@ Node.js 22 or newer is required.
19
19
 
20
20
  ```bash
21
21
  mxs auth login
22
- mxs post create --file ./post.xml
23
- mxs post update my-slug --title "New title" --state publish
24
- mxs post get my-slug --output llm
22
+ mxs post create --file ./post.xml --open --silent # open admin preview, terse output
23
+ mxs post get my-slug --output xml > /tmp/post.xml # round-trip envelope
24
+ # edit /tmp/post.xml ...
25
+ mxs post update my-slug --file /tmp/post.xml --open
26
+ mxs post publish my-slug
25
27
  ```
26
28
 
27
29
  When the CLI cannot resolve an API URL, it starts an interactive onboarding prompt in TTY contexts. Use `MXS_API_URL` or `--api-url` for non-interactive environments.
@@ -206,6 +208,14 @@ Existing installations that use the legacy flat files (`~/.config/mxs/config.jso
206
208
  | `--related <csv>` | Comma-separated related document ids. |
207
209
  | `--meta <spec>` | JSON literal or `file=<path>`. |
208
210
  | `--file <path>` | LiteXML envelope. |
211
+ | `--open` | After success, open the admin edit page in the default browser. |
212
+ | `--silent` | On success, emit `ok` instead of the full server response. |
213
+
214
+ `--open` and `--silent` are also available on `post update`, `post edit`,
215
+ `note create`/`update`, and `page create`/`update`. The admin URL is
216
+ resolved from the server's `/options/url.admin_url` config; the opened
217
+ URL follows the admin-vue3 hash-router convention
218
+ (`${admin_url}#/<kind>/edit?id=<id>`).
209
219
 
210
220
  ## Notes
211
221
 
package/dist/bin/mxs.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { t as run } from "../mxs-BbNjmEgB.mjs";
2
+ import { t as run } from "../mxs-D9X72Mkv.mjs";
3
3
  export { run };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as defaultMessageFor, c as tagToCode, i as codeForTag, l as toErrorEnvelope, n as defaultGlobalFlags, o as exitCodeForError, r as parseGlobalFlags, s as exitCodeForTag, t as run } from "./mxs-BbNjmEgB.mjs";
1
+ import { a as defaultMessageFor, c as tagToCode, i as codeForTag, l as toErrorEnvelope, n as defaultGlobalFlags, o as exitCodeForError, r as parseGlobalFlags, s as exitCodeForTag, t as run } from "./mxs-D9X72Mkv.mjs";
2
2
  export { codeForTag, defaultGlobalFlags, defaultMessageFor, exitCodeForError, exitCodeForTag, parseGlobalFlags, run, tagToCode, toErrorEnvelope };
@@ -13,7 +13,7 @@ import { webcrypto } from "node:crypto";
13
13
  import * as NFS from "node:fs";
14
14
  import fs, { mkdirSync, readFileSync, realpathSync, renameSync, writeFileSync } from "node:fs";
15
15
  import * as OS from "node:os";
16
- import os from "node:os";
16
+ import os, { arch, platform } from "node:os";
17
17
  import * as Https from "node:https";
18
18
  import { Readable } from "node:stream";
19
19
  import { pipeline } from "node:stream/promises";
@@ -9304,7 +9304,7 @@ const isInSsh = Boolean(process$1.env.SSH_CONNECTION || process$1.env.SSH_CLIENT
9304
9304
  const fallbackAttemptSymbol = Symbol("fallbackAttempt");
9305
9305
  const __dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
9306
9306
  const localXdgOpenPath = path.join(__dirname, "xdg-open");
9307
- const { platform, arch } = process$1;
9307
+ const { platform: platform$1, arch: arch$1 } = process$1;
9308
9308
  const tryEachApp = async (apps, opener) => {
9309
9309
  if (apps.length === 0) return;
9310
9310
  const errors = [];
@@ -9385,13 +9385,13 @@ const baseOpen = async (options) => {
9385
9385
  const childProcessOptions = {};
9386
9386
  let shouldUseWindowsInWsl = false;
9387
9387
  if (is_wsl_default && !isInsideContainer() && !isInSsh && !app) shouldUseWindowsInWsl = await canAccessPowerShell();
9388
- if (platform === "darwin") {
9388
+ if (platform$1 === "darwin") {
9389
9389
  command = "open";
9390
9390
  if (options.wait) cliArguments.push("--wait-apps");
9391
9391
  if (options.background) cliArguments.push("--background");
9392
9392
  if (options.newInstance) cliArguments.push("--new");
9393
9393
  if (app) cliArguments.push("-a", app);
9394
- } else if (platform === "win32" || shouldUseWindowsInWsl) {
9394
+ } else if (platform$1 === "win32" || shouldUseWindowsInWsl) {
9395
9395
  command = await powerShellPath();
9396
9396
  cliArguments.push(...executePowerShell.argumentsPrefix);
9397
9397
  if (!is_wsl_default) childProcessOptions.windowsVerbatimArguments = true;
@@ -9417,7 +9417,7 @@ const baseOpen = async (options) => {
9417
9417
  await fs$1.access(localXdgOpenPath, constants.X_OK);
9418
9418
  exeLocalXdgOpen = true;
9419
9419
  } catch {}
9420
- command = process$1.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen) ? "xdg-open" : localXdgOpenPath;
9420
+ command = process$1.versions.electron ?? (platform$1 === "android" || isBundled || !exeLocalXdgOpen) ? "xdg-open" : localXdgOpenPath;
9421
9421
  }
9422
9422
  if (appArguments.length > 0) cliArguments.push(...appArguments);
9423
9423
  if (!options.wait) {
@@ -9425,7 +9425,7 @@ const baseOpen = async (options) => {
9425
9425
  childProcessOptions.detached = true;
9426
9426
  }
9427
9427
  }
9428
- if (platform === "darwin" && appArguments.length > 0) cliArguments.push("--args", ...appArguments);
9428
+ if (platform$1 === "darwin" && appArguments.length > 0) cliArguments.push("--args", ...appArguments);
9429
9429
  if (options.target) cliArguments.push(options.target);
9430
9430
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
9431
9431
  if (options.wait) return new Promise((resolve, reject) => {
@@ -9470,13 +9470,13 @@ const open = (target, options) => {
9470
9470
  };
9471
9471
  function detectArchBinary(binary) {
9472
9472
  if (typeof binary === "string" || Array.isArray(binary)) return binary;
9473
- const { [arch]: archBinary } = binary;
9474
- if (!archBinary) throw new Error(`${arch} is not supported`);
9473
+ const { [arch$1]: archBinary } = binary;
9474
+ if (!archBinary) throw new Error(`${arch$1} is not supported`);
9475
9475
  return archBinary;
9476
9476
  }
9477
- function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
9477
+ function detectPlatformBinary({ [platform$1]: platformBinary }, { wsl } = {}) {
9478
9478
  if (wsl && is_wsl_default) return detectArchBinary(wsl);
9479
- if (!platformBinary) throw new Error(`${platform} is not supported`);
9479
+ if (!platformBinary) throw new Error(`${platform$1} is not supported`);
9480
9480
  return detectArchBinary(platformBinary);
9481
9481
  }
9482
9482
  const apps = {
@@ -26802,6 +26802,32 @@ const extractServerMessage = (body) => {
26802
26802
  return null;
26803
26803
  };
26804
26804
  //#endregion
26805
+ //#region src/domain/version.ts
26806
+ const requireFrom$2 = createRequire(import.meta.url);
26807
+ const resolveCliVersion$2 = () => {
26808
+ for (const candidate of [
26809
+ "../package.json",
26810
+ "../../package.json",
26811
+ "../../../package.json"
26812
+ ]) try {
26813
+ const pkg = requireFrom$2(candidate);
26814
+ if (pkg.name === "@mx-space/cli" && typeof pkg.version === "string") return pkg.version;
26815
+ } catch {}
26816
+ return "0.0.0-unknown";
26817
+ };
26818
+ /**
26819
+ * RFC-7231-style User-Agent. Format:
26820
+ * `mxs/<cli-version> (<os-platform> <os-arch>; node/<node-version>)`
26821
+ *
26822
+ * Example: `mxs/0.4.0 (darwin arm64; node/v22.22.2)`
26823
+ *
26824
+ * mx-core's spider guard whitelists any UA containing `mx-space`; this string
26825
+ * does (`mxs` is the @mx-space/cli binary). Authenticated requests bypass the
26826
+ * guard regardless of UA, but a well-formed UA helps server-side analytics
26827
+ * tell agent traffic apart from human browser sessions.
26828
+ */
26829
+ const USER_AGENT = `mxs/${resolveCliVersion$2()} (${platform()} ${arch()}; node/${process.version}) @mx-space/cli`;
26830
+ //#endregion
26805
26831
  //#region src/services/Api.ts
26806
26832
  var Api = class Api extends Tag$2("Api")() {
26807
26833
  /**
@@ -26883,6 +26909,7 @@ function makeApiService(http, config, auth, opts) {
26883
26909
  const url = buildUrl(resolved.apiBase, path, effectiveQuery);
26884
26910
  const baseHeaders = {
26885
26911
  accept: "application/json",
26912
+ "user-agent": USER_AGENT,
26886
26913
  ...options.headers
26887
26914
  };
26888
26915
  if (token) baseHeaders.authorization = `Bearer ${token}`;
@@ -27459,6 +27486,32 @@ const configCmd = make$12("config").pipe(withDescription(help$5.description), wi
27459
27486
  edit$3
27460
27487
  ]));
27461
27488
  //#endregion
27489
+ //#region src/domain/admin-link.ts
27490
+ const buildEditUrl = (adminUrl, kind, id) => {
27491
+ return `${adminUrl.replace(/\/+$/, "")}#/${kind}/edit?id=${encodeURIComponent(id)}`;
27492
+ };
27493
+ /**
27494
+ * Resolve the server's admin URL from `/options/url`, build the admin
27495
+ * edit-page URL for the given resource, and open it in the user's browser.
27496
+ * Non-fatal: missing admin_url or browser-launch failures emit a warning
27497
+ * and the parent effect continues.
27498
+ */
27499
+ const openAdminEdit = (kind, id) => gen(function* () {
27500
+ const renderer = yield* Renderer;
27501
+ const opts = yield* (yield* Api).request("/options/url");
27502
+ const adminUrl = opts.data?.admin_url ?? opts.admin_url;
27503
+ if (!adminUrl) {
27504
+ yield* renderer.emitWarn("admin_url is not configured on the server; skipping --open");
27505
+ return;
27506
+ }
27507
+ const url = buildEditUrl(adminUrl, kind, id);
27508
+ yield* renderer.emitInfo(`opening admin: ${url}`);
27509
+ yield* tryPromise({
27510
+ try: () => open(url),
27511
+ catch: () => /* @__PURE__ */ new Error("failed to launch browser")
27512
+ }).pipe(catchAll((e) => renderer.emitWarn(`could not launch browser: ${e instanceof Error ? e.message : String(e)}`)));
27513
+ });
27514
+ //#endregion
27462
27515
  //#region ../../node_modules/.pnpm/@lexical+table@0.44.0/node_modules/@lexical/table/LexicalTable.node.mjs
27463
27516
  /**
27464
27517
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -29130,28 +29183,102 @@ const resolveContent = (flagSpec, envelope, format) => gen(function* () {
29130
29183
  };
29131
29184
  });
29132
29185
  //#endregion
29133
- //#region src/cli/note/_flags.ts
29186
+ //#region src/cli/post/_flags.ts
29134
29187
  const optional$1 = (self) => optional$2(self);
29135
29188
  const unwrap$4 = (value) => getOrUndefined(value);
29136
29189
  const title$2 = optional$1(text$1("title"));
29137
29190
  const slug$4 = optional$1(text$1("slug"));
29138
- const topic = optional$1(text$1("topic"));
29191
+ const category = optional$1(text$1("category"));
29139
29192
  const content$2 = optional$1(text$1("content"));
29140
- const mood = optional$1(text$1("mood"));
29141
- const weather = optional$1(text$1("weather"));
29142
- const publicAt = optional$1(text$1("public-at"));
29143
- const password = optional$1(text$1("password"));
29144
- const coords = optional$1(text$1("coords"));
29145
- const location$1 = optional$1(text$1("location"));
29146
- const images = optional$1(text$1("images"));
29147
- const meta$2 = optional$1(text$1("meta"));
29193
+ const summary = optional$1(text$1("summary"));
29148
29194
  const file$2 = optional$1(text$1("file"));
29149
- const bookmark = optional$1(text$1("bookmark"));
29150
- const noteWriteOptions = {
29195
+ const meta$2 = optional$1(text$1("meta"));
29196
+ const pin = optional$1(text$1("pin"));
29197
+ const format$2 = choice("format", ["lexical", "markdown"]).pipe(optional$2);
29198
+ const state$3 = choice("state", ["publish", "draft"]).pipe(optional$2);
29199
+ const tags = optional$1(text$1("tags"));
29200
+ const related = optional$1(text$1("related"));
29201
+ const pinOrder = optional$1(integer("pin-order"));
29202
+ const copyright = optional$1(text$1("copyright"));
29203
+ const openFlag$2 = boolean("open").pipe(withDescription$3("After success, open the admin edit page in the default browser."));
29204
+ const silentFlag$2 = boolean("silent").pipe(withDescription$3("On success, emit a minimal `ok` instead of the full server response (saves output tokens). Errors still print normally."));
29205
+ const parseCsv = (v) => {
29206
+ if (v === void 0) return void 0;
29207
+ return v.split(",").map((s) => s.trim()).filter(Boolean);
29208
+ };
29209
+ const parseCopyright = (v) => v === void 0 ? void 0 : v === "true";
29210
+ const postWriteOptions = {
29151
29211
  title: title$2,
29152
29212
  slug: slug$4,
29153
- topic,
29213
+ category,
29154
29214
  content: content$2,
29215
+ format: format$2,
29216
+ summary,
29217
+ state: state$3,
29218
+ tags,
29219
+ copyright,
29220
+ pin,
29221
+ pinOrder,
29222
+ related,
29223
+ meta: meta$2,
29224
+ file: file$2,
29225
+ open: openFlag$2,
29226
+ silent: silentFlag$2
29227
+ };
29228
+ /** Resolve `__categoryName` placeholder (set by `buildPostPayload`) → `categoryId`. */
29229
+ const resolveCategoryRefs = (payload) => gen(function* () {
29230
+ const next = { ...payload };
29231
+ const nameRef = next.__categoryName;
29232
+ delete next.__categoryName;
29233
+ if (typeof nameRef === "string" && nameRef.length > 0 && !next.categoryId) next.categoryId = yield* (yield* Resolver).resolveCategory(nameRef);
29234
+ return next;
29235
+ });
29236
+ const toPostFlagInputs = (opts) => ({
29237
+ title: unwrap$4(opts.title),
29238
+ slug: unwrap$4(opts.slug),
29239
+ category: unwrap$4(opts.category),
29240
+ content: unwrap$4(opts.content),
29241
+ format: unwrap$4(opts.format),
29242
+ summary: unwrap$4(opts.summary),
29243
+ state: unwrap$4(opts.state),
29244
+ tags: parseCsv(unwrap$4(opts.tags)),
29245
+ copyright: parseCopyright(unwrap$4(opts.copyright)),
29246
+ pin: unwrap$4(opts.pin),
29247
+ pinOrder: unwrap$4(opts.pinOrder),
29248
+ related: parseCsv(unwrap$4(opts.related)),
29249
+ meta: unwrap$4(opts.meta),
29250
+ file: unwrap$4(opts.file)
29251
+ });
29252
+ /** Extract the id from a server response — handles both `id` and `_id`. */
29253
+ const extractId = (res) => {
29254
+ if (!res || typeof res !== "object") return void 0;
29255
+ const r = res;
29256
+ if (typeof r.id === "string") return r.id;
29257
+ if (typeof r._id === "string") return r._id;
29258
+ };
29259
+ //#endregion
29260
+ //#region src/cli/note/_flags.ts
29261
+ const optional = (self) => optional$2(self);
29262
+ const unwrap$3 = (value) => getOrUndefined(value);
29263
+ const title$1 = optional(text$1("title"));
29264
+ const slug$3 = optional(text$1("slug"));
29265
+ const topic = optional(text$1("topic"));
29266
+ const content$1 = optional(text$1("content"));
29267
+ const mood = optional(text$1("mood"));
29268
+ const weather = optional(text$1("weather"));
29269
+ const publicAt = optional(text$1("public-at"));
29270
+ const password = optional(text$1("password"));
29271
+ const coords = optional(text$1("coords"));
29272
+ const location$1 = optional(text$1("location"));
29273
+ const images = optional(text$1("images"));
29274
+ const meta$1 = optional(text$1("meta"));
29275
+ const file$1 = optional(text$1("file"));
29276
+ const bookmark = optional(text$1("bookmark"));
29277
+ const noteWriteOptions = {
29278
+ title: title$1,
29279
+ slug: slug$3,
29280
+ topic,
29281
+ content: content$1,
29155
29282
  format: choice("format", ["lexical", "markdown"]).pipe(optional$2),
29156
29283
  state: choice("state", ["publish", "draft"]).pipe(optional$2),
29157
29284
  mood,
@@ -29162,27 +29289,29 @@ const noteWriteOptions = {
29162
29289
  coords,
29163
29290
  location: location$1,
29164
29291
  images,
29165
- meta: meta$2,
29166
- file: file$2
29292
+ meta: meta$1,
29293
+ file: file$1,
29294
+ open: boolean("open").pipe(withDescription$3("After success, open the admin edit page in the default browser.")),
29295
+ silent: boolean("silent").pipe(withDescription$3("On success, emit a minimal `ok` instead of the full server response (saves output tokens). Errors still print normally."))
29167
29296
  };
29168
29297
  const parseBoolean = (v) => v === void 0 ? void 0 : v === "true";
29169
29298
  const toNoteFlagInputs = (opts) => ({
29170
- title: unwrap$4(opts.title),
29171
- slug: unwrap$4(opts.slug),
29172
- topic: unwrap$4(opts.topic),
29173
- content: unwrap$4(opts.content),
29174
- format: unwrap$4(opts.format),
29175
- state: unwrap$4(opts.state),
29176
- mood: unwrap$4(opts.mood),
29177
- weather: unwrap$4(opts.weather),
29178
- publicAt: unwrap$4(opts.publicAt),
29179
- password: unwrap$4(opts.password),
29180
- bookmark: parseBoolean(unwrap$4(opts.bookmark)),
29181
- coords: unwrap$4(opts.coords),
29182
- location: unwrap$4(opts.location),
29183
- images: unwrap$4(opts.images),
29184
- meta: unwrap$4(opts.meta),
29185
- file: unwrap$4(opts.file)
29299
+ title: unwrap$3(opts.title),
29300
+ slug: unwrap$3(opts.slug),
29301
+ topic: unwrap$3(opts.topic),
29302
+ content: unwrap$3(opts.content),
29303
+ format: unwrap$3(opts.format),
29304
+ state: unwrap$3(opts.state),
29305
+ mood: unwrap$3(opts.mood),
29306
+ weather: unwrap$3(opts.weather),
29307
+ publicAt: unwrap$3(opts.publicAt),
29308
+ password: unwrap$3(opts.password),
29309
+ bookmark: parseBoolean(unwrap$3(opts.bookmark)),
29310
+ coords: unwrap$3(opts.coords),
29311
+ location: unwrap$3(opts.location),
29312
+ images: unwrap$3(opts.images),
29313
+ meta: unwrap$3(opts.meta),
29314
+ file: unwrap$3(opts.file)
29186
29315
  });
29187
29316
  /** Resolve `__topicName` placeholder → `topicId`. */
29188
29317
  const resolveTopicRefs = (payload) => gen(function* () {
@@ -29202,7 +29331,11 @@ const create$3 = make$12("create", noteWriteOptions, (opts) => gen(function* ()
29202
29331
  method: "POST",
29203
29332
  body: payload
29204
29333
  });
29205
- yield* renderer.emitSuccess(res);
29334
+ yield* renderer.emitSuccess(opts.silent ? { ok: true } : res);
29335
+ if (opts.open) {
29336
+ const id = extractId(res);
29337
+ if (id) yield* openAdminEdit("notes", id);
29338
+ }
29206
29339
  })).pipe(withDescription("create a note"));
29207
29340
  const del$3 = make$12("delete", {
29208
29341
  slugOrId: text$3({ name: "slugOrId" }),
@@ -29405,21 +29538,21 @@ const get$3 = make$12("get", { slugOrId: text$3({ name: "slugOrId" }) }, ({ slug
29405
29538
  //#region src/cli/note/list.ts
29406
29539
  const page$1 = integer("page").pipe(optional$2);
29407
29540
  const size$1 = integer("size").pipe(optional$2);
29408
- const state$2 = text$1("state").pipe(optional$2);
29541
+ const state$1 = text$1("state").pipe(optional$2);
29409
29542
  const sort$1 = text$1("sort").pipe(optional$2);
29410
- const unwrap$3 = (value) => getOrUndefined(value);
29543
+ const unwrap$2 = (value) => getOrUndefined(value);
29411
29544
  const list$3 = make$12("list", {
29412
29545
  page: page$1,
29413
29546
  size: size$1,
29414
- state: state$2,
29547
+ state: state$1,
29415
29548
  sort: sort$1
29416
29549
  }, ({ page, size, sort }) => gen(function* () {
29417
29550
  const api = yield* Api;
29418
29551
  const renderer = yield* Renderer;
29419
29552
  const res = yield* api.request("/notes", { query: {
29420
- page: unwrap$3(page),
29421
- size: unwrap$3(size),
29422
- sortBy: unwrap$3(sort)
29553
+ page: unwrap$2(page),
29554
+ size: unwrap$2(size),
29555
+ sortBy: unwrap$2(sort)
29423
29556
  } });
29424
29557
  yield* renderer.emitSuccess(res);
29425
29558
  })).pipe(withDescription("list notes"));
@@ -29464,7 +29597,8 @@ const update$3 = make$12("update", {
29464
29597
  method: "PATCH",
29465
29598
  body: resolved
29466
29599
  });
29467
- yield* renderer.emitSuccess(res);
29600
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
29601
+ if (rest.open) yield* openAdminEdit("notes", id);
29468
29602
  })).pipe(withDescription("partially update a note"));
29469
29603
  //#endregion
29470
29604
  //#region src/cli/note/index.ts
@@ -29549,18 +29683,20 @@ const pageWriteOptions = {
29549
29683
  content: optional$2(text$1("content")),
29550
29684
  format: choice("format", ["lexical", "markdown"]).pipe(optional$2),
29551
29685
  meta: optional$2(text$1("meta")),
29552
- file: optional$2(text$1("file"))
29686
+ file: optional$2(text$1("file")),
29687
+ open: boolean("open").pipe(withDescription$3("After success, open the admin edit page in the default browser.")),
29688
+ silent: boolean("silent").pipe(withDescription$3("On success, emit a minimal `ok` instead of the full server response (saves output tokens). Errors still print normally."))
29553
29689
  };
29554
- const unwrap$2 = (value) => getOrUndefined(value);
29690
+ const unwrap$1 = (value) => getOrUndefined(value);
29555
29691
  const toPageFlagInputs = (opts) => ({
29556
- title: unwrap$2(opts.title),
29557
- slug: unwrap$2(opts.slug),
29558
- subtitle: unwrap$2(opts.subtitle),
29559
- order: unwrap$2(opts.order),
29560
- content: unwrap$2(opts.content),
29561
- format: unwrap$2(opts.format),
29562
- meta: unwrap$2(opts.meta),
29563
- file: unwrap$2(opts.file)
29692
+ title: unwrap$1(opts.title),
29693
+ slug: unwrap$1(opts.slug),
29694
+ subtitle: unwrap$1(opts.subtitle),
29695
+ order: unwrap$1(opts.order),
29696
+ content: unwrap$1(opts.content),
29697
+ format: unwrap$1(opts.format),
29698
+ meta: unwrap$1(opts.meta),
29699
+ file: unwrap$1(opts.file)
29564
29700
  });
29565
29701
  const create$2 = make$12("create", pageWriteOptions, (opts) => gen(function* () {
29566
29702
  const built = yield* buildPagePayload(toPageFlagInputs(opts));
@@ -29570,7 +29706,11 @@ const create$2 = make$12("create", pageWriteOptions, (opts) => gen(function* ()
29570
29706
  method: "POST",
29571
29707
  body: built.payload
29572
29708
  });
29573
- yield* renderer.emitSuccess(res);
29709
+ yield* renderer.emitSuccess(opts.silent ? { ok: true } : res);
29710
+ if (opts.open) {
29711
+ const id = extractId(res);
29712
+ if (id) yield* openAdminEdit("pages", id);
29713
+ }
29574
29714
  }));
29575
29715
  //#endregion
29576
29716
  //#region src/cli/page/delete.ts
@@ -29803,7 +29943,8 @@ const update$2 = make$12("update", {
29803
29943
  method: "PATCH",
29804
29944
  body
29805
29945
  });
29806
- yield* renderer.emitSuccess(res);
29946
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
29947
+ if (rest.open) yield* openAdminEdit("pages", id);
29807
29948
  }));
29808
29949
  //#endregion
29809
29950
  //#region src/cli/page/index.ts
@@ -29863,69 +30004,6 @@ const pageCmd = make$12("page").pipe(withDescription(help$3.description), withSu
29863
30004
  del$2
29864
30005
  ]));
29865
30006
  //#endregion
29866
- //#region src/cli/post/_flags.ts
29867
- const optional = (self) => optional$2(self);
29868
- const unwrap$1 = (value) => getOrUndefined(value);
29869
- const title = optional(text$1("title"));
29870
- const slug$2 = optional(text$1("slug"));
29871
- const category = optional(text$1("category"));
29872
- const content = optional(text$1("content"));
29873
- const summary = optional(text$1("summary"));
29874
- const file = optional(text$1("file"));
29875
- const meta = optional(text$1("meta"));
29876
- const pin = optional(text$1("pin"));
29877
- const format = choice("format", ["lexical", "markdown"]).pipe(optional$2);
29878
- const state$1 = choice("state", ["publish", "draft"]).pipe(optional$2);
29879
- const tags = optional(text$1("tags"));
29880
- const related = optional(text$1("related"));
29881
- const pinOrder = optional(integer("pin-order"));
29882
- const copyright = optional(text$1("copyright"));
29883
- const parseCsv = (v) => {
29884
- if (v === void 0) return void 0;
29885
- return v.split(",").map((s) => s.trim()).filter(Boolean);
29886
- };
29887
- const parseCopyright = (v) => v === void 0 ? void 0 : v === "true";
29888
- const postWriteOptions = {
29889
- title,
29890
- slug: slug$2,
29891
- category,
29892
- content,
29893
- format,
29894
- summary,
29895
- state: state$1,
29896
- tags,
29897
- copyright,
29898
- pin,
29899
- pinOrder,
29900
- related,
29901
- meta,
29902
- file
29903
- };
29904
- /** Resolve `__categoryName` placeholder (set by `buildPostPayload`) → `categoryId`. */
29905
- const resolveCategoryRefs = (payload) => gen(function* () {
29906
- const next = { ...payload };
29907
- const nameRef = next.__categoryName;
29908
- delete next.__categoryName;
29909
- if (typeof nameRef === "string" && nameRef.length > 0 && !next.categoryId) next.categoryId = yield* (yield* Resolver).resolveCategory(nameRef);
29910
- return next;
29911
- });
29912
- const toPostFlagInputs = (opts) => ({
29913
- title: unwrap$1(opts.title),
29914
- slug: unwrap$1(opts.slug),
29915
- category: unwrap$1(opts.category),
29916
- content: unwrap$1(opts.content),
29917
- format: unwrap$1(opts.format),
29918
- summary: unwrap$1(opts.summary),
29919
- state: unwrap$1(opts.state),
29920
- tags: parseCsv(unwrap$1(opts.tags)),
29921
- copyright: parseCopyright(unwrap$1(opts.copyright)),
29922
- pin: unwrap$1(opts.pin),
29923
- pinOrder: unwrap$1(opts.pinOrder),
29924
- related: parseCsv(unwrap$1(opts.related)),
29925
- meta: unwrap$1(opts.meta),
29926
- file: unwrap$1(opts.file)
29927
- });
29928
- //#endregion
29929
30007
  //#region src/cli/post/create.ts
29930
30008
  const create$1 = make$12("create", postWriteOptions, (opts) => gen(function* () {
29931
30009
  const payload = yield* resolveCategoryRefs((yield* buildPostPayload(toPostFlagInputs(opts))).payload);
@@ -29935,7 +30013,11 @@ const create$1 = make$12("create", postWriteOptions, (opts) => gen(function* ()
29935
30013
  method: "POST",
29936
30014
  body: payload
29937
30015
  });
29938
- yield* renderer.emitSuccess(res);
30016
+ yield* renderer.emitSuccess(opts.silent ? { ok: true } : res);
30017
+ if (opts.open) {
30018
+ const id = extractId(res);
30019
+ if (id) yield* openAdminEdit("posts", id);
30020
+ }
29939
30021
  })).pipe(withDescription("create a post"));
29940
30022
  const del$1 = make$12("delete", {
29941
30023
  slugOrId: text$3({ name: "slugOrId" }),
@@ -30029,7 +30111,8 @@ const edit = make$12("edit", {
30029
30111
  method: "PUT",
30030
30112
  body: resolved
30031
30113
  });
30032
- yield* renderer.emitSuccess(res);
30114
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
30115
+ if (rest.open) yield* openAdminEdit("posts", id);
30033
30116
  return;
30034
30117
  }
30035
30118
  const resolved = yield* resolveCategoryRefs((yield* buildPostPayload(flags)).payload);
@@ -30038,7 +30121,8 @@ const edit = make$12("edit", {
30038
30121
  method: "PUT",
30039
30122
  body: resolved
30040
30123
  });
30041
- yield* renderer.emitSuccess(res);
30124
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
30125
+ if (rest.open) yield* openAdminEdit("posts", id);
30042
30126
  })).pipe(withDescription("edit a post via $EDITOR or flags"));
30043
30127
  //#endregion
30044
30128
  //#region src/cli/post/view.ts
@@ -30223,7 +30307,8 @@ const update$1 = make$12("update", {
30223
30307
  method: "PATCH",
30224
30308
  body: resolved
30225
30309
  });
30226
- yield* renderer.emitSuccess(res);
30310
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
30311
+ if (rest.open) yield* openAdminEdit("posts", id);
30227
30312
  })).pipe(withDescription("partially update a post"));
30228
30313
  //#endregion
30229
30314
  //#region src/cli/post/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-space/cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Command line interface for mx-space (mx-core) — auth, content, configuration",
5
5
  "keywords": [
6
6
  "mx-space",