generated from nhcarrigan/template
fix: resolve lint issues for Python and TypeScript
CI / dependency-pin-check-typescript (pull_request) Successful in 4s
CI / dependency-pin-check-python (pull_request) Successful in 4s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m15s
CI / typescript (pull_request) Successful in 9m40s
CI / python (pull_request) Successful in 9m22s
CI / dependency-pin-check-typescript (pull_request) Successful in 4s
CI / dependency-pin-check-python (pull_request) Successful in 4s
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m15s
CI / typescript (pull_request) Successful in 9m40s
CI / python (pull_request) Successful in 9m22s
- Update pyproject.toml to ignore T201 (print statements) and other rules - Fix quote styles, bare except, set comprehensions in Python scripts - Rename interactive-runner.ts to interactiveRunner.ts (camelCase) - Refactor TypeScript to use import.meta.url instead of __dirname - Add proper JSDoc headers and rename abbreviated variables
This commit is contained in:
@@ -1,165 +0,0 @@
|
||||
import { select } from "@inquirer/prompts";
|
||||
import { execSync } from "child_process";
|
||||
import { readdirSync, statSync, existsSync } from "fs";
|
||||
import { join, relative } from "path";
|
||||
|
||||
interface ScriptOption {
|
||||
name: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const getTypeScriptCategories = (): string[] => {
|
||||
const srcPath = join(__dirname, "..");
|
||||
const entries = readdirSync(srcPath);
|
||||
|
||||
return entries
|
||||
.filter((entry) => {
|
||||
const fullPath = join(srcPath, entry);
|
||||
return statSync(fullPath).isDirectory() && entry !== "utils" && entry !== "interfaces";
|
||||
})
|
||||
.sort();
|
||||
};
|
||||
|
||||
const getTypeScriptScripts = (category: string): ScriptOption[] => {
|
||||
const categoryPath = join(__dirname, "..", category);
|
||||
const scripts: ScriptOption[] = [];
|
||||
|
||||
const walkDirectory = (dir: string) => {
|
||||
const entries = readdirSync(dir);
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(dir, entry);
|
||||
const stat = statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
walkDirectory(fullPath);
|
||||
} else if (entry.endsWith(".ts") && entry !== "index.ts") {
|
||||
const relativePath = relative(join(__dirname, ".."), fullPath);
|
||||
scripts.push({
|
||||
name: entry.replace(".ts", ""),
|
||||
value: relativePath,
|
||||
description: relativePath,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
walkDirectory(categoryPath);
|
||||
return scripts.sort((a, b) => a.name.localeCompare(b.name));
|
||||
};
|
||||
|
||||
const getPythonCategories = (): string[] => {
|
||||
const pythonPath = join(__dirname, "../../../../python");
|
||||
const entries = readdirSync(pythonPath);
|
||||
|
||||
const categories = entries
|
||||
.filter((entry) => {
|
||||
const fullPath = join(pythonPath, entry);
|
||||
return statSync(fullPath).isDirectory() &&
|
||||
!entry.startsWith(".") &&
|
||||
entry !== "__pycache__";
|
||||
})
|
||||
.sort();
|
||||
|
||||
// Also check for scripts in the root
|
||||
const hasRootScripts = entries.some(entry => entry.endsWith(".py"));
|
||||
if (hasRootScripts) {
|
||||
categories.unshift("(root)");
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
const getPythonScripts = (category: string): ScriptOption[] => {
|
||||
const pythonPath = join(__dirname, "../../../../python");
|
||||
const searchPath = category === "(root)" ? pythonPath : join(pythonPath, category);
|
||||
|
||||
const scripts: ScriptOption[] = [];
|
||||
const entries = readdirSync(searchPath);
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.endsWith(".py") && !entry.startsWith("__")) {
|
||||
const relativePath = category === "(root)" ? entry : join(category, entry);
|
||||
scripts.push({
|
||||
name: entry.replace(".py", ""),
|
||||
value: relativePath,
|
||||
description: relativePath,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return scripts.sort((a, b) => a.name.localeCompare(b.name));
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
console.log("🌸 Welcome to Ephemere Script Runner! 💖\n");
|
||||
|
||||
// Select language
|
||||
const language = await select({
|
||||
message: "Which language would you like to run?",
|
||||
choices: [
|
||||
{ name: "TypeScript", value: "typescript", description: "Run a TypeScript script" },
|
||||
{ name: "Python", value: "python", description: "Run a Python script" },
|
||||
],
|
||||
});
|
||||
|
||||
// Get categories based on language
|
||||
const categories = language === "typescript"
|
||||
? getTypeScriptCategories()
|
||||
: getPythonCategories();
|
||||
|
||||
if (categories.length === 0) {
|
||||
console.error(`No categories found for ${language}!`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Select category
|
||||
const category = await select({
|
||||
message: "Which category?",
|
||||
choices: categories.map(cat => ({
|
||||
name: cat === "(root)" ? "Root Directory" : cat.charAt(0).toUpperCase() + cat.slice(1),
|
||||
value: cat,
|
||||
})),
|
||||
});
|
||||
|
||||
// Get scripts for selected category
|
||||
const scripts = language === "typescript"
|
||||
? getTypeScriptScripts(category)
|
||||
: getPythonScripts(category);
|
||||
|
||||
if (scripts.length === 0) {
|
||||
console.error(`No scripts found in ${category}!`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Select script
|
||||
const script = await select({
|
||||
message: "Which script would you like to run?",
|
||||
choices: scripts,
|
||||
});
|
||||
|
||||
// Build and execute the command
|
||||
const prodEnvPath = join(__dirname, "../../../../../prod.env");
|
||||
let command: string;
|
||||
|
||||
if (language === "typescript") {
|
||||
command = `cd ${join(__dirname, "../../../")} && op run --env-file=${prodEnvPath} -- pnpm exec tsx src/${script}`;
|
||||
} else {
|
||||
command = `cd ${join(__dirname, "../../../../python")} && op run --env-file=${prodEnvPath} -- uv run python ${script}`;
|
||||
}
|
||||
|
||||
console.log(`\n✨ Running: ${script}\n`);
|
||||
|
||||
try {
|
||||
execSync(command, {
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("\n❌ Script execution failed!");
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* @file Interactive script runner for ephemere project.
|
||||
* @copyright 2025 Naomi Carrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
import { execSync } from "node:child_process";
|
||||
import { readdirSync, statSync } from "node:fs";
|
||||
import { dirname, join, relative } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { select } from "@inquirer/prompts";
|
||||
|
||||
const currentFilename = fileURLToPath(import.meta.url);
|
||||
const currentDirectory = dirname(currentFilename);
|
||||
|
||||
interface ScriptOption {
|
||||
name: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const getTypeScriptCategories = (): Array<string> => {
|
||||
const sourcePath = join(currentDirectory, "..");
|
||||
const entries = readdirSync(sourcePath);
|
||||
|
||||
return entries.
|
||||
filter((entry) => {
|
||||
const fullPath = join(sourcePath, entry);
|
||||
const entryIsDirectory = statSync(fullPath).isDirectory();
|
||||
return entryIsDirectory && entry !== "utils" && entry !== "interfaces";
|
||||
}).
|
||||
sort((a, b) => {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
};
|
||||
|
||||
const getTypeScriptScripts = (category: string): Array<ScriptOption> => {
|
||||
const categoryPath = join(currentDirectory, "..", category);
|
||||
const scripts: Array<ScriptOption> = [];
|
||||
|
||||
const walkDirectory = (directory: string): void => {
|
||||
const entries = readdirSync(directory);
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(directory, entry);
|
||||
const stat = statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
walkDirectory(fullPath);
|
||||
} else if (entry.endsWith(".ts") && entry !== "index.ts") {
|
||||
const relativePath = relative(join(currentDirectory, ".."), fullPath);
|
||||
scripts.push({
|
||||
description: relativePath,
|
||||
name: entry.replace(".ts", ""),
|
||||
value: relativePath,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
walkDirectory(categoryPath);
|
||||
return scripts.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
};
|
||||
|
||||
const getPythonCategories = (): Array<string> => {
|
||||
const pythonPath = join(currentDirectory, "../../../../python");
|
||||
const entries = readdirSync(pythonPath);
|
||||
|
||||
const categories = entries.
|
||||
filter((entry) => {
|
||||
const fullPath = join(pythonPath, entry);
|
||||
const entryIsDirectory = statSync(fullPath).isDirectory();
|
||||
const isNotHidden = !entry.startsWith(".");
|
||||
return entryIsDirectory && isNotHidden && entry !== "__pycache__";
|
||||
}).
|
||||
sort((a, b) => {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
|
||||
// Also check for scripts in the root
|
||||
const hasRootScripts = entries.some((entry) => {
|
||||
return entry.endsWith(".py");
|
||||
});
|
||||
if (hasRootScripts) {
|
||||
categories.unshift("(root)");
|
||||
}
|
||||
|
||||
return categories;
|
||||
};
|
||||
|
||||
const getPythonScripts = (category: string): Array<ScriptOption> => {
|
||||
const pythonPath = join(currentDirectory, "../../../../python");
|
||||
const searchPath = category === "(root)"
|
||||
? pythonPath
|
||||
: join(pythonPath, category);
|
||||
|
||||
const scripts: Array<ScriptOption> = [];
|
||||
const entries = readdirSync(searchPath);
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.endsWith(".py") && !entry.startsWith("__")) {
|
||||
const relativePath = category === "(root)"
|
||||
? entry
|
||||
: join(category, entry);
|
||||
scripts.push({
|
||||
description: relativePath,
|
||||
name: entry.replace(".py", ""),
|
||||
value: relativePath,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return scripts.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
};
|
||||
|
||||
const selectLanguage = async(): Promise<string> => {
|
||||
return await select({
|
||||
choices: [
|
||||
{
|
||||
description: "Run a TypeScript script",
|
||||
name: "TypeScript",
|
||||
value: "typescript",
|
||||
},
|
||||
{
|
||||
description: "Run a Python script",
|
||||
name: "Python",
|
||||
value: "python",
|
||||
},
|
||||
],
|
||||
message: "Which language would you like to run?",
|
||||
});
|
||||
};
|
||||
|
||||
const selectCategory = async(categories: Array<string>): Promise<string> => {
|
||||
return await select({
|
||||
choices: categories.map((cat) => {
|
||||
return {
|
||||
name: cat === "(root)"
|
||||
? "Root Directory"
|
||||
: cat.charAt(0).toUpperCase() + cat.slice(1),
|
||||
value: cat,
|
||||
};
|
||||
}),
|
||||
message: "Which category?",
|
||||
});
|
||||
};
|
||||
|
||||
const buildCommand = (language: string, script: string): string => {
|
||||
const environmentPath = join(currentDirectory, "../../../../../prod.env");
|
||||
const typescriptDirectory = join(currentDirectory, "../../../");
|
||||
const pythonDirectory = join(currentDirectory, "../../../../python");
|
||||
|
||||
return language === "typescript"
|
||||
? `cd ${typescriptDirectory} && op run --env-file=${environmentPath} -- pnpm exec tsx src/${script}`
|
||||
: `cd ${pythonDirectory} && op run --env-file=${environmentPath} -- uv run python ${script}`;
|
||||
};
|
||||
|
||||
const executeScript = (script: string, command: string): void => {
|
||||
console.log(`\n✨ Running: ${script}\n`);
|
||||
|
||||
try {
|
||||
execSync(command, {
|
||||
shell: "/bin/bash",
|
||||
stdio: "inherit",
|
||||
});
|
||||
} catch {
|
||||
console.error("\n❌ Script execution failed!");
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
const main = async(): Promise<void> => {
|
||||
console.log("🌸 Welcome to Ephemere Script Runner! 💖\n");
|
||||
|
||||
const language = await selectLanguage();
|
||||
|
||||
const categories = language === "typescript"
|
||||
? getTypeScriptCategories()
|
||||
: getPythonCategories();
|
||||
|
||||
if (categories.length === 0) {
|
||||
console.error(`No categories found for ${language}!`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const category = await selectCategory(categories);
|
||||
|
||||
const scripts = language === "typescript"
|
||||
? getTypeScriptScripts(category)
|
||||
: getPythonScripts(category);
|
||||
|
||||
if (scripts.length === 0) {
|
||||
console.error(`No scripts found in ${category}!`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const script = await select({
|
||||
choices: scripts,
|
||||
message: "Which script would you like to run?",
|
||||
});
|
||||
|
||||
const command = buildCommand(language, script);
|
||||
executeScript(script, command);
|
||||
};
|
||||
|
||||
await main();
|
||||
Reference in New Issue
Block a user