bluefairy 0.0.1 → 0.0.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.
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+
3
+ _bluefairy_home="${BLUEFAIRY_HOME:-$HOME/.bluefairy}"
4
+
5
+ if command -v bluefairy >/dev/null 2>&1; then
6
+ bluefairy init --quiet >/dev/null 2>&1 || return $?
7
+ fi
8
+
9
+ case ":$PATH:" in
10
+ *":$_bluefairy_home/shims:"*) ;;
11
+ *) PATH="$_bluefairy_home/shims:$PATH" ;;
12
+ esac
13
+
14
+ export PATH
15
+ unset _bluefairy_home
@@ -0,0 +1,15 @@
1
+ @echo off
2
+ setlocal
3
+ if "%BLUEFAIRY_HOME%"=="" set "BLUEFAIRY_HOME=%USERPROFILE%\.bluefairy"
4
+
5
+ call bluefairy init --quiet >NUL 2>&1
6
+ if errorlevel 1 (
7
+ endlocal & exit /b %errorlevel%
8
+ )
9
+
10
+ echo %PATH% | find /I "%BLUEFAIRY_HOME%\shims" >NUL
11
+ if errorlevel 1 (
12
+ endlocal & set "PATH=%BLUEFAIRY_HOME%\shims;%PATH%"
13
+ ) else (
14
+ endlocal & set "PATH=%PATH%"
15
+ )
@@ -0,0 +1,15 @@
1
+ if (-not $env:BLUEFAIRY_HOME) {
2
+ $env:BLUEFAIRY_HOME = Join-Path $HOME ".bluefairy"
3
+ }
4
+
5
+ & bluefairy init --quiet *> $null
6
+ if ($LASTEXITCODE -ne 0) {
7
+ return
8
+ }
9
+
10
+ $shimDir = Join-Path $env:BLUEFAIRY_HOME "shims"
11
+ $pathEntries = $env:PATH -split ';'
12
+
13
+ if (-not ($pathEntries | Where-Object { $_ -eq $shimDir })) {
14
+ $env:PATH = "$shimDir;$env:PATH"
15
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ import process from "node:process";
3
+ import { loadConfig } from "./config.js";
4
+ import { runDoctor } from "./commands/doctor.js";
5
+ import { runInit } from "./commands/init.js";
6
+ import { runShim } from "./runtime.js";
7
+ import { BLUEFAIRY_VERSION } from "./version.js";
8
+ function printHelp() {
9
+ console.log(`Bluefairy
10
+
11
+ Usage:
12
+ bluefairy init [--quiet]
13
+ bluefairy doctor [--short|--oneline]
14
+
15
+ Internal:
16
+ bluefairy internal-shim <uv|npm> [args...]
17
+ `);
18
+ }
19
+ function printVersion() {
20
+ console.log(BLUEFAIRY_VERSION);
21
+ }
22
+ async function main() {
23
+ const argv = process.argv.slice(2);
24
+ const [command, ...rest] = argv;
25
+ if (!command || command === "--help" || command === "-h") {
26
+ printHelp();
27
+ return;
28
+ }
29
+ if (command === "--version" || command === "-V") {
30
+ printVersion();
31
+ return;
32
+ }
33
+ const config = loadConfig(process.env);
34
+ switch (command) {
35
+ case "init":
36
+ await runInit(config, rest);
37
+ return;
38
+ case "doctor":
39
+ await runDoctor(config, rest);
40
+ return;
41
+ case "internal-shim": {
42
+ const [tool, ...toolArgs] = rest;
43
+ if (tool !== "uv" && tool !== "npm") {
44
+ throw new Error(`Unsupported shim target: ${tool ?? "(missing)"}`);
45
+ }
46
+ await runShim(tool, toolArgs, config);
47
+ return;
48
+ }
49
+ default:
50
+ throw new Error(`Unknown command: ${command}`);
51
+ }
52
+ }
53
+ main().catch((error) => {
54
+ const message = error instanceof Error ? error.message : `Unknown error: ${String(error)}`;
55
+ console.error(`bluefairy: ${message}`);
56
+ process.exitCode = 1;
57
+ });
58
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;CAQb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAChD,YAAY,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC5B,OAAO;QACT,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9B,OAAO;QACT,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC;YACjC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7E,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,134 @@
1
+ import { exists } from "../fs-utils.js";
2
+ import { getPathValue, isSameOrDescendantPath, resolveBinaryOnPath, resolveRealBinary, samePath, stripShimDirFromPath } from "../runtime.js";
3
+ import { createPalette, shouldUseColor } from "../terminal.js";
4
+ import path from "node:path";
5
+ function pathEntries(env) {
6
+ return getPathValue(env).split(path.delimiter).filter(Boolean);
7
+ }
8
+ async function collectToolReport(config, env, tool) {
9
+ const currentPathResolution = await resolveBinaryOnPath(tool, env);
10
+ const underlyingBinaryResolution = await resolveRealBinary(tool, env, config.paths);
11
+ const strippedPath = stripShimDirFromPath(env, config.paths);
12
+ return {
13
+ name: tool,
14
+ currentPathResolution,
15
+ underlyingBinaryResolution,
16
+ shimDirStrippedFromPath: strippedPath !== getPathValue(env)
17
+ };
18
+ }
19
+ export async function collectDoctorReport(config, env = process.env) {
20
+ return {
21
+ homeDir: config.paths.homeDir,
22
+ shimDir: config.paths.shimDir,
23
+ shimDirExists: await exists(config.paths.shimDir),
24
+ activatedInCurrentShell: pathEntries(env).some((entry) => samePath(entry, config.paths.shimDir)),
25
+ tools: [
26
+ await collectToolReport(config, env, "uv"),
27
+ await collectToolReport(config, env, "npm")
28
+ ]
29
+ };
30
+ }
31
+ function formatStatus(palette, value) {
32
+ return value ? palette.green("yes") : palette.red("no");
33
+ }
34
+ function formatPathValue(palette, value) {
35
+ return value ?? palette.yellow("(not found)");
36
+ }
37
+ function isShimPath(report, value) {
38
+ return value !== null && isSameOrDescendantPath(report.shimDir, value);
39
+ }
40
+ function summarizeTool(report, tool) {
41
+ if (tool.currentPathResolution === null ||
42
+ tool.underlyingBinaryResolution === null) {
43
+ return "missing";
44
+ }
45
+ if (isShimPath(report, tool.currentPathResolution)) {
46
+ return "protected";
47
+ }
48
+ return "not-protected";
49
+ }
50
+ function summarizeDoctorReport(report) {
51
+ const toolStates = Object.fromEntries(report.tools.map((tool) => [tool.name, summarizeTool(report, tool)]));
52
+ const install = report.shimDirExists ? "ready" : "missing";
53
+ let level = "OK";
54
+ if (install === "missing" ||
55
+ Object.values(toolStates).some((state) => state === "missing")) {
56
+ level = "FAIL";
57
+ }
58
+ else if (!report.activatedInCurrentShell ||
59
+ Object.values(toolStates).some((state) => state === "not-protected")) {
60
+ level = "WARN";
61
+ }
62
+ return {
63
+ level,
64
+ active: report.activatedInCurrentShell,
65
+ install,
66
+ toolStates
67
+ };
68
+ }
69
+ function formatSummaryLevel(palette, level) {
70
+ switch (level) {
71
+ case "OK":
72
+ return palette.greenBadge(level);
73
+ case "WARN":
74
+ return palette.yellowBadge(level);
75
+ case "FAIL":
76
+ return palette.redBadge(level);
77
+ }
78
+ }
79
+ function formatSummaryValue(palette, value) {
80
+ switch (value) {
81
+ case "yes":
82
+ case "ready":
83
+ case "protected":
84
+ return palette.greenBadge(value);
85
+ case "no":
86
+ case "not-protected":
87
+ return palette.yellowBadge(value);
88
+ case "missing":
89
+ return palette.redBadge(value);
90
+ default:
91
+ return palette.bold(value);
92
+ }
93
+ }
94
+ export function renderDoctorShortReport(report, options = {}) {
95
+ const palette = createPalette(options.color ?? false);
96
+ const summary = summarizeDoctorReport(report);
97
+ return [
98
+ `${palette.bold("Bluefairy doctor:")} ${formatSummaryLevel(palette, summary.level)}`,
99
+ `active=${formatSummaryValue(palette, summary.active ? "yes" : "no")}`,
100
+ `install=${formatSummaryValue(palette, summary.install)}`,
101
+ `uv=${formatSummaryValue(palette, summary.toolStates.uv)}`,
102
+ `npm=${formatSummaryValue(palette, summary.toolStates.npm)}`
103
+ ].join(" | ");
104
+ }
105
+ export function renderDoctorReport(report, options = {}) {
106
+ const palette = createPalette(options.color ?? false);
107
+ const lines = [
108
+ palette.bold(palette.cyan("Bluefairy doctor")),
109
+ `${palette.dim("home:")} ${report.homeDir}`,
110
+ `${palette.dim("shims:")} ${report.shimDir}`,
111
+ `${palette.dim("shim dir exists:")} ${formatStatus(palette, report.shimDirExists)}`,
112
+ `${palette.dim("activated in current shell:")} ${formatStatus(palette, report.activatedInCurrentShell)}`,
113
+ ""
114
+ ];
115
+ for (const [index, tool] of report.tools.entries()) {
116
+ lines.push(palette.bold(`${tool.name}:`));
117
+ lines.push(` ${palette.dim("current PATH resolution:")} ${formatPathValue(palette, tool.currentPathResolution)}`);
118
+ lines.push(` ${palette.dim("underlying binary resolution:")} ${formatPathValue(palette, tool.underlyingBinaryResolution)}`);
119
+ lines.push(` ${palette.dim("shim dir stripped from PATH:")} ${formatStatus(palette, tool.shimDirStrippedFromPath)}`);
120
+ if (index < report.tools.length - 1) {
121
+ lines.push("");
122
+ }
123
+ }
124
+ return lines.join("\n");
125
+ }
126
+ export async function runDoctor(config, args = []) {
127
+ const report = await collectDoctorReport(config, process.env);
128
+ const color = shouldUseColor();
129
+ const output = args.includes("--short") || args.includes("--oneline")
130
+ ? renderDoctorShortReport(report, { color })
131
+ : renderDoctorReport(report, { color });
132
+ console.log(output);
133
+ }
134
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { ensureDir } from "../fs-utils.js";
2
+ import { ensureManagedShims } from "../shims.js";
3
+ function hasFlag(args, flag) {
4
+ return args.includes(flag);
5
+ }
6
+ export async function runInit(config, args) {
7
+ const quiet = hasFlag(args, "--quiet");
8
+ await ensureDir(config.paths.homeDir);
9
+ await ensureDir(config.paths.tempDir);
10
+ await ensureDir(config.paths.stateDir);
11
+ await ensureManagedShims(config.paths);
12
+ if (quiet) {
13
+ return;
14
+ }
15
+ console.log(`Bluefairy initialized at ${config.paths.homeDir}`);
16
+ console.log(`Managed shims: ${config.paths.shimDir}`);
17
+ console.log("");
18
+ console.log("Activate for this shell session:");
19
+ console.log(" POSIX: . bluefairy-activate");
20
+ console.log(" cmd.exe: CALL bluefairy-activate.cmd");
21
+ console.log(" PowerShell: . bluefairy-activate.ps1");
22
+ }
23
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY;IAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAuB,EACvB,IAAc;IAEd,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEvC,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACxD,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,44 @@
1
+ import { getRuntimePaths } from "./paths.js";
2
+ function parseBoolean(value, fallback) {
3
+ if (value === undefined || value === "") {
4
+ return fallback;
5
+ }
6
+ switch (value.trim().toLowerCase()) {
7
+ case "1":
8
+ case "true":
9
+ case "yes":
10
+ case "on":
11
+ return true;
12
+ case "0":
13
+ case "false":
14
+ case "no":
15
+ case "off":
16
+ return false;
17
+ default:
18
+ return fallback;
19
+ }
20
+ }
21
+ function parseNumber(value, fallback) {
22
+ if (value === undefined || value === "") {
23
+ return fallback;
24
+ }
25
+ const parsed = Number(value);
26
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
27
+ }
28
+ export function loadConfig(env) {
29
+ const delayHours = parseNumber(env.BLUEFAIRY_DELAY_HOURS, 72);
30
+ const paths = getRuntimePaths(env);
31
+ return {
32
+ enabled: parseBoolean(env.BLUEFAIRY_ENABLED, true),
33
+ delayHours,
34
+ npmEnabled: parseBoolean(env.BLUEFAIRY_NPM_ENABLED, true),
35
+ uvEnabled: parseBoolean(env.BLUEFAIRY_UV_ENABLED, true),
36
+ npmDelayHours: parseNumber(env.BLUEFAIRY_NPM_DELAY_HOURS, delayHours),
37
+ pythonDelayHours: parseNumber(env.BLUEFAIRY_PYTHON_DELAY_HOURS, delayHours),
38
+ failOpen: parseBoolean(env.BLUEFAIRY_FAIL_OPEN, true),
39
+ verbose: parseBoolean(env.BLUEFAIRY_VERBOSE, false),
40
+ debug: parseBoolean(env.BLUEFAIRY_DEBUG, false),
41
+ paths
42
+ };
43
+ }
44
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAC;AAehE,SAAS,YAAY,CAAC,KAAyB,EAAE,QAAiB;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACnC,KAAK,GAAG,CAAC;QACT,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd,KAAK,GAAG,CAAC;QACT,KAAK,OAAO,CAAC;QACb,KAAK,IAAI,CAAC;QACV,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB,EAAE,QAAgB;IAC9D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAsB;IAC/C,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEnC,OAAO;QACL,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC;QAClD,UAAU;QACV,UAAU,EAAE,YAAY,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC;QACzD,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC;QACvD,aAAa,EAAE,WAAW,CAAC,GAAG,CAAC,yBAAyB,EAAE,UAAU,CAAC;QACrE,gBAAgB,EAAE,WAAW,CAAC,GAAG,CAAC,4BAA4B,EAAE,UAAU,CAAC;QAC3E,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC;QACrD,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC;QACnD,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC;QAC/C,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { access, mkdir, writeFile } from "node:fs/promises";
2
+ import { constants } from "node:fs";
3
+ export async function exists(filePath) {
4
+ try {
5
+ await access(filePath);
6
+ return true;
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ export async function ensureDir(dirPath) {
13
+ await mkdir(dirPath, { recursive: true });
14
+ }
15
+ export async function writeExecutableFile(filePath, contents) {
16
+ await writeFile(filePath, contents, { mode: 0o755 });
17
+ }
18
+ export async function isExecutable(filePath) {
19
+ try {
20
+ if (process.platform === "win32") {
21
+ await access(filePath);
22
+ }
23
+ else {
24
+ await access(filePath, constants.X_OK);
25
+ }
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ //# sourceMappingURL=fs-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,QAAgB;IAEhB,MAAM,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/dist/log.js ADDED
@@ -0,0 +1,17 @@
1
+ export class Logger {
2
+ config;
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ info(message) {
7
+ if (this.config.verbose || this.config.debug) {
8
+ console.error(`[bluefairy] ${message}`);
9
+ }
10
+ }
11
+ debug(message) {
12
+ if (this.config.debug) {
13
+ console.error(`[bluefairy:debug] ${message}`);
14
+ }
15
+ }
16
+ }
17
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,MAAM;IACmB;IAApC,YAAoC,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAExD,IAAI,CAAC,OAAe;QACzB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,OAAe;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;CACF"}
package/dist/paths.js ADDED
@@ -0,0 +1,26 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export function getBluefairyHome(env) {
4
+ const explicit = env.BLUEFAIRY_HOME?.trim();
5
+ return explicit && explicit.length > 0
6
+ ? path.resolve(explicit)
7
+ : path.join(os.homedir(), ".bluefairy");
8
+ }
9
+ export function getRuntimePaths(env) {
10
+ const homeDir = getBluefairyHome(env);
11
+ return {
12
+ homeDir,
13
+ shimDir: path.join(homeDir, "shims"),
14
+ tempDir: path.join(homeDir, "tmp"),
15
+ stateDir: path.join(homeDir, "state")
16
+ };
17
+ }
18
+ export function getUserUvConfigPath(env) {
19
+ if (process.platform === "win32") {
20
+ const appData = env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
21
+ return path.join(appData, "uv", "uv.toml");
22
+ }
23
+ const xdgConfig = env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
24
+ return path.join(xdgConfig, "uv", "uv.toml");
25
+ }
26
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B,MAAM,UAAU,gBAAgB,CAAC,GAAsB;IACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IAC5C,OAAO,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QACpC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAsB;IACpD,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO;QACL,OAAO;QACP,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;QACpC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC;QAClC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAsB;IACxD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GACX,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,182 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { access } from "node:fs/promises";
5
+ import { constants } from "node:fs";
6
+ import { Logger } from "./log.js";
7
+ import { buildNpmExecution } from "./wrappers/npm.js";
8
+ import { buildUvExecution } from "./wrappers/uv.js";
9
+ export function shouldUseShellForBinary(binary) {
10
+ if (process.platform !== "win32") {
11
+ return false;
12
+ }
13
+ const ext = path.extname(binary).toLowerCase();
14
+ return ext === ".cmd" || ext === ".bat";
15
+ }
16
+ function getEnvKey(env, key) {
17
+ if (process.platform !== "win32") {
18
+ return key;
19
+ }
20
+ if (key.toLowerCase() === "path" && "Path" in env) {
21
+ return "Path";
22
+ }
23
+ const exactMatch = Object.keys(env).find((entry) => entry === key);
24
+ if (exactMatch) {
25
+ return exactMatch;
26
+ }
27
+ const caseInsensitiveMatch = Object.keys(env).find((entry) => entry.toLowerCase() === key.toLowerCase());
28
+ if (caseInsensitiveMatch) {
29
+ return caseInsensitiveMatch;
30
+ }
31
+ return key.toLowerCase() === "path" ? "Path" : key;
32
+ }
33
+ function getEnvValue(env, key) {
34
+ const resolvedKey = getEnvKey(env, key);
35
+ return env[resolvedKey];
36
+ }
37
+ export function getPathValue(env) {
38
+ return getEnvValue(env, "PATH") ?? "";
39
+ }
40
+ export function withPathValue(env, pathValue) {
41
+ const resolvedKey = getEnvKey(env, "PATH");
42
+ const nextEnv = { ...env };
43
+ if (process.platform === "win32") {
44
+ for (const key of Object.keys(nextEnv)) {
45
+ if (key !== resolvedKey && key.toLowerCase() === "path") {
46
+ delete nextEnv[key];
47
+ }
48
+ }
49
+ }
50
+ nextEnv[resolvedKey] = pathValue;
51
+ return nextEnv;
52
+ }
53
+ function normalizeComparablePath(filePath) {
54
+ const normalized = path.normalize(path.resolve(filePath));
55
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
56
+ }
57
+ export function samePath(left, right) {
58
+ return normalizeComparablePath(left) === normalizeComparablePath(right);
59
+ }
60
+ export function isSameOrDescendantPath(basePath, candidatePath) {
61
+ const normalizedBase = normalizeComparablePath(basePath);
62
+ const normalizedCandidate = normalizeComparablePath(candidatePath);
63
+ const normalizedBaseWithSeparator = normalizedBase.endsWith(path.sep)
64
+ ? normalizedBase
65
+ : `${normalizedBase}${path.sep}`;
66
+ return (normalizedCandidate === normalizedBase ||
67
+ normalizedCandidate.startsWith(normalizedBaseWithSeparator));
68
+ }
69
+ function pathEntries(env) {
70
+ const rawPath = getPathValue(env);
71
+ const separator = path.delimiter;
72
+ return rawPath.split(separator).filter((entry) => entry.length > 0);
73
+ }
74
+ export function stripShimDirFromPath(env, paths) {
75
+ const separator = path.delimiter;
76
+ return pathEntries(env)
77
+ .filter((entry) => !samePath(entry, paths.shimDir))
78
+ .join(separator);
79
+ }
80
+ async function executableExists(candidate) {
81
+ try {
82
+ if (process.platform === "win32") {
83
+ await access(candidate);
84
+ }
85
+ else {
86
+ await access(candidate, constants.X_OK);
87
+ }
88
+ return true;
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ function getCandidateNames(command, env) {
95
+ if (process.platform !== "win32") {
96
+ return [command];
97
+ }
98
+ const ext = path.extname(command);
99
+ if (ext) {
100
+ return [command];
101
+ }
102
+ const pathext = (getEnvValue(env, "PATHEXT") ?? ".EXE;.CMD;.BAT;.COM")
103
+ .split(";")
104
+ .filter(Boolean);
105
+ return [...pathext.map((suffix) => `${command}${suffix}`), command];
106
+ }
107
+ export async function resolveBinaryOnPath(command, env) {
108
+ for (const directory of pathEntries(env)) {
109
+ for (const candidateName of getCandidateNames(command, env)) {
110
+ const candidate = path.join(directory, candidateName);
111
+ if (await executableExists(candidate)) {
112
+ return candidate;
113
+ }
114
+ }
115
+ }
116
+ return null;
117
+ }
118
+ export async function resolveRealBinary(command, env, paths) {
119
+ const cleanEnv = withPathValue(env, stripShimDirFromPath(env, paths));
120
+ return resolveBinaryOnPath(command, cleanEnv);
121
+ }
122
+ function capture(binary, args, env) {
123
+ const result = spawnSync(binary, args, {
124
+ env,
125
+ encoding: "utf8",
126
+ shell: shouldUseShellForBinary(binary),
127
+ windowsHide: true
128
+ });
129
+ return {
130
+ status: result.status,
131
+ stdout: result.stdout ?? "",
132
+ stderr: result.stderr ?? ""
133
+ };
134
+ }
135
+ export async function runShim(tool, toolArgs, config) {
136
+ const logger = new Logger(config);
137
+ const strippedEnv = withPathValue(process.env, stripShimDirFromPath(process.env, config.paths));
138
+ const realBinary = await resolveRealBinary(tool, process.env, config.paths);
139
+ if (!realBinary) {
140
+ throw new Error(`Could not resolve the real ${tool} binary`);
141
+ }
142
+ logger.debug(`Resolved ${tool} to ${realBinary}`);
143
+ const execution = tool === "uv"
144
+ ? await buildUvExecution({
145
+ binary: realBinary,
146
+ args: toolArgs,
147
+ env: strippedEnv,
148
+ cwd: process.cwd(),
149
+ config,
150
+ capture,
151
+ logger
152
+ })
153
+ : await buildNpmExecution({
154
+ binary: realBinary,
155
+ args: toolArgs,
156
+ env: strippedEnv,
157
+ config,
158
+ capture,
159
+ logger
160
+ });
161
+ const child = spawn(execution.binary, execution.args, {
162
+ env: execution.env,
163
+ stdio: "inherit",
164
+ shell: shouldUseShellForBinary(execution.binary),
165
+ windowsHide: true
166
+ });
167
+ child.on("error", (error) => {
168
+ console.error(`bluefairy: failed to execute ${tool}: ${error.message}`);
169
+ process.exit(1);
170
+ });
171
+ child.on("exit", (code, signal) => {
172
+ if (signal) {
173
+ process.kill(process.pid, signal);
174
+ return;
175
+ }
176
+ process.exit(code ?? 1);
177
+ });
178
+ return await new Promise(() => {
179
+ // The process exits via the child process handlers above.
180
+ });
181
+ }
182
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
package/dist/shims.js ADDED
@@ -0,0 +1,26 @@
1
+ import path from "node:path";
2
+ import { ensureDir, writeExecutableFile } from "./fs-utils.js";
3
+ const TOOLS = ["uv", "npm"];
4
+ function posixShim(tool) {
5
+ return `#!/bin/sh
6
+ exec bluefairy internal-shim ${tool} "$@"
7
+ `;
8
+ }
9
+ function cmdShim(tool) {
10
+ return `@echo off
11
+ call bluefairy internal-shim ${tool} %*
12
+ `;
13
+ }
14
+ function ps1Shim(tool) {
15
+ return `& bluefairy internal-shim ${tool} @args
16
+ `;
17
+ }
18
+ export async function ensureManagedShims(paths) {
19
+ await ensureDir(paths.shimDir);
20
+ for (const tool of TOOLS) {
21
+ await writeExecutableFile(path.join(paths.shimDir, tool), posixShim(tool));
22
+ await writeExecutableFile(path.join(paths.shimDir, `${tool}.cmd`), cmdShim(tool));
23
+ await writeExecutableFile(path.join(paths.shimDir, `${tool}.ps1`), ps1Shim(tool));
24
+ }
25
+ }
26
+ //# sourceMappingURL=shims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shims.js","sourceRoot":"","sources":["../src/shims.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;AAErC,SAAS,SAAS,CAAC,IAA4B;IAC7C,OAAO;+BACsB,IAAI;CAClC,CAAC;AACF,CAAC;AAED,SAAS,OAAO,CAAC,IAA4B;IAC3C,OAAO;+BACsB,IAAI;CAClC,CAAC;AACF,CAAC;AAED,SAAS,OAAO,CAAC,IAA4B;IAC3C,OAAO,6BAA6B,IAAI;CACzC,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAmB;IAC1D,MAAM,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,MAAM,mBAAmB,CACvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,MAAM,CAAC,EACvC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;QACF,MAAM,mBAAmB,CACvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,MAAM,CAAC,EACvC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC;AACH,CAAC"}