refactor: comprehensive code quality, security, and release readiness improvements
Lint & Test / test (push) Failing after 48s
Lint & Test / test (push) Failing after 48s
Security: tighten CORS defaults, add webhook rate limiting, fix XSS in automations, guard WebSocket JSON.parse, validate ADB address input, seal debug exception leak, URL-encode WS tokens, CSS.escape in selectors. Code quality: add Pydantic models for brightness/power endpoints, fix thread safety and name uniqueness in DeviceStore, immutable update pattern, split 6 oversized files into 16 focused modules, enable TypeScript strictNullChecks (741→102 errors), type state variables, add dom-utils helper, migrate 3 modules from inline onclick to event delegation, ProcessorDependencies dataclass. Performance: async store saves, health endpoint log level, command palette debounce, optimized entity-events comparison, fix service worker precache list. Testing: expand from 45 to 293 passing tests — add store tests (141), route tests (25), core logic tests (42), E2E flow tests (33), organize into tests/api/, tests/storage/, tests/core/, tests/e2e/. DevOps: CI test pipeline, pre-commit config, Dockerfile multi-stage build with non-root user and health check, docker-compose improvements, version bump to 0.2.0. Docs: rewrite CLAUDE.md (202→56 lines), server/CLAUDE.md (212→76), create contexts/server-operations.md, fix .js→.ts references, fix env var prefix in README, rewrite INSTALLATION.md, add CONTRIBUTING.md and .env.example.
This commit is contained in:
@@ -280,7 +280,7 @@ export function selectCalibrationLine(idx: number): void {
|
||||
const prev = _state.selectedLine;
|
||||
_state.selectedLine = idx;
|
||||
// Update selection in-place without rebuilding the list DOM
|
||||
const container = document.getElementById('advcal-line-list');
|
||||
const container = document.getElementById('advcal-line-list')!;
|
||||
const items = container.querySelectorAll('.advcal-line-item');
|
||||
if (prev >= 0 && prev < items.length) items[prev].classList.remove('selected');
|
||||
if (idx >= 0 && idx < items.length) items[idx].classList.add('selected');
|
||||
@@ -361,14 +361,14 @@ function _buildMonitorLayout(psList: any[], cssId: string | null): void {
|
||||
// Load saved positions from localStorage
|
||||
const savedKey = `advcal_positions_${cssId}`;
|
||||
let saved = {};
|
||||
try { saved = JSON.parse(localStorage.getItem(savedKey)) || {}; } catch { /* ignore */ }
|
||||
try { saved = JSON.parse(localStorage.getItem(savedKey) ?? '{}') || {}; } catch { /* ignore */ }
|
||||
|
||||
const canvas = document.getElementById('advcal-canvas') as HTMLCanvasElement;
|
||||
const canvasW = canvas.width;
|
||||
const canvasH = canvas.height;
|
||||
|
||||
// Default layout: arrange monitors in a row
|
||||
const monitors = [];
|
||||
const monitors: any[] = [];
|
||||
const padding = 20;
|
||||
const maxMonW = (canvasW - padding * 2) / Math.max(psList.length, 1) - 10;
|
||||
const monH = canvasH * 0.6;
|
||||
@@ -423,7 +423,7 @@ function _placeNewMonitor(): void {
|
||||
|
||||
function _updateTotalLeds(): void {
|
||||
const used = _state.lines.reduce((s, l) => s + l.led_count, 0);
|
||||
const el = document.getElementById('advcal-total-leds');
|
||||
const el = document.getElementById('advcal-total-leds')!;
|
||||
if (_state.totalLedCount > 0) {
|
||||
el.textContent = `${used}/${_state.totalLedCount}`;
|
||||
el.style.color = used > _state.totalLedCount ? 'var(--danger-color, #ff5555)' : '';
|
||||
@@ -436,7 +436,7 @@ function _updateTotalLeds(): void {
|
||||
/* ── Line list rendering ────────────────────────────────────── */
|
||||
|
||||
function _renderLineList(): void {
|
||||
const container = document.getElementById('advcal-line-list');
|
||||
const container = document.getElementById('advcal-line-list')!;
|
||||
container.innerHTML = '';
|
||||
|
||||
_state.lines.forEach((line, i) => {
|
||||
@@ -470,7 +470,7 @@ function _renderLineList(): void {
|
||||
}
|
||||
|
||||
function _showLineProps(): void {
|
||||
const propsEl = document.getElementById('advcal-line-props');
|
||||
const propsEl = document.getElementById('advcal-line-props')!;
|
||||
const idx = _state.selectedLine;
|
||||
if (idx < 0 || idx >= _state.lines.length) {
|
||||
propsEl.style.display = 'none';
|
||||
@@ -553,7 +553,7 @@ function _fitView(): void {
|
||||
function _renderCanvas(): void {
|
||||
const canvas = document.getElementById('advcal-canvas') as HTMLCanvasElement | null;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
const W = canvas.width;
|
||||
const H = canvas.height;
|
||||
|
||||
@@ -679,7 +679,7 @@ function _drawLineTicks(ctx: CanvasRenderingContext2D, line: CalibrationLine, x1
|
||||
return (line.reverse ? (1 - f) : f) * edgeLen;
|
||||
};
|
||||
|
||||
const placed = [];
|
||||
const placed: number[] = [];
|
||||
|
||||
// Place intermediate labels at nice steps
|
||||
for (let i = 0; i < count; i++) {
|
||||
|
||||
Reference in New Issue
Block a user