diff --git a/.cursor/rules/app/timesafari_development.mdc b/.cursor/rules/app/timesafari_development.mdc index e72c68dc..2806dbc0 100644 --- a/.cursor/rules/app/timesafari_development.mdc +++ b/.cursor/rules/app/timesafari_development.mdc @@ -11,7 +11,7 @@ # Web (development) -npm run build:web +npm run dev # Mobile diff --git a/.cursor/rules/app/timesafari_platforms.mdc b/.cursor/rules/app/timesafari_platforms.mdc index c31f2222..787a948c 100644 --- a/.cursor/rules/app/timesafari_platforms.mdc +++ b/.cursor/rules/app/timesafari_platforms.mdc @@ -13,7 +13,7 @@ - **File System**: Limited browser APIs -- **Build**: `npm run build:web` (development build) +- **Build**: `npm run dev` (development server), `npm run build:web` (production build into `dist/`) ### Mobile (Capacitor) @@ -59,7 +59,7 @@ # Web (development) -npm run build:web +npm run dev # Mobile diff --git a/.cursor/rules/architecture/build_testing.mdc b/.cursor/rules/architecture/build_testing.mdc index 4d0301dc..142674a6 100644 --- a/.cursor/rules/architecture/build_testing.mdc +++ b/.cursor/rules/architecture/build_testing.mdc @@ -39,7 +39,7 @@ ### Rollback Verification -- **Web**: `npm run build:web:dev` and `npm run build:web:prod` +- **Web**: `npm run dev` and `npm run build:web:prod` - **Mobile**: `npm run build:android:test` and `npm run build:ios:test` diff --git a/.cursor/rules/architecture/build_validation.mdc b/.cursor/rules/architecture/build_validation.mdc index da78c63f..91d4dac6 100644 --- a/.cursor/rules/architecture/build_validation.mdc +++ b/.cursor/rules/architecture/build_validation.mdc @@ -19,7 +19,7 @@ ### After Build System Change -- [ ] **Web Platform**: Does `npm run build:web:dev` work? +- [ ] **Web Platform**: Does `npm run dev` work? - [ ] **Mobile Platforms**: Do iOS/Android builds succeed? @@ -33,7 +33,7 @@ ### Web Platform -- **Development**: `npm run build:web:dev` - serve and load app +- **Development**: `npm run dev` - serve and load app - **Production**: `npm run build:web:prod` - verify SW and WASM present diff --git a/.env.test b/.env.test index 19e23299..55f9a316 100644 --- a/.env.test +++ b/.env.test @@ -5,7 +5,7 @@ VITE_LOG_LEVEL=info # iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Test" -VITE_APP_SERVER=https://test.timesafari.app +VITE_APP_SERVER=https://test.` # This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not # This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). diff --git a/BUILDING.md b/BUILDING.md index 34593c5c..b70adeee 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -9,9 +9,9 @@ This guide explains how to build TimeSafari for different platforms using the co ```bash # 🖥️ Web Development npm install # setup -- and pkgx.dev `dev` command before this will set environment with npm, etc -npm run build:web:serve -- --test # Start with test endorser server npm run dev # Start development server with hot reload with local endorser server -npm run build:web:prod # Production build +npm run build:web:serve:test # Test build served from dist/ (test endorser server) +npm run build:web # Production build into dist/ # 📱 Mobile Development npm run build:ios # iOS build (opens Xcode) @@ -225,30 +225,35 @@ npm install ```bash # Local development -npm run dev # Start development server with hot reload (shortcut for `build:web:dev`) +npm run dev # Start development server with hot reload (writes nothing to dist/) -# Web builds -npm run build:web # Development build (starts dev server with hot reload) +# Web builds (each one writes dist/) +npm run build:web # Production build (same as build:web:prod) npm run build:web:test # Test environment build (optimized for testing) npm run build:web:prod # Production build (optimized for production) -npm run build:web:serve # Build and serve locally for production testing + +# Build, then serve dist/ locally +npm run build:web:serve # Production build, then serve +npm run build:web:serve:test # Test build, then serve # Docker builds -npm run build:web:docker # Development build with Docker containerization +npm run build:web:docker # Production build with Docker containerization npm run build:web:docker:test # Test build with Docker containerization npm run build:web:docker:prod # Production build with Docker containerization ``` ### Local Development -Start the development server using `npm run dev` (a shortcut for `npm run build:web:dev`) or `npm run build:web` (both start the development server with hot reload). +Start the development server with hot reload using `npm run dev`. Open it at `http://localhost:8080/`, not at a wildcard address such as `http://[::]:8080/` or `http://0.0.0.0:8080/`: browsers only allow the cryptography the app needs on HTTPS, `localhost`, `127.0.0.1`, or `[::1]`, so any other plain-HTTP address shows a "Cannot Start Here" page. ### Web Build for Server -1. Run the production build using `npm run build:web:prod` +1. Run the production build using `npm run build:web` (or `npm run build:web:test` for the test server) 2. The built files will be in the `dist` directory 3. To test the production build locally, use `npm run build:web:serve` (builds then serves) +`dist/` is shared with the Android, iOS, Electron, and Capacitor builds, which overwrite it with non-web output. Run the web build immediately before deploying, and confirm that the browser console reports `Loading TimeSafari for platform: web`. + **Why Use `serve`?** - **Production Testing**: Test your optimized production build locally before deployment - **SPA Routing Validation**: Verify deep linking and navigation work correctly (handles routes like `/discover`, `/account`) @@ -1603,8 +1608,7 @@ Use the commands above to check and fix code quality issues. 1. **Environment Setup**: Load platform-specific environment variables 2. **Asset Building**: Vite builds optimized web assets -3. **PWA Generation**: Service worker and manifest creation -4. **Output**: Production-ready files in `dist/` directory +3. **Output**: Production-ready files in `dist/` directory ### Electron Build Process @@ -1880,14 +1884,14 @@ npx prettier --write ./sw_scripts/ The `prebuild` script automatically runs before any build: ```json -"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js" +"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node scripts/copy-wasm.js" ``` -**What happens automatically:** +npm runs `prebuild` only before a script named `build`. This project defines no `build` script, so none of the `build:*` commands trigger it. -- **ESLint**: Checks and fixes code formatting in `src/` -- **Script Combination**: `sw_combine.js` combines all `sw_scripts/*.js` files - into `sw_scripts-combined.js` +**What it does when run:** + +- **ESLint**: Checks code formatting in `src/` - **WASM Copy**: `copy-wasm.js` copies SQLite WASM files to `public/wasm/` #### Build Process Architecture @@ -1897,9 +1901,8 @@ The `prebuild` script automatically runs before any build: ```text 1. Pre-Build: ESLint + Script Combination + WASM Copy 2. Environment Setup: Load .env files, set NODE_ENV -3. Vite Build: Bundle web assets with PWA support -4. Service Worker: Inject combined scripts into PWA -5. Output: Production-ready files in dist/ +3. Vite Build: Bundle web assets +4. Output: Production-ready files in dist/ ``` **Electron Build Process:** @@ -2062,31 +2065,34 @@ environment setup, Vite build, and optional Docker containerization. ```bash # Direct script usage -./scripts/build-web.sh # Development build -./scripts/build-web.sh --dev # Development build (explicit) +./scripts/build-web.sh # Production build into dist/ +./scripts/build-web.sh --prod # Production build (explicit) ./scripts/build-web.sh --test # Test environment build -./scripts/build-web.sh --prod # Production environment build -./scripts/build-web.sh --docker # Build with Docker containerization +./scripts/build-web.sh --dev # Start Vite dev server (no dist/) +./scripts/build-web.sh --docker # Production build + Docker image ./scripts/build-web.sh --docker:test # Test environment + Docker ./scripts/build-web.sh --docker:prod # Production environment + Docker -./scripts/build-web.sh --serve # Build and serve locally +./scripts/build-web.sh --serve # Production build, then serve dist/ ./scripts/build-web.sh --help # Show help ./scripts/build-web.sh --verbose # Enable verbose logging # NPM Script Equivalents -npm run build:web # Development build +npm run dev # Vite dev server +npm run build:web # Production build npm run build:web:test # Test environment build npm run build:web:prod # Production environment build -npm run build:web:docker # Docker build +npm run build:web:docker # Production Docker build npm run build:web:docker:test # Test Docker build npm run build:web:docker:prod # Production Docker build +npm run build:web:serve # Production build, then serve +npm run build:web:serve:test # Test build, then serve ``` **Build Modes**: -- **Development**: Starts Vite dev server with hot reload (default) +- **Production**: Optimized for production with full minification (default) - **Test**: Optimized for testing with minimal minification -- **Production**: Optimized for production with full minification +- **Development**: Starts Vite dev server with hot reload (`--dev` alone); with `--serve` or `--docker`, builds `dist/` in development mode **Script Features**: diff --git a/CHANGELOG.md b/CHANGELOG.md index 91a60779..19f35156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Changed +- Various npm build script inconsistencies were modified + + ## [1.4.9] - 2026.10.11 ### Fixed - Startup DB error for new installations diff --git a/Dockerfile b/Dockerfile index 81e0a635..e4cac088 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,13 +21,13 @@ # Using npm scripts (recommended): # Production: npm run build:web:docker:prod # Test: npm run build:web:docker:test -# Development: npm run build:web:docker +# Development: ./scripts/build-web.sh --docker --dev # # Manual workflow: -# 1. Build web assets: npm run build:web:build -- --mode production +# 1. Build web assets: npm run build:web:prod # 2. Build Docker: docker build -t timesafari:latest . # -# Note: For development, use npm run build:web directly (no Docker needed) +# Note: For development, use npm run dev directly (no Docker needed) # # Build Arguments: # BUILD_MODE: development, test, or production (default: production) diff --git a/docker-compose.yml b/docker-compose.yml index 7d6baa44..50240b8a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,10 +5,9 @@ # IMPORTANT: Build web assets first using npm scripts before running docker-compose # # Usage: -# 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 +# Test: npm run docker:up:test (runs npm run build:web:test && docker-compose up test) +# Production: npm run docker:up:prod (runs npm run build:web:prod && docker-compose up production) +# Custom: npm run build:web:test && BUILD_MODE=test docker-compose up custom # # Environment Variables: # BUILD_MODE: development, test, or production (default: production) @@ -16,7 +15,7 @@ # PORT: port to expose (default: 80 for production, 8080 for test) # ENV_FILE: environment file to use (default: .env.production) # -# Note: For development, use npm run build:web directly (no Docker needed) +# Note: For development, use npm run dev directly (no Docker needed) version: '3.8' diff --git a/package.json b/package.json index 513565ad..41b4ab2a 100644 --- a/package.json +++ b/package.json @@ -90,9 +90,8 @@ "build:ios:test:custom": "./scripts/build-ios.sh --test --api-ip", "build:ios:test:run": "./scripts/build-ios.sh --test --auto-run", "build:ios:test:run:custom": "./scripts/build-ios.sh --test --api-ip --auto-run", - "build:native": "vite build && npx cap sync && node scripts/restore-local-plugins.js && bash -c 'source scripts/common.sh && ensure_ios_capacitor_asset_directories' && npx capacitor-assets generate --assetPath resources", + "build:native": "npm run build:capacitor:sync && bash -c 'source scripts/common.sh && ensure_ios_capacitor_asset_directories' && npx capacitor-assets generate --assetPath resources", "build:web": "./scripts/build-web.sh", - "build:web:dev": "./scripts/build-web.sh --dev", "build:web:docker": "./scripts/build-web.sh --docker", "build:web:docker:prod": "./scripts/build-web.sh --docker:prod", "build:web:docker:test": "./scripts/build-web.sh --docker:test", @@ -110,12 +109,12 @@ "clean:electron": "./scripts/build-electron.sh --clean", "clean:ios": "rm -rf ios/App/build ios/App/Pods ios/App/output ios/App/App/public ios/DerivedData ios/capacitor-cordova-ios-plugins ios/App/App/capacitor.config.json ios/App/App/config.xml || true", "deps:update-daily-notification-plugin": "npm install @timesafari/daily-notification-plugin@git+https://gitea.anomalistdesign.com/trent_larson/daily-notification-plugin.git#master", - "dev": "npm run build:web:dev", + "dev": "./scripts/build-web.sh --dev", "docker:down": "docker-compose down", "docker:logs": "docker-compose logs -f", "docker:up": "docker-compose up", - "docker:up:prod": "npm run build:web:build -- --mode production && docker-compose up production", - "docker:up:test": "npm run build:web:build -- --mode test && docker-compose up test", + "docker:up:prod": "npm run build:web:prod && docker-compose up production", + "docker:up:test": "npm run build:web:test && docker-compose up test", "guard": "bash ./scripts/build-arch-guard.sh", "guard:setup": "npm run prepare && echo 'Build Architecture Guard is now active!'", "guard:test": "bash ./scripts/build-arch-guard.sh --staged", @@ -124,7 +123,7 @@ "markdown:check": "markdownlint-cli2", "markdown:fix": "markdownlint-cli2 --fix", "markdown:setup": "./scripts/setup-markdown-hooks.sh", - "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js", + "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node scripts/copy-wasm.js", "prepare": "husky", "test:all": "npm run lint && npm run type-check && npm run type-check:vue && npm run test:unit && npm run test:web && npm run test:mobile && echo '\n\n\nGotta add the performance tests'", "test:android": "node scripts/test-android.js", diff --git a/playwright.config-local.ts b/playwright.config-local.ts index acb8d49d..c358735e 100644 --- a/playwright.config-local.ts +++ b/playwright.config-local.ts @@ -106,7 +106,7 @@ export default defineConfig({ */ webServer: { command: - "VITE_APP_SERVER=http://localhost:8080 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build:web -- --port=8080", + "VITE_APP_SERVER=http://localhost:8080 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run dev", url: "http://localhost:8080", reuseExistingServer: !process.env.CI, }, diff --git a/pull_request_template.md b/pull_request_template.md index 8739bdbd..8f0f9441 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -15,7 +15,7 @@ ## Commands Run (paste exact logs/snips) -- [ ] Web: `npm run build:web` / `:prod` +- [ ] Web: `npm run dev` / `npm run build:web` - [ ] Electron: `npm run build:electron:dev` / package step - [ ] Mobile: `npm run build:android:test` / iOS equivalent - [ ] Clean/auto-run impacted scripts diff --git a/scripts/build-web.sh b/scripts/build-web.sh index 54c9c6a4..d61a7dda 100755 --- a/scripts/build-web.sh +++ b/scripts/build-web.sh @@ -5,25 +5,31 @@ # This script handles the complete web build process including cleanup, # environment setup, Vite build, and optional Docker containerization. # +# Every invocation except --dev writes dist/. --dev alone starts the Vite dev +# server and writes nothing. +# # Usage: -# ./scripts/build-web.sh # Development build -# ./scripts/build-web.sh --dev # Development build (explicit) +# ./scripts/build-web.sh # Production build into dist/ +# ./scripts/build-web.sh --prod # Production build (explicit) # ./scripts/build-web.sh --test # Test environment build -# ./scripts/build-web.sh --prod # Production environment build -# ./scripts/build-web.sh --docker # Build with Docker containerization +# ./scripts/build-web.sh --dev # Start Vite dev server (no dist/) +# ./scripts/build-web.sh --docker # Production build + Docker image # ./scripts/build-web.sh --docker:test # Test environment + Docker # ./scripts/build-web.sh --docker:prod # Production environment + Docker -# ./scripts/build-web.sh --serve # Build and serve locally +# ./scripts/build-web.sh --serve # Production build, then serve dist/ # ./scripts/build-web.sh --help # Show help # ./scripts/build-web.sh --verbose # Enable verbose logging # # NPM Script Equivalents: -# npm run build:web # Development build +# npm run dev # Vite dev server +# npm run build:web # Production build # npm run build:web:test # Test environment build # npm run build:web:prod # Production environment build -# npm run build:web:docker # Docker build +# npm run build:web:docker # Production Docker build # npm run build:web:docker:test # Test Docker build # npm run build:web:docker:prod # Production Docker build +# npm run build:web:serve # Production build, then serve +# npm run build:web:serve:test # Test build, then serve # # Exit Codes: # 1 - Web cleanup failed @@ -40,7 +46,7 @@ set -e source "$(dirname "$0")/common.sh" # Default values -BUILD_MODE="development" +BUILD_MODE="production" BUILD_ACTION="build" DOCKER_BUILD=false SERVE_BUILD=false @@ -51,9 +57,10 @@ show_usage() { Usage: $0 [OPTIONS] OPTIONS: - --dev, --development Build for development environment (default) + --prod, --production Build for production environment (default) --test Build for test environment - --prod, --production Build for production environment + --dev, --development Start the Vite dev server (with --serve or + --docker: build for development instead) --docker Build and create Docker container --docker:test Build for test environment and create Docker container --docker:prod Build for production environment and create Docker container @@ -63,18 +70,18 @@ OPTIONS: --env Show environment variables EXAMPLES: - $0 # Development build + $0 # Production build $0 --test # Test environment build - $0 --prod # Production environment build - $0 --docker # Development + Docker + $0 --dev # Development server + $0 --docker # Production + Docker $0 --docker:test # Test + Docker $0 --docker:prod # Production + Docker - $0 --serve # Build and serve + $0 --serve # Production build, then serve BUILD MODES: - development: Starts Vite development server with hot reload (default) + production: Optimized for production with full minification and optimization (default) test: Optimized for testing with minimal minification - production: Optimized for production with full minification and optimization + development: Starts Vite development server with hot reload EOF } diff --git a/scripts/clear-database.sh b/scripts/clear-database.sh index 580b8651..6ecfa2a1 100755 --- a/scripts/clear-database.sh +++ b/scripts/clear-database.sh @@ -161,4 +161,4 @@ echo "✅ Database clearing instructions completed!" echo "" echo "💡 Tip: After clearing the database, restart your development server:" echo " npm run build:electron:dev # For Electron" -echo " npm run build:web:dev # For Web" \ No newline at end of file +echo " npm run dev # For Web" \ No newline at end of file diff --git a/scripts/test-android.js b/scripts/test-android.js index 4f22f9fa..a65fcf04 100644 --- a/scripts/test-android.js +++ b/scripts/test-android.js @@ -283,7 +283,6 @@ const runDeeplinkTests = async (log) => { const buildWebAssets = async (log) => { log('🌐 Building web assets...'); execSync('rm -rf dist', { stdio: 'inherit' }); - execSync('npm run build:web', { stdio: 'inherit' }); execSync('npm run build:capacitor', { stdio: 'inherit' }); log('✅ Web assets built successfully'); }; diff --git a/scripts/test-ios.js b/scripts/test-ios.js index 0a19cbfa..8ec01052 100644 --- a/scripts/test-ios.js +++ b/scripts/test-ios.js @@ -147,7 +147,6 @@ export default config; log('🔄 Building web assets before adding iOS platform...'); try { execSync('rm -rf dist', { stdio: 'inherit' }); - execSync('npm run build:web', { stdio: 'inherit' }); execSync('npm run build:capacitor', { stdio: 'inherit' }); log('✅ Web assets built successfully'); } catch (error) { @@ -416,7 +415,6 @@ const generateTestData = async (log) => { const buildWebAssets = async (log) => { log('🌐 Building web assets...'); execSync('rm -rf dist', { stdio: 'inherit' }); - execSync('npm run build:web', { stdio: 'inherit' }); execSync('npm run build:capacitor', { stdio: 'inherit' }); log('✅ Web assets built successfully'); }; diff --git a/src/main.web.ts b/src/main.web.ts index 5ceebdd6..3325975e 100644 --- a/src/main.web.ts +++ b/src/main.web.ts @@ -1,20 +1,51 @@ -import { initializeApp } from "./main.common"; import { logger } from "./utils/logger"; const platform = process.env.VITE_PLATFORM; -// PWA service worker is automatically registered by VitePWA plugin - -const app = initializeApp(); - -// Note: Worker initialization is now handled by WebPlatformService -// This ensures single-point database access and prevents double migrations -if (platform === "web" || platform === "development") { - logger.debug( - "[Web] Database initialization will be handled by WebPlatformService", - ); -} else { - logger.debug("[Web] SQL not initialized for platform", { platform }); +/** + * Browsers withhold crypto.subtle outside secure contexts (HTTPS, localhost, + * 127.0.0.1, [::1]), and identity creation cannot run without it. Addresses + * like http://[::]:8000 or http://192.168.x.x would otherwise fail later with + * a misleading "could not open its data" startup error. main.common is loaded + * only after this check because importing the router starts navigation. + */ +function showInsecureContextError(): void { + const container = document.getElementById("app"); + if (!container) { + return; + } + container.innerHTML = ` +
+

Time Safari Cannot Start Here

+

This page must be opened over HTTPS or from localhost.

+

The browser does not treat as secure, so it disables the cryptography the app uses for identities.

+

On a local server, use http://localhost:PORT/ instead of http://[::]:PORT/ or http://0.0.0.0:PORT/.

+
`; + const originCode = container.querySelectorAll("code")[1]; + if (originCode) { + originCode.textContent = window.location.origin; + } } -app.mount("#app"); +if (!window.isSecureContext) { + logger.error("[Web] Not a secure context; app will not start", { + origin: window.location.origin, + }); + showInsecureContextError(); +} else { + import("./main.common").then(({ initializeApp }) => { + const app = initializeApp(); + + // Note: Worker initialization is now handled by WebPlatformService + // This ensures single-point database access and prevents double migrations + if (platform === "web" || platform === "development") { + logger.debug( + "[Web] Database initialization will be handled by WebPlatformService", + ); + } else { + logger.debug("[Web] SQL not initialized for platform", { platform }); + } + + app.mount("#app"); + }); +}