Adapt per review

This commit is contained in:
Reinier Criel 2026-04-14 11:30:29 -07:00
parent 63b7a5ee5e
commit 6ff2ee3367
20 changed files with 118 additions and 119 deletions

View file

@ -3,7 +3,6 @@ import * as os from "os";
import fs from "fs";
import path from "path";
import { ECOSYSTEM_JS, ECOSYSTEM_PY } from "../config/settings.js";
import { getSafeChainBaseDir } from "../config/safeChainDir.js";
import { safeSpawn } from "../utils/safeSpawn.js";
import { ui } from "../environment/userInteraction.js";
@ -122,34 +121,6 @@ export function getPackageManagerList() {
return `${tools.join(", ")}, and ${lastTool} commands`;
}
/**
* Returns the safe-chain base directory.
* Uses the packaged binary location when available, otherwise defaults to ~/.safe-chain.
* @returns {string}
*/
export { getSafeChainBaseDir };
/**
* @returns {string}
*/
export function getBinDir() {
return path.join(getSafeChainBaseDir(), "bin");
}
/**
* @returns {string}
*/
export function getShimsDir() {
return path.join(getSafeChainBaseDir(), "shims");
}
/**
* @returns {string}
*/
export function getScriptsDir() {
return path.join(getSafeChainBaseDir(), "scripts");
}
/**
* @param {string} executableName
*

View file

@ -186,22 +186,27 @@ describe("removeLinesMatchingPatternTests", () => {
describe("getSafeChainBaseDir / getBinDir / getShimsDir / getScriptsDir", () => {
it("defaults base dir to ~/.safe-chain when no packaged install dir is available", async () => {
const { getSafeChainBaseDir } = await import("./helpers.js");
const { getSafeChainBaseDir } = await import("../config/safeChainDir.js");
assert.strictEqual(getSafeChainBaseDir(), path.join(homedir(), ".safe-chain"));
});
it("getBinDir returns ~/.safe-chain/bin by default", async () => {
const { getBinDir } = await import("./helpers.js");
const { getBinDir } = await import("../config/safeChainDir.js");
assert.strictEqual(getBinDir(), path.join(homedir(), ".safe-chain", "bin"));
});
it("getShimsDir returns ~/.safe-chain/shims by default", async () => {
const { getShimsDir } = await import("./helpers.js");
const { getShimsDir } = await import("../config/safeChainDir.js");
assert.strictEqual(getShimsDir(), path.join(homedir(), ".safe-chain", "shims"));
});
it("getScriptsDir returns ~/.safe-chain/scripts by default", async () => {
const { getScriptsDir } = await import("./helpers.js");
const { getScriptsDir } = await import("../config/safeChainDir.js");
assert.strictEqual(getScriptsDir(), path.join(homedir(), ".safe-chain", "scripts"));
});
it("getCertsDir returns ~/.safe-chain/certs by default", async () => {
const { getCertsDir } = await import("../config/safeChainDir.js");
assert.strictEqual(getCertsDir(), path.join(homedir(), ".safe-chain", "certs"));
});
});

View file

@ -1,24 +1,14 @@
import chalk from "chalk";
import { ui } from "../environment/userInteraction.js";
import { getPackageManagerList, knownAikidoTools, getShimsDir, getBinDir } from "./helpers.js";
import { getPackageManagerList, knownAikidoTools } from "./helpers.js";
import {
getShimsDir,
getBinDir,
getPathWrapperTemplatePath,
} from "../config/safeChainDir.js";
import fs from "fs";
import os from "os";
import path from "path";
import { fileURLToPath } from "url";
/** @type {string} */
// This checks the current file's dirname in a way that's compatible with:
// - Modulejs (import.meta.url)
// - ES modules (__dirname)
// This is needed because safe-chain's npm package is built using ES modules,
// but building the binaries requires commonjs.
let dirname;
if (import.meta.url) {
const filename = fileURLToPath(import.meta.url);
dirname = path.dirname(filename);
} else {
dirname = __dirname;
}
/**
* Loops over the detected shells and calls the setup function for each.
@ -50,12 +40,7 @@ export async function setupCi() {
*/
function createUnixShims(shimsDir) {
// Read the template file
const templatePath = path.resolve(
dirname,
"path-wrappers",
"templates",
"unix-wrapper.template.sh"
);
const templatePath = getPathWrapperTemplatePath(import.meta.url, "unix-wrapper.template.sh");
if (!fs.existsSync(templatePath)) {
ui.writeError(`Template file not found: ${templatePath}`);
@ -89,12 +74,7 @@ function createUnixShims(shimsDir) {
*/
function createWindowsShims(shimsDir) {
// Read the template file
const templatePath = path.resolve(
dirname,
"path-wrappers",
"templates",
"windows-wrapper.template.cmd"
);
const templatePath = getPathWrapperTemplatePath(import.meta.url, "windows-wrapper.template.cmd");
if (!fs.existsSync(templatePath)) {
ui.writeError(`Windows template file not found: ${templatePath}`);

View file

@ -50,8 +50,15 @@ describe("Setup CI shell integration", () => {
{ tool: "yarn", aikidoCommand: "aikido-yarn" },
],
getPackageManagerList: () => "npm, yarn",
},
});
mock.module("../config/safeChainDir.js", {
namedExports: {
getShimsDir: () => mockShimsDir,
getBinDir: () => path.join(mockHomeDir, ".safe-chain", "bin"),
getPathWrapperTemplatePath: (_moduleUrl, fileName) =>
path.join(mockTemplateDir, "path-wrappers", "templates", fileName),
},
});
@ -64,22 +71,6 @@ describe("Setup CI shell integration", () => {
},
});
// Mock path module to resolve templates correctly
mock.module("path", {
namedExports: {
join: path.join,
dirname: () => mockTemplateDir,
resolve: (...args) => path.resolve(mockTemplateDir, ...args.slice(1)),
},
});
// Mock fileURLToPath
mock.module("url", {
namedExports: {
fileURLToPath: () => path.join(mockTemplateDir, "setup-ci.js"),
},
});
// Import setupCi module after mocking
setupCi = (await import("./setup-ci.js")).setupCi;
});

View file

@ -1,28 +1,10 @@
import chalk from "chalk";
import { ui } from "../environment/userInteraction.js";
import { detectShells } from "./shellDetection.js";
import {
knownAikidoTools,
getPackageManagerList,
getScriptsDir,
} from "./helpers.js";
import { knownAikidoTools, getPackageManagerList } from "./helpers.js";
import { getScriptsDir, getStartupScriptSourcePath } from "../config/safeChainDir.js";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
/** @type {string} */
// This checks the current file's dirname in a way that's compatible with:
// - Modulejs (import.meta.url)
// - ES modules (__dirname)
// This is needed because safe-chain's npm package is built using ES modules,
// but building the binaries requires commonjs.
let dirname;
if (import.meta.url) {
const filename = fileURLToPath(import.meta.url);
dirname = path.dirname(filename);
} else {
dirname = __dirname;
}
/**
* Loops over the detected shells and calls the setup function for each.
@ -122,7 +104,7 @@ function copyStartupFiles() {
fs.mkdirSync(targetDir, { recursive: true });
}
const sourcePath = path.join(dirname, "startup-scripts", file);
const sourcePath = getStartupScriptSourcePath(import.meta.url, file);
fs.copyFileSync(sourcePath, targetPath);
}
}

View file

@ -2,8 +2,8 @@ import {
addLineToFile,
doesExecutableExistOnSystem,
removeLinesMatchingPattern,
getScriptsDir,
} from "../helpers.js";
import { getScriptsDir } from "../../config/safeChainDir.js";
import { execSync, spawnSync } from "child_process";
import * as os from "os";
import path from "path";

View file

@ -19,7 +19,6 @@ describe("Bash shell integration", () => {
mock.module("../helpers.js", {
namedExports: {
doesExecutableExistOnSystem: () => true,
getScriptsDir: () => "/test-home/.safe-chain/scripts",
addLineToFile: (filePath, line) => {
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, "", "utf-8");
@ -36,6 +35,12 @@ describe("Bash shell integration", () => {
},
});
mock.module("../../config/safeChainDir.js", {
namedExports: {
getScriptsDir: () => "/test-home/.safe-chain/scripts",
},
});
// Mock child_process execSync
mock.module("child_process", {
namedExports: {

View file

@ -2,8 +2,8 @@ import {
addLineToFile,
doesExecutableExistOnSystem,
removeLinesMatchingPattern,
getScriptsDir,
} from "../helpers.js";
import { getScriptsDir } from "../../config/safeChainDir.js";
import { execSync } from "child_process";
import path from "path";

View file

@ -17,7 +17,6 @@ describe("Fish shell integration", () => {
mock.module("../helpers.js", {
namedExports: {
doesExecutableExistOnSystem: () => true,
getScriptsDir: () => "/test-home/.safe-chain/scripts",
addLineToFile: (filePath, line) => {
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, "", "utf-8");
@ -34,6 +33,12 @@ describe("Fish shell integration", () => {
},
});
mock.module("../../config/safeChainDir.js", {
namedExports: {
getScriptsDir: () => "/test-home/.safe-chain/scripts",
},
});
// Mock child_process execSync
mock.module("child_process", {
namedExports: {

View file

@ -3,8 +3,8 @@ import {
doesExecutableExistOnSystem,
removeLinesMatchingPattern,
validatePowerShellExecutionPolicy,
getScriptsDir,
} from "../helpers.js";
import { getScriptsDir } from "../../config/safeChainDir.js";
import { execSync } from "child_process";
import path from "path";

View file

@ -40,6 +40,11 @@ describe("PowerShell Core shell integration", () => {
fs.writeFileSync(filePath, filteredLines.join("\n"), "utf-8");
},
validatePowerShellExecutionPolicy: () => executionPolicyResult,
},
});
mock.module("../../config/safeChainDir.js", {
namedExports: {
getScriptsDir: () => "/test-home/.safe-chain/scripts",
},
});

View file

@ -3,8 +3,8 @@ import {
doesExecutableExistOnSystem,
removeLinesMatchingPattern,
validatePowerShellExecutionPolicy,
getScriptsDir,
} from "../helpers.js";
import { getScriptsDir } from "../../config/safeChainDir.js";
import { execSync } from "child_process";
import path from "path";

View file

@ -40,6 +40,11 @@ describe("Windows PowerShell shell integration", () => {
fs.writeFileSync(filePath, filteredLines.join("\n"), "utf-8");
},
validatePowerShellExecutionPolicy: () => executionPolicyResult,
},
});
mock.module("../../config/safeChainDir.js", {
namedExports: {
getScriptsDir: () => "/test-home/.safe-chain/scripts",
},
});

View file

@ -2,8 +2,8 @@ import {
addLineToFile,
doesExecutableExistOnSystem,
removeLinesMatchingPattern,
getScriptsDir,
} from "../helpers.js";
import { getScriptsDir } from "../../config/safeChainDir.js";
import { execSync } from "child_process";
import path from "path";

View file

@ -17,7 +17,6 @@ describe("Zsh shell integration", () => {
mock.module("../helpers.js", {
namedExports: {
doesExecutableExistOnSystem: () => true,
getScriptsDir: () => "/test-home/.safe-chain/scripts",
addLineToFile: (filePath, line) => {
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, "", "utf-8");
@ -34,6 +33,12 @@ describe("Zsh shell integration", () => {
},
});
mock.module("../../config/safeChainDir.js", {
namedExports: {
getScriptsDir: () => "/test-home/.safe-chain/scripts",
},
});
// Mock child_process execSync
mock.module("child_process", {
namedExports: {

View file

@ -1,7 +1,8 @@
import chalk from "chalk";
import { ui } from "../environment/userInteraction.js";
import { detectShells } from "./shellDetection.js";
import { knownAikidoTools, getPackageManagerList, getShimsDir, getScriptsDir } from "./helpers.js";
import { knownAikidoTools, getPackageManagerList } from "./helpers.js";
import { getShimsDir, getScriptsDir } from "../config/safeChainDir.js";
import fs from "fs";
/**