From d12d7326714ec9851b2ec01820b572af5c257ef7 Mon Sep 17 00:00:00 2001 From: eduard256 Date: Wed, 12 Nov 2025 11:45:46 +0300 Subject: [PATCH] Fix SSE stream discovery and add ESLint for WebUI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JavaScript fixes: - Fix Invalid URL error in stream-discovery.js by adding window.location.origin as base URL - Fix SSE race condition: ensure all stream_found events sent before complete event - Comment unused eventType variable in stream-discovery.js - Comment unused FrigateGenerator import in config-panel.js - Fix quote style (double to single quotes) Go fixes: - Add sync.WaitGroup for result collector to prevent premature SSE closure - Add logging for stream_found events - Fix ERR_INCOMPLETE_CHUNKED_ENCODING by waiting for all streams to be sent ESLint setup: - Add ESLint v8.57.1 with .eslintrc.cjs config for ES2022 modules - Add npm scripts for lint and lint:fix - Update .gitignore for node_modules and package-lock.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .gitignore | 6 +++++- internal/camera/discovery/scanner.go | 8 ++++++++ webui/.eslintrc.cjs | 25 +++++++++++++++++++++++++ webui/package.json | 18 ++++++++++++++++++ webui/web/js/api/stream-discovery.js | 5 +++-- webui/web/js/ui/config-panel.js | 2 +- webui/web/js/ui/stream-carousel.js | 2 +- 7 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 webui/.eslintrc.cjs create mode 100644 webui/package.json diff --git a/.gitignore b/.gitignore index 302c88f..6de6d7a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,8 @@ temp/ *_output.txt # Configuration (user-specific) -strix.yaml \ No newline at end of file +strix.yaml + +# Node.js / NPM +node_modules/ +package-lock.json \ No newline at end of file diff --git a/internal/camera/discovery/scanner.go b/internal/camera/discovery/scanner.go index 1360694..6296333 100644 --- a/internal/camera/discovery/scanner.go +++ b/internal/camera/discovery/scanner.go @@ -434,10 +434,15 @@ func (s *Scanner) testStreamsConcurrently(ctx context.Context, streams []models. }() // Start result collector + var collectorWg sync.WaitGroup + collectorWg.Add(1) go func() { + defer collectorWg.Done() for stream := range streamsChan { result.Streams = append(result.Streams, stream) + s.logger.Info("sending stream_found event", "url", stream.URL, "type", stream.Type) + // Send to SSE _ = streamWriter.SendJSON("stream_found", map[string]interface{}{ "stream": stream, @@ -522,6 +527,9 @@ TestLoop: wg.Wait() close(streamsChan) + // Wait for result collector to finish processing all streams + collectorWg.Wait() + // Update final counts result.TotalTested = int(atomic.LoadInt32(&tested)) result.TotalFound = int(atomic.LoadInt32(&found)) diff --git a/webui/.eslintrc.cjs b/webui/.eslintrc.cjs new file mode 100644 index 0000000..8cd5221 --- /dev/null +++ b/webui/.eslintrc.cjs @@ -0,0 +1,25 @@ +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + globals: { + EventSource: 'readonly', + }, + rules: { + 'no-unused-vars': 'warn', + 'no-undef': 'error', + 'no-console': 'off', // Allow console for debugging + 'semi': ['error', 'always'], + 'quotes': ['warn', 'single', { avoidEscape: true }], + 'no-var': 'error', + 'prefer-const': 'warn', + 'eqeqeq': ['error', 'always'], + 'no-unreachable': 'error', + }, +}; diff --git a/webui/package.json b/webui/package.json new file mode 100644 index 0000000..5887739 --- /dev/null +++ b/webui/package.json @@ -0,0 +1,18 @@ +{ + "name": "webui", + "version": "1.0.0", + "type": "module", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "eslint web/js/**/*.js", + "lint:fix": "eslint web/js/**/*.js --fix" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "eslint": "^8.57.1" + } +} diff --git a/webui/web/js/api/stream-discovery.js b/webui/web/js/api/stream-discovery.js index da0ce31..7de1a4a 100644 --- a/webui/web/js/api/stream-discovery.js +++ b/webui/web/js/api/stream-discovery.js @@ -12,7 +12,7 @@ export class StreamDiscoveryAPI { discover(request, callbacks) { this.close(); - const url = new URL(`${this.baseURL}/api/v1/streams/discover`); + const url = new URL(`${this.baseURL}/api/v1/streams/discover`, window.location.origin); fetch(url, { method: 'POST', @@ -39,7 +39,8 @@ export class StreamDiscoveryAPI { for (const line of lines) { if (line.startsWith('event:')) { - const eventType = line.substring(6).trim(); + // Parse event type (not currently used, but available for future features) + // const eventType = line.substring(6).trim(); continue; } diff --git a/webui/web/js/ui/config-panel.js b/webui/web/js/ui/config-panel.js index 876ed31..5c1abc1 100644 --- a/webui/web/js/ui/config-panel.js +++ b/webui/web/js/ui/config-panel.js @@ -1,5 +1,5 @@ import { Go2RTCGenerator } from '../config-generators/go2rtc/index.js'; -import { FrigateGenerator } from '../config-generators/frigate/index.js'; +// import { FrigateGenerator } from '../config-generators/frigate/index.js'; // Reserved for future use export class ConfigPanel { constructor() { diff --git a/webui/web/js/ui/stream-carousel.js b/webui/web/js/ui/stream-carousel.js index 26dcb34..372e75b 100644 --- a/webui/web/js/ui/stream-carousel.js +++ b/webui/web/js/ui/stream-carousel.js @@ -45,7 +45,7 @@ export class StreamCarousel {
${this.truncateURL(stream.url)}
${stream.resolution ? `
Resolution: ${stream.resolution}
` : ''} ${stream.codec ? `
Codec: ${stream.codec}${stream.fps ? ` • ${stream.fps} fps` : ''}${stream.bitrate ? ` • ${Math.round(stream.bitrate / 1000)} Kbps` : ''}
` : ''} - ${stream.has_audio ? `
Audio: Yes
` : ''} + ${stream.has_audio ? '
Audio: Yes
' : ''}