Skip to content

Commit 3331324

Browse files
committed
fix(installer): support npm-linked cli wrapper
1 parent a2ab37d commit 3331324

3 files changed

Lines changed: 50 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111
- (placeholder for next release)
1212

13+
### Fixed
14+
- Local `npm link` installs now run the CLI wrapper correctly by resolving symlinked bin paths before direct-execution detection.
15+
1316
## [6.1.7] - 2026-04-25
1417

1518
### Added

scripts/install-oc-codex-multi-auth.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
11
#!/usr/bin/env node
22

3+
import { realpathSync } from "node:fs";
34
import { resolve } from "node:path";
45
import { fileURLToPath } from "node:url";
56
import { runInstaller } from "./install-oc-codex-multi-auth-core.js";
67

78
export * from "./install-oc-codex-multi-auth-core.js";
89

9-
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
10+
const __filename = fileURLToPath(import.meta.url);
11+
12+
function normalizePathForCompare(path, resolveRealPath = realpathSync) {
13+
const resolved = resolve(path);
14+
try {
15+
const realPath = resolveRealPath(resolved);
16+
return process.platform === "win32" ? realPath.toLowerCase() : realPath;
17+
} catch {
18+
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
19+
}
20+
}
21+
22+
export function isDirectRunPath(
23+
argvPath = process.argv[1],
24+
modulePath = __filename,
25+
resolveRealPath = realpathSync,
26+
) {
27+
if (!argvPath) return false;
28+
return (
29+
normalizePathForCompare(argvPath, resolveRealPath) ===
30+
normalizePathForCompare(modulePath, resolveRealPath)
31+
);
32+
}
33+
34+
if (isDirectRunPath()) {
1035
runInstaller().catch((error) => {
1136
const message = error instanceof Error ? error.message : String(error);
1237
console.error(`Installer failed: ${message}`);

test/install-oc-codex-multi-auth.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, describe, expect, it, vi } from "vitest";
22
import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
33
import { tmpdir } from "node:os";
4-
import { join } from "node:path";
4+
import { join, resolve } from "node:path";
55

66
type OpenAiTemplate = {
77
provider: {
@@ -42,6 +42,26 @@ describe("install-oc-codex-multi-auth script", () => {
4242
expect(errorSpy).not.toHaveBeenCalled();
4343
});
4444

45+
it("detects direct CLI execution after path normalization", async () => {
46+
vi.resetModules();
47+
const { isDirectRunPath } = await import("../scripts/install-oc-codex-multi-auth.js");
48+
const scriptPath = resolve("scripts", "install-oc-codex-multi-auth.js");
49+
const symlinkedScriptPath = join(
50+
process.cwd(),
51+
"global",
52+
"node_modules",
53+
"oc-codex-multi-auth",
54+
"install-oc-codex-multi-auth.js",
55+
);
56+
const resolveRealPath = (path: string) => path === symlinkedScriptPath ? scriptPath : path;
57+
58+
expect(isDirectRunPath(symlinkedScriptPath, scriptPath, resolveRealPath)).toBe(true);
59+
expect(
60+
isDirectRunPath(resolve("scripts", "install-oc-codex-multi-auth-core.js"), scriptPath),
61+
).toBe(false);
62+
expect(isDirectRunPath(undefined, scriptPath)).toBe(false);
63+
});
64+
4565
it("writes compact UI catalog by default, preserves user model entries, and normalizes plugin entries", async () => {
4666
vi.resetModules();
4767
tempHome = await createTempHome();

0 commit comments

Comments
 (0)