diff --git a/.env.development b/.env.development index e9628ae4..420490a5 100644 --- a/.env.development +++ b/.env.development @@ -1 +1,2 @@ VITE_DEFAULT_ENDORSER_API_SERVER=http://127.0.0.1:3000 +VITE_PWA_ENABLED=true diff --git a/.env.production b/.env.production index bbf73a08..e6be236e 100644 --- a/.env.production +++ b/.env.production @@ -10,3 +10,4 @@ VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://timesafari.app +VITE_PWA_ENABLED=true diff --git a/.env.staging b/.env.test similarity index 96% rename from .env.staging rename to .env.test index a01c323c..ec1cfdfa 100644 --- a/.env.staging +++ b/.env.test @@ -11,3 +11,4 @@ VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app VITE_PASSKEYS_ENABLED=true +VITE_PWA_ENABLED=false diff --git a/BUILDING.md b/BUILDING.md index cde074d3..daaa767e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -83,7 +83,7 @@ TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari. rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari ``` -(Let's replace that with a .env.development or .env.staging file.) +(Let's replace that with a .env.development or .env.test file.) (Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.) diff --git a/Dockerfile b/Dockerfile index 9cc2543f..9ed80d9b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,10 @@ # # Build Process: # 1. Base stage: Node.js with build dependencies -# 2. Builder stage: Compile web assets with Vite +# 2. Builder stage: Copy pre-built web assets from host # 3. Production stage: Nginx server with optimized assets +# +# Note: Web assets are built on the host using npm scripts before Docker build # # Security Features: # - Non-root user execution @@ -14,25 +16,26 @@ # - No build dependencies in final image # # Usage: -# Production: docker build -t timesafari:latest . -# Staging: docker build --build-arg BUILD_MODE=staging -t timesafari:staging . -# Development: docker build --build-arg BUILD_MODE=development -t timesafari:dev . +# IMPORTANT: Build web assets first, then build Docker image +# +# Using npm scripts (recommended): +# Production: npm run build:web:docker:prod +# Test: npm run build:web:docker:test +# Development: npm run build:web:docker +# +# Manual workflow: +# 1. Build web assets: npm run build:web:build -- --mode production +# 2. Build Docker: docker build -t timesafari:latest . +# +# Note: For development, use npm run build:web directly (no Docker needed) # # Build Arguments: -# BUILD_MODE: development, staging, or production (default: production) +# BUILD_MODE: development, test, or production (default: production) # NODE_ENV: node environment (default: production) -# VITE_PLATFORM: vite platform (default: web) -# VITE_PWA_ENABLED: enable PWA (default: true) -# VITE_DISABLE_PWA: disable PWA (default: false) # # Environment Variables: # NODE_ENV: Build environment (development/production) -# VITE_APP_SERVER: Application server URL -# VITE_DEFAULT_ENDORSER_API_SERVER: Endorser API server URL -# VITE_DEFAULT_IMAGE_API_SERVER: Image API server URL -# VITE_DEFAULT_PARTNER_API_SERVER: Partner API server URL -# VITE_DEFAULT_PUSH_SERVER: Push notification server URL -# VITE_PASSKEYS_ENABLED: Enable passkeys feature +# BUILD_MODE: Build mode for asset selection (development/test/production) # ============================================================================= # BASE STAGE - Common dependencies and setup @@ -66,34 +69,20 @@ RUN npm ci --only=production --audit --fund=false && \ npm audit fix --audit-level=moderate || true # ============================================================================= -# BUILDER STAGE - Compile web assets +# BUILDER STAGE - Copy pre-built assets # ============================================================================= FROM base AS builder # Define build arguments with defaults ARG BUILD_MODE=production ARG NODE_ENV=production -ARG VITE_PLATFORM=web -ARG VITE_PWA_ENABLED=true -ARG VITE_DISABLE_PWA=false # Set environment variables from build arguments ENV BUILD_MODE=${BUILD_MODE} ENV NODE_ENV=${NODE_ENV} -ENV VITE_PLATFORM=${VITE_PLATFORM} -ENV VITE_PWA_ENABLED=${VITE_PWA_ENABLED} -ENV VITE_DISABLE_PWA=${VITE_DISABLE_PWA} - -# Install all dependencies (including dev dependencies) -RUN npm ci --audit --fund=false && \ - npm audit fix --audit-level=moderate || true - -# Copy source code -COPY . . -# Build the application with proper error handling -RUN echo "Building TimeSafari in ${BUILD_MODE} mode..." && \ - npm run build:web || (echo "Build failed. Check the logs above." && exit 1) +# Copy pre-built assets from host +COPY dist/ ./dist/ # Verify build output exists RUN ls -la dist/ || (echo "Build output not found in dist/ directory" && exit 1) @@ -150,52 +139,22 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ # Start nginx with proper signal handling CMD ["nginx", "-g", "daemon off;"] -# ============================================================================= -# DEVELOPMENT STAGE - For development with hot reloading -# ============================================================================= -FROM base AS development - -# Define build arguments for development stage -ARG BUILD_MODE=development -ARG NODE_ENV=development -ARG VITE_PLATFORM=web -ARG VITE_PWA_ENABLED=true -ARG VITE_DISABLE_PWA=false - -# Set environment variables -ENV BUILD_MODE=${BUILD_MODE} -ENV NODE_ENV=${NODE_ENV} -ENV VITE_PLATFORM=${VITE_PLATFORM} -ENV VITE_PWA_ENABLED=${VITE_PWA_ENABLED} -ENV VITE_DISABLE_PWA=${VITE_DISABLE_PWA} - -# Install all dependencies including dev dependencies -RUN npm ci --audit --fund=false && \ - npm audit fix --audit-level=moderate || true - -# Copy source code -COPY . . - -# Expose development port -EXPOSE 5173 -# Start development server -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] # ============================================================================= -# STAGING STAGE - For staging environment testing +# TEST STAGE - For test environment testing # ============================================================================= -FROM production AS staging +FROM production AS test -# Define build arguments for staging stage -ARG BUILD_MODE=staging -ARG NODE_ENV=staging +# Define build arguments for test stage +ARG BUILD_MODE=test +ARG NODE_ENV=test # Set environment variables ENV BUILD_MODE=${BUILD_MODE} ENV NODE_ENV=${NODE_ENV} -# Copy staging-specific nginx configuration +# Copy test-specific nginx configuration COPY docker/staging.conf /etc/nginx/conf.d/default.conf # Expose port 80 diff --git a/docker-compose.yml b/docker-compose.yml index f82980f5..7d6baa44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,24 +2,21 @@ # Author: Matthew Raymer # Description: Multi-environment Docker Compose setup for TimeSafari # +# IMPORTANT: Build web assets first using npm scripts before running docker-compose +# # Usage: -# Development: docker-compose up dev -# Staging: docker-compose up staging -# Production: docker-compose up production -# Custom: BUILD_MODE=staging docker-compose up custom +# Development: npm run build:web:build -- --mode development && docker-compose up dev +# Test: npm run build:web:build -- --mode test && docker-compose up test +# Production: npm run build:web:build -- --mode production && docker-compose up production +# Custom: BUILD_MODE=test npm run build:web:build -- --mode test && docker-compose up custom # # Environment Variables: -# BUILD_MODE: development, staging, or production (default: production) +# BUILD_MODE: development, test, or production (default: production) # NODE_ENV: node environment (default: production) -# VITE_PLATFORM: vite platform (default: web) -# VITE_PWA_ENABLED: enable PWA (default: true) -# VITE_DISABLE_PWA: disable PWA (default: false) -# PORT: port to expose (default: 80 for production, 5173 for dev) +# PORT: port to expose (default: 80 for production, 8080 for test) # ENV_FILE: environment file to use (default: .env.production) # -# See .env files for application-specific configuration -# VITE_APP_SERVER: Application server URL -# VITE_DEFAULT_ENDORSER_API_SERVER: Endorser API server URL +# Note: For development, use npm run build:web directly (no Docker needed) version: '3.8' @@ -31,9 +28,6 @@ x-defaults: &defaults args: BUILD_MODE: ${BUILD_MODE:-production} NODE_ENV: ${NODE_ENV:-production} - VITE_PLATFORM: ${VITE_PLATFORM:-web} - VITE_PWA_ENABLED: ${VITE_PWA_ENABLED:-true} - VITE_DISABLE_PWA: ${VITE_DISABLE_PWA:-false} restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] @@ -43,60 +37,23 @@ x-defaults: &defaults start_period: 40s services: - # Development service with hot reloading - dev: - <<: *defaults - build: - context: . - dockerfile: Dockerfile - target: development - args: - BUILD_MODE: development - NODE_ENV: development - VITE_PLATFORM: web - VITE_PWA_ENABLED: true - VITE_DISABLE_PWA: false - ports: - - "${DEV_PORT:-5173}:5173" - volumes: - - .:/app - - /app/node_modules - environment: - - NODE_ENV=development - - VITE_PLATFORM=web - - VITE_PWA_ENABLED=true - - VITE_DISABLE_PWA=false - env_file: - - ${DEV_ENV_FILE:-.env.development} - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:5173"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - # Staging service for testing - staging: + # Test service for testing environment + test: <<: *defaults build: context: . dockerfile: Dockerfile - target: staging + target: test args: - BUILD_MODE: staging - NODE_ENV: staging - VITE_PLATFORM: web - VITE_PWA_ENABLED: true - VITE_DISABLE_PWA: false + BUILD_MODE: test + NODE_ENV: test ports: - - "${STAGING_PORT:-8080}:80" + - "${TEST_PORT:-8080}:80" environment: - - NODE_ENV=staging - - VITE_PLATFORM=web - - VITE_PWA_ENABLED=true - - VITE_DISABLE_PWA=false + - NODE_ENV=test + - BUILD_MODE=test env_file: - - ${STAGING_ENV_FILE:-.env.staging} + - ${TEST_ENV_FILE:-.env.test} # Production service production: @@ -108,16 +65,11 @@ services: args: BUILD_MODE: production NODE_ENV: production - VITE_PLATFORM: web - VITE_PWA_ENABLED: true - VITE_DISABLE_PWA: false ports: - "${PROD_PORT:-80}:80" environment: - NODE_ENV=production - - VITE_PLATFORM=web - - VITE_PWA_ENABLED=true - - VITE_DISABLE_PWA=false + - BUILD_MODE=production env_file: - ${PROD_ENV_FILE:-.env.production} @@ -131,17 +83,12 @@ services: args: BUILD_MODE: production NODE_ENV: production - VITE_PLATFORM: web - VITE_PWA_ENABLED: true - VITE_DISABLE_PWA: false ports: - "${SSL_PORT:-443}:443" - "${HTTP_PORT:-80}:80" environment: - NODE_ENV=production - - VITE_PLATFORM=web - - VITE_PWA_ENABLED=true - - VITE_DISABLE_PWA=false + - BUILD_MODE=production env_file: - ${PROD_ENV_FILE:-.env.production} volumes: @@ -164,16 +111,11 @@ services: args: BUILD_MODE: ${BUILD_MODE:-production} NODE_ENV: ${NODE_ENV:-production} - VITE_PLATFORM: ${VITE_PLATFORM:-web} - VITE_PWA_ENABLED: ${VITE_PWA_ENABLED:-true} - VITE_DISABLE_PWA: ${VITE_DISABLE_PWA:-false} ports: - "${CUSTOM_PORT:-8080}:${CUSTOM_INTERNAL_PORT:-80}" environment: - NODE_ENV=${NODE_ENV:-production} - - VITE_PLATFORM=${VITE_PLATFORM:-web} - - VITE_PWA_ENABLED=${VITE_PWA_ENABLED:-true} - - VITE_DISABLE_PWA=${VITE_DISABLE_PWA:-false} + - BUILD_MODE=${BUILD_MODE:-production} env_file: - ${CUSTOM_ENV_FILE:-.env.production} healthcheck: diff --git a/docker/README.md b/docker/README.md index 83f5bc27..d28f52bf 100644 --- a/docker/README.md +++ b/docker/README.md @@ -121,7 +121,7 @@ Docker Compose supports these environment variables: | `STAGING_PORT` | `8080` | Staging port | | `PROD_PORT` | `80` | Production port | | `DEV_ENV_FILE` | `.env.development` | Development env file | -| `STAGING_ENV_FILE` | `.env.staging` | Staging env file | +| `TEST_ENV_FILE` | `.env.test` | Test env file | | `PROD_ENV_FILE` | `.env.production` | Production env file | ### Environment Files @@ -137,7 +137,7 @@ VITE_DEFAULT_PARTNER_API_SERVER=https://dev-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://dev.timesafari.app VITE_PASSKEYS_ENABLED=true -# .env.staging +# .env.test VITE_APP_SERVER=https://staging.timesafari.app VITE_DEFAULT_ENDORSER_API_SERVER=https://staging-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://staging-image-api.timesafari.app diff --git a/docs/build-pattern-conversion-plan.md b/docs/build-pattern-conversion-plan.md index 0a58247f..970bb8ad 100644 --- a/docs/build-pattern-conversion-plan.md +++ b/docs/build-pattern-conversion-plan.md @@ -2,7 +2,7 @@ **Author**: Matthew Raymer **Date**: 2025-07-09 -**Status**: 🎯 **PLANNING** - Ready for Implementation +**Status**: **PLANNING** - Ready for Implementation ## Overview @@ -12,7 +12,7 @@ management and consistency across all build targets. ## Why Vite Mode Instead of NODE_ENV? -### ✅ Vite's Native Mode System +### Vite's Native Mode System Vite is designed to work with `mode`, which: @@ -21,7 +21,7 @@ Vite is designed to work with `mode`, which: - Is used to set behavior for dev/prod/test at config level - Provides better integration with Vite's build system -### 🚫 NODE_ENV Limitations +### NODE_ENV Limitations `NODE_ENV` is legacy from Webpack-era tooling: @@ -33,23 +33,25 @@ Vite is designed to work with `mode`, which: ### Usage Pattern ```bash -# ✅ Correct: Use Vite's mode system +# Correct: Use Vite's mode system vite build --mode production vite build --mode development vite build --mode test -# ⚠️ Only if third-party libraries require NODE_ENV +# Only if third-party libraries require NODE_ENV NODE_ENV=production vite build --mode production ``` ### Development vs Build Environments **Development Environment:** + - **Build with defaults**: `npm run build:*` - Uses `--mode development` by default - **Purpose**: Development builds for testing and debugging - **Output**: Bundled files with development optimizations **Testing/Production Environments:** + - **Build with explicit mode**: `npm run build:* -- --mode test/production` - **Purpose**: Validate and deploy the bundled application - **Output**: Optimized, bundled files for specific environment @@ -76,6 +78,7 @@ npm run build:electron -- --mode production ``` **Key Points:** + - Base scripts have **no hardcoded `--mode`** to allow override - `npm run build:electron` defaults to `--mode development` - `npm run build:electron -- --mode test` overrides to `--mode test` @@ -98,6 +101,36 @@ npm run build:capacitor -- --mode production && npx cap sync android npm run build:capacitor -- --mode development && npx cap sync ios ``` +### Docker Build Commands + +Docker builds include both Vite asset generation and Docker image creation: + +```bash +# General Docker build (Vite build + Docker image) +npm run build:web:docker + +# Environment-specific Docker builds +npm run build:web:docker:test # Test environment + Docker image +npm run build:web:docker:prod # Production environment + Docker image + +# Manual mode overrides for Docker builds +npm run build:web:docker -- --mode test +npm run build:web:docker -- --mode production +``` + +**Docker Build Process:** + +1. **Vite Build**: Creates optimized web assets with environment-specific variables +2. **Docker Build**: Creates Docker image using `Dockerfile` in project root +3. **Image Tagging**: Images are tagged as `timesafari-web` for consistent management + +**Key Features:** + +- Complete end-to-end Docker workflow in single command +- Environment-aware builds (test/production configurations) +- Consistent image tagging for deployment +- Mode override flexibility for custom environments + ### Electron Platform-Specific Commands Electron requires platform-specific build commands after the Vite build: @@ -189,8 +222,12 @@ npm run build:capacitor -- --mode production && npx cap sync npm run build:electron -- --mode production # Docker builds -npm run build:web-docker -- --mode test -npm run build:web-docker -- --mode production +npm run build:web:docker -- --mode test +npm run build:web:docker -- --mode production + +# Docker environment-specific builds +npm run build:web:docker:test +npm run build:web:docker:prod # Capacitor platform-specific builds npm run build:capacitor:android -- --mode test @@ -221,11 +258,12 @@ npm run build:electron:dmg -- --mode production ```json { - "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", + "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite --mode development --config vite.config.web.mts", "build:web:dev": "npm run build:web", - "build:web:test": "npm run build:web -- --mode test", - "build:web:prod": "npm run build:web -- --mode production" - "build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", + "build:web:build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode development --config vite.config.web.mts", + "build:web:test": "npm run build:web:build -- --mode test", + "build:web:prod": "npm run build:web:build -- --mode production", + "build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .", "build:web:docker:test": "npm run build:web:docker -- --mode test", "build:web:docker:prod": "npm run build:web:docker -- --mode production", @@ -235,7 +273,7 @@ npm run build:electron:dmg -- --mode production "build:capacitor:android": "npm run build:capacitor:sync && npx cap sync android", "build:capacitor:ios": "npm run build:capacitor:sync && npx cap sync ios", - "build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.electron.mts", + "build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.electron.mts", "build:electron:dev": "npm run build:electron && cd electron && npm run electron:start", "build:electron:windows": "npm run build:electron && cd electron && npm run build:windows", "build:electron:mac": "npm run build:electron && cd electron && npm run build:mac", @@ -348,12 +386,19 @@ export default defineConfig(({ mode }) => { ```json { - "build:web-docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", - "build:web-docker-test": "npm run build:web-docker -- --mode test", - "build:web-docker-prod": "npm run build:web-docker -- --mode production" + "build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .", + "build:web:docker:test": "npm run build:web:docker -- --mode test", + "build:web:docker:prod": "npm run build:web:docker -- --mode production" } ``` +**Docker Build Features:** + +- Complete Vite build + Docker image creation workflow +- Environment-specific configurations (test/production) +- Consistent image tagging (`timesafari-web`) +- Mode override flexibility for custom environments + ### Phase 3: Shell Script Updates (Day 2) #### 3.1 Update build-electron.sh @@ -418,6 +463,8 @@ export default defineConfig(({ mode }) => { - [ ] Test electron appimage builds across environments - [ ] Test electron dmg builds across environments - [ ] Test docker builds across environments +- [ ] Test docker image creation and tagging +- [ ] Test docker environment-specific configurations #### 5.3 Integration Testing diff --git a/docs/playwright_mcp.md b/docs/playwright_mcp.md index f3ae6c48..3d5a2d17 100644 --- a/docs/playwright_mcp.md +++ b/docs/playwright_mcp.md @@ -36,7 +36,6 @@ First, install the Playwright MCP server with your client. A typical configurati [Install in VS Code](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [Install in VS Code Insiders](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) -
Install in VS Code You can also install the Playwright MCP server using the VS Code CLI: @@ -324,7 +323,7 @@ npx @playwright/mcp@latest --config path/to/config.json // List of origins to block the browser to request. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked. blockedOrigins?: string[]; }; - + /** * Do not send image responses to the client. */ @@ -791,5 +790,5 @@ X Y coordinate space, based on the provided screenshot.
- + diff --git a/package.json b/package.json index db6e0628..79bc1842 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,6 @@ "name": "Time Safari Team" }, "scripts": { - "dev": "vite --config vite.config.dev.mts --host", - "serve": "vite preview", - "build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.mts", - "build:optimized": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.optimized.mts", - "dev:optimized": "vite --config vite.config.optimized.mts --host", "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src", "lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src", "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", @@ -23,7 +18,19 @@ "check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)", "check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)", "build:capacitor": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode capacitor --config vite.config.capacitor.mts", - "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", + "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite --mode development --config vite.config.web.mts", + "build:web:dev": "npm run build:web", + "build:web:build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode development --config vite.config.web.mts", + "build:web:test": "npm run build:web:build -- --mode test", + "build:web:prod": "npm run build:web:build -- --mode production", + "build:web:docker": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts && docker build -t timesafari-web .", + "build:web:docker:test": "npm run build:web:docker -- --mode test", + "build:web:docker:prod": "npm run build:web:docker -- --mode production", + "docker:up": "docker-compose up", + "docker:up:test": "npm run build:web:build -- --mode test && docker-compose up test", + "docker:up:prod": "npm run build:web:build -- --mode production && docker-compose up production", + "docker:down": "docker-compose down", + "docker:logs": "docker-compose logs -f", "build:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --mode electron --config vite.config.electron.mts", "electron:dev": "npm run build:electron && npx cap copy electron && cd electron && npm run electron:start", "electron:setup": "./scripts/setup-electron.sh", diff --git a/scripts/format-markdown.sh b/scripts/format-markdown.sh new file mode 100755 index 00000000..1ce4a2ff --- /dev/null +++ b/scripts/format-markdown.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# format-markdown.sh +# Author: Matthew Raymer +# Date: 2025-07-09 +# Description: Format markdown files to comply with project markdown ruleset + +set -e + +if [ $# -eq 0 ]; then + echo "Usage: $0 [more files...]" + exit 1 +fi + +for target in "$@"; do + if [ -d "$target" ]; then + files=$(find "$target" -type f -name "*.md") + else + files="$target" + fi + for file in $files; do + # Remove trailing spaces + sed -i 's/[[:space:]]*$//' "$file" + # Remove multiple consecutive blank lines + awk 'NF{blank=0} !NF{blank++} blank<2' "$file" > "$file.tmp" && mv "$file.tmp" "$file" + # Ensure file ends with a single newline + awk '1; END{if (NR && $0!="") print ""}' "$file" > "$file.tmp" && mv "$file.tmp" "$file" + # Optionally run markdownlint (requires npx and markdownlint-cli) + if command -v npx >/dev/null 2>&1; then + npx markdownlint "$file" + else + echo "npx/markdownlint not found, skipping lint check for $file" + fi + done +done + +echo "Markdown formatting complete." \ No newline at end of file diff --git a/src/main.common.ts b/src/main.common.ts index 27d06333..bb33414a 100644 --- a/src/main.common.ts +++ b/src/main.common.ts @@ -10,8 +10,6 @@ import { FontAwesomeIcon } from "./libs/fontawesome"; import Camera from "simple-vue-camera"; import { logger } from "./utils/logger"; -// const platform = process.env.VITE_PLATFORM; -// const pwa_enabled = process.env.VITE_PWA_ENABLED === "true"; // Global Error Handler function setupGlobalErrorHandler(app: VueApp) { diff --git a/src/main.web.ts b/src/main.web.ts index 41863749..ff7e2097 100644 --- a/src/main.web.ts +++ b/src/main.web.ts @@ -4,17 +4,6 @@ import { logger } from "./utils/logger"; const platform = process.env.VITE_PLATFORM; const pwa_enabled = process.env.VITE_PWA_ENABLED === "true"; -// Only log SharedArrayBuffer info for web platform in development -if (platform === "web" && process.env.NODE_ENV !== "production") { - logger.debug( - `[SharedArrayBuffer] Available: ${typeof SharedArrayBuffer !== "undefined"}`, - ); - logger.debug(`[Browser] User Agent: ${navigator.userAgent}`); - logger.debug( - `[Headers] Check COOP/COEP in Network tab if SharedArrayBuffer is false`, - ); -} - // Only import service worker for web builds if (pwa_enabled) { import("./registerServiceWorker"); // Web PWA support diff --git a/vite.config.common.mts b/vite.config.common.mts index 16a0b22f..ecbfe693 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -11,16 +11,19 @@ dotenv.config(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -export async function createBuildConfig(mode: string): Promise { +export async function createBuildConfig(platform: string): Promise { const appConfig = await loadAppConfig(); - const isCapacitor = mode === "capacitor"; - const isElectron = mode === "electron"; + const isCapacitor = platform === "capacitor"; + const isElectron = platform === "electron"; const isNative = isCapacitor || isElectron; - // Set platform and disable PWA for native platforms - process.env.VITE_PLATFORM = mode; - process.env.VITE_PWA_ENABLED = isNative ? 'false' : 'true'; - process.env.VITE_DISABLE_PWA = isNative ? 'true' : 'false'; + // Set platform and configure PWA based on environment or platform + process.env.VITE_PLATFORM = platform; + + // Use .env file value if set, otherwise default based on platform + if (process.env.VITE_PWA_ENABLED === undefined) { + process.env.VITE_PWA_ENABLED = isNative ? 'false' : 'true'; + } if (isNative) { process.env.VITE_PWA_ENABLED = 'false'; @@ -59,9 +62,8 @@ export async function createBuildConfig(mode: string): Promise { }, define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), - 'process.env.VITE_PLATFORM': JSON.stringify(mode), + 'process.env.VITE_PLATFORM': JSON.stringify(platform), 'process.env.VITE_PWA_ENABLED': JSON.stringify(!isNative), - 'process.env.VITE_DISABLE_PWA': JSON.stringify(isNative), __dirname: JSON.stringify(process.cwd()), __IS_MOBILE__: JSON.stringify(isCapacitor), __IS_ELECTRON__: JSON.stringify(isElectron), diff --git a/vite.config.web.mts b/vite.config.web.mts index 738c2030..1774f362 100644 --- a/vite.config.web.mts +++ b/vite.config.web.mts @@ -3,11 +3,79 @@ import { VitePWA } from "vite-plugin-pwa"; import { createBuildConfig } from "./vite.config.common.mts"; import { loadAppConfig } from "./vite.config.utils.mts"; -export default defineConfig(async () => { +export default defineConfig(async ({ mode }) => { const baseConfig = await createBuildConfig('web'); const appConfig = await loadAppConfig(); + // Environment-specific configuration based on mode + const getEnvironmentConfig = (mode: string) => { + switch (mode) { + case 'production': + return { + // Production optimizations + build: { + minify: 'terser', + sourcemap: false, + rollupOptions: { + output: { + manualChunks: { + vendor: ['vue', 'vue-router', 'pinia'], + utils: ['luxon', 'ramda', 'zod'], + crypto: ['@ethersproject/wallet', '@ethersproject/hdnode', 'ethereum-cryptography'], + sql: ['@jlongster/sql.js', 'absurd-sql'] + } + } + } + }, + define: { + __DEV__: false, + __TEST__: false, + __PROD__: true + } + }; + case 'test': + return { + // Test environment configuration + build: { + minify: false, + sourcemap: true, + rollupOptions: { + output: { + manualChunks: undefined + } + } + }, + define: { + __DEV__: false, + __TEST__: true, + __PROD__: false + } + }; + default: // development + return { + // Development configuration + build: { + minify: false, + sourcemap: true, + rollupOptions: { + output: { + manualChunks: undefined + } + } + }, + define: { + __DEV__: true, + __TEST__: false, + __PROD__: false + } + }; + } + }; + + const environmentConfig = getEnvironmentConfig(mode); + return mergeConfig(baseConfig, { + ...environmentConfig, // Server configuration inherited from base config // CORS headers removed to allow images from any domain plugins: [ @@ -15,13 +83,13 @@ export default defineConfig(async () => { registerType: 'autoUpdate', manifest: appConfig.pwaConfig?.manifest, devOptions: { - enabled: false + enabled: mode === 'development' }, workbox: { cleanupOutdatedCaches: true, skipWaiting: true, clientsClaim: true, - sourcemap: true, + sourcemap: mode !== 'production', maximumFileSizeToCacheInBytes: 10 * 1024 * 1024 // 10MB } })