Files
2026-07-13 13:20:22 +08:00

462 lines
16 KiB
Makefile

# AionUI Development Justfile
# Usage: just <recipe>
# On Windows, simple recipes (no shebang) use PowerShell
set windows-shell := ["powershell.exe", "-NoProfile", "-Command"]
# Default recipe: show available commands
default:
@just --list --unsorted
# ============================================================
# Development
# ============================================================
# Start development server (Electron + Vite HMR)
dev:
bun run start
# Start WebUI development mode
webui:
bun run webui
# Start WebUI with remote access
webui-remote:
bun run webui:remote
# Start WebUI production mode
webui-prod:
bun run webui:prod
# Run CLI mode
cli:
bun run cli
# ============================================================
# Environment Checks (requires pwsh)
# ============================================================
# Check all build prerequisites are met
[no-exit-message]
preflight:
#!/usr/bin/env pwsh
$ErrorActionPreference = 'Continue'
$failed = $false
Write-Host "=========================================="
Write-Host " AionUI Build Preflight Check"
Write-Host "=========================================="
Write-Host ""
Write-Host "[1/6] Node.js..."
try {
$nodeVer = (node --version 2>&1).Trim()
$major = [int]($nodeVer -replace '^v','').Split('.')[0]
if ($major -ge 22) { Write-Host " OK Node.js $nodeVer" }
else { Write-Host " WARN Node.js $nodeVer (recommend >= 22)" }
} catch { Write-Host " FAIL Node.js not found"; $failed = $true }
Write-Host "[2/6] bun..."
try {
$bunVer = (bun --version 2>&1).Trim()
Write-Host " OK bun $bunVer"
} catch { Write-Host " FAIL bun not found"; $failed = $true }
Write-Host "[3/6] Python (for native modules)..."
try {
$pyVer = (python --version 2>&1).Trim()
Write-Host " OK $pyVer"
} catch { Write-Host " WARN Python not found (needed for native module compilation)" }
Write-Host "[4/6] Dependencies (node_modules)..."
if ((Test-Path "node_modules") -and ((Test-Path "bun.lock") -or (Test-Path "package-lock.json"))) {
Write-Host " OK node_modules exists"
} else {
Write-Host " WARN node_modules missing - running: just install"
just install
if (Test-Path "node_modules") { Write-Host " OK node_modules installed" }
else { Write-Host " FAIL Failed to install dependencies"; $failed = $true }
}
Write-Host "[5/6] Native modules (better-sqlite3)..."
$nativeOk = (Test-Path "node_modules/better-sqlite3/build/Release/better_sqlite3.node") -or (Test-Path "node_modules/better-sqlite3/prebuilds")
if ($nativeOk) { Write-Host " OK better-sqlite3 native module found" }
else { Write-Host " WARN better-sqlite3 native binary missing - run: just rebuild-native" }
Write-Host "[6/6] Electron version..."
try {
$electronVer = (node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')" 2>&1).Trim()
Write-Host " OK Electron $electronVer"
} catch { Write-Host " FAIL Cannot read Electron version"; $failed = $true }
Write-Host ""
Write-Host "=========================================="
if ($failed) { Write-Host " PREFLIGHT FAILED"; exit 1 }
else { Write-Host " PREFLIGHT PASSED" }
Write-Host "=========================================="
# Show current build environment info
info:
#!/usr/bin/env bash
echo "AionUI Build Environment"
echo "========================"
echo "Node: $(node --version)"
echo "bun: $(bun --version)"
electronVer=$(node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')")
appVer=$(node -p "require('./package.json').version")
echo "App: v$appVer"
echo "Electron: $electronVer"
echo "Branch: $(git branch --show-current)"
echo "Commit: $(git rev-parse --short HEAD)"
# ============================================================
# Dependencies & Native Modules
# ============================================================
# Install dependencies (clean install)
install:
bun install
# Install dependencies (with lockfile update)
install-update:
bun install
# Full setup: install deps + rebuild native modules
setup: install rebuild-native
# Rebuild native modules for Electron (critical step!)
# On Windows, ensure MSVC build tools are installed via:
# choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools"
# or install Visual Studio 2022 with "Desktop development with C++" workload.
[no-exit-message]
rebuild-native:
#!/usr/bin/env pwsh
$ErrorActionPreference = 'Stop'
$electronVer = (node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')" 2>&1).Trim()
Write-Host "=========================================="
Write-Host "Rebuilding native modules for Electron $electronVer"
Write-Host "=========================================="
Write-Host ""
Write-Host "[Step 1] electron-rebuild..."
bunx electron-rebuild -f -w better-sqlite3
Write-Host " OK electron-rebuild completed"
Write-Host ""
Write-Host "[Verify] Checking native modules..."
$verified = $true
$sqliteNode = "node_modules/better-sqlite3/build/Release/better_sqlite3.node"
if (Test-Path $sqliteNode) {
$size = [math]::Round((Get-Item $sqliteNode).Length / 1MB, 1)
Write-Host " OK better-sqlite3 ($size MB)"
} elseif (Test-Path "node_modules/better-sqlite3/prebuilds") {
Write-Host " OK better-sqlite3 (prebuilds)"
} else {
Write-Host " FAIL better-sqlite3 native module not found"
$verified = $false
}
Write-Host ""
if ($verified) {
Write-Host " All native modules verified"
} else {
Write-Host " NATIVE MODULE VERIFICATION FAILED"
exit 1
}
# Verify native modules can actually be loaded by Node.js
[no-exit-message]
verify-native:
#!/usr/bin/env pwsh
Write-Host "Verifying native modules can be loaded..."
$result = node -e "try { require('better-sqlite3'); console.log('OK'); } catch(e) { console.log('FAIL: ' + e.message); process.exit(1); }" 2>&1
if ($result -match "OK") {
Write-Host " OK better-sqlite3 loads correctly"
} else {
Write-Host " FAIL better-sqlite3: $result"
Write-Host " Run: just rebuild-native"
exit 1
}
Write-Host "All native modules verified and loadable."
# ============================================================
# Build (mirrors CI workflow environment setup)
# ============================================================
# Build for current platform (preflight → build)
build: preflight
#!/usr/bin/env bash
export NODE_OPTIONS="--max-old-space-size=8192"
bun run build
# Quick build - uses cached Vite output if available
build-quick: preflight
#!/usr/bin/env bash
export NODE_OPTIONS="--max-old-space-size=8192"
node scripts/build-with-builder.js auto --skip-native
# Build package only (no installer) - fastest iteration
build-package: preflight
#!/usr/bin/env bash
export NODE_OPTIONS="--max-old-space-size=8192"
node scripts/build-with-builder.js auto --pack-only --skip-native
# Force full rebuild (clears cache)
build-force: preflight clean
#!/usr/bin/env bash
export NODE_OPTIONS="--max-old-space-size=8192"
node scripts/build-with-builder.js auto --force
# Build for Windows x64
build-win-x64: preflight
#!/usr/bin/env pwsh
Write-Host "Ensuring npm dependencies..."
if (-not (Test-Path "node_modules")) { npm install } else { npm install --prefer-offline }
$env:NODE_OPTIONS = "--max-old-space-size=8192"
$env:npm_config_runtime = "electron"
$env:npm_config_target = (node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')" 2>&1).Trim()
$env:npm_config_arch = "x64"
$env:npm_config_target_arch = "x64"
$env:npm_config_disturl = "https://electronjs.org/headers"
$env:npm_config_build_from_source = "true"
$env:MSVS_VERSION = "2022"
$env:GYP_MSVS_VERSION = "2022"
node scripts/build-with-builder.js x64 --win --x64
# Build for Windows arm64
build-win-arm64: preflight
#!/usr/bin/env pwsh
Write-Host "Ensuring npm dependencies..."
if (-not (Test-Path "node_modules")) { npm install } else { npm install --prefer-offline }
$env:NODE_OPTIONS = "--max-old-space-size=8192"
$env:npm_config_runtime = "electron"
$env:npm_config_target = (node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')" 2>&1).Trim()
$env:npm_config_arch = "arm64"
$env:npm_config_target_arch = "arm64"
$env:npm_config_disturl = "https://electronjs.org/headers"
$env:npm_config_build_from_source = "true"
$env:MSVS_VERSION = "2022"
$env:GYP_MSVS_VERSION = "2022"
node scripts/build-with-builder.js arm64 --win --arm64
# Build for Windows (auto-detect arch)
build-win: preflight
#!/usr/bin/env pwsh
Write-Host "Cleaning output directory..."
Get-Process -Name "AionUI","electron" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
if (Test-Path "out") { Remove-Item -Recurse -Force "out" -ErrorAction SilentlyContinue }
npm install
npm run postinstall; if ($LASTEXITCODE -ne 0) { Write-Host "postinstall failed (continuing)"; $LASTEXITCODE = 0 }
$env:NODE_OPTIONS = "--max-old-space-size=8192"
$env:MSVS_VERSION = "2022"
$env:GYP_MSVS_VERSION = "2022"
bun run build-win
# Build for macOS ARM64
build-mac-arm64: preflight
#!/usr/bin/env bash
echo "Ensuring npm dependencies..."
[ -d "node_modules" ] && npm install --prefer-offline || npm install
export NODE_OPTIONS="--max-old-space-size=8192"
export npm_config_runtime="electron"
export npm_config_target=$(node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')")
export npm_config_disturl="https://electronjs.org/headers"
node scripts/build-with-builder.js arm64 --mac --arm64
# Build for macOS x64
build-mac-x64: preflight
#!/usr/bin/env bash
echo "Ensuring npm dependencies..."
[ -d "node_modules" ] && npm install --prefer-offline || npm install
export NODE_OPTIONS="--max-old-space-size=8192"
export npm_config_runtime="electron"
export npm_config_target=$(node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')")
export npm_config_disturl="https://electronjs.org/headers"
node scripts/build-with-builder.js x64 --mac --x64
# Build for macOS (arm64 + x64)
build-mac: preflight
#!/usr/bin/env bash
echo "Ensuring npm dependencies..."
[ -d "node_modules" ] && npm install --prefer-offline || npm install
export NODE_OPTIONS="--max-old-space-size=8192"
export npm_config_runtime="electron"
export npm_config_target=$(node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')")
export npm_config_disturl="https://electronjs.org/headers"
bun run build-mac
# Build for Linux
build-linux: preflight
#!/usr/bin/env bash
echo "Ensuring npm dependencies..."
[ -d "node_modules" ] && npm install --prefer-offline || npm install
export NODE_OPTIONS="--max-old-space-size=8192"
export npm_config_runtime="electron"
export npm_config_target=$(node -p "require('./package.json').devDependencies.electron.replace(/[\^~]/g, '')")
export npm_config_disturl="https://electronjs.org/headers"
bun run build-deb
# Package only (electron-vite build, no installer)
package:
bun run package
# Distribute (shortcut)
dist:
bun run dist
# ============================================================
# Code Quality
# ============================================================
# Run linter
lint:
bun run lint
# Run linter with auto-fix
lint-fix:
bun run lint:fix
# Format code
fmt:
bun run format
# Check formatting
fmt-check:
bun run format:check
# Type check
typecheck:
bunx tsc --noEmit
# Run i18n type generation and validation
i18n-check:
bun run i18n:types
node scripts/check-i18n.js
# Run all checks (lint + format + typecheck + i18n) — mirrors CI code-quality job
check: lint fmt-check typecheck i18n-check
# Pre-push gate: lint + format check + typecheck + i18n + test, then push
# Uses --quiet to suppress warnings (exit code is still non-zero on errors)
push *ARGS: lint-strict fmt-check typecheck i18n-check test
git push {{ ARGS }}
# Lint with only errors reported (for CI/push gates)
lint-strict:
bun run lint -- --quiet
# ============================================================
# Testing
# ============================================================
# Run all tests
test:
bun run test
# Run tests in watch mode
test-watch:
bun run test:watch
# Run tests with coverage
test-coverage:
bun run test:coverage
# Run contract tests
test-contract:
bun run test:contract
# Run integration tests
test-integration:
bun run test:integration
# Verify packaged artifact contains complete renderer assets (i18n safety)
test-packaged-i18n:
bun run test:packaged:i18n
# Run E2E tests (Playwright + Electron — auto-launches app)
# Builds main+preload+renderer into out/ first to ensure fresh artifacts.
e2e-test:
bun run package
bunx playwright test --config playwright.config.ts
# Run only extension-related E2E tests (faster iteration)
e2e-test-ext:
bun run package
bunx playwright test --config playwright.config.ts tests/e2e/specs/ext-*.e2e.ts
# Run E2E tests with headed browser (for debugging)
e2e-test-headed:
bun run package
bunx playwright test --config playwright.config.ts --headed
# Open Playwright HTML report after test run
e2e-report:
bunx playwright show-report tests/e2e/report
# ============================================================
# Extension System (RFC-001)
# ============================================================
# Start dev server with example extensions loaded
# CDP remote debugging is enabled by default on port 9222 in dev mode
dev-ext:
node scripts/dev-bootstrap.mjs launch start --extensions
# Start WebUI with example extensions loaded
webui-ext:
node scripts/dev-bootstrap.mjs launch webui --extensions
# Start CLI with example extensions loaded
cli-ext:
node scripts/dev-bootstrap.mjs launch cli --extensions
# Cross-platform diagnosis for dev extension startup
dev-ext-doctor:
node scripts/dev-bootstrap.mjs doctor
# Launch packaged (unpacked) app with example extensions for one-click debugging
# Requires out/*-unpacked artifacts
packaged-ext:
node scripts/packaged-launch.mjs
# Build package first, then launch with example extensions
packaged-ext-build: build-package
node scripts/packaged-launch.mjs
# Validate extension system types compile correctly
ext-typecheck:
bunx tsc --noEmit --project tsconfig.json
# Run extension system tests
ext-test:
bunx vitest run tests/extensions/ --passWithNoTests
# Run extension system tests in watch mode
ext-test-watch:
bunx vitest tests/extensions/
# ============================================================
# Utilities
# ============================================================
# Reset WebUI password
reset-password:
bun run resetpass
# Clean build artifacts
clean:
#!/usr/bin/env bash
rm -rf out dist
echo "Build artifacts cleaned."
# Deep clean (build artifacts + node_modules)
clean-all: clean
#!/usr/bin/env bash
if [ -d "node_modules" ]; then
echo "Removing node_modules..."
rm -rf node_modules
fi
echo "Full clean complete. Run: just setup"
# List build output artifacts
list-artifacts:
#!/usr/bin/env bash
if [ -d "out" ]; then
find out -type f \( -name "*.exe" -o -name "*.msi" -o -name "*.dmg" -o -name "*.deb" -o -name "*.AppImage" -o -name "*.zip" \) -exec ls -lh {} \; | awk '{print " " $NF " (" $5 ")"}'
else
echo "No build output found. Run: just build"
fi
# CI-like full build validation (mirrors GitHub Actions workflow)
ci-local: check test build
@echo "CI-local pipeline passed!"