@logionsh/cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,7 @@ On install, the postinstall hook:
22
22
 
23
23
  1. Finds a working Python 3.12+.
24
24
  2. Installs `logion-cli==<pinned-version>` from PyPI via `pipx`/`uv`/venv.
25
- 3. Shims the `logion` and `lgn` binaries onto your PATH.
25
+ 3. Shims the `logion` binary onto your PATH.
26
26
 
27
27
  The pinned PyPI version is baked into the npm tarball at publish
28
28
  time, so `npm install -g @logionsh/cli@0.3.0` always installs the
@@ -25,43 +25,14 @@ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__
25
25
 
26
26
  // src/bin/logion.ts
27
27
  var import_node_child_process = require("child_process");
28
-
29
- // src/lib/which.ts
30
28
  var import_node_fs = __toESM(require("fs"));
29
+ var import_node_os = __toESM(require("os"));
31
30
  var import_node_path = __toESM(require("path"));
32
- function candidatesForName(name) {
33
- if (process.platform !== "win32") {
34
- return [name];
35
- }
36
- const pathext = (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean);
37
- if (import_node_path.default.extname(name)) {
38
- return [name];
39
- }
40
- return [name, ...pathext.map((ext) => name + ext.toLowerCase())];
41
- }
42
- function which(name) {
43
- const rawPath = process.env.PATH ?? "";
44
- const dirs = rawPath.split(import_node_path.default.delimiter).filter(Boolean);
45
- for (const dir of dirs) {
46
- for (const candidate of candidatesForName(name)) {
47
- const full = import_node_path.default.join(dir, candidate);
48
- try {
49
- const stat = import_node_fs.default.statSync(full);
50
- if (stat.isFile()) {
51
- return full;
52
- }
53
- } catch {
54
- }
55
- }
56
- }
57
- return null;
58
- }
59
-
60
- // src/bin/logion.ts
61
- var target = which("logion");
62
- if (!target) {
31
+ var managedVenvDir = import_node_path.default.join(import_node_os.default.homedir(), ".logion", "npm-managed-venv");
32
+ var target = process.platform === "win32" ? import_node_path.default.join(managedVenvDir, "Scripts", "logion.exe") : import_node_path.default.join(managedVenvDir, "bin", "logion");
33
+ if (!import_node_fs.default.existsSync(target)) {
63
34
  process.stderr.write(
64
- "logion binary not found. Reinstall with `npm install -g @logionsh/cli` or install directly via `pipx install logion-cli`.\n"
35
+ "logion binary not found in the npm-managed environment. Reinstall with `npm install -g @logionsh/cli` or rerun `npx @logionsh/cli`.\n"
65
36
  );
66
37
  process.exit(127);
67
38
  }
@@ -44,7 +44,10 @@ function candidatesForName(name) {
44
44
  }
45
45
  return [name, ...pathext.map((ext) => name + ext.toLowerCase())];
46
46
  }
47
- function which(name) {
47
+ function which(name, options = {}) {
48
+ const excluded = new Set(
49
+ (options.excludeRealpaths ?? []).map((p) => import_node_fs.default.realpathSync.native(p))
50
+ );
48
51
  const rawPath = process.env.PATH ?? "";
49
52
  const dirs = rawPath.split(import_node_path.default.delimiter).filter(Boolean);
50
53
  for (const dir of dirs) {
@@ -52,7 +55,7 @@ function which(name) {
52
55
  const full = import_node_path.default.join(dir, candidate);
53
56
  try {
54
57
  const stat = import_node_fs.default.statSync(full);
55
- if (stat.isFile()) {
58
+ if (stat.isFile() && !excluded.has(import_node_fs.default.realpathSync.native(full))) {
56
59
  return full;
57
60
  }
58
61
  } catch {
@@ -249,7 +252,6 @@ var HOME = import_node_os2.default.homedir();
249
252
  var LOGION_DIR2 = import_node_path3.default.join(HOME, ".logion");
250
253
  var MANAGED_VENV_DIR = import_node_path3.default.join(LOGION_DIR2, "npm-managed-venv");
251
254
  var MARKER_PATH = import_node_path3.default.join(LOGION_DIR2, "npm-wrapper-installer.json");
252
- var LOCAL_BIN = import_node_path3.default.join(HOME, ".local", "bin");
253
255
  var PLACEHOLDER_VERSION = "0.0.0-placeholder";
254
256
  function log(msg) {
255
257
  process.stderr.write(`[logion-postinstall] ${msg}
@@ -310,48 +312,15 @@ function venvBin(name) {
310
312
  }
311
313
  return import_node_path3.default.join(MANAGED_VENV_DIR, "bin", name);
312
314
  }
313
- function linkOrCopy(src, dest) {
314
- if (import_node_fs3.default.existsSync(dest)) {
315
- import_node_fs3.default.unlinkSync(dest);
316
- }
317
- try {
318
- import_node_fs3.default.symlinkSync(src, dest);
319
- } catch {
320
- import_node_fs3.default.copyFileSync(src, dest);
321
- }
322
- }
323
- function shimNamesFor(base) {
324
- return process.platform === "win32" ? [`${base}.exe`] : [base];
325
- }
326
315
  function installViaVenv(version, py) {
327
316
  log(`Installing logion-cli==${version} via managed venv...`);
328
- runChecked(py.cmd, [...py.args, "-m", "venv", MANAGED_VENV_DIR]);
317
+ runChecked(py.cmd, [...py.args, "-m", "venv", "--clear", MANAGED_VENV_DIR]);
329
318
  runChecked(venvBin("pip"), ["install", `logion-cli==${version}`]);
330
- import_node_fs3.default.mkdirSync(LOCAL_BIN, { recursive: true });
331
- for (const base of ["logion", "lgn"]) {
332
- const src = venvBin(base);
333
- if (!import_node_fs3.default.existsSync(src)) {
334
- continue;
335
- }
336
- for (const destName of shimNamesFor(base)) {
337
- const dest = import_node_path3.default.join(LOCAL_BIN, destName);
338
- try {
339
- linkOrCopy(src, dest);
340
- } catch (error) {
341
- const msg = error instanceof Error ? error.message : String(error);
342
- log(
343
- `Warning: could not create shim ${dest}: ${msg}. Add ${LOCAL_BIN} to PATH manually.`
344
- );
345
- }
346
- }
347
- }
348
319
  }
349
- function verifyInstall(version) {
350
- const target = which("logion");
351
- if (!target) {
352
- log(
353
- "Warning: logion not on PATH yet. Ensure your installer's bin directory is exported."
354
- );
320
+ function verifyInstall(version, installer) {
321
+ const target = installer === "venv" ? venvBin("logion") : which("logion");
322
+ if (!target || !import_node_fs3.default.existsSync(target)) {
323
+ log("Warning: logion binary was not found after install.");
355
324
  return;
356
325
  }
357
326
  const r = (0, import_node_child_process2.spawnSync)(target, ["--version"], {
@@ -371,12 +340,6 @@ function pickInstaller(forced) {
371
340
  if (forced !== void 0 && forced.length > 0) {
372
341
  return null;
373
342
  }
374
- if (which("pipx")) {
375
- return "pipx";
376
- }
377
- if (which("uv")) {
378
- return "uv";
379
- }
380
343
  return "venv";
381
344
  }
382
345
  function maybePrintOnboardingPointer() {
@@ -407,9 +370,7 @@ function main() {
407
370
  "Error: Python 3.12+ not found. Install Python 3.12+ or set LOGION_NPM_PYTHON."
408
371
  );
409
372
  log("See: https://www.python.org/downloads/");
410
- log(
411
- "Or set LOGION_NPM_SKIP_INSTALL=1 and install manually: pipx install logion-cli"
412
- );
373
+ log("Or set LOGION_NPM_SKIP_INSTALL=1 to skip the Python CLI install.");
413
374
  process.exit(1);
414
375
  }
415
376
  log(`Using Python: ${py.cmd} ${py.args.join(" ")}`.trim());
@@ -427,7 +388,7 @@ function main() {
427
388
  installViaVenv(version, py);
428
389
  }
429
390
  writeMarker(installer, version);
430
- verifyInstall(version);
391
+ verifyInstall(version, installer);
431
392
  maybePrintOnboardingPointer();
432
393
  log(`Installed logion-cli ${version} via ${installer}.`);
433
394
  }
@@ -41,7 +41,10 @@ function candidatesForName(name) {
41
41
  }
42
42
  return [name, ...pathext.map((ext) => name + ext.toLowerCase())];
43
43
  }
44
- function which(name) {
44
+ function which(name, options = {}) {
45
+ const excluded = new Set(
46
+ (options.excludeRealpaths ?? []).map((p) => import_node_fs.default.realpathSync.native(p))
47
+ );
45
48
  const rawPath = process.env.PATH ?? "";
46
49
  const dirs = rawPath.split(import_node_path.default.delimiter).filter(Boolean);
47
50
  for (const dir of dirs) {
@@ -49,7 +52,7 @@ function which(name) {
49
52
  const full = import_node_path.default.join(dir, candidate);
50
53
  try {
51
54
  const stat = import_node_fs.default.statSync(full);
52
- if (stat.isFile()) {
55
+ if (stat.isFile() && !excluded.has(import_node_fs.default.realpathSync.native(full))) {
53
56
  return full;
54
57
  }
55
58
  } catch {
@@ -64,7 +67,6 @@ var HOME = import_node_os.default.homedir();
64
67
  var LOGION_DIR = import_node_path2.default.join(HOME, ".logion");
65
68
  var MANAGED_VENV_DIR = import_node_path2.default.join(LOGION_DIR, "npm-managed-venv");
66
69
  var MARKER_PATH = import_node_path2.default.join(LOGION_DIR, "npm-wrapper-installer.json");
67
- var LOCAL_BIN = import_node_path2.default.join(HOME, ".local", "bin");
68
70
  function log(msg) {
69
71
  process.stderr.write(`[logion-uninstall] ${msg}
70
72
  `);
@@ -95,28 +97,13 @@ function removeManagedVenv() {
95
97
  log(`Warning: could not remove managed venv: ${msg}`);
96
98
  }
97
99
  }
98
- function removeShims() {
99
- const names = process.platform === "win32" ? ["logion.exe", "lgn.exe", "logion.cmd", "lgn.cmd"] : ["logion", "lgn"];
100
- for (const name of names) {
101
- const link = import_node_path2.default.join(LOCAL_BIN, name);
102
- try {
103
- const stat = import_node_fs2.default.lstatSync(link);
104
- if (stat.isSymbolicLink() || stat.isFile()) {
105
- import_node_fs2.default.unlinkSync(link);
106
- }
107
- } catch {
108
- }
109
- }
110
- }
111
100
  function main() {
112
101
  const marker = readMarker();
113
102
  if (!marker) {
114
- removeShims();
115
103
  return;
116
104
  }
117
105
  if (marker.installer === "venv") {
118
106
  removeManagedVenv();
119
- removeShims();
120
107
  } else if (marker.installer === "pipx" && which("pipx")) {
121
108
  log("Uninstalling logion-cli via pipx...");
122
109
  tryRun("pipx", ["uninstall", "logion-cli"]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@logionsh/cli",
3
- "version": "0.1.0",
4
- "description": "Logion CLI — installs and shims the canonical Python logion-cli from PyPI.",
3
+ "version": "0.1.2",
4
+ "description": "Logion CLI — installs and runs the canonical Python logion-cli from a managed environment.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -19,8 +19,7 @@
19
19
  "agent"
20
20
  ],
21
21
  "bin": {
22
- "logion": "dist/bin/logion.js",
23
- "lgn": "dist/bin/lgn.js"
22
+ "logion": "dist/bin/logion.js"
24
23
  },
25
24
  "scripts": {
26
25
  "build": "tsup",
@@ -66,5 +65,5 @@
66
65
  "typescript-eslint": "^8.20.0",
67
66
  "vitest": "^3.2.0"
68
67
  },
69
- "logionCliVersion": "0.1.0"
68
+ "logionCliVersion": "0.1.2"
70
69
  }
package/dist/bin/lgn.js DELETED
@@ -1,74 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target2, "default", { value: mod, enumerable: true }) : target2,
23
- mod
24
- ));
25
-
26
- // src/bin/lgn.ts
27
- var import_node_child_process = require("child_process");
28
-
29
- // src/lib/which.ts
30
- var import_node_fs = __toESM(require("fs"));
31
- var import_node_path = __toESM(require("path"));
32
- function candidatesForName(name) {
33
- if (process.platform !== "win32") {
34
- return [name];
35
- }
36
- const pathext = (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean);
37
- if (import_node_path.default.extname(name)) {
38
- return [name];
39
- }
40
- return [name, ...pathext.map((ext) => name + ext.toLowerCase())];
41
- }
42
- function which(name) {
43
- const rawPath = process.env.PATH ?? "";
44
- const dirs = rawPath.split(import_node_path.default.delimiter).filter(Boolean);
45
- for (const dir of dirs) {
46
- for (const candidate of candidatesForName(name)) {
47
- const full = import_node_path.default.join(dir, candidate);
48
- try {
49
- const stat = import_node_fs.default.statSync(full);
50
- if (stat.isFile()) {
51
- return full;
52
- }
53
- } catch {
54
- }
55
- }
56
- }
57
- return null;
58
- }
59
-
60
- // src/bin/lgn.ts
61
- var target = which("lgn") ?? which("logion");
62
- if (!target) {
63
- process.stderr.write(
64
- "lgn/logion binary not found. Reinstall with `npm install -g @logionsh/cli` or install directly via `pipx install logion-cli`.\n"
65
- );
66
- process.exit(127);
67
- }
68
- var r = (0, import_node_child_process.spawnSync)(target, process.argv.slice(2), { stdio: "inherit" });
69
- if (r.error) {
70
- process.stderr.write(`${r.error.message}
71
- `);
72
- process.exit(1);
73
- }
74
- process.exit(r.status ?? 1);