@mx-space/cli 0.1.0 → 0.1.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.
Files changed (110) hide show
  1. package/README.md +5 -1
  2. package/dist/{auth-DIFZzoMm.mjs → auth-OeKZZ_2x.mjs} +2 -2
  3. package/dist/{auth-DIFZzoMm.mjs.map → auth-OeKZZ_2x.mjs.map} +1 -1
  4. package/dist/bin/mxs.d.mts +1 -0
  5. package/dist/bin/mxs.mjs +39 -39
  6. package/dist/bin/mxs.mjs.map +1 -1
  7. package/dist/config-store-WL7dNMS6.mjs +226 -0
  8. package/dist/config-store-WL7dNMS6.mjs.map +1 -0
  9. package/dist/{create-Dz6rJJSS.mjs → create-BVHnXtIH.mjs} +2 -2
  10. package/dist/{create-Dz6rJJSS.mjs.map → create-BVHnXtIH.mjs.map} +1 -1
  11. package/dist/{create-DT1l2hue.mjs → create-BWA2WGrW.mjs} +2 -2
  12. package/dist/{create-DT1l2hue.mjs.map → create-BWA2WGrW.mjs.map} +1 -1
  13. package/dist/{create-B2AOQL1e.mjs → create-C85MSrtt.mjs} +2 -2
  14. package/dist/{create-B2AOQL1e.mjs.map → create-C85MSrtt.mjs.map} +1 -1
  15. package/dist/{create-DjlRHPXy.mjs → create-Cxnqt_Wt.mjs} +2 -2
  16. package/dist/{create-DjlRHPXy.mjs.map → create-Cxnqt_Wt.mjs.map} +1 -1
  17. package/dist/{create-CwjGcv2n.mjs → create-DUOSAqBm.mjs} +2 -2
  18. package/dist/{create-CwjGcv2n.mjs.map → create-DUOSAqBm.mjs.map} +1 -1
  19. package/dist/{delete-YzRliRn8.mjs → delete-BEXOOFAJ.mjs} +2 -2
  20. package/dist/{delete-YzRliRn8.mjs.map → delete-BEXOOFAJ.mjs.map} +1 -1
  21. package/dist/{delete-B4dGrrus.mjs → delete-CGy-cV6k.mjs} +2 -2
  22. package/dist/{delete-B4dGrrus.mjs.map → delete-CGy-cV6k.mjs.map} +1 -1
  23. package/dist/{delete-BH6ZngTz.mjs → delete-CKqlAUT8.mjs} +2 -2
  24. package/dist/{delete-BH6ZngTz.mjs.map → delete-CKqlAUT8.mjs.map} +1 -1
  25. package/dist/{delete-CaG2d_xt.mjs → delete-CcyrLNZv.mjs} +2 -2
  26. package/dist/{delete-CaG2d_xt.mjs.map → delete-CcyrLNZv.mjs.map} +1 -1
  27. package/dist/{delete-BrY5zJ6S.mjs → delete-Cjxehwj7.mjs} +2 -2
  28. package/dist/{delete-BrY5zJ6S.mjs.map → delete-Cjxehwj7.mjs.map} +1 -1
  29. package/dist/{document-output-BVB8emLt.mjs → document-output-C5PWbz2p.mjs} +57 -2
  30. package/dist/document-output-C5PWbz2p.mjs.map +1 -0
  31. package/dist/{edit-Bb0Ze4w6.mjs → edit-BRaZ6GGg.mjs} +2 -2
  32. package/dist/{edit-Bb0Ze4w6.mjs.map → edit-BRaZ6GGg.mjs.map} +1 -1
  33. package/dist/{edit-z55ofr1S.mjs → edit-BuKMUNVC.mjs} +2 -2
  34. package/dist/{edit-z55ofr1S.mjs.map → edit-BuKMUNVC.mjs.map} +1 -1
  35. package/dist/{edit-BeFmC3XD.mjs → edit-DFnOnk4i.mjs} +2 -2
  36. package/dist/{edit-BeFmC3XD.mjs.map → edit-DFnOnk4i.mjs.map} +1 -1
  37. package/dist/{edit-DLDw_ZWX.mjs → edit-t108N11Q.mjs} +2 -2
  38. package/dist/{edit-DLDw_ZWX.mjs.map → edit-t108N11Q.mjs.map} +1 -1
  39. package/dist/{get-ClkpDBTL.mjs → get-BYoAlJwB.mjs} +3 -3
  40. package/dist/get-BYoAlJwB.mjs.map +1 -0
  41. package/dist/{get-DJfUJ3sP.mjs → get-CwcNFb39.mjs} +3 -3
  42. package/dist/get-CwcNFb39.mjs.map +1 -0
  43. package/dist/{get-DiqaQvoS.mjs → get-DnDvLa9S.mjs} +4 -4
  44. package/dist/get-DnDvLa9S.mjs.map +1 -0
  45. package/dist/{get-2qjq0wgG.mjs → get-Doi-NKAh.mjs} +6 -6
  46. package/dist/get-Doi-NKAh.mjs.map +1 -0
  47. package/dist/{get-CRR13lgj.mjs → get-DxTU7Nom.mjs} +2 -2
  48. package/dist/{get-CRR13lgj.mjs.map → get-DxTU7Nom.mjs.map} +1 -1
  49. package/dist/{get-BGAk1Zmv.mjs → get-GdRz82RW.mjs} +4 -4
  50. package/dist/get-GdRz82RW.mjs.map +1 -0
  51. package/dist/index.d.mts +15 -3
  52. package/dist/index.mjs +5 -5
  53. package/dist/{list-Fp4nKfQb.mjs → list-CLAcZYZ4.mjs} +3 -3
  54. package/dist/list-CLAcZYZ4.mjs.map +1 -0
  55. package/dist/{list-DY-tPNG-.mjs → list-CtME3aDw.mjs} +2 -2
  56. package/dist/{list-DY-tPNG-.mjs.map → list-CtME3aDw.mjs.map} +1 -1
  57. package/dist/{list-DlQSkbqx.mjs → list-DHG-MzOM.mjs} +3 -3
  58. package/dist/list-DHG-MzOM.mjs.map +1 -0
  59. package/dist/{list-BYzhflDg.mjs → list-DN81zVDA.mjs} +4 -4
  60. package/dist/list-DN81zVDA.mjs.map +1 -0
  61. package/dist/list-DVunNsXr.mjs +10 -0
  62. package/dist/list-DVunNsXr.mjs.map +1 -0
  63. package/dist/list-DbNCVZbz.mjs +15 -0
  64. package/dist/list-DbNCVZbz.mjs.map +1 -0
  65. package/dist/{login-CLOJ-fTJ.mjs → login-mjliJn8U.mjs} +4 -4
  66. package/dist/{login-CLOJ-fTJ.mjs.map → login-mjliJn8U.mjs.map} +1 -1
  67. package/dist/{logout-v8ihxsim.mjs → logout-Bslt_ZJ4.mjs} +2 -2
  68. package/dist/{logout-v8ihxsim.mjs.map → logout-Bslt_ZJ4.mjs.map} +1 -1
  69. package/dist/{onboarding-640IldLz.mjs → onboarding-C1t1yoay.mjs} +3 -3
  70. package/dist/{onboarding-640IldLz.mjs.map → onboarding-C1t1yoay.mjs.map} +1 -1
  71. package/dist/output-BM7aBFwt.mjs.map +1 -1
  72. package/dist/{publish-pRBfTJfe.mjs → publish-CN3NTJ_r.mjs} +2 -2
  73. package/dist/{publish-pRBfTJfe.mjs.map → publish-CN3NTJ_r.mjs.map} +1 -1
  74. package/dist/{publish-DkTYB-eK.mjs → publish-akQWYsnL.mjs} +2 -2
  75. package/dist/{publish-DkTYB-eK.mjs.map → publish-akQWYsnL.mjs.map} +1 -1
  76. package/dist/{set-BEGQz2si.mjs → set-ClbrGFGv.mjs} +2 -2
  77. package/dist/{set-BEGQz2si.mjs.map → set-ClbrGFGv.mjs.map} +1 -1
  78. package/dist/{shared-D0HVBDHI.mjs → shared-C2EAn5h_.mjs} +11 -4
  79. package/dist/shared-C2EAn5h_.mjs.map +1 -0
  80. package/dist/{status-LXrN9fI-.mjs → status-Cvyrrx-J.mjs} +3 -3
  81. package/dist/{status-LXrN9fI-.mjs.map → status-Cvyrrx-J.mjs.map} +1 -1
  82. package/dist/{update-BMZQPOvR.mjs → update-CHmckeo8.mjs} +2 -2
  83. package/dist/{update-BMZQPOvR.mjs.map → update-CHmckeo8.mjs.map} +1 -1
  84. package/dist/{update-q66TLS38.mjs → update-CJjwg09n.mjs} +2 -2
  85. package/dist/{update-q66TLS38.mjs.map → update-CJjwg09n.mjs.map} +1 -1
  86. package/dist/{update-Dx6AF8tf.mjs → update-Duh-iVOZ.mjs} +2 -2
  87. package/dist/{update-Dx6AF8tf.mjs.map → update-Duh-iVOZ.mjs.map} +1 -1
  88. package/dist/{update-B9ynFCdZ.mjs → update-dc-72pUN.mjs} +2 -2
  89. package/dist/{update-B9ynFCdZ.mjs.map → update-dc-72pUN.mjs.map} +1 -1
  90. package/dist/{update-BXz0l7Lz.mjs → update-qfiC-9Og.mjs} +2 -2
  91. package/dist/{update-BXz0l7Lz.mjs.map → update-qfiC-9Og.mjs.map} +1 -1
  92. package/dist/{whoami-CTkctOEd.mjs → whoami-UwcdRchK.mjs} +3 -3
  93. package/dist/{whoami-CTkctOEd.mjs.map → whoami-UwcdRchK.mjs.map} +1 -1
  94. package/package.json +1 -1
  95. package/dist/config-store-DIu7x0ao.mjs +0 -121
  96. package/dist/config-store-DIu7x0ao.mjs.map +0 -1
  97. package/dist/document-output-BVB8emLt.mjs.map +0 -1
  98. package/dist/get-2qjq0wgG.mjs.map +0 -1
  99. package/dist/get-BGAk1Zmv.mjs.map +0 -1
  100. package/dist/get-ClkpDBTL.mjs.map +0 -1
  101. package/dist/get-DJfUJ3sP.mjs.map +0 -1
  102. package/dist/get-DiqaQvoS.mjs.map +0 -1
  103. package/dist/list-BYzhflDg.mjs.map +0 -1
  104. package/dist/list-DlQSkbqx.mjs.map +0 -1
  105. package/dist/list-DsrA5wIz.mjs +0 -15
  106. package/dist/list-DsrA5wIz.mjs.map +0 -1
  107. package/dist/list-Fp4nKfQb.mjs.map +0 -1
  108. package/dist/list-s_tloiEX.mjs +0 -10
  109. package/dist/list-s_tloiEX.mjs.map +0 -1
  110. package/dist/shared-D0HVBDHI.mjs.map +0 -1
package/README.md CHANGED
@@ -31,11 +31,12 @@ When the CLI cannot resolve an API URL, it starts an interactive onboarding prom
31
31
  | `--api-url <url>` | Override the configured mx-core API origin. |
32
32
  | `--token <token>` | Override the stored access token. |
33
33
  | `--api-key <key>` | Authenticate with an API key through the `x-api-key` header. |
34
+ | `--lang <code>` | Request translated data for read commands, such as `ja` or `en`. |
34
35
  | `--quiet`, `-q` | Suppress non-error stderr messages. |
35
36
  | `--verbose` | Print HTTP method, URL, status, and duration to stderr. |
36
37
  | `--dry-run` | Resolve payloads without mutating the server where supported. |
37
38
 
38
- `readable`, `llm`, and `envelope` are currently document output modes for `post get`, `note get`, and `page get`. Other commands keep their existing JSON-oriented output.
39
+ `readable`, `llm`, and `envelope` are document output modes for `post get`, `note get`, and `page get`. `post list` additionally supports `readable` and `llm` for concise list summaries. Other commands keep their existing JSON-oriented output.
39
40
 
40
41
  ## Output Modes
41
42
 
@@ -53,6 +54,7 @@ Example:
53
54
 
54
55
  ```bash
55
56
  mxs post get my-slug --output llm
57
+ mxs --lang ja post list --output llm
56
58
  ```
57
59
 
58
60
  ```text
@@ -112,6 +114,8 @@ local expiry from the refreshed session.
112
114
  | `--state <state>` | Publication filter, such as `draft` or `publish`. |
113
115
  | `--sort <field>` | Sort field passed as `sortBy`, such as `created` or `modified`. |
114
116
 
117
+ `mxs post list --output llm` emits one compact metadata block per post and omits full article bodies.
118
+
115
119
  ### Post Write Flags
116
120
 
117
121
  | Flag | Field |
@@ -1,5 +1,5 @@
1
1
  import { s as MxsError } from "./output-BM7aBFwt.mjs";
2
- import { c as readCredentials, d as writeCredentials } from "./config-store-DIu7x0ao.mjs";
2
+ import { s as readCredentials, u as writeCredentials } from "./config-store-WL7dNMS6.mjs";
3
3
  //#region src/core/auth.ts
4
4
  const SUPPORTED_API_VERSIONS = [2];
5
5
  function defaultHttp() {
@@ -208,4 +208,4 @@ async function ensureFreshToken(authBase, clientId, http = defaultHttp()) {
208
208
  //#endregion
209
209
  export { loadCredentialsOrThrow as a, refreshAccessToken as c, isExpiringSoon as i, requestDeviceCode as l, defaultHttp as n, pollDeviceToken as o, ensureFreshToken as r, probeAuthEndpoint as s, SUPPORTED_API_VERSIONS as t, toCredentials as u };
210
210
 
211
- //# sourceMappingURL=auth-DIFZzoMm.mjs.map
211
+ //# sourceMappingURL=auth-OeKZZ_2x.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-DIFZzoMm.mjs","names":[],"sources":["../src/core/auth.ts"],"sourcesContent":["import {\n type CredentialsShape,\n readCredentials,\n writeCredentials,\n} from './config-store'\nimport { MxsError } from './errors'\n\nexport const SUPPORTED_API_VERSIONS = [2] as const\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete?: string\n expires_in: number\n interval: number\n}\n\nexport interface DeviceTokenResponse {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token?: string\n scope?: string\n user?: {\n id?: string\n email?: string\n name?: string\n }\n}\n\nexport interface ProbeResult {\n apiUrl: string\n apiBase: string\n authBase: string\n apiVersion: number\n}\n\nexport interface AuthHttp {\n fetch: typeof fetch\n}\n\nexport function defaultHttp(): AuthHttp {\n return { fetch: globalThis.fetch.bind(globalThis) }\n}\n\nexport async function probeAuthEndpoint(\n apiUrl: string,\n http: AuthHttp = defaultHttp(),\n): Promise<ProbeResult> {\n const candidates: { prefix: string; version: number | null }[] = [\n ...SUPPORTED_API_VERSIONS.map((v) => ({\n prefix: `/api/v${v}/auth`,\n version: v,\n })),\n { prefix: '/auth', version: null },\n ]\n for (const cand of candidates) {\n const probeUrl = `${apiUrl}${cand.prefix}/ok`\n let res: Response\n try {\n res = await http.fetch(probeUrl, { method: 'GET' })\n } catch {\n continue\n }\n if (res.ok) {\n const apiVersion = cand.version ?? SUPPORTED_API_VERSIONS[0]\n const apiBase =\n cand.prefix === '/auth' ? apiUrl : `${apiUrl}/api/v${apiVersion}`\n const authBase = `${apiUrl}${cand.prefix}`\n return { apiUrl, apiBase, authBase, apiVersion }\n }\n }\n throw new MxsError({\n code: 'auth.probe',\n message: 'cannot detect auth endpoint',\n hint: 'verify the URL points at a running mx-core server',\n })\n}\n\nexport async function requestDeviceCode(\n authBase: string,\n clientId: string,\n scope = 'openid profile email',\n http: AuthHttp = defaultHttp(),\n): Promise<DeviceCodeResponse> {\n const res = await http.fetch(`${authBase}/device/code`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ client_id: clientId, scope }),\n })\n if (!res.ok) {\n let body: unknown\n try {\n body = await res.json()\n } catch {\n body = await res.text()\n }\n throw new MxsError({\n code: 'auth.denied',\n message: `device code request failed (${res.status})`,\n details: body,\n })\n }\n return (await res.json()) as DeviceCodeResponse\n}\n\nexport interface PollOptions {\n intervalSec: number\n expiresInSec: number\n signal?: AbortSignal\n onTick?: (state: 'pending' | 'slow_down') => void\n http?: AuthHttp\n}\n\nexport async function pollDeviceToken(\n authBase: string,\n clientId: string,\n deviceCode: string,\n opts: PollOptions,\n): Promise<DeviceTokenResponse> {\n const http = opts.http ?? defaultHttp()\n const deadline = Date.now() + opts.expiresInSec * 1000\n let intervalMs = Math.max(1, opts.intervalSec) * 1000\n while (Date.now() < deadline) {\n if (opts.signal?.aborted) {\n throw new MxsError({ code: 'auth.denied', message: 'aborted by user' })\n }\n await sleep(intervalMs, opts.signal)\n const res = await http.fetch(`${authBase}/device/token`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: clientId,\n }),\n })\n let body: any\n try {\n body = await res.json()\n } catch {\n body = null\n }\n if (res.ok && body?.access_token) {\n return body as DeviceTokenResponse\n }\n const err = body?.error as string | undefined\n if (err === 'authorization_pending') {\n opts.onTick?.('pending')\n continue\n }\n if (err === 'slow_down') {\n intervalMs += 5000\n opts.onTick?.('slow_down')\n continue\n }\n if (err === 'access_denied') {\n throw new MxsError({\n code: 'auth.denied',\n message: 'user denied the authorization request',\n })\n }\n if (err === 'expired_token') {\n throw new MxsError({\n code: 'auth.expired',\n message: 'device code expired before authorization completed',\n hint: 'run `mxs auth login` again',\n })\n }\n throw new MxsError({\n code: 'auth.denied',\n message: `device token request failed (${res.status})`,\n details: body,\n })\n }\n throw new MxsError({\n code: 'auth.expired',\n message: 'device authorization timed out',\n hint: 'run `mxs auth login` again',\n })\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(new Error('aborted'))\n const timer = setTimeout(() => {\n if (signal) signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n const onAbort = () => {\n clearTimeout(timer)\n reject(new Error('aborted'))\n }\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport function toCredentials(resp: DeviceTokenResponse): CredentialsShape {\n return {\n access_token: resp.access_token,\n refresh_token: resp.refresh_token,\n expires_at: Date.now() + resp.expires_in * 1000,\n user: resp.user,\n }\n}\n\nexport function isExpiringSoon(\n cred: CredentialsShape,\n bufferMs = 60_000,\n): boolean {\n return cred.expires_at < Date.now() + bufferMs\n}\n\nexport async function refreshAccessToken(\n authBase: string,\n clientId: string,\n cred: CredentialsShape,\n http: AuthHttp = defaultHttp(),\n): Promise<CredentialsShape | null> {\n if (!cred.refresh_token) {\n return refreshSessionToken(authBase, cred, http)\n }\n const res = await http.fetch(`${authBase}/token`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: cred.refresh_token,\n client_id: clientId,\n }),\n })\n if (!res.ok) return null\n const body = (await res.json()) as DeviceTokenResponse\n if (!body?.access_token) return null\n return {\n access_token: body.access_token,\n refresh_token: body.refresh_token ?? cred.refresh_token,\n expires_at: Date.now() + body.expires_in * 1000,\n user: body.user ?? cred.user,\n }\n}\n\nasync function refreshSessionToken(\n authBase: string,\n cred: CredentialsShape,\n http: AuthHttp,\n): Promise<CredentialsShape | null> {\n const res = await http.fetch(`${authBase}/get-session`, {\n method: 'GET',\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${cred.access_token}`,\n },\n })\n if (!res.ok) return null\n const body = (await res.json().catch(() => null)) as\n | {\n session?: { expiresAt?: string | Date | number }\n user?: CredentialsShape['user']\n }\n | null\n const expiresAt = normalizeExpiresAt(body?.session?.expiresAt)\n if (!expiresAt || expiresAt <= cred.expires_at) return null\n return {\n access_token: res.headers.get('set-auth-token') ?? cred.access_token,\n refresh_token: cred.refresh_token,\n expires_at: expiresAt,\n user: body?.user ?? cred.user,\n }\n}\n\nfunction normalizeExpiresAt(value: string | Date | number | undefined) {\n if (value === undefined) return null\n const time =\n value instanceof Date\n ? value.getTime()\n : typeof value === 'number'\n ? value\n : new Date(value).getTime()\n return Number.isFinite(time) ? time : null\n}\n\nexport async function loadCredentialsOrThrow(): Promise<CredentialsShape> {\n const cred = await readCredentials()\n if (!cred) {\n throw new MxsError({\n code: 'auth.missing',\n message: 'not authenticated',\n hint: 'run `mxs auth login`',\n })\n }\n return cred\n}\n\nexport async function ensureFreshToken(\n authBase: string,\n clientId: string,\n http: AuthHttp = defaultHttp(),\n): Promise<CredentialsShape> {\n const cred = await loadCredentialsOrThrow()\n if (!isExpiringSoon(cred)) return cred\n const refreshed = await refreshAccessToken(authBase, clientId, cred, http)\n if (!refreshed) return cred\n await writeCredentials(refreshed)\n return refreshed\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth-OeKZZ_2x.mjs","names":[],"sources":["../src/core/auth.ts"],"sourcesContent":["import {\n type CredentialsShape,\n readCredentials,\n writeCredentials,\n} from './config-store'\nimport { MxsError } from './errors'\n\nexport const SUPPORTED_API_VERSIONS = [2] as const\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n verification_uri_complete?: string\n expires_in: number\n interval: number\n}\n\nexport interface DeviceTokenResponse {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token?: string\n scope?: string\n user?: {\n id?: string\n email?: string\n name?: string\n }\n}\n\nexport interface ProbeResult {\n apiUrl: string\n apiBase: string\n authBase: string\n apiVersion: number\n}\n\nexport interface AuthHttp {\n fetch: typeof fetch\n}\n\nexport function defaultHttp(): AuthHttp {\n return { fetch: globalThis.fetch.bind(globalThis) }\n}\n\nexport async function probeAuthEndpoint(\n apiUrl: string,\n http: AuthHttp = defaultHttp(),\n): Promise<ProbeResult> {\n const candidates: { prefix: string; version: number | null }[] = [\n ...SUPPORTED_API_VERSIONS.map((v) => ({\n prefix: `/api/v${v}/auth`,\n version: v,\n })),\n { prefix: '/auth', version: null },\n ]\n for (const cand of candidates) {\n const probeUrl = `${apiUrl}${cand.prefix}/ok`\n let res: Response\n try {\n res = await http.fetch(probeUrl, { method: 'GET' })\n } catch {\n continue\n }\n if (res.ok) {\n const apiVersion = cand.version ?? SUPPORTED_API_VERSIONS[0]\n const apiBase =\n cand.prefix === '/auth' ? apiUrl : `${apiUrl}/api/v${apiVersion}`\n const authBase = `${apiUrl}${cand.prefix}`\n return { apiUrl, apiBase, authBase, apiVersion }\n }\n }\n throw new MxsError({\n code: 'auth.probe',\n message: 'cannot detect auth endpoint',\n hint: 'verify the URL points at a running mx-core server',\n })\n}\n\nexport async function requestDeviceCode(\n authBase: string,\n clientId: string,\n scope = 'openid profile email',\n http: AuthHttp = defaultHttp(),\n): Promise<DeviceCodeResponse> {\n const res = await http.fetch(`${authBase}/device/code`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ client_id: clientId, scope }),\n })\n if (!res.ok) {\n let body: unknown\n try {\n body = await res.json()\n } catch {\n body = await res.text()\n }\n throw new MxsError({\n code: 'auth.denied',\n message: `device code request failed (${res.status})`,\n details: body,\n })\n }\n return (await res.json()) as DeviceCodeResponse\n}\n\nexport interface PollOptions {\n intervalSec: number\n expiresInSec: number\n signal?: AbortSignal\n onTick?: (state: 'pending' | 'slow_down') => void\n http?: AuthHttp\n}\n\nexport async function pollDeviceToken(\n authBase: string,\n clientId: string,\n deviceCode: string,\n opts: PollOptions,\n): Promise<DeviceTokenResponse> {\n const http = opts.http ?? defaultHttp()\n const deadline = Date.now() + opts.expiresInSec * 1000\n let intervalMs = Math.max(1, opts.intervalSec) * 1000\n while (Date.now() < deadline) {\n if (opts.signal?.aborted) {\n throw new MxsError({ code: 'auth.denied', message: 'aborted by user' })\n }\n await sleep(intervalMs, opts.signal)\n const res = await http.fetch(`${authBase}/device/token`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: clientId,\n }),\n })\n let body: any\n try {\n body = await res.json()\n } catch {\n body = null\n }\n if (res.ok && body?.access_token) {\n return body as DeviceTokenResponse\n }\n const err = body?.error as string | undefined\n if (err === 'authorization_pending') {\n opts.onTick?.('pending')\n continue\n }\n if (err === 'slow_down') {\n intervalMs += 5000\n opts.onTick?.('slow_down')\n continue\n }\n if (err === 'access_denied') {\n throw new MxsError({\n code: 'auth.denied',\n message: 'user denied the authorization request',\n })\n }\n if (err === 'expired_token') {\n throw new MxsError({\n code: 'auth.expired',\n message: 'device code expired before authorization completed',\n hint: 'run `mxs auth login` again',\n })\n }\n throw new MxsError({\n code: 'auth.denied',\n message: `device token request failed (${res.status})`,\n details: body,\n })\n }\n throw new MxsError({\n code: 'auth.expired',\n message: 'device authorization timed out',\n hint: 'run `mxs auth login` again',\n })\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(new Error('aborted'))\n const timer = setTimeout(() => {\n if (signal) signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n const onAbort = () => {\n clearTimeout(timer)\n reject(new Error('aborted'))\n }\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport function toCredentials(resp: DeviceTokenResponse): CredentialsShape {\n return {\n access_token: resp.access_token,\n refresh_token: resp.refresh_token,\n expires_at: Date.now() + resp.expires_in * 1000,\n user: resp.user,\n }\n}\n\nexport function isExpiringSoon(\n cred: CredentialsShape,\n bufferMs = 60_000,\n): boolean {\n return cred.expires_at < Date.now() + bufferMs\n}\n\nexport async function refreshAccessToken(\n authBase: string,\n clientId: string,\n cred: CredentialsShape,\n http: AuthHttp = defaultHttp(),\n): Promise<CredentialsShape | null> {\n if (!cred.refresh_token) {\n return refreshSessionToken(authBase, cred, http)\n }\n const res = await http.fetch(`${authBase}/token`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: cred.refresh_token,\n client_id: clientId,\n }),\n })\n if (!res.ok) return null\n const body = (await res.json()) as DeviceTokenResponse\n if (!body?.access_token) return null\n return {\n access_token: body.access_token,\n refresh_token: body.refresh_token ?? cred.refresh_token,\n expires_at: Date.now() + body.expires_in * 1000,\n user: body.user ?? cred.user,\n }\n}\n\nasync function refreshSessionToken(\n authBase: string,\n cred: CredentialsShape,\n http: AuthHttp,\n): Promise<CredentialsShape | null> {\n const res = await http.fetch(`${authBase}/get-session`, {\n method: 'GET',\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${cred.access_token}`,\n },\n })\n if (!res.ok) return null\n const body = (await res.json().catch(() => null)) as\n | {\n session?: { expiresAt?: string | Date | number }\n user?: CredentialsShape['user']\n }\n | null\n const expiresAt = normalizeExpiresAt(body?.session?.expiresAt)\n if (!expiresAt || expiresAt <= cred.expires_at) return null\n return {\n access_token: res.headers.get('set-auth-token') ?? cred.access_token,\n refresh_token: cred.refresh_token,\n expires_at: expiresAt,\n user: body?.user ?? cred.user,\n }\n}\n\nfunction normalizeExpiresAt(value: string | Date | number | undefined) {\n if (value === undefined) return null\n const time =\n value instanceof Date\n ? value.getTime()\n : typeof value === 'number'\n ? value\n : new Date(value).getTime()\n return Number.isFinite(time) ? time : null\n}\n\nexport async function loadCredentialsOrThrow(): Promise<CredentialsShape> {\n const cred = await readCredentials()\n if (!cred) {\n throw new MxsError({\n code: 'auth.missing',\n message: 'not authenticated',\n hint: 'run `mxs auth login`',\n })\n }\n return cred\n}\n\nexport async function ensureFreshToken(\n authBase: string,\n clientId: string,\n http: AuthHttp = defaultHttp(),\n): Promise<CredentialsShape> {\n const cred = await loadCredentialsOrThrow()\n if (!isExpiringSoon(cred)) return cred\n const refreshed = await refreshAccessToken(authBase, clientId, cred, http)\n if (!refreshed) return cred\n await writeCredentials(refreshed)\n return refreshed\n}\n"],"mappings":"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"}
@@ -916,6 +916,7 @@ interface GlobalOptions {
916
916
  apiUrl?: string;
917
917
  token?: string;
918
918
  apiKey?: string;
919
+ lang?: string;
919
920
  quiet?: boolean;
920
921
  verbose?: boolean;
921
922
  dryRun?: boolean;
package/dist/bin/mxs.mjs CHANGED
@@ -3014,7 +3014,7 @@ const { program: program$1, createCommand, createArgument, createOption, Command
3014
3014
  //#endregion
3015
3015
  //#region src/bin/mxs.ts
3016
3016
  const program = new Command();
3017
- program.name("mxs").description("mx-space CLI — manage your mx-core blog from the command line").version("0.1.0").option("--json", "emit JSON output").option("--output <mode>", "pretty-json | json | readable | llm | envelope").option("--api-url <url>", "override the configured API URL").option("--token <t>", "override the stored access token").option("--api-key <key>", "authenticate with an x-api-key API key").option("-q, --quiet", "suppress non-error stderr").option("--verbose", "log HTTP method/url/status/duration").option("--dry-run", "show resolved payload without calling the server");
3017
+ program.name("mxs").description("mx-space CLI — manage your mx-core blog from the command line").version("0.1.0").option("--json", "emit JSON output").option("--output <mode>", "pretty-json | json | readable | llm | envelope").option("--api-url <url>", "override the configured API URL").option("--token <t>", "override the stored access token").option("--api-key <key>", "authenticate with an x-api-key API key").option("--lang <code>", "request translated read data for a locale").option("-q, --quiet", "suppress non-error stderr").option("--verbose", "log HTTP method/url/status/duration").option("--dry-run", "show resolved payload without calling the server");
3018
3018
  addAuthCommands(program);
3019
3019
  addPostCommands(program);
3020
3020
  addNoteCommands(program);
@@ -3041,45 +3041,45 @@ function readGlobalFlags(cmd) {
3041
3041
  function addAuthCommands(parent) {
3042
3042
  const auth = parent.command("auth").description("authentication");
3043
3043
  auth.command("login").description("start device authorization flow").action(async (_opts, command) => {
3044
- const { run } = await import("../login-CLOJ-fTJ.mjs");
3044
+ const { run } = await import("../login-mjliJn8U.mjs");
3045
3045
  await run(readGlobalFlags(command), readGlobalOptions(command));
3046
3046
  });
3047
3047
  auth.command("logout").description("delete stored credentials").action(async (_opts, command) => {
3048
- const { run } = await import("../logout-v8ihxsim.mjs");
3048
+ const { run } = await import("../logout-Bslt_ZJ4.mjs");
3049
3049
  await run(readGlobalFlags(command), readGlobalOptions(command));
3050
3050
  });
3051
3051
  auth.command("whoami").description("show the authenticated user").action(async (_opts, command) => {
3052
- const { run } = await import("../whoami-CTkctOEd.mjs");
3052
+ const { run } = await import("../whoami-UwcdRchK.mjs");
3053
3053
  await run(readGlobalFlags(command), readGlobalOptions(command));
3054
3054
  });
3055
3055
  auth.command("status").description("show token validity and expiry").action(async (_opts, command) => {
3056
- const { run } = await import("../status-LXrN9fI-.mjs");
3056
+ const { run } = await import("../status-Cvyrrx-J.mjs");
3057
3057
  await run(readGlobalFlags(command), readGlobalOptions(command));
3058
3058
  });
3059
3059
  }
3060
3060
  function addPostCommands(parent) {
3061
3061
  const post = parent.command("post").description("manage posts");
3062
3062
  post.command("list").option("--page <n>", "page number", (v) => Number(v)).option("--size <n>", "page size", (v) => Number(v)).option("--state <s>", "draft | publish").option("--sort <s>", "created | modified").action(async (opts, command) => {
3063
- const { run } = await import("../list-DsrA5wIz.mjs");
3063
+ const { run } = await import("../list-DbNCVZbz.mjs");
3064
3064
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3065
3065
  });
3066
3066
  post.command("get <slugOrId>").action(async (id, _opts, command) => {
3067
- const { run } = await import("../get-DiqaQvoS.mjs");
3067
+ const { run } = await import("../get-DnDvLa9S.mjs");
3068
3068
  await run(id, readGlobalFlags(command), readGlobalOptions(command));
3069
3069
  });
3070
3070
  addPostWriteCommand(post, "create");
3071
3071
  addPostWriteCommand(post, "edit", true);
3072
3072
  addPostWriteCommand(post, "update", true);
3073
3073
  post.command("delete <slugOrId>").option("--force", "skip confirmation").action(async (id, opts, command) => {
3074
- const { run } = await import("../delete-B4dGrrus.mjs");
3074
+ const { run } = await import("../delete-CGy-cV6k.mjs");
3075
3075
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3076
3076
  });
3077
3077
  post.command("publish <slugOrId>").action(async (id, _opts, command) => {
3078
- const { run } = await import("../publish-DkTYB-eK.mjs");
3078
+ const { run } = await import("../publish-akQWYsnL.mjs");
3079
3079
  await run(id, true, readGlobalFlags(command), readGlobalOptions(command));
3080
3080
  });
3081
3081
  post.command("unpublish <slugOrId>").action(async (id, _opts, command) => {
3082
- const { run } = await import("../publish-DkTYB-eK.mjs");
3082
+ const { run } = await import("../publish-akQWYsnL.mjs");
3083
3083
  await run(id, false, readGlobalFlags(command), readGlobalOptions(command));
3084
3084
  });
3085
3085
  }
@@ -3091,13 +3091,13 @@ function addPostWriteCommand(parent, name, requiresId = false) {
3091
3091
  const opts = args.at(-2);
3092
3092
  const id = requiresId ? args[0] : void 0;
3093
3093
  if (name === "create") {
3094
- const { run } = await import("../create-B2AOQL1e.mjs");
3094
+ const { run } = await import("../create-C85MSrtt.mjs");
3095
3095
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3096
3096
  } else if (name === "edit") {
3097
- const { run } = await import("../edit-DLDw_ZWX.mjs");
3097
+ const { run } = await import("../edit-t108N11Q.mjs");
3098
3098
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3099
3099
  } else {
3100
- const { run } = await import("../update-B9ynFCdZ.mjs");
3100
+ const { run } = await import("../update-dc-72pUN.mjs");
3101
3101
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3102
3102
  }
3103
3103
  });
@@ -3108,26 +3108,26 @@ function attachPostWriteFlags(cmd) {
3108
3108
  function addNoteCommands(parent) {
3109
3109
  const note = parent.command("note").description("manage notes");
3110
3110
  note.command("list").option("--page <n>", "", (v) => Number(v)).option("--size <n>", "", (v) => Number(v)).option("--state <s>").option("--sort <s>").action(async (opts, command) => {
3111
- const { run } = await import("../list-BYzhflDg.mjs");
3111
+ const { run } = await import("../list-DN81zVDA.mjs");
3112
3112
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3113
3113
  });
3114
3114
  note.command("get <slugOrId>").action(async (id, _opts, command) => {
3115
- const { run } = await import("../get-2qjq0wgG.mjs");
3115
+ const { run } = await import("../get-Doi-NKAh.mjs");
3116
3116
  await run(id, readGlobalFlags(command), readGlobalOptions(command));
3117
3117
  });
3118
3118
  addNoteWriteCommand(note, "create");
3119
3119
  addNoteWriteCommand(note, "edit", true);
3120
3120
  addNoteWriteCommand(note, "update", true);
3121
3121
  note.command("delete <slugOrId>").option("--force").action(async (id, opts, command) => {
3122
- const { run } = await import("../delete-BH6ZngTz.mjs");
3122
+ const { run } = await import("../delete-CKqlAUT8.mjs");
3123
3123
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3124
3124
  });
3125
3125
  note.command("publish <slugOrId>").action(async (id, _opts, command) => {
3126
- const { run } = await import("../publish-pRBfTJfe.mjs");
3126
+ const { run } = await import("../publish-CN3NTJ_r.mjs");
3127
3127
  await run(id, true, readGlobalFlags(command), readGlobalOptions(command));
3128
3128
  });
3129
3129
  note.command("unpublish <slugOrId>").action(async (id, _opts, command) => {
3130
- const { run } = await import("../publish-pRBfTJfe.mjs");
3130
+ const { run } = await import("../publish-CN3NTJ_r.mjs");
3131
3131
  await run(id, false, readGlobalFlags(command), readGlobalOptions(command));
3132
3132
  });
3133
3133
  }
@@ -3139,13 +3139,13 @@ function addNoteWriteCommand(parent, name, requiresId = false) {
3139
3139
  const opts = args.at(-2);
3140
3140
  const id = requiresId ? args[0] : void 0;
3141
3141
  if (name === "create") {
3142
- const { run } = await import("../create-DjlRHPXy.mjs");
3142
+ const { run } = await import("../create-Cxnqt_Wt.mjs");
3143
3143
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3144
3144
  } else if (name === "edit") {
3145
- const { run } = await import("../edit-Bb0Ze4w6.mjs");
3145
+ const { run } = await import("../edit-BRaZ6GGg.mjs");
3146
3146
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3147
3147
  } else {
3148
- const { run } = await import("../update-Dx6AF8tf.mjs");
3148
+ const { run } = await import("../update-Duh-iVOZ.mjs");
3149
3149
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3150
3150
  }
3151
3151
  });
@@ -3153,11 +3153,11 @@ function addNoteWriteCommand(parent, name, requiresId = false) {
3153
3153
  function addPageCommands(parent) {
3154
3154
  const page = parent.command("page").description("manage pages");
3155
3155
  page.command("list").action(async (_opts, command) => {
3156
- const { run } = await import("../list-DlQSkbqx.mjs");
3156
+ const { run } = await import("../list-DHG-MzOM.mjs");
3157
3157
  await run({}, readGlobalFlags(command), readGlobalOptions(command));
3158
3158
  });
3159
3159
  page.command("get <slugOrId>").action(async (id, _opts, command) => {
3160
- const { run } = await import("../get-BGAk1Zmv.mjs");
3160
+ const { run } = await import("../get-GdRz82RW.mjs");
3161
3161
  await run(id, readGlobalFlags(command), readGlobalOptions(command));
3162
3162
  });
3163
3163
  const writeCmd = (name, requiresId) => {
@@ -3167,79 +3167,79 @@ function addPageCommands(parent) {
3167
3167
  const command = args.at(-1);
3168
3168
  const opts = args.at(-2);
3169
3169
  const id = requiresId ? args[0] : void 0;
3170
- await (name === "create" ? await import("../create-Dz6rJJSS.mjs") : name === "edit" ? await import("../edit-BeFmC3XD.mjs") : await import("../update-BXz0l7Lz.mjs")).run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3170
+ await (name === "create" ? await import("../create-BVHnXtIH.mjs") : name === "edit" ? await import("../edit-DFnOnk4i.mjs") : await import("../update-qfiC-9Og.mjs")).run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3171
3171
  });
3172
3172
  };
3173
3173
  writeCmd("create", false);
3174
3174
  writeCmd("edit", true);
3175
3175
  writeCmd("update", true);
3176
3176
  page.command("delete <slugOrId>").option("--force").action(async (id, opts, command) => {
3177
- const { run } = await import("../delete-CaG2d_xt.mjs");
3177
+ const { run } = await import("../delete-CcyrLNZv.mjs");
3178
3178
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3179
3179
  });
3180
3180
  }
3181
3181
  function addCategoryCommands(parent) {
3182
3182
  const cat = parent.command("category").description("manage categories / tags");
3183
3183
  cat.command("list").action(async (_o, command) => {
3184
- const { run } = await import("../list-Fp4nKfQb.mjs");
3184
+ const { run } = await import("../list-CLAcZYZ4.mjs");
3185
3185
  await run(readGlobalFlags(command), readGlobalOptions(command));
3186
3186
  });
3187
3187
  cat.command("get <slugOrId>").action(async (id, _o, command) => {
3188
- const { run } = await import("../get-DJfUJ3sP.mjs");
3188
+ const { run } = await import("../get-CwcNFb39.mjs");
3189
3189
  await run(id, readGlobalFlags(command), readGlobalOptions(command));
3190
3190
  });
3191
3191
  cat.command("create").requiredOption("--name <s>").requiredOption("--slug <s>").option("--type <s>", "category | tag").option("--icon <s>").action(async (opts, command) => {
3192
- const { run } = await import("../create-CwjGcv2n.mjs");
3192
+ const { run } = await import("../create-DUOSAqBm.mjs");
3193
3193
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3194
3194
  });
3195
3195
  cat.command("update <slugOrId>").option("--name <s>").option("--slug <s>").option("--type <s>").option("--icon <s>").action(async (id, opts, command) => {
3196
- const { run } = await import("../update-BMZQPOvR.mjs");
3196
+ const { run } = await import("../update-CHmckeo8.mjs");
3197
3197
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3198
3198
  });
3199
3199
  cat.command("delete <slugOrId>").option("--force").action(async (id, opts, command) => {
3200
- const { run } = await import("../delete-BrY5zJ6S.mjs");
3200
+ const { run } = await import("../delete-Cjxehwj7.mjs");
3201
3201
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3202
3202
  });
3203
3203
  }
3204
3204
  function addTopicCommands(parent) {
3205
3205
  const topic = parent.command("topic").description("manage topics");
3206
3206
  topic.command("list").action(async (_o, command) => {
3207
- const { run } = await import("../list-s_tloiEX.mjs");
3207
+ const { run } = await import("../list-DVunNsXr.mjs");
3208
3208
  await run(readGlobalFlags(command), readGlobalOptions(command));
3209
3209
  });
3210
3210
  topic.command("get <slugOrId>").action(async (id, _o, command) => {
3211
- const { run } = await import("../get-ClkpDBTL.mjs");
3211
+ const { run } = await import("../get-BYoAlJwB.mjs");
3212
3212
  await run(id, readGlobalFlags(command), readGlobalOptions(command));
3213
3213
  });
3214
3214
  topic.command("create").requiredOption("--name <s>").requiredOption("--slug <s>").option("--description <s>").option("--icon <s>").action(async (opts, command) => {
3215
- const { run } = await import("../create-DT1l2hue.mjs");
3215
+ const { run } = await import("../create-BWA2WGrW.mjs");
3216
3216
  await run(opts, readGlobalFlags(command), readGlobalOptions(command));
3217
3217
  });
3218
3218
  topic.command("update <slugOrId>").option("--name <s>").option("--slug <s>").option("--description <s>").option("--icon <s>").action(async (id, opts, command) => {
3219
- const { run } = await import("../update-q66TLS38.mjs");
3219
+ const { run } = await import("../update-CJjwg09n.mjs");
3220
3220
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3221
3221
  });
3222
3222
  topic.command("delete <slugOrId>").option("--force").action(async (id, opts, command) => {
3223
- const { run } = await import("../delete-YzRliRn8.mjs");
3223
+ const { run } = await import("../delete-BEXOOFAJ.mjs");
3224
3224
  await run(id, opts, readGlobalFlags(command), readGlobalOptions(command));
3225
3225
  });
3226
3226
  }
3227
3227
  function addConfigCommands(parent) {
3228
3228
  const cfg = parent.command("config").description("manage server options");
3229
3229
  cfg.command("list").action(async (_o, command) => {
3230
- const { run } = await import("../list-DY-tPNG-.mjs");
3230
+ const { run } = await import("../list-CtME3aDw.mjs");
3231
3231
  await run(readGlobalFlags(command), readGlobalOptions(command));
3232
3232
  });
3233
3233
  cfg.command("get <key>").action(async (key, _o, command) => {
3234
- const { run } = await import("../get-CRR13lgj.mjs");
3234
+ const { run } = await import("../get-DxTU7Nom.mjs");
3235
3235
  await run(key, readGlobalFlags(command), readGlobalOptions(command));
3236
3236
  });
3237
3237
  cfg.command("set <key> <value>").option("--type <t>", "json | string | number | bool").action(async (key, value, opts, command) => {
3238
- const { run } = await import("../set-BEGQz2si.mjs");
3238
+ const { run } = await import("../set-ClbrGFGv.mjs");
3239
3239
  await run(key, value, opts, readGlobalFlags(command), readGlobalOptions(command));
3240
3240
  });
3241
3241
  cfg.command("edit").action(async (_o, command) => {
3242
- const { run } = await import("../edit-z55ofr1S.mjs");
3242
+ const { run } = await import("../edit-BuKMUNVC.mjs");
3243
3243
  await run(readGlobalFlags(command), readGlobalOptions(command));
3244
3244
  });
3245
3245
  }