change directory

This commit is contained in:
John Overton
2025-04-21 08:59:06 -05:00
parent 53b3e9e99d
commit be585b2ccc
7 changed files with 0 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
# This script creates a backup of the project directory
# It stops the service before backup and starts it afterward
# Excludes .next and node_modules directories
# Get the directory name of the project and its parent
PROJECT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
PARENT_DIR=$(dirname "$PROJECT_DIR")
PROJECT_NAME=$(basename "$PROJECT_DIR")
BACKUP_DIR="${PARENT_DIR}/${PROJECT_NAME}_backup_$(date +%Y%m%d_%H%M%S)"
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# Stop the service before backup
echo "Stopping service before backup..."
"$SCRIPT_DIR/service.sh" stop
if [ $? -ne 0 ]; then
echo "Error: Failed to stop service!"
exit 1
fi
# Create backup
echo "Creating backup in $BACKUP_DIR..."
mkdir -p "$BACKUP_DIR"
# Exclude .next, node_modules, and the backup directory itself when copying
rsync -av --exclude='.next' --exclude='node_modules' --exclude="*_backup_*" "$PROJECT_DIR/" "$BACKUP_DIR/"
BACKUP_STATUS=$?
# Start the service after backup
echo "Starting service after backup..."
"$SCRIPT_DIR/service.sh" start
if [ $BACKUP_STATUS -eq 0 ]; then
echo "Backup completed successfully!"
echo "Backup location: $BACKUP_DIR"
else
echo "Error: Backup failed!"
exit 1
fi
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# This script performs a full deployment:
# 1. Creates a backup
# 2. Stops the service
# 3. Deletes the .next folder
# 4. Updates the application
# Service management is handled by the individual scripts
# Get the script directory and project directory
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
echo "Starting deployment process..."
# Step 1: Create backup
echo "Step 1: Creating backup..."
"$SCRIPT_DIR/backup.sh"
if [ $? -ne 0 ]; then
echo "Error: Backup failed! Deployment aborted."
exit 1
fi
# Step 2: Stop the service
echo "Step 2: Stopping service..."
"$SCRIPT_DIR/service.sh" stop
if [ $? -ne 0 ]; then
echo "Error: Failed to stop service! Deployment aborted."
exit 1
fi
# Step 3: Delete .next folder
echo "Step 3: Deleting .next folder..."
if [ -d "$PROJECT_DIR/.next" ]; then
rm -rf "$PROJECT_DIR/.next"
echo ".next folder deleted successfully."
else
echo ".next folder not found, continuing deployment."
fi
# Step 4: Update application
echo "Step 4: Updating application..."
"$SCRIPT_DIR/update.sh"
if [ $? -ne 0 ]; then
echo "Error: Update failed! Deployment aborted."
"$SCRIPT_DIR/service.sh" start # Try to restart service even if update failed
exit 1
fi
echo "Deployment completed successfully!"
echo "Use '$SCRIPT_DIR/service.sh status' to check service status."
+230
View File
@@ -0,0 +1,230 @@
#!/bin/bash
# This script helps with Docker setup and management for Sprout Track
# It provides commands for building, starting, stopping, and managing the Docker containers
# Get the project directory (one level up from the script location)
PROJECT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
cd "$PROJECT_DIR" || exit 1
# Function to display usage information
show_usage() {
echo "Sprout Track Docker Management Script"
echo ""
echo "Usage: $0 [command]"
echo ""
echo "Commands:"
echo " build Build the Docker image"
echo " start Start the Docker containers"
echo " stop Stop the Docker containers"
echo " restart Restart the Docker containers"
echo " update Update the container with latest code and run migrations"
echo " backup Create a backup of the database volume"
echo " logs View container logs"
echo " status Check container status"
echo " clean Remove containers, images, and volumes (caution: data loss)"
echo " help Show this help message"
echo ""
echo "Environment Variables:"
echo " PORT Port to expose the application (default: 3000)"
echo ""
echo "Examples:"
echo " $0 build # Build the Docker image"
echo " PORT=8080 $0 start # Start containers with custom port"
}
# Check if Docker is installed
check_docker() {
if ! command -v docker &> /dev/null; then
echo "Error: Docker is not installed or not in PATH"
echo "Please install Docker and try again"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo "Error: docker-compose is not installed or not in PATH"
echo "Please install docker-compose and try again"
exit 1
fi
}
# Build the Docker image
build_image() {
echo "Building Sprout Track Docker image..."
docker-compose build
}
# Start the Docker containers
start_containers() {
echo "Starting Sprout Track containers..."
docker-compose up -d
echo "Containers started. The application should be available at:"
echo " http://localhost:${PORT:-3000}"
}
# Stop the Docker containers
stop_containers() {
echo "Stopping Sprout Track containers..."
docker-compose down
}
# Restart the Docker containers
restart_containers() {
echo "Restarting Sprout Track containers..."
docker-compose restart
}
# View container logs
view_logs() {
echo "Viewing Sprout Track container logs..."
docker-compose logs -f
}
# Check container status
check_status() {
echo "Checking Sprout Track container status..."
docker-compose ps
}
# Create a backup of the database volume
backup_database() {
echo "Creating backup of the database volume..."
# Get current timestamp for backup filename
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${PROJECT_DIR}/backups"
BACKUP_FILE="${BACKUP_DIR}/sprout-track-db-${TIMESTAMP}.tar"
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Check if the container is running
if docker-compose ps | grep -q "sprout-track"; then
# Create a temporary container to access the volume and create a backup
echo "Creating backup from volume..."
docker run --rm \
--volumes-from sprout-track \
-v "${BACKUP_DIR}:/backup" \
alpine \
tar -cf "/backup/sprout-track-db-${TIMESTAMP}.tar" /db
if [ $? -eq 0 ]; then
echo "Backup completed successfully!"
echo "Backup location: $BACKUP_FILE"
else
echo "Error: Backup failed!"
return 1
fi
else
echo "Error: Container is not running. Start the container first."
return 1
fi
return 0
}
# Update the container with latest code and run migrations
update_container() {
echo "Updating Sprout Track container..."
# Pull latest changes from git
echo "Pulling latest changes from git..."
cd "$PROJECT_DIR" || exit 1
git pull
if [ $? -ne 0 ]; then
echo "Error: Git pull failed!"
return 1
fi
# Create a backup before updating
echo "Creating backup before update..."
backup_database
if [ $? -ne 0 ]; then
echo "Warning: Backup failed, but continuing with update..."
fi
# Rebuild the Docker image with the latest code
echo "Rebuilding Docker image..."
docker-compose build
if [ $? -ne 0 ]; then
echo "Error: Docker build failed!"
return 1
fi
# Stop the container
echo "Stopping container..."
docker-compose down
if [ $? -ne 0 ]; then
echo "Error: Failed to stop container!"
return 1
fi
# Start the container with the new image
# This will automatically run migrations on startup due to our entrypoint script
echo "Starting container with new image..."
docker-compose up -d
if [ $? -ne 0 ]; then
echo "Error: Failed to start container!"
return 1
fi
echo "Update completed successfully!"
echo "The application should be available at:"
echo " http://localhost:${PORT:-3000}"
echo "Check logs with: $0 logs"
return 0
}
# Clean up Docker resources
clean_resources() {
echo "WARNING: This will remove all Sprout Track Docker resources, including data volumes."
read -p "Are you sure you want to continue? (y/N): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
echo "Removing Sprout Track containers, images, and volumes..."
docker-compose down -v
docker rmi sprout-track
echo "Cleanup completed."
else
echo "Cleanup cancelled."
fi
}
# Main script logic
check_docker
case "$1" in
build)
build_image
;;
start)
start_containers
;;
stop)
stop_containers
;;
restart)
restart_containers
;;
update)
update_container
;;
backup)
backup_database
;;
logs)
view_logs
;;
status)
check_status
;;
clean)
clean_resources
;;
help|*)
show_usage
;;
esac
exit 0
+172
View File
@@ -0,0 +1,172 @@
/**
* Improved script to check and update all time fields in the database to UTC
* Run with: node scripts/ensure-utc-dates-improved.js
*
* This version has improved DST handling and more reliable UTC detection
*/
import { PrismaClient } from '@prisma/client';
import { execSync } from 'child_process';
const prisma = new PrismaClient();
// Models and their date fields
const dateFieldsByModel = {
Baby: ['birthDate', 'createdAt', 'updatedAt', 'deletedAt'],
Caretaker: ['createdAt', 'updatedAt', 'deletedAt'],
SleepLog: ['startTime', 'endTime', 'createdAt', 'updatedAt', 'deletedAt'],
FeedLog: ['time', 'startTime', 'endTime', 'createdAt', 'updatedAt', 'deletedAt'],
DiaperLog: ['time', 'createdAt', 'updatedAt', 'deletedAt'],
MoodLog: ['time', 'createdAt', 'updatedAt', 'deletedAt'],
Note: ['time', 'createdAt', 'updatedAt', 'deletedAt'],
Settings: ['createdAt', 'updatedAt'],
Milestone: ['date', 'createdAt', 'updatedAt', 'deletedAt'],
PumpLog: ['startTime', 'endTime', 'createdAt', 'updatedAt', 'deletedAt'],
PlayLog: ['startTime', 'endTime', 'createdAt', 'updatedAt', 'deletedAt'],
BathLog: ['time', 'createdAt', 'updatedAt', 'deletedAt'],
Measurement: ['date', 'createdAt', 'updatedAt', 'deletedAt'],
Unit: ['createdAt', 'updatedAt']
};
/**
* Get the system timezone directly
* @returns The detected system timezone string
*/
function getSystemTimezone() {
try {
// Try to get timezone from process.env.TZ
if (process.env.TZ) {
return process.env.TZ;
}
// Different commands based on platform
if (process.platform === 'darwin') { // macOS
const tzOutput = execSync('systemsetup -gettimezone').toString().trim();
// Extract timezone from "Time Zone: America/Denver" format
const match = tzOutput.match(/Time Zone: (.+)$/);
if (match && match[1]) {
return match[1];
}
} else if (process.platform === 'linux') {
return execSync('cat /etc/timezone').toString().trim();
}
// Fallback to Intl API for Windows or other platforms
return Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (error) {
console.error('Error detecting system timezone:', error);
// Fallback to a safe default if detection fails
return 'UTC';
}
}
/**
* Check if a date is in UTC
* This improved version is more reliable during DST transitions
* @param date The date to check
* @returns True if the date is in UTC, false otherwise
*/
function isUtcDate(date) {
if (!(date instanceof Date)) {
return false;
}
// Get the ISO string representation
const isoString = date.toISOString();
// Create a new Date from the ISO string
// This will be in UTC by definition
const utcDate = new Date(isoString);
// Compare the time values directly
// If they're the same, the original date was in UTC
return date.getTime() === utcDate.getTime();
}
/**
* Convert a date to UTC
* @param date The date to convert
* @returns The date in UTC
*/
function toUtc(date) {
// Create a new date from the ISO string, which is always in UTC
return new Date(date.toISOString());
}
/**
* Process a model to ensure all date fields are in UTC
* @param modelName The name of the model to process
*/
async function processModel(modelName) {
console.log(`Processing ${modelName}...`);
const dateFields = dateFieldsByModel[modelName];
if (!dateFields || dateFields.length === 0) {
console.log(`No date fields found for ${modelName}`);
return;
}
// Get all records for the model
const records = await prisma[modelName.charAt(0).toLowerCase() + modelName.slice(1)].findMany();
console.log(`Found ${records.length} records for ${modelName}`);
let updatedCount = 0;
// Process each record
for (const record of records) {
const updates = {};
let needsUpdate = false;
// Check each date field
for (const field of dateFields) {
const date = record[field];
if (date && date instanceof Date) {
if (!isUtcDate(date)) {
updates[field] = toUtc(date);
needsUpdate = true;
console.log(`Converting ${field} for ${modelName} record ${record.id}`);
}
}
}
// Update the record if needed
if (needsUpdate) {
try {
await prisma[modelName.charAt(0).toLowerCase() + modelName.slice(1)].update({
where: { id: record.id },
data: updates
});
updatedCount++;
} catch (error) {
console.error(`Error updating ${modelName} record ${record.id}:`, error);
}
}
}
console.log(`Updated ${updatedCount} records for ${modelName}`);
}
/**
* Main function to process all models
*/
async function main() {
console.log('Starting UTC date conversion...');
console.log(`System timezone: ${getSystemTimezone()}`);
// Process each model
for (const modelName of Object.keys(dateFieldsByModel)) {
await processModel(modelName);
}
console.log('UTC date conversion complete!');
}
// Run the main function
main()
.catch(e => {
console.error('Error in UTC date conversion:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
# This script manages the service operations (start/stop)
# The service name should be configured in the .env file
# Get the directory name of the project (one level up from the script location)
PROJECT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
# Read service name from .env file
if [ ! -f "$PROJECT_DIR/.env" ]; then
echo "Error: .env file not found!"
exit 1
fi
SERVICE_NAME=$(grep "SERVICE_NAME" "$PROJECT_DIR/.env" | cut -d '"' -f 2)
if [ -z "$SERVICE_NAME" ]; then
echo "Error: SERVICE_NAME not found in .env file!"
exit 1
fi
# Function to start the service
start_service() {
echo "Starting $SERVICE_NAME service..."
sudo systemctl start "$SERVICE_NAME"
echo "Service started successfully!"
}
# Function to stop the service
stop_service() {
echo "Stopping $SERVICE_NAME service..."
sudo systemctl stop "$SERVICE_NAME"
echo "Service stopped successfully!"
}
# Function to show service status
status_service() {
echo "Checking $SERVICE_NAME service status..."
sudo systemctl status "$SERVICE_NAME"
}
# Check command line arguments
case "$1" in
start)
start_service
;;
stop)
stop_service
;;
restart)
stop_service
start_service
;;
status)
status_service
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
exit 0
+100
View File
@@ -0,0 +1,100 @@
#!/bin/bash
# This script performs the initial setup for the Sprout Track application:
# 1. Checks for Node.js installation (must be installed beforehand)
# 2. Installs dependencies
# 3. Generates the Prisma client
# 4. Runs database migrations (creates the database schema)
# 5. Seeds the database with initial data (creates default settings with PIN 111222 and adds units)
# 6. Builds the Next.js application
# Get the project directory (one level up from the script location)
PROJECT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
cd "$PROJECT_DIR" || exit 1
echo "Starting Sprout Track setup..."
# Step 1: Check if Node.js is installed
echo "Step 1: Checking for Node.js installation..."
# Check if node is installed
if command -v node &> /dev/null; then
NODE_VERSION=$(node -v)
echo "Node.js is installed (${NODE_VERSION})."
# Check if npm is installed
if command -v npm &> /dev/null; then
NPM_VERSION=$(npm -v)
echo "npm is installed (${NPM_VERSION})."
else
echo "Error: npm is not installed! Please install npm before running this script."
exit 1
fi
else
echo "Error: Node.js is not installed! Please install Node.js (v22 recommended) before running this script."
echo "Visit https://nodejs.org/ for installation instructions."
exit 1
fi
# Step 2: Install dependencies
echo "Step 2: Installing dependencies..."
npm install
if [ $? -ne 0 ]; then
echo "Error: npm install failed! Setup aborted."
exit 1
fi
echo "Dependencies installed successfully."
# Disable Next.js telemetry
echo "Disabling Next.js telemetry..."
npm exec next telemetry disable
echo "Next.js telemetry disabled."
# Step 3: Generate Prisma client
echo "Step 3: Generating Prisma client..."
npm run prisma:generate
if [ $? -ne 0 ]; then
echo "Error: Prisma client generation failed! Setup aborted."
exit 1
fi
echo "Prisma client generated successfully."
# Step 4: Run database migrations
echo "Step 4: Running database migrations..."
npm run prisma:migrate
if [ $? -ne 0 ]; then
echo "Error: Prisma migrations failed! Setup aborted."
exit 1
fi
echo "Database migrations applied successfully."
# Step 5: Seed the database (creates default settings with PIN 111222)
echo "Step 5: Seeding the database with default settings and units..."
npm run prisma:seed
if [ $? -ne 0 ]; then
echo "Error: Database seeding failed! Setup aborted."
exit 1
fi
echo "Database seeded successfully with default settings (PIN: 111222) and units."
# Step 6: Build the Next.js application
echo "Step 6: Building the Next.js application..."
npm run build
if [ $? -ne 0 ]; then
echo "Error: Build process failed! Setup aborted."
exit 1
fi
echo "Next.js application built successfully."
echo "-------------------------------------"
echo "Sprout Track setup completed successfully!"
echo "Default security PIN: 111222"
echo ""
echo "To run the development server:"
echo " npm run dev"
echo ""
echo "To run the production server:"
echo " npm run start"
echo "-------------------------------------"
exit 0
+97
View File
@@ -0,0 +1,97 @@
#!/bin/bash
# This script updates the application:
# - Pulls latest changes from git
# - Runs Prisma operations
# - Builds the application
# Get the directory name of the project (one level up from the script location)
PROJECT_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# Stop the service before update
echo "Stopping service before update..."
"$SCRIPT_DIR/service.sh" stop
if [ $? -ne 0 ]; then
echo "Error: Failed to stop service!"
exit 1
fi
# Stash any local changes before pulling
echo "Stashing any local changes..."
cd "$PROJECT_DIR" || exit 1
git stash
STASH_RESULT=$?
# Pull latest changes from git
echo "Pulling latest changes from git..."
git pull
if [ $? -ne 0 ]; then
echo "Error: Git pull failed!"
# Apply stashed changes if there were any
if [ $STASH_RESULT -eq 0 ]; then
echo "Applying stashed changes..."
git stash pop
fi
"$SCRIPT_DIR/service.sh" start
exit 1
fi
# Apply stashed changes if there were any
if [ $STASH_RESULT -eq 0 ]; then
echo "Applying stashed changes..."
git stash pop
# Note: We continue even if there are conflicts
fi
# Install dependencies
echo "Installing dependencies..."
npm install
if [ $? -ne 0 ]; then
echo "Error: npm install failed!"
"$SCRIPT_DIR/service.sh" start
exit 1
fi
# Generate Prisma client
echo "Generating Prisma client..."
npm run prisma:generate
if [ $? -ne 0 ]; then
echo "Error: Prisma client generation failed!"
"$SCRIPT_DIR/service.sh" start
exit 1
fi
# Run Prisma migrations
echo "Running database migrations..."
npm run prisma:migrate
if [ $? -ne 0 ]; then
echo "Error: Prisma migrations failed!"
"$SCRIPT_DIR/service.sh" start
exit 1
fi
# Seed the database with any new data
echo "Seeding the database with any new settings and units..."
npm run prisma:seed
if [ $? -ne 0 ]; then
echo "Error: Database seeding failed!"
"$SCRIPT_DIR/service.sh" start
exit 1
fi
# Build the application
echo "Building the application..."
npm run build
BUILD_STATUS=$?
# Start the service after update
echo "Starting service after update..."
"$SCRIPT_DIR/service.sh" start
if [ $BUILD_STATUS -eq 0 ]; then
echo "Update completed successfully!"
else
echo "Error: Build failed!"
exit 1
fi