fix: run qmd from unbuilt checkouts
This commit is contained in:
parent
632c34d120
commit
2b250f3dca
31
bin/qmd
31
bin/qmd
@ -25,6 +25,31 @@ if [ "$1" = "mcp" ]; then
|
||||
export GGML_BACKEND_SILENT="${GGML_BACKEND_SILENT:-1}"
|
||||
fi
|
||||
|
||||
JS="$DIR/dist/cli/qmd.js"
|
||||
|
||||
# In published packages dist/ is always present. In a fresh checkout, however,
|
||||
# people often run ./bin/qmd before building. Prefer a source-mode fallback when
|
||||
# dependencies are installed; otherwise fail with an actionable message instead
|
||||
# of a low-level "Module not found" from Node/Bun.
|
||||
if [ ! -f "$JS" ]; then
|
||||
TS="$DIR/src/cli/qmd.ts"
|
||||
if [ -f "$TS" ]; then
|
||||
if [ -f "$DIR/bun.lock" ] || [ -f "$DIR/bun.lockb" ]; then
|
||||
if command -v bun >/dev/null 2>&1; then
|
||||
exec bun "$TS" "$@"
|
||||
fi
|
||||
fi
|
||||
if [ -f "$DIR/node_modules/tsx/dist/cli.mjs" ]; then
|
||||
exec node "$DIR/node_modules/tsx/dist/cli.mjs" "$TS" "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "qmd is not built: missing $JS" >&2
|
||||
echo "Run: bun install && bun run build" >&2
|
||||
echo "Or: npm install && npm run build" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect the package manager that installed dependencies by checking lockfiles.
|
||||
# $BUN_INSTALL is intentionally NOT checked — it only indicates that bun exists
|
||||
# on the system, not that it was used to install this package (see #361).
|
||||
@ -34,9 +59,9 @@ fi
|
||||
# builds that use npm would be incorrectly routed to bun, causing ABI
|
||||
# mismatches with better-sqlite3 / sqlite-vec (see #381).
|
||||
if [ -f "$DIR/package-lock.json" ]; then
|
||||
exec node "$DIR/dist/cli/qmd.js" "$@"
|
||||
exec node "$JS" "$@"
|
||||
elif [ -f "$DIR/bun.lock" ] || [ -f "$DIR/bun.lockb" ]; then
|
||||
exec bun "$DIR/dist/cli/qmd.js" "$@"
|
||||
exec bun "$JS" "$@"
|
||||
else
|
||||
exec node "$DIR/dist/cli/qmd.js" "$@"
|
||||
exec node "$JS" "$@"
|
||||
fi
|
||||
|
||||
@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "vitest";
|
||||
import { chmodSync, copyFileSync, mkdtempSync, mkdirSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join, relative } from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { execFileSync, spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const repoRoot = fileURLToPath(new URL("..", import.meta.url));
|
||||
@ -27,13 +27,24 @@ function makeTempFixture() {
|
||||
return { root, capturePath, runtimeBin };
|
||||
}
|
||||
|
||||
function makePackage(root: string, packagePath: string, lockfiles: string[] = []) {
|
||||
function makePackage(root: string, packagePath: string, lockfiles: string[] = [], options: { dist?: boolean; source?: boolean; tsx?: boolean } = {}) {
|
||||
const packageRoot = join(root, packagePath);
|
||||
const includeDist = options.dist ?? true;
|
||||
mkdirSync(join(packageRoot, "bin"), { recursive: true });
|
||||
mkdirSync(join(packageRoot, "dist", "cli"), { recursive: true });
|
||||
copyFileSync(join(repoRoot, "bin", "qmd"), join(packageRoot, "bin", "qmd"));
|
||||
chmodSync(join(packageRoot, "bin", "qmd"), 0o755);
|
||||
writeFileSync(join(packageRoot, "dist", "cli", "qmd.js"), "// fixture\n");
|
||||
if (includeDist) {
|
||||
mkdirSync(join(packageRoot, "dist", "cli"), { recursive: true });
|
||||
writeFileSync(join(packageRoot, "dist", "cli", "qmd.js"), "// fixture\n");
|
||||
}
|
||||
if (options.source) {
|
||||
mkdirSync(join(packageRoot, "src", "cli"), { recursive: true });
|
||||
writeFileSync(join(packageRoot, "src", "cli", "qmd.ts"), "// source fixture\n");
|
||||
}
|
||||
if (options.tsx) {
|
||||
mkdirSync(join(packageRoot, "node_modules", "tsx", "dist"), { recursive: true });
|
||||
writeFileSync(join(packageRoot, "node_modules", "tsx", "dist", "cli.mjs"), "// tsx fixture\n");
|
||||
}
|
||||
for (const lockfile of lockfiles) {
|
||||
writeFileSync(join(packageRoot, lockfile), "");
|
||||
}
|
||||
@ -161,4 +172,45 @@ describe("bin/qmd package wrapper", () => {
|
||||
expect(result.runtime).toBe("node");
|
||||
expect(result.scriptPath).toBe(realpathSync(join(packageRoot, "dist", "cli", "qmd.js")));
|
||||
});
|
||||
|
||||
test("falls back to source with bun in an unbuilt Bun checkout", () => {
|
||||
const { root, runtimeBin, capturePath } = makeTempFixture();
|
||||
const packageRoot = makePackage(root, "qmd", ["bun.lock"], { dist: false, source: true });
|
||||
|
||||
const result = runWrapper(join(packageRoot, "bin", "qmd"), runtimeBin, capturePath);
|
||||
|
||||
expect(result.runtime).toBe("bun");
|
||||
expect(result.scriptPath).toBe(realpathSync(join(packageRoot, "src", "cli", "qmd.ts")));
|
||||
expect(result.args).toEqual(["--version"]);
|
||||
});
|
||||
|
||||
test("falls back to source through tsx in an unbuilt Node checkout", () => {
|
||||
const { root, runtimeBin, capturePath } = makeTempFixture();
|
||||
const packageRoot = makePackage(root, "qmd", [], { dist: false, source: true, tsx: true });
|
||||
|
||||
const result = runWrapper(join(packageRoot, "bin", "qmd"), runtimeBin, capturePath);
|
||||
|
||||
expect(result.runtime).toBe("node");
|
||||
expect(result.scriptPath).toBe(realpathSync(join(packageRoot, "node_modules", "tsx", "dist", "cli.mjs")));
|
||||
expect(result.args).toEqual([realpathSync(join(packageRoot, "src", "cli", "qmd.ts")), "--version"]);
|
||||
});
|
||||
|
||||
test("explains how to build when dist is missing and source cannot run", () => {
|
||||
const { root, runtimeBin } = makeTempFixture();
|
||||
const packageRoot = makePackage(root, "qmd", [], { dist: false });
|
||||
|
||||
const result = spawnSync(join(packageRoot, "bin", "qmd"), ["--version"], {
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `${runtimeBin}:${process.env.PATH ?? ""}`,
|
||||
},
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain("qmd is not built");
|
||||
expect(result.stderr).toContain("bun install && bun run build");
|
||||
expect(result.stderr).toContain("npm install && npm run build");
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user