Skip to content

Commit b325ac4

Browse files
wishket-pjwJeremyDev87
authored andcommitted
fix: Enable npx codingbuddy to work within monorepo
- Create scripts/link-workspace-bins.js with Unix/Windows support - Generate .cmd and .ps1 shims for Windows compatibility - Skip gracefully when dist/ doesn't exist (pre-build state) - Update package.json postinstall to use new script close #84
1 parent af0877d commit b325ac4

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"apps/*"
77
],
88
"scripts": {
9+
"postinstall": "node scripts/link-workspace-bins.js",
10+
"build": "yarn workspace codingbuddy build && yarn postinstall",
911
"lint": "eslint .",
1012
"lint:fix": "eslint . --fix",
1113
"format": "prettier --write .",

scripts/link-workspace-bins.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Link workspace package binaries to node_modules/.bin
4+
*
5+
* This script creates executable shims for workspace packages,
6+
* enabling `npx codingbuddy` to work within the monorepo.
7+
*
8+
* Cross-platform: Creates symlinks on Unix, .cmd shims on Windows.
9+
*/
10+
11+
const fs = require('fs');
12+
const path = require('path');
13+
14+
const WORKSPACE_BINS = [
15+
{
16+
name: 'codingbuddy',
17+
target: 'apps/mcp-server/dist/src/cli/cli.js',
18+
},
19+
];
20+
21+
const BIN_DIR = path.join(__dirname, '..', 'node_modules', '.bin');
22+
const isWindows = process.platform === 'win32';
23+
24+
/**
25+
* Create Unix shell shim
26+
*/
27+
function createUnixShim(binPath, targetPath) {
28+
const shim = `#!/bin/sh
29+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
30+
exec node "$basedir/${targetPath}" "$@"
31+
`;
32+
fs.writeFileSync(binPath, shim, { mode: 0o755 });
33+
}
34+
35+
/**
36+
* Create Windows cmd shim
37+
*/
38+
function createWindowsShim(binPath, targetPath) {
39+
const cmdShim = `@ECHO off
40+
GOTO start
41+
:find_dp0
42+
SET dp0=%~dp0
43+
EXIT /b
44+
:start
45+
SETLOCAL
46+
CALL :find_dp0
47+
node "%dp0%\\${targetPath.replace(/\//g, '\\')}" %*
48+
`;
49+
fs.writeFileSync(binPath + '.cmd', cmdShim);
50+
51+
// Also create PowerShell shim
52+
const ps1Shim = `#!/usr/bin/env pwsh
53+
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
54+
$exe=""
55+
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
56+
$exe=".exe"
57+
}
58+
& "$basedir/../node$exe" "$basedir/${targetPath}" $args
59+
`;
60+
fs.writeFileSync(binPath + '.ps1', ps1Shim);
61+
}
62+
63+
/**
64+
* Link a single binary
65+
*/
66+
function linkBin({ name, target }) {
67+
const targetFullPath = path.join(__dirname, '..', target);
68+
const binPath = path.join(BIN_DIR, name);
69+
const relativePath = path.relative(BIN_DIR, targetFullPath);
70+
71+
// Check if target exists
72+
if (!fs.existsSync(targetFullPath)) {
73+
console.log(`[skip] ${name}: target not found (run build first)`);
74+
return false;
75+
}
76+
77+
// Ensure bin directory exists
78+
fs.mkdirSync(BIN_DIR, { recursive: true });
79+
80+
// Remove existing files
81+
try {
82+
fs.unlinkSync(binPath);
83+
} catch {}
84+
try {
85+
fs.unlinkSync(binPath + '.cmd');
86+
} catch {}
87+
try {
88+
fs.unlinkSync(binPath + '.ps1');
89+
} catch {}
90+
91+
// Create shims
92+
if (isWindows) {
93+
createWindowsShim(binPath, relativePath);
94+
console.log(`[link] ${name} -> ${target} (.cmd + .ps1)`);
95+
} else {
96+
createUnixShim(binPath, relativePath);
97+
console.log(`[link] ${name} -> ${target}`);
98+
}
99+
100+
// Ensure target is executable
101+
try {
102+
fs.chmodSync(targetFullPath, 0o755);
103+
} catch {}
104+
105+
return true;
106+
}
107+
108+
// Main
109+
console.log('Linking workspace binaries...');
110+
let linked = 0;
111+
112+
for (const bin of WORKSPACE_BINS) {
113+
if (linkBin(bin)) {
114+
linked++;
115+
}
116+
}
117+
118+
console.log(`Done: ${linked}/${WORKSPACE_BINS.length} binaries linked`);

0 commit comments

Comments
 (0)