Created
November 8, 2023 20:31
-
-
Save FridayCandour/75f8c7abb7fed21c3d6aad8366aa9ae7 to your computer and use it in GitHub Desktop.
A node script to position your node projects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
import util from "node:util"; | |
import path from "node:path"; | |
import fs from "node:fs"; | |
import child_process from "node:child_process"; | |
// Parse command line arguments | |
const P_args = process.argv.slice(2); | |
const seen_p = {}; | |
// Utility functions | |
const exec = util.promisify(child_process.exec); | |
// Function to run a command and handle errors | |
async function runCmd(command) { | |
try { | |
return await exec(command); | |
} catch (error) { | |
console.log(error.stderr); | |
return error; | |
} | |
} | |
// Function to handle and suppress errors gracefully | |
async function AvoidErrorInCB(cb) { | |
try { | |
return (await cb()) || true; | |
} catch (e) { | |
// Handle errors or log them as needed | |
// console.log(e); | |
return false; | |
} | |
} | |
// Parse command line arguments and extract relevant options | |
const parseInput = async () => { | |
if (P_args.length) { | |
if (P_args.join("").includes("--port=")) { | |
const a = P_args.join(" ").split("--port=")[1].split(" ")[0]; | |
seen_p.port = a; | |
} | |
if (P_args.join("").includes("--mode=")) { | |
const a = P_args.join(" ").split("--mode=")[1].split(" ")[0]; | |
if (a === "install" || a === "position") { | |
seen_p.mode = a; | |
} | |
} | |
if (P_args.join("").includes("--appDir=")) { | |
const a = P_args.join(" ").split("--appDir=")[1].split(" ")[0]; | |
if (a) { | |
seen_p.folderName = a; | |
} | |
} | |
if (seen_p.mode === "position") { | |
return; | |
} | |
if (P_args.join("").includes("--repoLink=") && seen_p.mode === "install") { | |
const a = P_args.join(" ").split("--repoLink=")[1].split(" ")[0]; | |
// Extract username and token from the repoLink | |
// Note: This code assumes a specific format for the repoLink | |
const ks = a.indexOf("https:"); | |
const kz = a.indexOf(".git"); | |
const ghurl = a.slice(ks, kz) + ".git"; | |
const urlWithoutCredentials = ghurl.replace( | |
/https:\/\/(.*?):(.*?)@/g, | |
"https://" | |
); | |
const repo = await AvoidErrorInCB(async () => { | |
let yut = ghurl.split(":"); | |
const username = yut[1].split("//")[1]; | |
const token = yut[2].split("@")[0]; | |
seen_p.token = token; | |
seen_p.username = username; | |
const ghs = await fetch(urlWithoutCredentials, { | |
method: "HEAD", | |
headers: { | |
Authorization: `Basic ${Buffer.from( | |
`${username}:${token}` | |
).toString("base64")}`, | |
}, | |
}); | |
if (ghs.ok) { | |
return true; | |
} | |
console.log(ghs); | |
return false; | |
}); | |
if (repo) { | |
seen_p.repoLink = a; | |
seen_p.repo = urlWithoutCredentials; | |
seen_p.repo_retrieved = true; | |
} else { | |
seen_p.repo = "repo verification failed"; | |
seen_p.repo_retrieved = false; | |
} | |
} | |
} | |
}; | |
// Parse input options | |
await parseInput(); | |
// Display parsed options | |
console.log("OPTIONS:"); | |
console.table(seen_p); | |
// Check if required options are present | |
if ( | |
!seen_p.mode || | |
!seen_p.folderName || | |
(seen_p.mode === "install" && !seen_p.repoLink) | |
) { | |
console.log("OPTIONS TO RUN SCRIPT CANNOT BE DETERMINED FOR ARGS GIVEN"); | |
process.exit(89); | |
} | |
// Define constants | |
const ownPath = process.cwd(); | |
const appPath = path.join(ownPath, seen_p.folderName); | |
// Function to set up the project | |
async function setup() { | |
try { | |
// Check if directory already exists | |
let makeAppDir = await AvoidErrorInCB(() => { | |
fs.mkdirSync(appPath); | |
}); | |
if (!makeAppDir) { | |
await runCmd("rm -rf " + seen_p.folderName); | |
} | |
// Clone the repository | |
console.log(`cloning app from repo ${seen_p.repoLink}`); | |
await runCmd(`git clone --depth 1 ${seen_p.repoLink} ${seen_p.folderName}`); | |
console.log("Cloned successfully."); | |
console.log(""); | |
// Change directory to the appPath | |
process.chdir(seen_p.folderName); | |
// Install dependencies | |
console.log("Installing dependencies ..."); | |
await runCmd("npm run install"); // You can use "npm install" or "bun install" as needed | |
console.log("Dependencies installed successfully."); | |
// Delete the .git folder | |
await runCmd("rm -rf .git"); | |
console.log("Installation is now complete!"); | |
console.log(""); | |
} catch (error) { | |
console.log(error); | |
} | |
} | |
// Function to launch the application | |
async function launch() { | |
console.log("Running..."); | |
const { stderr } = await runCmd("npm run start &"); | |
prob(stderr); | |
} | |
// Function to handle port-related issues | |
async function prob(stderr) { | |
if (stderr.includes("EADDRINUSE:")) { | |
console.log(stderr); | |
console.log("Port is in use."); | |
const { stdout } = await runCmd(`lsof -i :${seen_p.port}`); | |
const outers = stdout.split(" "); | |
const pid = outers.find((s, r) => { | |
if (Number(s) && outers[r - 1] === "") { | |
return s; | |
} | |
}); | |
if (Number(pid)) { | |
console.log("Killing port " + seen_p.port + " on PID '" + pid + "' ..."); | |
await runCmd(`kill -15 ${pid}`); | |
launch(); | |
} | |
} | |
} | |
// Function to start the application in 'position' mode | |
async function running() { | |
try { | |
const fex = await AvoidErrorInCB(() => { | |
fs.mkdirSync(appPath); | |
}); | |
if (!fex) { | |
console.log("App folder '" + seen_p.folderName + "' located!"); | |
} else { | |
// Handle the case where the app directory is not found | |
console.log("Error: Could not find app directory - " + seen_p.folderName); | |
process.exit(1); | |
} | |
process.chdir(seen_p.folderName); | |
await launch(); | |
// Further handle issues like port already in use | |
} catch (error) { | |
console.log(error); | |
process.exit(1); | |
} | |
} | |
// Main execution based on 'mode' option | |
if (seen_p.mode === "install") { | |
setup(); | |
} | |
if (seen_p.mode === "position") { | |
running(); | |
} | |
// repoLink=https://<username>:<gh-token>github.com/<username>/<repo>.git <-b <branch> if needed> | |
// repoLink=https://github.com/<username>/<repo>.git <-b <branch> if needed> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example Usage:
mode: install
node positioner.js --mode=install --appDir=app --repoLink="https:
//fridaycandour:[email protected]/fridaycandour/positioner.git -b main"
mode: position
node positioner.js --mode=position --appDir=app --port=3000