chore(scripts): clean up setup; add start + update

This commit is contained in:
Cory Dransfeldt 2025-06-20 17:31:11 -07:00
parent 555d611c2a
commit 4bc85bde57
No known key found for this signature in database
10 changed files with 103 additions and 63 deletions

View file

@ -179,8 +179,8 @@ export const loadConfig = async () => {
}; };
const fetchGlobals = async () => { const fetchGlobals = async () => {
const POSTGREST_URL = process.env.POSTGREST_URL; const POSTGREST_URL = process.env.POSTGREST_URL?.replace(/^"(.*)"$/, "$1");
const POSTGREST_API_KEY = process.env.POSTGREST_API_KEY; const POSTGREST_API_KEY = process.env.POSTGREST_API_KEY?.replace(/^"(.*)"$/, "$1");
if (!POSTGREST_URL || !POSTGREST_API_KEY) { if (!POSTGREST_URL || !POSTGREST_API_KEY) {
console.warn("⚠️ Missing POSTGREST_URL or POSTGREST_API_KEY in env, skipping globals fetch."); console.warn("⚠️ Missing POSTGREST_URL or POSTGREST_API_KEY in env, skipping globals fetch.");

View file

@ -13,11 +13,13 @@ let API_URL;
export const initDirectusClient = (config) => { export const initDirectusClient = (config) => {
API_URL = config.directus?.apiUrl; API_URL = config.directus?.apiUrl;
const token = process.env.DIRECTUS_API_TOKEN; const token = process.env.DIRECTUS_API_TOKEN?.replace(/^"(.*)"$/, "$1");
if (!API_URL || !token) throw new Error("Missing Directus API URL or token."); if (!API_URL || !token) throw new Error("Missing Directus API URL or token.");
directus = createDirectus(API_URL).with(staticToken(process.env.DIRECTUS_API_TOKEN)).with(rest()); directus = createDirectus(API_URL)
.with(staticToken(process.env.DIRECTUS_API_TOKEN?.replace(/^"(.*)"$/, "$1")))
.with(rest());
}; };
export const getDirectusClient = () => { export const getDirectusClient = () => {
@ -27,7 +29,7 @@ export const getDirectusClient = () => {
}; };
const request = async (method, endpoint, body = null) => { const request = async (method, endpoint, body = null) => {
const API_TOKEN = process.env.DIRECTUS_API_TOKEN; const API_TOKEN = process.env.DIRECTUS_API_TOKEN?.replace(/^"(.*)"$/, "$1");
const res = await fetch(`${API_URL}/items/${endpoint}`, { const res = await fetch(`${API_URL}/items/${endpoint}`, {
method, method,
headers: { headers: {
@ -47,7 +49,7 @@ const request = async (method, endpoint, body = null) => {
}; };
export const searchItems = async (collection, query = "", filters = {}) => { export const searchItems = async (collection, query = "", filters = {}) => {
const API_TOKEN = process.env.DIRECTUS_API_TOKEN; const API_TOKEN = process.env.DIRECTUS_API_TOKEN?.replace(/^"(.*)"$/, "$1");
const params = new URLSearchParams(); const params = new URLSearchParams();
if (query) params.append("search", query); if (query) params.append("search", query);

View file

@ -119,7 +119,7 @@ export const runJobsMenu = async () => {
if (job.paramsPrompt) { if (job.paramsPrompt) {
const answers = await inquirer.prompt(job.paramsPrompt); const answers = await inquirer.prompt(job.paramsPrompt);
const token = process.env[job.tokenEnvVar]; const token = process.env[job.tokenEnvVar]?.replace(/^"(.*)"$/, "$1");
params = { ...answers, ...(token ? { token } : {}) }; params = { ...answers, ...(token ? { token } : {}) };
} }
@ -138,8 +138,8 @@ const runCurl = async ({
name, name,
params = null params = null
}) => { }) => {
const url = process.env[urlEnvVar] || apiUrl; const url = process.env[urlEnvVar]?.replace(/^"(.*)"$/, "$1") || apiUrl;
const token = tokenEnvVar ? process.env[tokenEnvVar] : null; const token = tokenEnvVar ? process.env[tokenEnvVar]?.replace(/^"(.*)"$/, "$1") : null;
if (!url) { if (!url) {
console.error(`❌ Missing URL for job. Check ${urlEnvVar} in your .env`); console.error(`❌ Missing URL for job. Check ${urlEnvVar} in your .env`);

4
cli/package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "coryd", "name": "coryd",
"version": "3.4.1", "version": "3.4.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "coryd", "name": "coryd",
"version": "3.4.1", "version": "3.4.2",
"dependencies": { "dependencies": {
"@directus/sdk": "^19.1.0", "@directus/sdk": "^19.1.0",
"chalk": "^5.4.1", "chalk": "^5.4.1",

View file

@ -1,6 +1,6 @@
{ {
"name": "coryd", "name": "coryd",
"version": "3.4.1", "version": "3.4.2",
"description": "The CLI for my site to handle tasks, run commands or jobs and download things.", "description": "The CLI for my site to handle tasks, run commands or jobs and download things.",
"type": "module", "type": "module",
"bin": { "bin": {

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "coryd.dev", "name": "coryd.dev",
"version": "10.8.7", "version": "10.9.7",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "coryd.dev", "name": "coryd.dev",
"version": "10.8.7", "version": "10.9.7",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"minisearch": "^7.1.2", "minisearch": "^7.1.2",

View file

@ -1,13 +1,13 @@
{ {
"name": "coryd.dev", "name": "coryd.dev",
"version": "10.8.7", "version": "10.9.7",
"description": "The source for my personal site. Built using 11ty (and other tools).", "description": "The source for my personal site. Built using 11ty (and other tools).",
"type": "module", "type": "module",
"engines": { "engines": {
"node": "22.x" "node": "22.x"
}, },
"scripts": { "scripts": {
"start": "npm run clean && npm run build && npm run start:quick", "start": "./scripts/start.sh",
"start:quick": "concurrently -k -n 11ty,PHP -c cyan,magenta \"npm run watch\" \"npm run php\"", "start:quick": "concurrently -k -n 11ty,PHP -c cyan,magenta \"npm run watch\" \"npm run php\"",
"watch": "eleventy --watch", "watch": "eleventy --watch",
"php": "export $(grep -v '^#' .env | xargs) && php -d error_reporting=E_ALL^E_DEPRECATED -S localhost:8080 -t dist", "php": "export $(grep -v '^#' .env | xargs) && php -d error_reporting=E_ALL^E_DEPRECATED -S localhost:8080 -t dist",
@ -16,7 +16,7 @@
"format": "npx prettier --write '**/*.{js,json,css,md,liquid}' && composer format:php && npm run format:sql", "format": "npx prettier --write '**/*.{js,json,css,md,liquid}' && composer format:php && npm run format:sql",
"format:sql": "find queries -name '*.sql' -print0 | xargs -0 -n 1 sql-formatter --language postgresql --fix", "format:sql": "find queries -name '*.sql' -print0 | xargs -0 -n 1 sql-formatter --language postgresql --fix",
"lint:md": "markdownlint '**/*.md'", "lint:md": "markdownlint '**/*.md'",
"update": "composer update && npm upgrade && npm --prefix cli upgrade && ncu && ncu --cwd cli", "update": "./scripts/update.sh",
"setup": "sh ./scripts/setup.sh", "setup": "sh ./scripts/setup.sh",
"setup:deploy": "sh ./scripts/setup.sh --deploy", "setup:deploy": "sh ./scripts/setup.sh --deploy",
"prepare": "husky" "prepare": "husky"

View file

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
set -eu
COLOR_BLUE="\033[38;2;51;100;255m" COLOR_BLUE="\033[38;2;51;100;255m"
COLOR_RESET="\033[0m" COLOR_RESET="\033[0m"
DEPLOY=false DEPLOY=false
@ -22,9 +24,13 @@ echo "${COLOR_RESET}"
# determine sed compatibility # determine sed compatibility
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
SED_INPLACE="sed -i ''" sed_inplace() {
sed -i '' "$@"
}
else else
SED_INPLACE="sed -i" sed_inplace() {
sed -i "$@"
}
fi fi
# get secrets from 1password # get secrets from 1password
@ -57,41 +63,46 @@ SECRETS_JSON='{
SECRETS=$(echo "$SECRETS_JSON" | op inject) SECRETS=$(echo "$SECRETS_JSON" | op inject)
if [ -z "$SECRETS" ]; then if echo "$SECRETS" | grep -q '{{'; then
echo "error: failed to retrieve secrets from 1Password." echo "❌ Error: Unresolved placeholders remain in injected secrets. Check 1Password references." >&2
exit 1 exit 1
fi fi
echo "${COLOR_BLUE}Writing .env file...${COLOR_RESET}" echo "${COLOR_BLUE}Writing .env file...${COLOR_RESET}"
echo "$SECRETS" | jq -r 'to_entries | .[] | "\(.key)=\(.value)"' > .env echo "$SECRETS" | jq -r 'to_entries | .[] | "\(.key)=\"\(.value | gsub("\""; "\\\""))\""' > .env
export $(grep -v '^#' .env | xargs) echo >> .env
echo "${COLOR_BLUE}📦 Installing root project dependencies...${COLOR_RESET}" while IFS= read -r line; do
npm install [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
export "${line?}"
done < .env
echo "${COLOR_BLUE}✅ Loaded $(grep -c '^[A-Z0-9_]\+=' .env) secrets into .env${COLOR_RESET}"
CLI_DIR="$(dirname "$0")/../cli"
echo "${COLOR_BLUE}🗳️ Installing root JS packages...${COLOR_RESET}"
npm install --loglevel=silent --no-audit --no-fund | grep -v "up to date" || :
echo "${COLOR_BLUE}🐺 Initializing Husky Git hooks...${COLOR_RESET}" echo "${COLOR_BLUE}🐺 Initializing Husky Git hooks...${COLOR_RESET}"
npm run prepare npm run prepare
echo "${COLOR_BLUE}📦 Installing PHP dependencies (composer)...${COLOR_RESET}" echo "${COLOR_BLUE}📦 Installing PHP packages...${COLOR_RESET}"
composer install composer install --no-progress --no-interaction 2>&1 | \
grep -Ev "^(Writing lock file|Generating optimized autoload files|Loading composer|Nothing to modify|Use the \`composer fund\`|No security vulnerability|Installing dependencies from lock file|Package operations|[0-9]+ packages you are using are looking for funding)"
echo "${COLOR_BLUE}📦 Installing CLI dependencies...${COLOR_RESET}" echo "${COLOR_BLUE}🗃️ Installing CLI JS packages...${COLOR_RESET}"
( ( cd "$CLI_DIR" && npm install --loglevel=silent --no-audit --no-fund | grep -v "up to date" || : )
cd cli
npm install
)
if ! command -v cd_cli >/dev/null 2>&1; then if ! command -v cd_cli >/dev/null 2>&1; then
echo "${COLOR_BLUE}🔗 Linking CLI globally...${COLOR_RESET}" echo "${COLOR_BLUE}🔗 Linking CLI globally...${COLOR_RESET}"
( ( cd "$CLI_DIR" && npm link )
cd cli
npm link
)
fi fi
echo "${COLOR_BLUE}⚙️ Initializing media storage config...${COLOR_RESET}" echo "${COLOR_BLUE}⚙️ Initializing media storage config...${COLOR_RESET}"
cd_cli init cd_cli init
rm -rf generated
mkdir -p generated mkdir -p generated
# escape sed replacements # escape sed replacements
@ -107,38 +118,19 @@ render_template() {
for key in $(jq -r 'keys_unsorted[]' <<< "$SECRETS"); do for key in $(jq -r 'keys_unsorted[]' <<< "$SECRETS"); do
value=$(jq -r --arg k "$key" '.[$k]' <<< "$SECRETS") value=$(jq -r --arg k "$key" '.[$k]' <<< "$SECRETS")
$SED_INPLACE "s|{{${key}}}|$(escape_special_chars "$value")|g" "$output" sed_inplace "s|{{${key}}}|$(escape_special_chars "$value")|g" "$output"
done done
} }
# render templates # render templates
for file in scripts/templates/*.template; do for filepath in scripts/templates/*.template; do
[ -e "$file" ] || continue [ -e "$filepath" ] || continue
filename=$(basename "$filepath" .template)
new_file="generated/$(basename "${file%.template}")" output="generated/$filename"
cp "$file" "$new_file" render_template "$filepath" "$output"
# replace placeholders
sed -i '' -e "s|{{POSTGREST_URL}}|$(escape_special_chars "$POSTGREST_URL")|g" "$new_file"
sed -i '' -e "s|{{POSTGREST_API_KEY}}|$(escape_special_chars "$POSTGREST_API_KEY")|g" "$new_file"
sed -i '' -e "s|{{MASTODON_ACCESS_TOKEN}}|$(escape_special_chars "$MASTODON_ACCESS_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{MASTODON_SYNDICATION_TOKEN}}|$(escape_special_chars "$MASTODON_SYNDICATION_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{FORWARDEMAIL_API_KEY}}|$(escape_special_chars "$FORWARDEMAIL_API_KEY")|g" "$new_file"
sed -i '' -e "s|{{BOOK_IMPORT_TOKEN}}|$(escape_special_chars "$BOOK_IMPORT_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{WATCHING_IMPORT_TOKEN}}|$(escape_special_chars "$WATCHING_IMPORT_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{ARTIST_IMPORT_TOKEN}}|$(escape_special_chars "$ARTIST_IMPORT_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{TMDB_API_KEY}}|$(escape_special_chars "$TMDB_API_KEY")|g" "$new_file"
sed -i '' -e "s|{{SEASONS_IMPORT_TOKEN}}|$(escape_special_chars "$SEASONS_IMPORT_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{NAVIDROME_SCROBBLE_TOKEN}}|$(escape_special_chars "$NAVIDROME_SCROBBLE_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{NAVIDROME_API_URL}}|$(escape_special_chars "$NAVIDROME_API_URL")|g" "$new_file"
sed -i '' -e "s|{{NAVIDROME_API_TOKEN}}|$(escape_special_chars "$NAVIDROME_API_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{COOLIFY_REBUILD_TOKEN}}|$(escape_special_chars "$COOLIFY_REBUILD_TOKEN")|g" "$new_file"
sed -i '' -e "s|{{COOLIFY_REBUILD_URL}}|$(escape_special_chars "$COOLIFY_REBUILD_URL")|g" "$new_file"
sed -i '' -e "s|{{GIT_REPO}}|$(escape_special_chars "$GIT_REPO")|g" "$new_file"
sed -i '' -e "s|{{SERVER_IP}}|$(escape_special_chars "$SERVER_IP")|g" "$new_file"
done done
echo "${COLOR_BLUE}all configurations generated in the 'generated' folder.${COLOR_RESET}" echo "${COLOR_BLUE}✅ All configurations generated in the 'generated' folder.${COLOR_RESET}"
echo "${COLOR_BLUE}" echo "${COLOR_BLUE}"
echo "==========================================" echo "=========================================="
@ -161,7 +153,9 @@ if [ "$DEPLOY" = true ]; then
# generate server setup script # generate server setup script
cat > generated/setup-server.sh <<EOF cat > generated/setup-server.sh <<EOF
#!/bin/bash #!/bin/bash
set -e # This file is generated by setup.sh
set -eu
echo "🔧 Enabling Apache modules..." echo "🔧 Enabling Apache modules..."
sudo a2enmod $REQUIRED_MODULES sudo a2enmod $REQUIRED_MODULES

25
scripts/start.sh Executable file
View file

@ -0,0 +1,25 @@
#!/bin/bash
set -eu
tmpfile=$(mktemp)
cleanup() {
echo -e "\n👋 Exiting. Cya!"
}
trap cleanup SIGINT SIGTERM
echo "🧼 Cleaning project..."
npm run clean --silent
echo "🛠️ Building project..."
npm run build --silent
echo "🚀 Starting development server..."
echo
npx concurrently -k -n 11ty,PHP \
"eleventy --watch" \
"bash -c 'set -a; source .env; set +a; php -d error_reporting=E_ALL^E_DEPRECATED -S localhost:8080 -t dist'" \
2>&1 | tee "$tmpfile" | grep --line-buffered -Ev '(exited with code|Sending SIGTERM)' || true

19
scripts/update.sh Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
set -eu
echo "📦 Updating PHP packages..."
composer update --no-progress --no-interaction 2>&1 | grep -Ev \
"^(Writing lock file|Generating optimized autoload files|Loading composer|Nothing to modify|Use the \`composer fund\`|No security vulnerability|Installing dependencies from lock file|Package operations|[0-9]+ packages you are using are looking for funding)"
echo "🗳️ Updating root JS packages..."
npm update --loglevel=silent --no-audit --no-fund | grep -v "up to date" || :
echo "🗃️ Updating CLI JS packages..."
npm --prefix cli update --loglevel=silent --no-audit --no-fund | grep -v "up to date" || :
echo "🔍 Checking for new versions (root)..."
ncu -u --loglevel silent 2>/dev/null | grep -v "All dependencies match" || :
echo "🔍 Checking for new versions (cli)..."
ncu -u --cwd "./cli" --loglevel silent 2>/dev/null | grep -v "All dependencies match" || :