@mx-space/cli 0.10.0 → 0.11.0

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/bin/mxs.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { t as run } from "../mxs-BLgwEih6.mjs";
2
+ import { t as run } from "../mxs-BNvfyLLp.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-BLgwEih6.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-BNvfyLLp.mjs";
2
2
  export { codeForTag, defaultGlobalFlags, defaultMessageFor, exitCodeForError, exitCodeForTag, parseGlobalFlags, run, tagToCode, toErrorEnvelope };
@@ -13,7 +13,7 @@ import fs, { existsSync, mkdirSync, openSync, readFileSync, realpathSync, rename
13
13
  import * as OS from "node:os";
14
14
  import os, { arch, platform } from "node:os";
15
15
  import * as Path from "node:path";
16
- import path from "node:path";
16
+ import path, { basename } from "node:path";
17
17
  import * as NodeUrl from "node:url";
18
18
  import { fileURLToPath } from "node:url";
19
19
  import * as readline from "node:readline";
@@ -23,7 +23,7 @@ import * as Https from "node:https";
23
23
  import { pipeline } from "node:stream/promises";
24
24
  import { promisify, styleText } from "node:util";
25
25
  import { Buffer as Buffer$1 } from "node:buffer";
26
- import fs$1, { constants } from "node:fs/promises";
26
+ import fs$1, { constants, readFile } from "node:fs/promises";
27
27
  import process$1, { stdin, stdout } from "node:process";
28
28
  //#region ../../node_modules/.pnpm/@effect+platform@0.96.1_effect@3.21.2/node_modules/@effect/platform/dist/esm/Error.js
29
29
  /**
@@ -4640,7 +4640,7 @@ const levensteinDistance = (first, second, config) => {
4640
4640
  //#endregion
4641
4641
  //#region ../../node_modules/.pnpm/@effect+cli@0.75.2_@effect+platform@0.96.1_effect@3.21.2__@effect+printer-ansi@0.49.0_@_4d5fe3e52e753e91ea7f4be1c61c2cec/node_modules/@effect/cli/dist/esm/internal/prompt/list.js
4642
4642
  /** @internal */
4643
- const list$9 = (options) => text$9(options).pipe(map$3((output) => output.split(options.delimiter || ",")));
4643
+ const list$10 = (options) => text$9(options).pipe(map$3((output) => output.split(options.delimiter || ",")));
4644
4644
  /** @internal */
4645
4645
  const OptionsTypeId = /*#__PURE__*/ Symbol.for("@effect/cli/Options");
4646
4646
  const proto$2 = {
@@ -4684,8 +4684,8 @@ const boolean$1 = (name, options) => {
4684
4684
  ...options
4685
4685
  };
4686
4686
  const option = makeSingle(name, aliases, boolean$2(some(ifPresent)));
4687
- if (isNonEmptyReadonlyArray(negationNames)) return withDefault(orElse(option, makeSingle(headNonEmpty(negationNames), tailNonEmpty(negationNames), boolean$2(some(!ifPresent)))), !ifPresent);
4688
- return withDefault(option, !ifPresent);
4687
+ if (isNonEmptyReadonlyArray(negationNames)) return withDefault$1(orElse(option, makeSingle(headNonEmpty(negationNames), tailNonEmpty(negationNames), boolean$2(some(!ifPresent)))), !ifPresent);
4688
+ return withDefault$1(option, !ifPresent);
4689
4689
  };
4690
4690
  /** @internal */
4691
4691
  const choice$1 = (name, choices) => {
@@ -4711,7 +4711,7 @@ const getUsage$1 = (self) => getUsageInternal$1(self);
4711
4711
  /** @internal */
4712
4712
  const map$1 = /*#__PURE__*/ dual(2, (self, f) => makeMap(self, (a) => right(f(a))));
4713
4713
  /** @internal */
4714
- const optional$4 = (self) => withDefault(map$1(self, some), none$3());
4714
+ const optional$4 = (self) => withDefault$1(map$1(self, some), none$3());
4715
4715
  /** @internal */
4716
4716
  const orElse = /*#__PURE__*/ dual(2, (self, that) => orElseEither(self, that).pipe(map$1(merge$2)));
4717
4717
  /** @internal */
@@ -4731,7 +4731,7 @@ const withAlias = /*#__PURE__*/ dual(2, (self, alias) => modifySingle(self, (sin
4731
4731
  return makeSingle(single.name, aliases, single.primitiveType, single.description, single.pseudoName);
4732
4732
  }));
4733
4733
  /** @internal */
4734
- const withDefault = /*#__PURE__*/ dual(2, (self, fallback) => makeWithDefault(self, fallback));
4734
+ const withDefault$1 = /*#__PURE__*/ dual(2, (self, fallback) => makeWithDefault(self, fallback));
4735
4735
  /** @internal */
4736
4736
  const withDescription$4 = /*#__PURE__*/ dual(2, (self, desc) => modifySingle(self, (single) => {
4737
4737
  const description = sequence(single.description, p$1(desc));
@@ -5058,7 +5058,7 @@ const wizardInternal$1 = (self, config) => {
5058
5058
  return parseCommandLine(self, args, config).pipe(as(args));
5059
5059
  }), zipLeft(log()));
5060
5060
  }
5061
- case "KeyValueMap": return list$9({
5061
+ case "KeyValueMap": return list$10({
5062
5062
  message: toAnsiText(p$1("Enter `key=value` pairs separated by spaces")).trim(),
5063
5063
  delimiter: " "
5064
5064
  }).pipe(flatMap$1((args) => {
@@ -5641,6 +5641,11 @@ const optional$3 = optional$4;
5641
5641
  * @since 1.0.0
5642
5642
  * @category combinators
5643
5643
  */
5644
+ const withDefault = withDefault$1;
5645
+ /**
5646
+ * @since 1.0.0
5647
+ * @category combinators
5648
+ */
5644
5649
  const withDescription$3 = withDescription$4;
5645
5650
  //#endregion
5646
5651
  //#region ../../node_modules/.pnpm/@effect+cli@0.75.2_@effect+platform@0.96.1_effect@3.21.2__@effect+printer-ansi@0.49.0_@_4d5fe3e52e753e91ea7f4be1c61c2cec/node_modules/@effect/cli/dist/esm/internal/builtInOptions.js
@@ -7249,7 +7254,7 @@ const readDirectory = (path, options) => tryPromise({
7249
7254
  try: () => NFS.promises.readdir(path, options),
7250
7255
  catch: (err) => handleErrnoException("FileSystem", "readDirectory")(err, [path])
7251
7256
  });
7252
- const readFile = (path) => async((resume, signal) => {
7257
+ const readFile$1 = (path) => async((resume, signal) => {
7253
7258
  try {
7254
7259
  NFS.readFile(path, { signal }, (err, data) => {
7255
7260
  if (err) resume(fail$2(handleErrnoException("FileSystem", "readFile")(err, [path])));
@@ -7267,7 +7272,7 @@ const realPath = /*#__PURE__*/ (() => {
7267
7272
  const nodeRealPath = /*#__PURE__*/ effectify(NFS.realpath, /*#__PURE__*/ handleErrnoException("FileSystem", "realPath"), /*#__PURE__*/ handleBadArgument("realPath"));
7268
7273
  return (path) => nodeRealPath(path);
7269
7274
  })();
7270
- const rename = /*#__PURE__*/ (() => {
7275
+ const rename$1 = /*#__PURE__*/ (() => {
7271
7276
  const nodeRename = /*#__PURE__*/ effectify(NFS.rename, /*#__PURE__*/ handleErrnoException("FileSystem", "rename"), /*#__PURE__*/ handleBadArgument("rename"));
7272
7277
  return (oldPath, newPath) => nodeRename(oldPath, newPath);
7273
7278
  })();
@@ -7370,11 +7375,11 @@ const layer$7 = /* @__PURE__ */ effect(FileSystem, /* @__PURE__ */ map$6(/*#__PU
7370
7375
  makeTempFileScoped,
7371
7376
  open: open$1,
7372
7377
  readDirectory,
7373
- readFile,
7378
+ readFile: readFile$1,
7374
7379
  readLink,
7375
7380
  realPath,
7376
7381
  remove: remove$3,
7377
- rename,
7382
+ rename: rename$1,
7378
7383
  stat,
7379
7384
  symlink,
7380
7385
  truncate,
@@ -8340,7 +8345,7 @@ const put$1 = /*#__PURE__*/ make$10("PUT");
8340
8345
  /** @internal */
8341
8346
  const patch$1 = /*#__PURE__*/ make$10("PATCH");
8342
8347
  /** @internal */
8343
- const del$8 = /*#__PURE__*/ make$10("DELETE");
8348
+ const del$9 = /*#__PURE__*/ make$10("DELETE");
8344
8349
  /** @internal */
8345
8350
  const head$1 = /*#__PURE__*/ make$10("HEAD");
8346
8351
  /** @internal */
@@ -8449,7 +8454,7 @@ const ClientProto = {
8449
8454
  return this.execute(patch$1(url, options));
8450
8455
  },
8451
8456
  del(url, options) {
8452
- return this.execute(del$8(url, options));
8457
+ return this.execute(del$9(url, options));
8453
8458
  },
8454
8459
  options(url, options) {
8455
8460
  return this.execute(options$1(url, options));
@@ -8612,7 +8617,7 @@ var InterruptibleResponse = class {
8612
8617
  return this.original[NodeInspectSymbol]();
8613
8618
  }
8614
8619
  };
8615
- const { del: del$7, execute, get: get$9, head, options, patch, post, put } = /*#__PURE__*/ serviceFunctions(tag);
8620
+ const { del: del$8, execute, get: get$9, head, options, patch, post, put } = /*#__PURE__*/ serviceFunctions(tag);
8616
8621
  /** @internal */
8617
8622
  const transformResponse = /*#__PURE__*/ dual(2, (self, f) => {
8618
8623
  const client = self;
@@ -12570,7 +12575,7 @@ function customAlphabet(alphabet, size = 21) {
12570
12575
  return customRandom(alphabet, size, random);
12571
12576
  }
12572
12577
  //#endregion
12573
- //#region ../../node_modules/.pnpm/@haklex+rich-litexml@0.21.0/node_modules/@haklex/rich-litexml/dist/src-CWxDj4Bd.js
12578
+ //#region ../../node_modules/.pnpm/@haklex+rich-litexml@0.22.0/node_modules/@haklex/rich-litexml/dist/src-CWxDj4Bd.js
12574
12579
  var impl = null;
12575
12580
  function registerParseHTML(fn) {
12576
12581
  impl = fn;
@@ -24908,7 +24913,7 @@ function Document() {
24908
24913
  }
24909
24914
  setPrototypeOf(Document, Document$1).prototype = Document$1.prototype;
24910
24915
  //#endregion
24911
- //#region ../../node_modules/.pnpm/@haklex+rich-litexml@0.21.0/node_modules/@haklex/rich-litexml/dist/node.mjs
24916
+ //#region ../../node_modules/.pnpm/@haklex+rich-litexml@0.22.0/node_modules/@haklex/rich-litexml/dist/node.mjs
24912
24917
  registerParseHTML((html) => parseHTML(html).document);
24913
24918
  //#endregion
24914
24919
  //#region ../editor/src/core/litexml.ts
@@ -25048,7 +25053,7 @@ const TRANSFORMERS = mod$1.TRANSFORMERS;
25048
25053
  mod$1.UNORDERED_LIST;
25049
25054
  mod$1.registerMarkdownShortcuts;
25050
25055
  //#endregion
25051
- //#region ../../node_modules/.pnpm/@haklex+rich-headless@0.20.0_lexical@0.45.0/node_modules/@haklex/rich-headless/dist/transformers.mjs
25056
+ //#region ../../node_modules/.pnpm/@haklex+rich-headless@0.22.0_lexical@0.45.0/node_modules/@haklex/rich-headless/dist/transformers.mjs
25052
25057
  /**
25053
25058
  * Headless Markdown transformers — export-only (Lexical → Markdown).
25054
25059
  * Import stubs are no-ops; used only for $convertToMarkdownString.
@@ -25475,7 +25480,7 @@ function $toMarkdown() {
25475
25480
  return $convertToMarkdownString(allHeadlessTransformers);
25476
25481
  }
25477
25482
  //#endregion
25478
- //#region ../../node_modules/.pnpm/@haklex+rich-headless@0.20.0_lexical@0.45.0/node_modules/@haklex/rich-headless/dist/index.mjs
25483
+ //#region ../../node_modules/.pnpm/@haklex+rich-headless@0.22.0_lexical@0.45.0/node_modules/@haklex/rich-headless/dist/index.mjs
25479
25484
  var INTRINSIC_TYPES = [
25480
25485
  "root",
25481
25486
  "paragraph",
@@ -26468,7 +26473,7 @@ const codeblockRenderer = (node, ctx) => {
26468
26473
  };
26469
26474
  //#endregion
26470
26475
  //#region src/cli/render/lexical/embeds.ts
26471
- const basename = (path) => {
26476
+ const basename$1 = (path) => {
26472
26477
  const idx = path.lastIndexOf("/");
26473
26478
  return idx >= 0 ? path.slice(idx + 1) : path;
26474
26479
  };
@@ -26476,7 +26481,7 @@ const imgRenderer = (node, ctx) => {
26476
26481
  const { alt, src, caption } = node.attrs;
26477
26482
  let label;
26478
26483
  if (alt) label = `[image: ${alt}]`;
26479
- else if (src) label = `[image: ${basename(src)}]`;
26484
+ else if (src) label = `[image: ${basename$1(src)}]`;
26480
26485
  else label = "[image]";
26481
26486
  const main = wrap(ANSI.dim, label, ctx.color);
26482
26487
  if (caption) return `${main}\n${wrap(ANSI.dim, caption, ctx.color)}`;
@@ -30971,7 +30976,7 @@ const whoami = make$13("whoami", {}, () => gen(function* () {
30971
30976
  }));
30972
30977
  //#endregion
30973
30978
  //#region src/cli/auth/index.ts
30974
- const help$10 = registerCommandHelp({
30979
+ const help$11 = registerCommandHelp({
30975
30980
  name: "auth",
30976
30981
  description: "authentication",
30977
30982
  verbs: [
@@ -30994,7 +30999,7 @@ const help$10 = registerCommandHelp({
30994
30999
  }
30995
31000
  ]
30996
31001
  });
30997
- const authCmd = make$13("auth").pipe(withDescription(help$10.description), withSubcommands([
31002
+ const authCmd = make$13("auth").pipe(withDescription(help$11.description), withSubcommands([
30998
31003
  login,
30999
31004
  logout,
31000
31005
  whoami,
@@ -31614,7 +31619,7 @@ var Resolver = class Resolver extends Tag$2("Resolver")() {
31614
31619
  return make$3(yield* Api);
31615
31620
  }));
31616
31621
  };
31617
- const del$6 = make$13("delete", {
31622
+ const del$7 = make$13("delete", {
31618
31623
  slugOrId: text$6({ name: "slugOrId" }),
31619
31624
  force: boolean("force")
31620
31625
  }, ({ slugOrId, force }) => gen(function* () {
@@ -31633,7 +31638,7 @@ const get$8 = make$13("get", { slugOrId: text$6({ name: "slugOrId" }) }, ({ slug
31633
31638
  }));
31634
31639
  //#endregion
31635
31640
  //#region src/cli/category/list.ts
31636
- const list$8 = make$13("list", {}, () => gen(function* () {
31641
+ const list$9 = make$13("list", {}, () => gen(function* () {
31637
31642
  const api = yield* Api;
31638
31643
  const renderer = yield* Renderer;
31639
31644
  const res = yield* api.request("/categories");
@@ -31666,7 +31671,7 @@ const update$5 = make$13("update", {
31666
31671
  }));
31667
31672
  //#endregion
31668
31673
  //#region src/cli/category/index.ts
31669
- const help$9 = registerCommandHelp({
31674
+ const help$10 = registerCommandHelp({
31670
31675
  name: "category",
31671
31676
  description: "manage categories / tags",
31672
31677
  verbs: [
@@ -31706,12 +31711,12 @@ const help$9 = registerCommandHelp({
31706
31711
  }
31707
31712
  ]
31708
31713
  });
31709
- const categoryCmd = make$13("category").pipe(withDescription(help$9.description), withSubcommands([
31710
- list$8,
31714
+ const categoryCmd = make$13("category").pipe(withDescription(help$10.description), withSubcommands([
31715
+ list$9,
31711
31716
  get$8,
31712
31717
  create$5,
31713
31718
  update$5,
31714
- del$6
31719
+ del$7
31715
31720
  ]));
31716
31721
  //#endregion
31717
31722
  //#region src/services/Comment.ts
@@ -31814,7 +31819,7 @@ var Comment = class Comment extends Tag$2("Comment")() {
31814
31819
  //#region src/cli/comment/_flags.ts
31815
31820
  const ids = text$6({ name: "id" }).pipe(repeated);
31816
31821
  const all$1 = boolean("all").pipe(withDescription$3("apply to every comment (optionally filtered by --state)"));
31817
- const force$7 = boolean("force").pipe(withDescription$3("skip TTY confirmation guard"));
31822
+ const force$8 = boolean("force").pipe(withDescription$3("skip TTY confirmation guard"));
31818
31823
  const stateFilter = choice("state", [
31819
31824
  "unread",
31820
31825
  "read",
@@ -31845,7 +31850,7 @@ const requireForceForSingleDelete = (params) => suspend(() => {
31845
31850
  const approve = make$13("approve", {
31846
31851
  ids,
31847
31852
  all: all$1,
31848
- force: force$7,
31853
+ force: force$8,
31849
31854
  state: stateFilter
31850
31855
  }, ({ ids, all, force, state }) => gen(function* () {
31851
31856
  yield* validateBatchSelection({
@@ -31869,10 +31874,10 @@ const approve = make$13("approve", {
31869
31874
  })).pipe(withDescription("mark comments as read; pass ids or --all [--state <s>]"));
31870
31875
  //#endregion
31871
31876
  //#region src/cli/comment/delete.ts
31872
- const del$5 = make$13("delete", {
31877
+ const del$6 = make$13("delete", {
31873
31878
  ids,
31874
31879
  all: all$1,
31875
- force: force$7,
31880
+ force: force$8,
31876
31881
  state: stateFilter
31877
31882
  }, ({ ids, all, force, state }) => gen(function* () {
31878
31883
  yield* validateBatchSelection({
@@ -32042,7 +32047,7 @@ const get$7 = make$13("get", { id: text$6({ name: "id" }) }, ({ id }) => gen(fun
32042
32047
  const res = yield* comment.get(id);
32043
32048
  yield* renderer.emit(commentView, res);
32044
32049
  })).pipe(withDescription("show a single comment by id"));
32045
- const list$7 = make$13("list", {
32050
+ const list$8 = make$13("list", {
32046
32051
  page: integer("page").pipe(optional$3),
32047
32052
  size: integer("size").pipe(optional$3),
32048
32053
  state: stateFilter,
@@ -32063,7 +32068,7 @@ const list$7 = make$13("list", {
32063
32068
  const reject = make$13("reject", {
32064
32069
  ids,
32065
32070
  all: all$1,
32066
- force: force$7,
32071
+ force: force$8,
32067
32072
  state: stateFilter
32068
32073
  }, ({ ids, all, force, state }) => gen(function* () {
32069
32074
  yield* validateBatchSelection({
@@ -32181,7 +32186,7 @@ const unread = make$13("unread", {
32181
32186
  })).pipe(withDescription("list unread comments (alias for `comment list --state unread`)"));
32182
32187
  //#endregion
32183
32188
  //#region src/cli/comment/index.ts
32184
- const help$8 = registerCommandHelp({
32189
+ const help$9 = registerCommandHelp({
32185
32190
  name: "comment",
32186
32191
  description: "list and moderate comments",
32187
32192
  verbs: [
@@ -32248,14 +32253,14 @@ const help$8 = registerCommandHelp({
32248
32253
  }
32249
32254
  ]
32250
32255
  });
32251
- const commentCmd = make$13("comment").pipe(withDescription(help$8.description), withSubcommands([
32252
- list$7,
32256
+ const commentCmd = make$13("comment").pipe(withDescription(help$9.description), withSubcommands([
32257
+ list$8,
32253
32258
  unread,
32254
32259
  get$7,
32255
32260
  reply,
32256
32261
  approve,
32257
32262
  reject,
32258
- del$5
32263
+ del$6
32259
32264
  ]));
32260
32265
  //#endregion
32261
32266
  //#region src/cli/config/edit.ts
@@ -32292,7 +32297,7 @@ const get$6 = make$13("get", { key: text$6({ name: "key" }) }, ({ key }) => gen(
32292
32297
  }));
32293
32298
  //#endregion
32294
32299
  //#region src/cli/config/list.ts
32295
- const list$6 = make$13("list", {}, () => gen(function* () {
32300
+ const list$7 = make$13("list", {}, () => gen(function* () {
32296
32301
  const api = yield* Api;
32297
32302
  const renderer = yield* Renderer;
32298
32303
  const res = yield* api.request("/options");
@@ -32339,7 +32344,7 @@ const set = make$13("set", {
32339
32344
  }));
32340
32345
  //#endregion
32341
32346
  //#region src/cli/config/index.ts
32342
- const help$7 = registerCommandHelp({
32347
+ const help$8 = registerCommandHelp({
32343
32348
  name: "config",
32344
32349
  description: "manage server options",
32345
32350
  verbs: [
@@ -32367,13 +32372,130 @@ const help$7 = registerCommandHelp({
32367
32372
  }
32368
32373
  ]
32369
32374
  });
32370
- const configCmd = make$13("config").pipe(withDescription(help$7.description), withSubcommands([
32371
- list$6,
32375
+ const configCmd = make$13("config").pipe(withDescription(help$8.description), withSubcommands([
32376
+ list$7,
32372
32377
  get$6,
32373
32378
  set,
32374
32379
  edit$4
32375
32380
  ]));
32376
32381
  //#endregion
32382
+ //#region src/cli/file/_shared.ts
32383
+ /** Mirrors the server's `FileTypeEnum` (apps/core modules/file/file.type.ts). */
32384
+ const FILE_TYPES = [
32385
+ "file",
32386
+ "image",
32387
+ "icon",
32388
+ "avatar"
32389
+ ];
32390
+ const typeOption = choice("type", FILE_TYPES).pipe(withDescription$3("server-side storage bucket for the file"), withDefault("file"));
32391
+ const silentFlag$5 = boolean("silent").pipe(withDescription$3("On success, emit a minimal `ok` instead of the full server response."));
32392
+ const del$5 = make$13("delete", {
32393
+ name: text$6({ name: "name" }),
32394
+ type: typeOption,
32395
+ force: boolean("force").pipe(withDescription$3("skip confirmation"))
32396
+ }, ({ name, type, force }) => gen(function* () {
32397
+ if (!force && !process.stdin.isTTY) return yield* fail$2(new ValidationFailed({ message: "refusing to delete without --force in non-TTY context" }));
32398
+ const api = yield* Api;
32399
+ const renderer = yield* Renderer;
32400
+ yield* api.request(`/objects/${type}/${encodeURIComponent(name)}`, { method: "DELETE" });
32401
+ yield* renderer.emitSuccess({ deleted: `${type}/${name}` });
32402
+ })).pipe(withDescription("delete an uploaded file"));
32403
+ //#endregion
32404
+ //#region src/cli/file/list.ts
32405
+ const list$6 = make$13("list", { type: typeOption }, ({ type }) => gen(function* () {
32406
+ const api = yield* Api;
32407
+ const renderer = yield* Renderer;
32408
+ const res = yield* api.request(`/objects/${type}`);
32409
+ yield* renderer.emitSuccess(res);
32410
+ })).pipe(withDescription("list uploaded files of a type (name, url, created)"));
32411
+ const rename = make$13("rename", {
32412
+ name: text$6({ name: "name" }),
32413
+ newName: text$6({ name: "newName" }),
32414
+ type: typeOption
32415
+ }, ({ name, newName, type }) => gen(function* () {
32416
+ const api = yield* Api;
32417
+ const renderer = yield* Renderer;
32418
+ yield* api.request(`/objects/${type}/${encodeURIComponent(name)}/rename`, {
32419
+ method: "PATCH",
32420
+ query: { newName }
32421
+ });
32422
+ yield* renderer.emitSuccess({
32423
+ renamed: `${type}/${name}`,
32424
+ to: newName
32425
+ });
32426
+ })).pipe(withDescription("rename an uploaded file"));
32427
+ const upload = make$13("upload", {
32428
+ path: text$6({ name: "path" }),
32429
+ type: typeOption,
32430
+ name: text$4("name").pipe(withDescription$3("override the uploaded filename (defaults to the local basename)"), optional$3),
32431
+ silent: silentFlag$5
32432
+ }, ({ path, type, name, silent }) => gen(function* () {
32433
+ const buffer = yield* tryPromise({
32434
+ try: () => readFile(path),
32435
+ catch: (err) => new Generic({
32436
+ message: `cannot read file: ${path}`,
32437
+ cause: err
32438
+ })
32439
+ });
32440
+ const filename = name._tag === "Some" ? name.value : basename(path);
32441
+ const form = new FormData();
32442
+ form.append("file", new File([new Uint8Array(buffer)], filename));
32443
+ const api = yield* Api;
32444
+ const renderer = yield* Renderer;
32445
+ const res = yield* api.request(`/objects/upload`, {
32446
+ method: "POST",
32447
+ query: { type },
32448
+ body: form
32449
+ });
32450
+ yield* renderer.emitSuccess(silent ? { ok: true } : res);
32451
+ })).pipe(withDescription(`upload a local file (--type ${FILE_TYPES.join("|")}); returns { url, name }`));
32452
+ //#endregion
32453
+ //#region src/cli/file/index.ts
32454
+ const help$7 = registerCommandHelp({
32455
+ name: "file",
32456
+ description: "upload and manage static files (images, icons, avatars)",
32457
+ verbs: [
32458
+ {
32459
+ name: "upload",
32460
+ args: [
32461
+ "<path>",
32462
+ "[--type file|image|icon|avatar]",
32463
+ "[--name <n>]"
32464
+ ],
32465
+ description: "upload a local file; returns { url, name }"
32466
+ },
32467
+ {
32468
+ name: "list",
32469
+ args: ["[--type <t>]"],
32470
+ description: "list uploaded files of a type"
32471
+ },
32472
+ {
32473
+ name: "delete",
32474
+ args: [
32475
+ "<name>",
32476
+ "[--type <t>]",
32477
+ "[--force]"
32478
+ ],
32479
+ description: "delete an uploaded file"
32480
+ },
32481
+ {
32482
+ name: "rename",
32483
+ args: [
32484
+ "<name>",
32485
+ "<newName>",
32486
+ "[--type <t>]"
32487
+ ],
32488
+ description: "rename an uploaded file"
32489
+ }
32490
+ ]
32491
+ });
32492
+ const fileCmd = make$13("file").pipe(withDescription(help$7.description), withSubcommands([
32493
+ upload,
32494
+ list$6,
32495
+ del$5,
32496
+ rename
32497
+ ]));
32498
+ //#endregion
32377
32499
  //#region src/domain/admin-link.ts
32378
32500
  const buildEditUrl = (adminUrl, kind, id) => {
32379
32501
  const base = adminUrl.replace(/\/+$/, "");
@@ -33080,7 +33202,7 @@ const del$4 = make$13("delete", {
33080
33202
  })).pipe(withDescription("delete a note"));
33081
33203
  //#endregion
33082
33204
  //#region src/cli/note/edit.ts
33083
- const slugOrId$17 = text$6({ name: "slugOrId" });
33205
+ const slugOrId$19 = text$6({ name: "slugOrId" });
33084
33206
  const esc = (s) => s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
33085
33207
  const materializeForEditor$2 = (slugOrId) => gen(function* () {
33086
33208
  const api = yield* Api;
@@ -33123,7 +33245,7 @@ const applyNoteEnvelopeMeta = (payload, rawMeta) => {
33123
33245
  return next;
33124
33246
  };
33125
33247
  const edit$3 = make$13("edit", {
33126
- slugOrId: slugOrId$17,
33248
+ slugOrId: slugOrId$19,
33127
33249
  ...noteWriteOptions
33128
33250
  }, ({ slugOrId, ...rest }) => gen(function* () {
33129
33251
  const flags = toNoteFlagInputs(rest);
@@ -33373,6 +33495,7 @@ const update$4 = make$13("update", {
33373
33495
  delete payload.text;
33374
33496
  delete payload.contentFormat;
33375
33497
  }
33498
+ if (flags.state === void 0) delete payload.isPublished;
33376
33499
  const resolved = yield* resolveTopicRefs(payload);
33377
33500
  const id = yield* (yield* Resolver).resolveNoteId(slugOrId);
33378
33501
  const api = yield* Api;
@@ -33498,7 +33621,7 @@ const create$3 = make$13("create", pageWriteOptions, (opts) => gen(function* ()
33498
33621
  }));
33499
33622
  //#endregion
33500
33623
  //#region src/cli/page/delete.ts
33501
- const slugOrId$12 = text$6({ name: "slugOrId" });
33624
+ const slugOrId$14 = text$6({ name: "slugOrId" });
33502
33625
  const force$5 = boolean("force");
33503
33626
  const resolvePageId$2 = (api, ref) => gen(function* () {
33504
33627
  if (isSnowflakeId(ref)) return ref;
@@ -33512,7 +33635,7 @@ const resolvePageId$2 = (api, ref) => gen(function* () {
33512
33635
  return id;
33513
33636
  });
33514
33637
  const del$3 = make$13("delete", {
33515
- slugOrId: slugOrId$12,
33638
+ slugOrId: slugOrId$14,
33516
33639
  force: force$5
33517
33640
  }, ({ slugOrId, force }) => gen(function* () {
33518
33641
  if (!force && !process.stdin.isTTY) return yield* fail$2(new ValidationFailed({ message: "refusing to delete without --force in non-TTY context" }));
@@ -33524,7 +33647,7 @@ const del$3 = make$13("delete", {
33524
33647
  }));
33525
33648
  //#endregion
33526
33649
  //#region src/cli/page/edit.ts
33527
- const slugOrId$11 = text$6({ name: "slugOrId" });
33650
+ const slugOrId$13 = text$6({ name: "slugOrId" });
33528
33651
  const escapeXml$1 = (s) => s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
33529
33652
  const resolvePageId$1 = (api, ref) => gen(function* () {
33530
33653
  if (isSnowflakeId(ref)) return ref;
@@ -33569,7 +33692,7 @@ const overlayPageMeta = (payload, rawMeta) => {
33569
33692
  return next;
33570
33693
  };
33571
33694
  const edit$2 = make$13("edit", {
33572
- slugOrId: slugOrId$11,
33695
+ slugOrId: slugOrId$13,
33573
33696
  ...pageWriteOptions
33574
33697
  }, ({ slugOrId, ...rest }) => gen(function* () {
33575
33698
  const flags = toPageFlagInputs(rest);
@@ -33700,7 +33823,7 @@ const list$4 = make$13("list", {}, () => gen(function* () {
33700
33823
  }));
33701
33824
  //#endregion
33702
33825
  //#region src/cli/page/update.ts
33703
- const slugOrId$9 = text$6({ name: "slugOrId" });
33826
+ const slugOrId$11 = text$6({ name: "slugOrId" });
33704
33827
  const resolvePageId = (api, ref) => gen(function* () {
33705
33828
  if (isSnowflakeId(ref)) return ref;
33706
33829
  const res = yield* api.request(`/pages/slug/${encodeURIComponent(ref)}`).pipe(catchAll(() => succeed$1(null)));
@@ -33713,7 +33836,7 @@ const resolvePageId = (api, ref) => gen(function* () {
33713
33836
  return id;
33714
33837
  });
33715
33838
  const update$3 = make$13("update", {
33716
- slugOrId: slugOrId$9,
33839
+ slugOrId: slugOrId$11,
33717
33840
  ...pageWriteOptions
33718
33841
  }, ({ slugOrId, ...rest }) => gen(function* () {
33719
33842
  const flags = toPageFlagInputs(rest);
@@ -33791,6 +33914,41 @@ const pageCmd = make$13("page").pipe(withDescription(help$5.description), withSu
33791
33914
  del$3
33792
33915
  ]));
33793
33916
  //#endregion
33917
+ //#region src/cli/post/apply.ts
33918
+ const slugOrId$10 = text$6({ name: "slugOrId" });
33919
+ const parseTypeSpecificData = (raw) => {
33920
+ if (!raw) return {};
33921
+ if (typeof raw === "object") return raw;
33922
+ try {
33923
+ const parsed = JSON.parse(raw);
33924
+ return typeof parsed === "object" && parsed !== null ? parsed : {};
33925
+ } catch {
33926
+ return {};
33927
+ }
33928
+ };
33929
+ const apply = make$13("apply", { slugOrId: slugOrId$10 }, ({ slugOrId }) => gen(function* () {
33930
+ const resolver = yield* Resolver;
33931
+ const api = yield* Api;
33932
+ const renderer = yield* Renderer;
33933
+ const id = yield* resolver.resolvePostId(slugOrId);
33934
+ const draft = yield* api.request(`/drafts/by-ref/post/${id}`);
33935
+ if (!draft || !draft.id) return yield* fail$2(new Generic({
33936
+ message: `no staged changes for post ${slugOrId}`,
33937
+ hint: "stage changes first with `mxs post stage <slugOrId> --file <article.xml>`"
33938
+ }));
33939
+ const body = { ...parseTypeSpecificData(draft.typeSpecificData) };
33940
+ if (draft.title !== void 0) body.title = draft.title;
33941
+ if (draft.text !== void 0) body.text = draft.text;
33942
+ if (draft.content !== void 0 && draft.content !== null) body.content = draft.content;
33943
+ if (draft.contentFormat !== void 0) body.contentFormat = draft.contentFormat;
33944
+ body.draftId = draft.id;
33945
+ const res = yield* api.request(`/posts/${id}`, {
33946
+ method: "PATCH",
33947
+ body
33948
+ });
33949
+ yield* renderer.emitSuccess(res);
33950
+ })).pipe(withDescription("apply the staged draft of a post to the live post (the confirm step after `post stage`)"));
33951
+ //#endregion
33794
33952
  //#region src/cli/post/create.ts
33795
33953
  const create$2 = make$13("create", postWriteOptions, (opts) => gen(function* () {
33796
33954
  const payload = yield* resolveCategoryRefs((yield* buildPostPayload(toPostFlagInputs(opts))).payload);
@@ -33820,7 +33978,7 @@ const del$2 = make$13("delete", {
33820
33978
  })).pipe(withDescription("delete a post"));
33821
33979
  //#endregion
33822
33980
  //#region src/cli/post/edit.ts
33823
- const slugOrId$7 = text$6({ name: "slugOrId" });
33981
+ const slugOrId$8 = text$6({ name: "slugOrId" });
33824
33982
  const escapeXml = (s) => s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
33825
33983
  const materializeForEditor = (slugOrId) => gen(function* () {
33826
33984
  const api = yield* Api;
@@ -33860,7 +34018,7 @@ const metaFromEnvelope = (meta) => {
33860
34018
  return overlay;
33861
34019
  };
33862
34020
  const edit$1 = make$13("edit", {
33863
- slugOrId: slugOrId$7,
34021
+ slugOrId: slugOrId$8,
33864
34022
  ...postWriteOptions
33865
34023
  }, ({ slugOrId, ...rest }) => gen(function* () {
33866
34024
  const flags = toPostFlagInputs(rest);
@@ -34072,6 +34230,42 @@ const publish = make$13("publish", { slugOrId: text$6({ name: "slugOrId" }) }, (
34072
34230
  });
34073
34231
  yield* renderer.emitSuccess(res);
34074
34232
  })).pipe(withDescription("publish a post"));
34233
+ //#endregion
34234
+ //#region src/cli/post/stage.ts
34235
+ const slugOrId$5 = text$6({ name: "slugOrId" });
34236
+ /** Draft-native fields; everything else rides along in `typeSpecificData`. */
34237
+ const DRAFT_CORE_KEYS = new Set([
34238
+ "title",
34239
+ "text",
34240
+ "content",
34241
+ "contentFormat",
34242
+ "meta"
34243
+ ]);
34244
+ const stage = make$13("stage", {
34245
+ slugOrId: slugOrId$5,
34246
+ ...postWriteOptions
34247
+ }, ({ slugOrId, ...rest }) => gen(function* () {
34248
+ const payload = yield* resolveCategoryRefs({ ...(yield* buildPostPayload(toPostFlagInputs(rest))).payload });
34249
+ delete payload.isPublished;
34250
+ if (Object.keys(payload).filter((k) => k !== "contentFormat").length === 0) return yield* fail$2(new ValidationFailed({ message: "nothing to stage: provide --file or content/meta flags" }));
34251
+ const draftBody = {};
34252
+ const typeSpecificData = {};
34253
+ for (const [key, value] of Object.entries(payload)) if (DRAFT_CORE_KEYS.has(key)) draftBody[key] = value;
34254
+ else typeSpecificData[key] = value;
34255
+ if (Object.keys(typeSpecificData).length > 0) draftBody.typeSpecificData = typeSpecificData;
34256
+ const id = yield* (yield* Resolver).resolvePostId(slugOrId);
34257
+ const api = yield* Api;
34258
+ const renderer = yield* Renderer;
34259
+ const res = yield* api.request(`/drafts`, {
34260
+ method: "POST",
34261
+ body: {
34262
+ refType: "post",
34263
+ refId: id,
34264
+ ...draftBody
34265
+ }
34266
+ });
34267
+ yield* renderer.emitSuccess(rest.silent ? { ok: true } : res);
34268
+ })).pipe(withDescription("stage changes as a draft attached to a published post (the live post is untouched until `post apply`)"));
34075
34269
  const unpublish = make$13("unpublish", { slugOrId: text$6({ name: "slugOrId" }) }, ({ slugOrId }) => gen(function* () {
34076
34270
  const resolver = yield* Resolver;
34077
34271
  const api = yield* Api;
@@ -34094,6 +34288,7 @@ const update$2 = make$13("update", {
34094
34288
  delete payload.text;
34095
34289
  delete payload.contentFormat;
34096
34290
  }
34291
+ if (flags.state === void 0) delete payload.isPublished;
34097
34292
  const resolved = yield* resolveCategoryRefs(payload);
34098
34293
  const id = yield* (yield* Resolver).resolvePostId(slugOrId);
34099
34294
  const api = yield* Api;
@@ -34167,6 +34362,20 @@ const help$4 = registerCommandHelp({
34167
34362
  name: "unpublish",
34168
34363
  args: ["<slugOrId>"],
34169
34364
  description: "unpublish a post"
34365
+ },
34366
+ {
34367
+ name: "stage",
34368
+ args: [
34369
+ "<slugOrId>",
34370
+ "[--file <path>]",
34371
+ "..."
34372
+ ],
34373
+ description: "stage changes as a draft; the live post stays untouched"
34374
+ },
34375
+ {
34376
+ name: "apply",
34377
+ args: ["<slugOrId>"],
34378
+ description: "apply the staged draft to the live post"
34170
34379
  }
34171
34380
  ]
34172
34381
  });
@@ -34178,7 +34387,9 @@ const postCmd = make$13("post").pipe(withDescription(help$4.description), withSu
34178
34387
  update$2,
34179
34388
  del$2,
34180
34389
  publish,
34181
- unpublish
34390
+ unpublish,
34391
+ stage,
34392
+ apply
34182
34393
  ]));
34183
34394
  //#endregion
34184
34395
  //#region src/cli/preview/index.ts
@@ -39819,6 +40030,7 @@ const rootCmd = make$13("mxs", {}, () => flatMap$1(Renderer, (r) => r.emitInfo("
39819
40030
  topicCmd,
39820
40031
  commentCmd,
39821
40032
  configCmd,
40033
+ fileCmd,
39822
40034
  skillCmd,
39823
40035
  previewCmd,
39824
40036
  updateCmd
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-space/cli",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Command line interface for mx-space (mx-core) — auth, content, configuration",
5
5
  "keywords": [
6
6
  "mx-space",
@@ -52,9 +52,9 @@
52
52
  "@effect/cli": "0.75.2",
53
53
  "@effect/platform": "0.96.1",
54
54
  "@effect/platform-node": "0.107.0",
55
- "@haklex/rich-headless": "0.20.0",
56
- "@haklex/rich-litexml": "0.21.0",
57
- "@haklex/rich-litexml-cli": "0.20.0",
55
+ "@haklex/rich-headless": "0.22.0",
56
+ "@haklex/rich-litexml": "0.22.0",
57
+ "@haklex/rich-litexml-cli": "0.22.0",
58
58
  "@lexical/headless": "^0.45.0",
59
59
  "better-auth": "^1.6.14",
60
60
  "effect": "3.21.2",