dsh-mnemon 0.1.3 → 0.1.5

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 (45) hide show
  1. package/README.md +102 -81
  2. package/README.zh-CN.md +187 -0
  3. package/SECURITY.md +2 -2
  4. package/cordis.patch.yml +3 -2
  5. package/docs/README.md +4 -4
  6. package/docs/en/README.md +5 -3
  7. package/docs/en/architecture.md +3 -1
  8. package/docs/en/configuration.md +28 -7
  9. package/docs/en/development.md +1 -1
  10. package/docs/en/getting-started.md +48 -4
  11. package/docs/en/operations.md +8 -1
  12. package/docs/en/project-overview.md +14 -2
  13. package/docs/en/storage-model.md +6 -0
  14. package/docs/en/ui-guide.md +1 -1
  15. package/docs/zh-CN/README.md +5 -3
  16. package/docs/zh-CN/architecture.md +3 -1
  17. package/docs/zh-CN/configuration.md +28 -7
  18. package/docs/zh-CN/development.md +1 -1
  19. package/docs/zh-CN/getting-started.md +48 -4
  20. package/docs/zh-CN/operations.md +8 -1
  21. package/docs/zh-CN/project-overview.md +14 -2
  22. package/docs/zh-CN/storage-model.md +6 -0
  23. package/docs/zh-CN/ui-guide.md +1 -1
  24. package/lib/client.js +269 -243
  25. package/lib/client.js.map +1 -1
  26. package/lib/index.js +74 -36
  27. package/lib/types/client/MnemonView.d.ts.map +1 -1
  28. package/lib/types/client/MnemonView.js +10 -1
  29. package/lib/types/client/MnemonView.js.map +1 -1
  30. package/lib/types/client/locales.d.ts +10 -0
  31. package/lib/types/client/locales.d.ts.map +1 -1
  32. package/lib/types/client/locales.js +12 -2
  33. package/lib/types/client/locales.js.map +1 -1
  34. package/lib/types/process.js +1 -1
  35. package/lib/types/process.js.map +1 -1
  36. package/lib/types/runner.d.ts +7 -1
  37. package/lib/types/runner.d.ts.map +1 -1
  38. package/lib/types/runner.js +65 -22
  39. package/lib/types/runner.js.map +1 -1
  40. package/lib/types/version-updates.d.ts +3 -0
  41. package/lib/types/version-updates.d.ts.map +1 -1
  42. package/lib/types/version-updates.js +12 -6
  43. package/lib/types/version-updates.js.map +1 -1
  44. package/package.json +20 -8
  45. package/README.en.md +0 -166
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import z from "schemastery";
2
- import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
2
+ import { basename, delimiter, dirname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import { accessSync, closeSync, constants, existsSync, fstatSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
5
5
  import { homedir, tmpdir } from "node:os";
@@ -2015,7 +2015,8 @@ const runProcess = (command, args, options) => new Promise((resolve, reject) =>
2015
2015
  "pipe",
2016
2016
  "pipe"
2017
2017
  ],
2018
- shell: false
2018
+ shell: false,
2019
+ windowsHide: true
2019
2020
  });
2020
2021
  const maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
2021
2022
  let stdout = "";
@@ -2078,47 +2079,70 @@ const runProcess = (command, args, options) => new Promise((resolve, reject) =>
2078
2079
  });
2079
2080
  //#endregion
2080
2081
  //#region lib/types/runner.js
2081
- const COMMON_CLI_PATHS = [
2082
+ const UNIX_COMMON_CLI_PATHS = [
2082
2083
  "~/.local/bin/mnemon",
2083
2084
  "/opt/homebrew/bin/mnemon",
2084
2085
  "/usr/local/bin/mnemon",
2085
2086
  "/usr/bin/mnemon"
2086
2087
  ];
2087
- function expandHome$1(path) {
2088
- if (path === "~") return homedir();
2089
- return path.startsWith("~/") ? join(homedir(), path.slice(2)) : path;
2088
+ function pathApi(platform) {
2089
+ return platform === "win32" ? win32 : posix;
2090
+ }
2091
+ function expandHome$1(path, home = homedir(), platform = process.platform) {
2092
+ if (path === "~") return home;
2093
+ return path.startsWith("~/") || path.startsWith("~\\") ? pathApi(platform).join(home, path.slice(2)) : path;
2094
+ }
2095
+ function envValue(env, name, platform) {
2096
+ if (platform !== "win32") return env[name];
2097
+ const key = Object.keys(env).find((candidate) => candidate.toLowerCase() === name.toLowerCase());
2098
+ return key === void 0 ? void 0 : env[key];
2090
2099
  }
2091
- function executable$1(path) {
2100
+ function executable$1(path, platform = process.platform) {
2101
+ if (platform === "win32" && win32.extname(path).toLowerCase() !== ".exe") return false;
2092
2102
  try {
2093
- accessSync(path, constants.X_OK);
2094
- return true;
2103
+ accessSync(path, platform === "win32" ? constants.F_OK : constants.X_OK);
2104
+ return statSync(path).isFile();
2095
2105
  } catch {
2096
2106
  return false;
2097
2107
  }
2098
2108
  }
2109
+ function windowsCommonCliPaths(env, home) {
2110
+ const candidates = [];
2111
+ const goBin = envValue(env, "GOBIN", "win32")?.trim();
2112
+ if (goBin !== void 0 && win32.isAbsolute(goBin)) candidates.push(win32.join(goBin, "mnemon.exe"));
2113
+ const goInstallRoot = (envValue(env, "GOPATH", "win32")?.trim())?.split(win32.delimiter).map((candidate) => candidate.trim()).find((candidate) => candidate !== "" && win32.isAbsolute(candidate)) ?? win32.join(home, "go");
2114
+ candidates.push(win32.join(goInstallRoot, "bin", "mnemon.exe"));
2115
+ const localAppData = envValue(env, "LOCALAPPDATA", "win32")?.trim();
2116
+ if (localAppData !== void 0 && win32.isAbsolute(localAppData)) candidates.push(win32.join(localAppData, "Programs", "mnemon", "mnemon.exe"));
2117
+ const programFiles = envValue(env, "ProgramFiles", "win32")?.trim();
2118
+ if (programFiles !== void 0 && win32.isAbsolute(programFiles)) candidates.push(win32.join(programFiles, "mnemon", "mnemon.exe"));
2119
+ return [...new Set(candidates)];
2120
+ }
2121
+ function commonCliPaths(platform, env, home) {
2122
+ if (platform === "win32") return windowsCommonCliPaths(env, home);
2123
+ return UNIX_COMMON_CLI_PATHS.map((candidate) => expandHome$1(candidate, home, platform));
2124
+ }
2099
2125
  /** Locate the local Mnemon binary without invoking a shell. */
2100
- function findMnemonCommand(config) {
2101
- if (config.cliPath !== void 0) return expandHome$1(config.cliPath);
2102
- const envPath = process.env.MNEMON_CLI_PATH?.trim();
2126
+ function findMnemonCommand(config, options = {}) {
2127
+ const platform = options.platform ?? process.platform;
2128
+ const env = options.env ?? process.env;
2129
+ const home = options.home ?? homedir();
2130
+ const isExecutable = options.isExecutable ?? ((path) => executable$1(path, platform));
2131
+ if (config.cliPath !== void 0) return expandHome$1(config.cliPath, home, platform);
2132
+ const envPath = envValue(env, "MNEMON_CLI_PATH", platform)?.trim();
2103
2133
  if (envPath !== void 0 && envPath !== "") {
2104
- const path = expandHome$1(envPath);
2105
- if (executable$1(path)) return path;
2134
+ const path = expandHome$1(envPath, home, platform);
2135
+ if (isExecutable(path)) return path;
2106
2136
  }
2107
- for (const directory of (process.env.PATH ?? "").split(delimiter)) {
2137
+ const paths = pathApi(platform);
2138
+ for (const directory of (envValue(env, "PATH", platform) ?? "").split(paths.delimiter)) {
2108
2139
  if (directory === "") continue;
2109
- for (const name of process.platform === "win32" ? [
2110
- "mnemon.exe",
2111
- "mnemon.cmd",
2112
- "mnemon"
2113
- ] : ["mnemon"]) {
2114
- const path = join(directory, name);
2115
- if (executable$1(path)) return path;
2140
+ for (const name of platform === "win32" ? ["mnemon.exe"] : ["mnemon"]) {
2141
+ const path = paths.join(directory, name);
2142
+ if (isExecutable(path)) return path;
2116
2143
  }
2117
2144
  }
2118
- for (const candidate of COMMON_CLI_PATHS) {
2119
- const path = expandHome$1(candidate);
2120
- if (executable$1(path)) return path;
2121
- }
2145
+ for (const path of commonCliPaths(platform, env, home)) if (isExecutable(path)) return path;
2122
2146
  }
2123
2147
  var MnemonCliError = class extends Error {
2124
2148
  exitCode;
@@ -2157,7 +2181,7 @@ function createRunner(config, processRunner = runProcess, workspaceRoot) {
2157
2181
  try {
2158
2182
  result = await processRunner(command, argv, processOptions);
2159
2183
  } catch (error) {
2160
- throw new MnemonCliError(`${error instanceof Error ? error.message : String(error)}. Install Mnemon and ensure "mnemon" is on PATH, or set dsh-mnemon.cliPath.`);
2184
+ throw new MnemonCliError(`${error instanceof Error ? error.message : String(error)}. ${process.platform === "win32" ? "Install the official Mnemon Windows release, ensure mnemon.exe is on PATH or under %LOCALAPPDATA%\\Programs\\mnemon, or set MNEMON_CLI_PATH or mnemon.cliPath to its absolute path." : "Install Mnemon and ensure \"mnemon\" is on PATH, or set MNEMON_CLI_PATH or mnemon.cliPath."}`);
2161
2185
  }
2162
2186
  if (result.exitCode !== 0) {
2163
2187
  const detail = result.stderr.trim() || result.stdout.trim() || "no output";
@@ -4840,11 +4864,16 @@ function profileFromAncestor(packageManifestPath) {
4840
4864
  let directory = dirname(packageManifestPath);
4841
4865
  for (let depth = 0; depth < 12; depth++) {
4842
4866
  const profile = manifest(join(directory, "package.json"));
4843
- if (profile?.name?.startsWith("dsh-profile-") === true) return {
4844
- mode: isLinkSpec(dependencySpec(profile)) ? "link" : "npm",
4845
- profileName: profile.name.slice(12),
4846
- profileDir: directory
4847
- };
4867
+ if (profile?.name?.startsWith("dsh-profile-") === true) {
4868
+ const spec = dependencySpec(profile);
4869
+ const linked = isLinkSpec(spec);
4870
+ return {
4871
+ mode: linked ? "link" : "npm",
4872
+ locationDir: linked && spec !== void 0 ? linkedTarget(directory, spec) ?? resolve(dirname(packageManifestPath)) : directory,
4873
+ profileName: profile.name.slice(12),
4874
+ profileDir: directory
4875
+ };
4876
+ }
4848
4877
  const parent = dirname(directory);
4849
4878
  if (parent === directory) break;
4850
4879
  directory = parent;
@@ -4865,19 +4894,24 @@ function linkedProfile(packageManifestPath, dshHome) {
4865
4894
  try {
4866
4895
  if (realpathSync(target) === packageRoot) matches.push({
4867
4896
  name: entry.name,
4868
- dir: profileDir
4897
+ dir: profileDir,
4898
+ locationDir: target
4869
4899
  });
4870
4900
  } catch {}
4871
4901
  }
4872
4902
  const match = matches[0];
4873
4903
  return match === void 0 ? void 0 : {
4874
4904
  mode: "link",
4905
+ locationDir: match.locationDir,
4875
4906
  profileName: match.name,
4876
4907
  profileDir: match.dir
4877
4908
  };
4878
4909
  }
4879
4910
  function inspectDshInstall(packageManifestPath, dshHome) {
4880
- return profileFromAncestor(packageManifestPath) ?? linkedProfile(packageManifestPath, dshHome) ?? { mode: "manual" };
4911
+ return profileFromAncestor(packageManifestPath) ?? linkedProfile(packageManifestPath, dshHome) ?? {
4912
+ mode: "manual",
4913
+ locationDir: resolve(dirname(packageManifestPath))
4914
+ };
4881
4915
  }
4882
4916
  async function resultOrThrow(runner, command, args, timeoutMs) {
4883
4917
  const result = await runner(command, args, {
@@ -4933,7 +4967,8 @@ var VersionUpdateManager = class {
4933
4967
  try {
4934
4968
  realCommand = realpathSync(command);
4935
4969
  } catch {}
4936
- if (realCommand.includes("/Caskroom/mnemon/")) {
4970
+ const normalizedCommand = realCommand.replaceAll("\\", "/");
4971
+ if (normalizedCommand.includes("/Caskroom/mnemon/")) {
4937
4972
  const brew = this.executable("brew");
4938
4973
  return {
4939
4974
  ...current === void 0 ? {} : { current },
@@ -4951,7 +4986,7 @@ var VersionUpdateManager = class {
4951
4986
  }
4952
4987
  };
4953
4988
  }
4954
- if (realCommand.includes("/Cellar/mnemon/")) {
4989
+ if (normalizedCommand.includes("/Cellar/mnemon/")) {
4955
4990
  const brew = this.executable("brew");
4956
4991
  return {
4957
4992
  ...current === void 0 ? {} : { current },
@@ -5006,6 +5041,7 @@ var VersionUpdateManager = class {
5006
5041
  components: [{
5007
5042
  id: "mnemon",
5008
5043
  name: "Mnemon CLI",
5044
+ ...mnemonLocal.install.command === void 0 ? {} : { executablePath: mnemonLocal.install.command },
5009
5045
  ...mnemonLocal.current === void 0 ? {} : { current: mnemonLocal.current },
5010
5046
  ...mnemonLatest === void 0 ? {} : { latest: mnemonLatest },
5011
5047
  outdated: mnemonOutdated,
@@ -5016,6 +5052,8 @@ var VersionUpdateManager = class {
5016
5052
  }, {
5017
5053
  id: "dsh-mnemon",
5018
5054
  name: "dsh-mnemon",
5055
+ ...dshInstall.profileName === void 0 ? {} : { installProfile: dshInstall.profileName },
5056
+ installPath: dshInstall.locationDir,
5019
5057
  current: this.currentDshMnemonVersion,
5020
5058
  ...dshLatest === void 0 ? {} : { latest: dshLatest },
5021
5059
  outdated: dshOutdated,
@@ -1 +1 @@
1
- {"version":3,"file":"MnemonView.d.ts","sourceRoot":"","sources":["../../../src/client/MnemonView.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAClF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAkB1C,OAAO,EAA+B,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAEhF,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,4BAA4B,CAAA;AAGnC,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,sBAAsB,CAAA;IAClC,aAAa,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,wBAAwB,CAAA;IAC7C,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,CAAC,CAAC,EAAE,eAAe,CAAA;IACnB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,OAAO,IAAI,IAAI,CAAA;CAChB;AA6oDD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CAI9D"}
1
+ {"version":3,"file":"MnemonView.d.ts","sourceRoot":"","sources":["../../../src/client/MnemonView.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAClF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAkB1C,OAAO,EAA+B,KAAK,eAAe,EAAE,MAAM,cAAc,CAAA;AAEhF,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,4BAA4B,CAAA;AAGnC,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,sBAAsB,CAAA;IAClC,aAAa,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,wBAAwB,CAAA;IAC7C,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,CAAC,CAAC,EAAE,eAAe,CAAA;IACnB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,OAAO,IAAI,IAAI,CAAA;CAChB;AAupDD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CAI9D"}
@@ -1365,6 +1365,15 @@ function versionHint(t, component) {
1365
1365
  return t('versions.hintInstall');
1366
1366
  return t('versions.hintManual');
1367
1367
  }
1368
+ function dshInstallLabel(t, component) {
1369
+ if (component.installMode === 'npm')
1370
+ return t('versions.profileLocation', { name: component.installProfile ?? '—' });
1371
+ if (component.installMode === 'link')
1372
+ return component.installProfile === undefined
1373
+ ? t('versions.sourceLocation')
1374
+ : t('versions.linkSourceLocation', { name: component.installProfile });
1375
+ return t('versions.packageLocation');
1376
+ }
1368
1377
  function VersionDialog(props) {
1369
1378
  const t = useT();
1370
1379
  const [snapshot, setSnapshot] = useState(null);
@@ -1411,7 +1420,7 @@ function VersionDialog(props) {
1411
1420
  return _jsx(SidebarModal, { title: t('versions.title'), description: t('versions.description'), busy: busy, onClose: props.onClose, children: _jsxs("div", { className: css.versionDialogBody, children: [checking && snapshot === null && _jsxs("div", { className: css.versionChecking, role: "status", children: [_jsx("span", {}), t('versions.checking')] }), error !== null && _jsxs("div", { className: css.versionError, role: "alert", children: [_jsx("strong", { children: t('versions.failed') }), _jsx("p", { children: error })] }), result !== null && _jsxs("div", { className: css.versionResult, role: "status", children: [_jsx("strong", { children: result.updated ? t('versions.updated', { name: result.component === 'mnemon' ? 'Mnemon CLI' : 'dsh-mnemon' }) : t('versions.alreadyCurrent') }), result.restartRequired && _jsx("p", { children: t('versions.restartRequired') })] }), snapshot !== null && _jsx("div", { className: css.versionList, children: snapshot.components.map(component => {
1412
1421
  const canUpdate = component.outdated && component.updateSupported && component.checkError === undefined;
1413
1422
  const state = component.checkError !== undefined ? t('versions.unknown') : component.outdated ? t('versions.available') : t('versions.current');
1414
- return _jsxs("article", { "data-outdated": component.outdated || undefined, children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("strong", { children: component.name }), _jsx("span", { children: versionModeLabel(t, component.installMode) })] }), _jsx("em", { children: state })] }), _jsxs("div", { className: css.versionNumbers, children: [_jsxs("div", { children: [_jsx("small", { children: t('versions.installed') }), _jsx("code", { children: component.current ?? '—' })] }), _jsx("span", { children: "\u2192" }), _jsxs("div", { children: [_jsx("small", { children: t('versions.latest') }), _jsx("code", { children: component.latest ?? '—' })] })] }), _jsxs("footer", { children: [_jsx("p", { children: versionHint(t, component) }), canUpdate && _jsx("button", { type: "button", className: css.primaryButton, disabled: busy, onClick: () => void update(component), children: updating === component.id ? t('versions.updating') : t('versions.update') })] })] }, component.id);
1423
+ return _jsxs("article", { "data-outdated": component.outdated || undefined, children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("strong", { children: component.name }), _jsx("span", { children: versionModeLabel(t, component.installMode) })] }), _jsx("em", { children: state })] }), _jsxs("div", { className: css.versionNumbers, children: [_jsxs("div", { children: [_jsx("small", { children: t('versions.installed') }), _jsx("code", { children: component.current ?? '—' })] }), _jsx("span", { children: "\u2192" }), _jsxs("div", { children: [_jsx("small", { children: t('versions.latest') }), _jsx("code", { children: component.latest ?? '—' })] })] }), component.id === 'mnemon' && component.executablePath !== undefined && _jsxs("small", { className: css.versionLocation, title: component.executablePath, children: [_jsx("span", { children: t('versions.executable') }), _jsx("code", { children: component.executablePath })] }), component.id === 'dsh-mnemon' && component.installPath !== undefined && _jsxs("small", { className: css.versionLocation, title: component.installPath, children: [_jsx("span", { children: dshInstallLabel(t, component) }), _jsx("code", { children: component.installPath })] }), _jsxs("footer", { children: [_jsx("p", { children: versionHint(t, component) }), canUpdate && _jsx("button", { type: "button", className: css.primaryButton, disabled: busy, onClick: () => void update(component), children: updating === component.id ? t('versions.updating') : t('versions.update') })] })] }, component.id);
1415
1424
  }) }), _jsxs("div", { className: css.versionDialogActions, children: [_jsx("span", { children: snapshot === null ? '' : t('versions.checkedAt', { time: new Date(snapshot.checkedAt).toLocaleTimeString() }) }), _jsxs("div", { children: [_jsx("button", { type: "button", className: css.ghostButton, disabled: busy, onClick: props.onClose, children: t('common.cancel') }), _jsx("button", { type: "button", "data-autofocus": true, className: css.secondaryButton, disabled: busy, onClick: () => void check(), children: checking ? t('versions.checkingShort') : t('versions.recheck') })] })] })] }) });
1416
1425
  }
1417
1426
  function StatusPage(props) {