WIP: Fixing installer

This commit is contained in:
John Haverlack 2026-07-04 18:31:26 -08:00
parent 198637a407
commit 6065d1db3f
17 changed files with 372 additions and 524 deletions

View File

@ -1,81 +1,11 @@
{
"releases": [
{
"version": "0.3.10",
"date": "2026-02-08",
"maturity": "ALPHA",
"version": "0.1.0",
"date": "2026-06-28",
"maturity": "INIT",
"summary": "",
"notes": ""
},
{
"version": "0.3.9",
"date": "2026-02-08",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.8",
"date": "2026-02-01",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.7",
"date": "2026-02-01",
"maturity": "ALPHA",
"summary": "sdl-wkr Telemetry",
"notes": ""
},
{
"version": "0.3.6",
"date": "2026-02-01",
"maturity": "ALPHA",
"summary": "Light/Dark Mode, Wkr Install, Cluster Stats",
"notes": ""
},
{
"version": "0.3.5",
"date": "2026-02-01",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.4",
"date": "2026-01-31",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.3",
"date": "2026-01-31",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.2",
"date": "2026-01-31",
"maturity": "ALPHA",
"summary": "",
"notes": ""
},
{
"version": "0.3.1",
"date": "2026-01-31",
"maturity": "ALPHA",
"summary": "README Cleanup",
"notes": ""
},
{
"version": "0.3.0",
"date": "2026-01-31",
"maturity": "ALPHA",
"summary": "Initial Codebase",
"notes": "Initial GitHub Release"
}
]
}

View File

@ -1,21 +0,0 @@
{
"name": "Project Name",
"desc": "Project Description",
"parameters" : {
"parm1": {
"name": "Parameter Name",
"desc": "Parameter Description",
"type": "integer",
"min": 0,
"max": 100
},
"parm2": {
"name": "Parameter Name",
"desc": "Parameter Description",
"type": "integer",
"min": 0,
"max": 100
}
},
"iterations": 1000
}

View File

@ -1,31 +0,0 @@
{
"id": "nks-ca",
"name": "NKS 1D CA",
"desc": "Exploration of 1D elementary New Kind of Science (NKS) Cellular Automata (CA)",
"date": "2026-02-09",
"version": "0.0.0",
"parameters" : {
"x": {
"name": "X Cells",
"desc": "Number of Binary Cells on the X Dimension",
"type": "integer",
"min": 3,
"max": 15
},
"rule": {
"name": "Rule",
"desc": "Update Rule Index",
"type": "integer",
"min": 0,
"max": 255
},
"init": {
"name": "Initial State",
"desc": "Initial Binary State",
"type": "integer",
"min": 0,
"max": "2^x"
}
},
"iterations": 100
}

View File

@ -1,34 +0,0 @@
{
"id": "ssl-evo-rnd",
"name": "SSL Random Evolution",
"desc": "State Space Locality (SSL) Random Perturbation Evolution Update Rule",
"date": "2026-02-09",
"version": "0.0.0",
"parameters" : {
"N": {
"name": "Nodes",
"desc": "N Node Directional Graph",
"type": "integer",
"min": 1,
"max": 1000
},
"rule": {
"name": "Rule",
"desc": "Proximity Update Rule",
"type": "text",
"eunum": [
"Pii",
"Poo",
"Pio",
"Poi"
]
},
"init": {
"name": "Initial State",
"desc": "NxN Adjacency Matrix",
"type": "matrix"
}
},
"iterations": 1000,
"permutations": {}
}

View File

@ -14,12 +14,12 @@ resolve_dirs() {
raw["$key"]="$val"
done < <(jq -r '.DIRS | to_entries[] | "\(.key)=\(.value)"' "$json")
if [[ -z "${raw[HOME]:-}" ]]; then
echo "ERROR: DIRS.HOME is not defined in config.json"
if [[ -z "${raw[SITE]:-}" ]]; then
echo "ERROR: DIRS.SITE is not defined in nwa-deploy-config.json"
exit 1
fi
resolved["HOME"]="${raw[HOME]/#\~/$HOME}"
resolved["SITE"]="${raw[SITE]/#\~/$HOME}"
local changed=true
while $changed; do
@ -32,7 +32,21 @@ resolve_dirs() {
val="${val/$rkey/${resolved[$rkey]:-}}"
done
if [[ "$val" != ** ]]; then
# if [[ "$val" != ** ]]; then
# resolved["$key"]="$val"
# changed=true
# fi
local unresolved=false
for unresolved_key in "${!raw[@]}"; do
if [[ -z "${resolved[$unresolved_key]:-}" && "$val" == *"$unresolved_key"* ]]; then
unresolved=true
break
fi
done
if [[ "$unresolved" == false ]]; then
resolved["$key"]="$val"
changed=true
fi
@ -61,6 +75,93 @@ use_systemd() {
return 1 # Use manual scripts
}
install_nodejs() {
NODE_TARGET="${OS_PLATFORM}:${OS_ARCH}"
NODE_PLATFORM="${OS_PLATFORM}-${OS_ARCH}"
echo ""
echo "Target NodeJS:"
echo " Target: $NODE_TARGET"
echo " Platform: $NODE_PLATFORM"
if ! jq -e --arg target "$NODE_TARGET" '.NODEJS.TARGETS[] | select(. == $target)' "$CONFIG_FILE" >/dev/null; then
echo "ERROR: NodeJS target not listed in config: $NODE_TARGET"
exit 1
fi
case "$OS_PLATFORM" in
linux)
EXT="tar.xz"
TAR_OPTS="-xJf"
;;
darwin)
EXT="tar.gz"
TAR_OPTS="-xzf"
;;
win)
echo "ERROR: win32 host install not supported by this installer"
exit 1
;;
*)
echo "ERROR: Unsupported OS platform: $OS_PLATFORM"
exit 1
;;
esac
NODE_DIR="node-v${NODE_VERSION}-${NODE_PLATFORM}"
NODE_TARBALL="${NODE_DIR}.${EXT}"
NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TARBALL}"
SHASUM_URL="https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt"
NODE_BIN="$NODEJS/current/bin/node"
if [[ -e "$NODE_BIN" ]]; then
NODE_BIN_VERSION="$("$NODE_BIN" --version)"
if [[ "$NODE_BIN_VERSION" == "v$NODE_VERSION" ]]; then
echo ""
echo "NodeJS $NODE_PLATFORM v$NODE_VERSION already installed"
return 0
fi
fi
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' RETURN
echo ""
echo "Installing NodeJS:"
echo " Version: $NODE_VERSION"
echo " Archive: $NODE_TARBALL"
echo " To: $NODEJS"
curl -sSL "$SHASUM_URL" -o "$TMP_DIR/SHASUMS256.txt"
curl -sSL "$NODE_URL" -o "$TMP_DIR/$NODE_TARBALL"
EXPECTED_SHA="$(grep " $NODE_TARBALL\$" "$TMP_DIR/SHASUMS256.txt" | awk '{print $1}')"
if [[ -z "$EXPECTED_SHA" ]]; then
echo "ERROR: SHA256 not found for $NODE_TARBALL"
exit 1
fi
ACTUAL_SHA="$(sha256sum "$TMP_DIR/$NODE_TARBALL" | awk '{print $1}')"
if [[ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]]; then
echo "ERROR: SHA mismatch for $NODE_TARBALL"
exit 1
fi
rm -rf "$NODEJS/$NODE_DIR"
tar $TAR_OPTS "$TMP_DIR/$NODE_TARBALL" -C "$NODEJS"
ln -sfn "$NODEJS/$NODE_DIR" "$NODEJS/current"
echo "NodeJS installed:"
echo " $NODEJS/current/bin/node"
}
# ------------------------------------------------------------
# Main
# ------------------------------------------------------------
@ -89,7 +190,7 @@ done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="$(cd "$SCRIPT_DIR" && pwd)"
CONFIG_FILE="$ROOT/config.json"
CONFIG_FILE="$ROOT/nwa-deploy-config.json"
META_FILE="$ROOT/metadata.json"
[[ -f "$CONFIG_FILE" ]] || { echo "ERROR: config.json not found"; exit 1; }
@ -175,7 +276,7 @@ VERSION_DATE="$(jq -r '.METADATA.version_date' "$META_FILE")"
COPYRIGHT="$(jq -r '.METADATA.copyright' "$META_FILE")"
AUTHOR="$(jq -r '.METADATA.author' "$META_FILE")"
LICENSE="$(jq -r '.METADATA.license' "$META_FILE")"
HOMEPAGE="$(jq -r '.METADATA.homepage' "$META_FILE")"
SITEPAGE="$(jq -r '.METADATA.SITEpage' "$META_FILE")"
REPO="$(jq -r '.METADATA.git_repo' "$META_FILE")"
@ -195,7 +296,7 @@ echo " Version Date: $VERSION_DATE"
echo " Copyright: (C) $COPYRIGHT"
echo " Author: $AUTHOR"
echo " License: $LICENSE"
echo " Homepage: $HOMEPAGE"
echo " SITEpage: $SITEPAGE"
echo " Repository: $REPO"
echo ""
@ -226,106 +327,80 @@ echo "Directories:"
echo " ROOT: $ROOT"
resolve_dirs "$CONFIG_FILE"
# ------------------------------------------------------------
# Build sdl-mgr tarball to DIST
# Always rebuild sdl-mgr_version.tgz from source
# Copy nwa to Prod Dir
# ------------------------------------------------------------
echo ""
echo "Generating: $DIST/sdl-mgr_$VERSION.tgz"
tar -czf "$DIST/sdl-mgr_$VERSION.tgz" -C "$ROOT" sdl-mgr
sha256sum "$DIST/sdl-mgr_$VERSION.tgz" | awk '{sub(".*/","",$2); print}' > "$DIST/sdl-mgr_$VERSION.tgz.sha256"
# ------------------------------------------------------------
# Build sdl-wkr tarball to DIST
# Always rebuild sdl-wkr_version.tgz from source
# ------------------------------------------------------------
echo ""
echo "Generating: $DIST/sdl-wkr_$VERSION.tgz"
tar -czf "$DIST/sdl-wkr_$VERSION.tgz" -C "$ROOT" sdl-wkr
sha256sum "$DIST/sdl-wkr_$VERSION.tgz" | awk '{sub(".*/","",$2); print}' > "$DIST/sdl-wkr_$VERSION.tgz.sha256"
# ------------------------------------------------------------
# Copy install-sdl-wkr.sh to DIST
# ------------------------------------------------------------
echo ""
echo "Copying: $DIST/install-sdl-wkr.sh"
cp "$ROOT/sdl-wkr/scripts/install-sdl-wkr.sh" "$DIST/install-sdl-wkr.sh"
sha256sum "$DIST/install-sdl-wkr.sh" | awk '{sub(".*/","",$2); print}' > "$DIST/install-sdl-wkr.sh.sha256"
echo "Installing nwa version $VERSION to $VERSIONS/nwa_$VERSION"
rsync -av $ROOT/nwa --exclude='node_modules' $VERSIONS/nwa_$VERSION
# ln -s $VERSIONS/nwa_$VERSION $VERSIONS/current
ln -sfnT "$VERSIONS/nwa_$VERSION" "$VERSIONS/current"
NWA="$VERSIONS/current/nwa"
# ------------------------------------------------------------
# Fetch NodeJS Tarballs / Zips to DIST
# ------------------------------------------------------------
echo ""
echo "Fetching NodeJS Binaries to $DIST"
SHASUM_URL="https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt"
curl -sSL "$SHASUM_URL" -o "$DIST/NODE_SHASUMS256.txt"
install_nodejs
# Download NodeJS tarball
# echo ""
# echo "Fetching NodeJS Binaries to $DIST"
# SHASUM_URL="https://nodejs.org/dist/v${NODE_VERSION}/SHASUMS256.txt"
# curl -sSL "$SHASUM_URL" -o "$DIST/NODE_SHASUMS256.txt"
for np in $NODE_PLATFORMS; do
IFS=":" read -r OS ARCH <<< "$np"
# # Download NodeJS tarball
case "$OS" in
linux) EXT="tar.xz" ;;
darwin) EXT="tar.gz" ;;
win) EXT="zip" ;;
*) echo "ERROR: Unknown NodeJS target OS: $OS"; exit 1 ;;
esac
# for np in $NODE_PLATFORMS; do
# IFS=":" read -r OS ARCH <<< "$np"
PLATFORM="${OS}-${ARCH}"
NODE_DIR="node-v${NODE_VERSION}-${PLATFORM}"
NODE_TARBALL="${NODE_DIR}.$EXT"
NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TARBALL}"
# case "$OS" in
# linux) EXT="tar.xz" ;;
# darwin) EXT="tar.gz" ;;
# win) EXT="zip" ;;
# *) echo "ERROR: Unknown NodeJS target OS: $OS"; exit 1 ;;
# esac
echo " $np: $NODE_TARBALL"
# PLATFORM="${OS}-${ARCH}"
# NODE_DIR="node-v${NODE_VERSION}-${PLATFORM}"
# NODE_TARBALL="${NODE_DIR}.$EXT"
# NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TARBALL}"
if [ ! -e "$DIST/$NODE_TARBALL" ]; then
# echo " $np: $NODE_TARBALL"
curl -sSL "$NODE_URL" -o "$DIST/$NODE_TARBALL"
# if [ ! -e "$DIST/$NODE_TARBALL" ]; then
EXPECTED_SHA="$(grep " $NODE_TARBALL\$" "$DIST/NODE_SHASUMS256.txt" | awk '{print $1}')"
# curl -sSL "$NODE_URL" -o "$DIST/$NODE_TARBALL"
if [[ -z "$EXPECTED_SHA" ]]; then
echo "Error: SHA256 not found for $NODE_TARBALL"
exit 1
fi
# EXPECTED_SHA="$(grep " $NODE_TARBALL\$" "$DIST/NODE_SHASUMS256.txt" | awk '{print $1}')"
ACTUAL_SHA="$(sha256sum "$DIST/$NODE_TARBALL" | awk '{print $1}')"
# if [[ -z "$EXPECTED_SHA" ]]; then
# echo "Error: SHA256 not found for $NODE_TARBALL"
# exit 1
# fi
if [[ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]]; then
echo "SHA mismatch $NODE_TARBALL"
rm -f "$DIST/$NODE_TARBALL"
exit 1
fi
# ACTUAL_SHA="$(sha256sum "$DIST/$NODE_TARBALL" | awk '{print $1}')"
echo "$EXPECTED_SHA $NODE_TARBALL" > "$DIST/$NODE_TARBALL.sha256"
fi
done
# if [[ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]]; then
# echo "SHA mismatch $NODE_TARBALL"
# rm -f "$DIST/$NODE_TARBALL"
# exit 1
# fi
# echo "$EXPECTED_SHA $NODE_TARBALL" > "$DIST/$NODE_TARBALL.sha256"
# fi
# done
unset OS ARCH
# ------------------------------------------------------------
# Copy NWA/current/conf/efault-nwa-config.json to CONF/nwa-config.json
# ------------------------------------------------------------
# ------------------------------------------------------------
# Extract sdl-mgr-VERSION tarball from DIST to MGR
# Symlink to MGR/current
# ------------------------------------------------------------
if [ ! -e "$CONF/nwa-config.json" ]; then
echo ""
echo "Extracting: $DIST/sdl-mgr_$VERSION.tgz to $MGR/sdl-mgr_$VERSION"
rm -rf "$MGR/sdl-mgr_$VERSION"
tar -xzf "$DIST/sdl-mgr_$VERSION.tgz" -C "$MGR"
mv "$MGR/sdl-mgr" "$MGR/sdl-mgr_$VERSION"
# rm "$MGR/current"
ln -sfn "$MGR/sdl-mgr_$VERSION" "$MGR/current"
# ------------------------------------------------------------
# Copy MGR/current/conf/efault-sdl-mgr-config.json to CONF/sdl-mgr-config.json
# ------------------------------------------------------------
if [ ! -e "$CONF/sdl-mgr-config.json" ]; then
echo ""
echo "Copying: $MGR/current/conf/default-sdl-mgr-config.json to $CONF/sdl-mgr-config.json"
cp "$MGR/current/conf/default-sdl-mgr-config.json" "$CONF/sdl-mgr-config.json"
# echo "Copying: $NWA/current/conf/default-nwa-config.json to $CONF/nwa-config.json"
# cp "$NWA/current/conf/default-nwa-config.json" "$CONF/nwa-config.json"
echo "Copying: $NWA/conf/nwa-config.json to $CONF/nwa-config.json"
rsync -av "$NWA/conf/nwa-config.json" "$CONF/nwa-config.json"
fi
# ------------------------------------------------------------
@ -333,56 +408,56 @@ fi
# Symlink to NODEJS/current
# ------------------------------------------------------------
# Check if NodeJS is already installed
# # Check if NodeJS is already installed
NODE_BIN="$NODEJS/current/bin/node"
NPM_BIN="$NODEJS/current/bin/npm"
# echo "NodeJS binary: $NODE_BIN"
if [ -e "$NODE_BIN" ]; then
NODE_BIN_VERSION="$("$NODE_BIN" --version)"
# echo "NodeJS bin version: $NODE_BIN_VERSION"
# echo "NodeJS version: v$NODE_VERSION"
case "$OS_PLATFORM" in
linux) EXT="tar.xz"; TAR_OPTS="-xJf" ;;
darwin) EXT="tar.gz"; TAR_OPTS="-xzf" ;;
win) EXT="zip" ;;
*) echo "ERROR: Unsupported OS platform: $OS_PLATFORM"; exit 1 ;;
esac
# if [ -e "$NODE_BIN" ]; then
# NODE_BIN_VERSION="$("$NODE_BIN" --version)"
# # echo "NodeJS bin version: $NODE_BIN_VERSION"
# # echo "NodeJS version: v$NODE_VERSION"
# case "$OS_PLATFORM" in
# linux) EXT="tar.xz"; TAR_OPTS="-xJf" ;;
# darwin) EXT="tar.gz"; TAR_OPTS="-xzf" ;;
# win) EXT="zip" ;;
# *) echo "ERROR: Unsupported OS platform: $OS_PLATFORM"; exit 1 ;;
# esac
if [ "$NODE_BIN_VERSION" != "v$NODE_VERSION" ]; then
echo ""
echo "Installing NodeJS: node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}"
# if [ "$NODE_BIN_VERSION" != "v$NODE_VERSION" ]; then
# echo ""
# echo "Installing NodeJS: node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}"
echo "Extracting: $DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT"
if [ $OS_PLATFORM == "win32" ]; then
echo "ERROR: win32 host install not supported by this installer"
exit 1
# unzip "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT" -d "$NODEJS"
else
tar $TAR_OPTS "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT" -C "$NODEJS"
fi
# rm "$NODEJS/current"
ln -sfn "$NODEJS/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}" "$NODEJS/current"
else
echo ""
echo "NodeJS $OS_PLATFORM-$OS_ARCH v$NODE_VERSION already installed"
fi
else
echo ""
echo "Installing NodeJS $NODE_VERSION"
# echo "Extracting: $DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT"
# if [ $OS_PLATFORM == "win32" ]; then
# echo "ERROR: win32 host install not supported by this installer"
# exit 1
# # unzip "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT" -d "$NODEJS"
# else
# tar $TAR_OPTS "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.$EXT" -C "$NODEJS"
# fi
# # rm "$NODEJS/current"
# ln -sfn "$NODEJS/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}" "$NODEJS/current"
# else
# echo ""
# echo "NodeJS $OS_PLATFORM-$OS_ARCH v$NODE_VERSION already installed"
# fi
# else
# echo ""
# echo "Installing NodeJS $NODE_VERSION"
echo "Extracting: $DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.tar.xz"
tar -xJf "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.tar.xz" -C "$NODEJS"
ln -sfn "$NODEJS/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}" "$NODEJS/current"
fi
# echo "Extracting: $DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.tar.xz"
# tar -xJf "$DIST/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}.tar.xz" -C "$NODEJS"
# ln -sfn "$NODEJS/node-v${NODE_VERSION}-${OS_PLATFORM}-${OS_ARCH}" "$NODEJS/current"
# fi
# ------------------------------------------------------------
# Install sdl-mgr Node Dependencies
# Install nwa Node Dependencies
# ------------------------------------------------------------
echo ""
echo "Installing NodeJS Dependencies"
cd "$MGR/current/app"
cd "$NWA/app"
export PATH="$NODEJS/current/bin:$PATH"
$NPM_BIN install
@ -390,40 +465,40 @@ $NPM_BIN install
# ------------------------------------------------------------
# Copy Start / Stop Scripts
# ------------------------------------------------------------
mkdir -p "$HOME/scripts/"
cp "$MGR/current/scripts/start-sdl-mgr.sh" "$HOME/scripts/"
cp "$MGR/current/scripts/stop-sdl-mgr.sh" "$HOME/scripts/"
cp "$MGR/current/scripts/status-sdl-mgr.sh" "$HOME/scripts/"
chmod u+x "$HOME/scripts/"*
mkdir -p "$SITE/scripts/"
cp "$NWA/scripts/start-nwa.sh" "$SITE/scripts/"
cp "$NWA/scripts/stop-nwa.sh" "$SITE/scripts/"
cp "$NWA/scripts/status-nwa.sh" "$SITE/scripts/"
chmod u+x "$SITE/scripts/"*
# ------------------------------------------------------------
# Install Systemd Unit Files
# Copy MGR/current/scripts/sdl-mgr.service to ~/.config/systemd/user
# Copy NWA/current/scripts/nwa.service to ~/.config/systemd/user
# ------------------------------------------------------------
if use_systemd; then
echo ""
echo "Installing SystemD Unit Files"
mkdir -p ~/.config/systemd/user
cp "$MGR/current/scripts/sdl-mgr.service" ~/.config/systemd/user/
cp "$NWA/scripts/nwa.service" ~/.config/systemd/user/
"${HOME}/scripts/stop-sdl-mgr.sh"
"${SITE}/scripts/stop-nwa.sh"
sleep 1
systemctl --user daemon-reload --no-pager
fi
# ------------------------------------------------------------
# Start SDL Manager
# Start NWA
# ------------------------------------------------------------
"${HOME}/scripts/start-sdl-mgr.sh"
"${SITE}/scripts/start-nwa.sh"
sleep 2
"${HOME}/scripts/status-sdl-mgr.sh"
"${SITE}/scripts/status-nwa.sh"
if [ $? -ne 0 ]; then
echo ""
echo "ERROR: SDL Manager failed to start"
echo "ERROR: NWA failed to start"
exit 1
fi
@ -432,6 +507,6 @@ fi
echo ""
echo "SDL Manager deployed:"
echo " to: $HOME"
echo "NWA deployed:"
echo " to: $SITE"

View File

@ -4,14 +4,14 @@
"description": "Node Web App",
"abbr": "NWA",
"version": "0.1.0",
"version_date": "2026-02-08",
"version_date": "2026-06-28",
"maturity": "PROD",
"author": "John Haverlack",
"copyright": "2026 John Haverlack",
"license": "MIT",
"license_url": "https://opensource.org/license/MIT",
"homepage": "https://github.com/jehaverlack/sdl",
"git_repo": "https://github.com/jehaverlack/sdl.git"
"homepage": "https://github.com/jehaverlack/nwa",
"git_repo": "https://github.com/jehaverlack/nwa.git"
},
"META_MAPS": {
"package.json": {

View File

@ -1,12 +1,13 @@
{
"DIRS": {
"HOME": "~/.nwa",
"CONF": "HOME/conf",
"DOCS": "HOME/docs",
"LOGS": "HOME/logs",
"DATA": "HOME/data",
"SCRIPTS": "HOME/scripts",
"NODEJS": "HOME/nodejs"
"SITE": "~/.nwa",
"CONF": "SITE/conf",
"DOCS": "SITE/docs",
"LOGS": "SITE/logs",
"DATA": "SITE/data",
"SCRIPTS": "SITE/scripts",
"NODEJS": "SITE/nodejs",
"VERSIONS": "SITE/versions"
},
"NODEJS": {
"VERSION": "24.18.0",

View File

@ -34,11 +34,14 @@ function load_config() {
.argv;
// console.log("DEBUG: dirname: " + __dirname);
let home = path.join(__dirname, '..', '..', '..'); // HOME Default
let mgr_cfg_file = path.join(home, 'conf', 'nwa-config.json');
let site = path.join(__dirname, '..', '..', '..', '..', '..', '..'); // site Default
// let base = path.join(__dirname, '..', '..', '..', '..'); // base Default
// let mgr_cfg_file = path.join(base, 'nwa', 'conf', 'nwa-config.json');
let mgr_cfg_file = path.join(site, 'conf', 'nwa-config.json');
// console.log("DEBUG: HOME: " + home);
// console.log("DEBUG: site: " + site);
// console.log("DEBUG: MGR_CFG_FILE: " + mgr_cfg_file);
try {
fs.accessSync(mgr_cfg_file, fs.constants.R_OK);
} catch (err) {
@ -46,38 +49,6 @@ function load_config() {
process.exit(1);
}
// // Load from ENV
// if (process.env.HOME) {
// home = process.env.HOME;
// mgr_cfg_file = path.join(home, 'conf', '-mgr-config.json');
// // console.log("DEBUG3: HOME: " + home);
// // console.log("DEBUG3: MGR_CFG_FILE: " + mgr_cfg_file);
// try {
// fs.accessSync(mgr_cfg_file, fs.constants.R_OK);
// } catch (err) {
// console.error(err);
// process.exit(1);
// }
// }
// // Load from ARGV
// if (argv.configfile) {
// home = path.dirname(argv.configfile);
// mgr_cfg_file = path.join(home, 'conf', '-mgr-config.json');
// // console.log("DEBUG4: HOME: " + home);
// // console.log("DEBUG4: MGR_CFG_FILE: " + mgr_cfg_file);
// try {
// fs.accessSync(mgr_cfg_file, fs.constants.R_OK);
// } catch (err) {
// console.error(err);
// process.exit(1);
// }
// }
// console.log("DEBUG: HOME: " + home);
// console.log("DEBUG: MGR_CFG_FILE: " + mgr_cfg_file);
// Load Config
try {
@ -87,13 +58,13 @@ function load_config() {
console.error(err);
}
// console.log("DEBUG: home: " + home);
// console.log("DEBUG: site: " + site);
// Expand Data Directory
let search_replace = {}
search_replace['DIRNAME'] = __dirname
// search_replace['HOME'] = home
config.dirs['home'] = home
// search_replace['site'] = site
config.dirs['site'] = site
for (let d in config.dirs) {
search_replace[d.toUpperCase()] = d
}
@ -131,23 +102,13 @@ function load_config() {
fs.mkdirSync(config.dirs[d], { recursive: true });
}
}
// for (let k in config.dependencies[d]) {
// // if k matches case insensitive "dependencies" the remove elemend k.
// if (k.match(/[Dd]ependencies/)) {
// delete config.dependencies[d][k]
// }
// if (k.match(/scripts/)) {
// delete config.dependencies[d][k]
// }
// }
// Load Package Info
config.package = JSON.parse(fs.readFileSync(path.join(config.dirs.app, 'package.json'), 'utf8'));
config.dependencies = {}
// Version
config.cluster.version = config.package.version
// config.nwa.version = config.package.version
for (let d in config.package.dependencies) {
config.dependencies[d] = JSON.parse(fs.readFileSync(path.join(config.dirs.app, 'node_modules', d, 'package.json'), 'utf8'));
@ -186,7 +147,8 @@ function load_config() {
};
config.nwa = {
version: config.package.version
version: config.package.version,
config_file: mgr_cfg_file
}
config.identity = {
@ -271,7 +233,7 @@ function load_config() {
try {
// console.log(JSON.stringify(config.dirs, null, 2));
const idinfo = load_or_create_id(config.dirs.home);
const idinfo = load_or_create_id(config.dirs.site);
config.identity.id = idinfo.id;
config.identity.created_at = idinfo.created_at;
config.identity.hostname = config.host.hostname;
@ -381,9 +343,9 @@ function computeBroadcast(address, netmask) {
}
}
function load_or_create_id(home) {
// console.log('DEBUG: load_or_create_id() home: ' + home);
const id_dir = path.join(home, 'conf');
function load_or_create_id(site) {
// console.log('DEBUG: load_or_create_id() site: ' + site);
const id_dir = path.join(site, 'conf');
const id_file = path.join(id_dir, 'nwa-id.json');
try {

View File

@ -1,19 +1,16 @@
{
"cluster": {
"id": "haverlab",
"name": "Haverlab",
"desc": "John Haverlack's Home Lab"
"site": {
"id": "nwa",
"name": "Node Web App",
"desc": "A Node.json Web App Template"
},
"dirs": {
"base": "DIRNAME/../..",
"app": "BASE/app",
"modules": "APP/modules",
"logs": "HOME/logs",
"data": "HOME/data",
"clstr": "DATA/cluster",
"proj": "DATA/proj",
"jobs": "DATA/jobs",
"conf": "HOME/conf",
"logs": "SITE/logs",
"data": "SITE/data",
"conf": "SITE/conf",
"modconf": "BASE/conf/modules",
"html": "BASE/html"
},

31
nwa/scripts/nwa.service Normal file
View File

@ -0,0 +1,31 @@
[Unit]
Description=Node Web App
After=network.target
[Service]
Type=simple
# Environment
Environment=NWA_HOME=%h/.nwa
Environment=NODE_ENV=production
# Paths
WorkingDirectory=%h/.nwa/versions/current/nwa/app
# Start command
ExecStart=%h/.nwa/nodejs/current/bin/node index.js
# Restart behavior
Restart=on-failure
RestartSec=3
# Logging
StandardOutput=append:%h/.nwa/logs/nwa.log
StandardError=append:%h/.nwa/logs/nwa.log
# Clean shutdown
KillSignal=SIGTERM
TimeoutStopSec=15
[Install]
WantedBy=default.target

View File

@ -1,29 +0,0 @@
[Unit]
Description=SDL Manager
After=network.target
[Service]
Type=simple
# Paths
Environment=SDL_HOME=%h/.sdl
WorkingDirectory=%h/.sdl/sdl-mgr/current/app
# Start command
ExecStart=%h/.sdl/nodejs/current/bin/node index.js
# Restart behavior
Restart=on-failure
RestartSec=3
# Logging
StandardOutput=append:%h/.sdl/logs/sdl-mgr.out.log
StandardError=append:%h/.sdl/logs/sdl-mgr.err.log
# Clean shutdown
KillSignal=SIGTERM
TimeoutStopSec=15
[Install]
WantedBy=default.target

65
nwa/scripts/start-nwa.sh Executable file
View File

@ -0,0 +1,65 @@
#!/usr/bin/env bash
# start-nwa.sh - Script to start Node Web App
set -euo pipefail
use_systemd() {
# Check if systemd user mode is available and service exists
if systemctl --user status >/dev/null 2>&1; then
# Check if our service file exists
if systemctl --user list-unit-files | grep -q "^nwa.service"; then
return 0 # Use systemd
fi
fi
return 1 # Use manual scripts
}
# Get $NWA_HOME directory from SCRIPT PATH
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NWA_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
if use_systemd; then
# Systemd mode - let systemd handle it
echo "Starting NWA (systemd)..."
systemctl --user start nwa
exit 0
fi
# Manual mode - continue with checks
NODE_BIN_DIR="${NWA_HOME}/nodejs/current/bin"
NODE_BIN="${NODE_BIN_DIR}/node"
NPM_BIN="${NODE_BIN_DIR}/npm"
NWA_APP_DIR="${NWA_HOME}/current/app"
# Check that nwa is not already running
NWA_PID=""
for pid in $(pgrep -f 'node' 2>/dev/null || true); do
cwd=$(readlink /proc/$pid/cwd 2>/dev/null || true)
if [[ "$cwd" == *"nwa"* ]]; then
NWA_PID="$pid"
break
fi
done
if [[ -n "$NWA_PID" ]]; then
echo "ERROR: NWA is already running with PID ${NWA_PID}"
echo " Stop it first: ${NWA_HOME}/scripts/stop-nwa.sh"
exit 1
fi
# Verify paths exist
if [[ ! -f "$NODE_BIN" ]]; then
echo "ERROR: Node.js not found at: $NODE_BIN"
echo " Run install.sh first"
exit 1
fi
if [[ ! -d "$NWA_APP_DIR" ]]; then
echo "ERROR: NWA app not found at: $NWA_APP_DIR"
echo " Run install.sh first"
exit 1
fi
echo "Starting NWA..."
echo " App Dir: ${NWA_APP_DIR}"
echo " Node:

View File

@ -1,65 +0,0 @@
#!/usr/bin/env bash
# start-sdl-mgr.sh - Script to start SDL Manager
set -euo pipefail
use_systemd() {
# Check if systemd user mode is available and service exists
if systemctl --user status >/dev/null 2>&1; then
# Check if our service file exists
if systemctl --user list-unit-files | grep -q "^sdl-mgr.service"; then
return 0 # Use systemd
fi
fi
return 1 # Use manual scripts
}
# Get $SDL_HOME directory from SCRIPT PATH
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SDL_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
if use_systemd; then
# Systemd mode - let systemd handle it
echo "Starting SDL Manager (systemd)..."
systemctl --user start sdl-mgr
exit 0
fi
# Manual mode - continue with checks
NODE_BIN_DIR="${SDL_HOME}/nodejs/current/bin"
NODE_BIN="${NODE_BIN_DIR}/node"
NPM_BIN="${NODE_BIN_DIR}/npm"
SDL_MGR_APP_DIR="${SDL_HOME}/sdl-mgr/current/app"
# Check that sdl-mgr is not already running
SDL_MGR_PID=""
for pid in $(pgrep -f 'node' 2>/dev/null || true); do
cwd=$(readlink /proc/$pid/cwd 2>/dev/null || true)
if [[ "$cwd" == *"sdl-mgr"* ]]; then
SDL_MGR_PID="$pid"
break
fi
done
if [[ -n "$SDL_MGR_PID" ]]; then
echo "ERROR: SDL Manager is already running with PID ${SDL_MGR_PID}"
echo " Stop it first: ${SDL_HOME}/scripts/stop-sdl-mgr.sh"
exit 1
fi
# Verify paths exist
if [[ ! -f "$NODE_BIN" ]]; then
echo "ERROR: Node.js not found at: $NODE_BIN"
echo " Run install-sdl.sh first"
exit 1
fi
if [[ ! -d "$SDL_MGR_APP_DIR" ]]; then
echo "ERROR: SDL Manager app not found at: $SDL_MGR_APP_DIR"
echo " Run install-sdl.sh first"
exit 1
fi
echo "Starting SDL Manager..."
echo " App Dir: ${SDL_MGR_APP_DIR}"
echo " Node:

View File

@ -1,12 +1,12 @@
#!/usr/bin/env bash
# status-sdl-mgr.sh - Script to show status of SDL Manager
# status-nwa.sh - Script to show status of NWA
set -euo pipefail
use_systemd() {
# Check if systemd user mode is available and service exists
if systemctl --user status >/dev/null 2>&1; then
# Check if our service file exists
if systemctl --user list-unit-files | grep -q "^sdl-mgr.service"; then
if systemctl --user list-unit-files | grep -q "^nwa.service"; then
return 0 # Use systemd
fi
fi
@ -14,28 +14,28 @@ use_systemd() {
}
if use_systemd; then
systemctl --user status sdl-mgr
systemctl --user status nwa
else
# Get sdl-mgr PID
SDL_MGR_PID=""
# Get nwa PID
NWA_PID=""
for pid in $(pgrep -f 'node' 2>/dev/null || true); do
cwd=$(readlink /proc/$pid/cwd 2>/dev/null || true)
if [[ "$cwd" == *"sdl-mgr"* ]]; then
SDL_MGR_PID="$pid"
if [[ "$cwd" == *"nwa"* ]]; then
NWA_PID="$pid"
break
fi
done
if [[ -z "$SDL_MGR_PID" ]]; then
echo "SDL Manager is not running"
if [[ -z "$NWA_PID" ]]; then
echo "NWA is not running"
exit 0
fi
# Get process uptime
PROCESS_START=$(ps -p "$SDL_MGR_PID" -o lstart= 2>/dev/null || echo "unknown")
PROCESS_START=$(ps -p "$NWA_PID" -o lstart= 2>/dev/null || echo "unknown")
echo "SDL Manager is running"
echo " PID: ${SDL_MGR_PID}"
echo "NWA is running"
echo " PID: ${NWA_PID}"
echo " Started: ${PROCESS_START}"
exit 0
fi

View File

@ -1,12 +1,12 @@
#!/usr/bin/env bash
# stop-sdl-mgr.sh - Script to stop SDL Manager
# stop-nwa.sh - Script to stop NWA
set -euo pipefail
use_systemd() {
# Check if systemd user mode is available and service exists
if systemctl --user status >/dev/null 2>&1; then
# Check if our service file exists
if systemctl --user list-unit-files | grep -q "^sdl-mgr.service"; then
if systemctl --user list-unit-files | grep -q "^nwa.service"; then
return 0 # Use systemd
fi
fi
@ -15,51 +15,51 @@ use_systemd() {
if use_systemd; then
# Systemd mode - let systemd handle it
echo "Stopping SDL Manager (systemd)..."
systemctl --user stop sdl-mgr --quiet 2>/dev/null || true
echo "SDL Manager stopped"
echo "Stopping NWA (systemd)..."
systemctl --user stop nwa --quiet 2>/dev/null || true
echo "NWA stopped"
exit 0
fi
# Manual mode - find and kill process
SDL_MGR_PID=""
NWA_PID=""
for pid in $(pgrep -f 'node' 2>/dev/null || true); do
cwd=$(readlink /proc/$pid/cwd 2>/dev/null || true)
if [[ "$cwd" == *"sdl-mgr"* ]]; then
SDL_MGR_PID="$pid"
if [[ "$cwd" == *"nwa"* ]]; then
NWA_PID="$pid"
break
fi
done
if [[ -z "$SDL_MGR_PID" ]]; then
echo "SDL Manager is not running"
if [[ -z "$NWA_PID" ]]; then
echo "NWA is not running"
exit 0
fi
echo "Stopping SDL Manager (PID: ${SDL_MGR_PID})..."
echo "Stopping NWA (PID: ${NWA_PID})..."
# Send SIGTERM for graceful shutdown
kill "$SDL_MGR_PID"
kill "$NWA_PID"
# Wait up to 10 seconds for process to exit
for i in {1..10}; do
if ! kill -0 "$SDL_MGR_PID" 2>/dev/null; then
echo "SDL Manager stopped successfully"
if ! kill -0 "$NWA_PID" 2>/dev/null; then
echo "NWA stopped successfully"
exit 0
fi
sleep 1
done
# If still running after 10 seconds, force kill
if kill -0 "$SDL_MGR_PID" 2>/dev/null; then
if kill -0 "$NWA_PID" 2>/dev/null; then
echo "WARNING: Graceful shutdown failed, forcing kill..."
kill -9 "$SDL_MGR_PID"
kill -9 "$NWA_PID"
sleep 1
if kill -0 "$SDL_MGR_PID" 2>/dev/null; then
echo "ERROR: Failed to stop SDL Manager"
if kill -0 "$NWA_PID" 2>/dev/null; then
echo "ERROR: Failed to stop NWA"
exit 1
fi
fi
echo "SDL Manager stopped"
echo "NWA stopped"

View File

@ -1,33 +0,0 @@
import socket
import sys
def main():
if len(sys.argv) != 2:
print("Usage: python udp_listener.py <port>")
return
port = int(sys.argv[1])
# Create a datagram socket
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error as msg:
print('Failed to create socket. ' + str(msg))
return
# Enable broadcasting mode
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
try:
# Bind the socket to a specific port
sock.bind(('', port))
except socket.error as msg:
print('Bind failed. ' + str(msg))
return
while True:
data, addr = sock.recvfrom(1024)
print(data.decode())
if __name__ == "__main__":
main()