- @if ( - currentLayout === 'vod-details' || - currentLayout === 'serial-details' - ) { - + } @else if (!isItvCategorySelected) { + } @if (!isItvCategorySelected) { - {{ selectedCategoryTitle() }} } diff --git a/apps/web/src/app/stalker/stalker-main-container.component.ts b/apps/web/src/app/stalker/stalker-main-container.component.ts index 16d39fe1c..5396e8223 100644 --- a/apps/web/src/app/stalker/stalker-main-container.component.ts +++ b/apps/web/src/app/stalker/stalker-main-container.component.ts @@ -236,4 +236,8 @@ export class StalkerMainContainerComponent { backToCategories() { this.stalkerStore.setSelectedCategory(null); } + + goBackToList() { + this.stalkerStore.clearSelectedItem(); + } } diff --git a/apps/web/src/app/stalker/stalker.store.ts b/apps/web/src/app/stalker/stalker.store.ts index 1da396a13..62335697b 100644 --- a/apps/web/src/app/stalker/stalker.store.ts +++ b/apps/web/src/app/stalker/stalker.store.ts @@ -332,6 +332,14 @@ export const StalkerStore = signalStore( selectedItem, }); }, + clearSelectedItem() { + patchState(store, { + selectedVodId: undefined, + selectedSerialId: undefined, + selectedItvId: undefined, + selectedItem: undefined, + }); + }, setCategories(type: 'vod' | 'series' | 'itv', categories: any[]) { if (type === 'vod') { patchState(store, { vodCategories: categories }); From 5f35d22076d166154b6e50785c0fad5bce09f065 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 23 Nov 2025 21:39:07 +0100 Subject: [PATCH 02/13] style: adjust overflow rules in xtream detail views Change overflow handling in the xtream detail-view SCSS files to avoid unwanted scrollbars and ensure proper layout stretching. In the web version, remove a global overflow:auto and set overflow:visible on the .details block and the grid container so inner content can expand as needed. In the tauri variant, remove a min-height that forced an artificial viewport-based height. These tweaks fix layout clipping and scrollbar issues when detail content grows, and allow natural sizing across web and Tauri builds. --- apps/web/src/app/xtream-tauri/detail-view.scss | 1 - apps/web/src/app/xtream/detail-view.scss | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/xtream-tauri/detail-view.scss b/apps/web/src/app/xtream-tauri/detail-view.scss index f789ce642..fabb0fd35 100644 --- a/apps/web/src/app/xtream-tauri/detail-view.scss +++ b/apps/web/src/app/xtream-tauri/detail-view.scss @@ -23,7 +23,6 @@ max-width: 100%; box-sizing: border-box; height: auto; - min-height: calc(100vh - 73px); &::before { content: ''; diff --git a/apps/web/src/app/xtream/detail-view.scss b/apps/web/src/app/xtream/detail-view.scss index 994a61046..c53623e16 100644 --- a/apps/web/src/app/xtream/detail-view.scss +++ b/apps/web/src/app/xtream/detail-view.scss @@ -2,10 +2,11 @@ width: 100%; display: flex; flex-direction: column; - overflow: auto; } .details { + overflow: visible; + h2 { word-wrap: break-word; } @@ -16,6 +17,7 @@ grid-gap: 10px; grid-template-columns: 320px 1fr; padding: 0 10px; + overflow: visible; &::before { content: ''; From 573ca01925eba3c5f347a1eff3a9499c2aa25b6e Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 23 Nov 2025 21:53:01 +0100 Subject: [PATCH 03/13] fix(artplayer): manage Hls instance and centralize player teardown Add a dedicated hls field and a destroyPlayer() helper to ensure Hls instances are properly destroyed when the component is torn down or re-initialized. Replace inline Hls creation with a guarded pattern that destroys any existing hls before creating a new one, preventing leaks or duplicate attachments. Use destroyPlayer() from ngOnDestroy and when the channel input changes to centralize teardown logic and keep lifecycle handling consistent. --- .../lib/art-player/art-player.component.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libs/ui/components/src/lib/art-player/art-player.component.ts b/libs/ui/components/src/lib/art-player/art-player.component.ts index 890d12ece..4f6580452 100644 --- a/libs/ui/components/src/lib/art-player/art-player.component.ts +++ b/libs/ui/components/src/lib/art-player/art-player.component.ts @@ -38,6 +38,7 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { @Input() showCaptions = false; private player!: Artplayer; + private hls: Hls | null = null; private readonly elementRef = inject(ElementRef); @@ -46,20 +47,26 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { } ngOnDestroy(): void { - if (this.player) { - this.player.destroy(); - } + this.destroyPlayer(); } ngOnChanges(changes: SimpleChanges): void { if (changes['channel'] && !changes['channel'].firstChange) { - if (this.player) { - this.player.destroy(); - } + this.destroyPlayer(); this.initPlayer(); } } + private destroyPlayer(): void { + if (this.hls) { + this.hls.destroy(); + this.hls = null; + } + if (this.player) { + this.player.destroy(); + } + } + private initPlayer(): void { const el = this.elementRef.nativeElement.querySelector( '.artplayer-container' @@ -89,11 +96,14 @@ export class ArtPlayerComponent implements OnInit, OnDestroy, OnChanges { mutex: true, theme: '#ff0000', customType: { - m3u8: function (video: HTMLVideoElement, url: string) { + m3u8: (video: HTMLVideoElement, url: string) => { if (Hls.isSupported()) { - const hls = new Hls(); - hls.loadSource(url); - hls.attachMedia(video); + if (this.hls) { + this.hls.destroy(); + } + this.hls = new Hls(); + this.hls.loadSource(url); + this.hls.attachMedia(video); } else if ( video.canPlayType('application/vnd.apple.mpegurl') ) { From 5b697f458abf2df683e5d62ab0d9de4dc85ade9e Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 23 Nov 2025 22:16:33 +0100 Subject: [PATCH 04/13] feat(electron): load epg worker from asar.unpacked in prod Update EPG worker path handling and unpack worker files for production builds so the worker can be spawned when the app is packaged with ASAR. - Change workerPath to let and, when the resolved path includes app.asar, replace it with app.asar.unpacked. This ensures the spawned worker points to the unpacked resource in production. - Add electron-builder asarUnpack pattern for workers/** so worker files are packaged outside the ASAR archive. These changes fix runtime errors where worker threads cannot be started from inside app.asar and ensure the EPG parser can run in packaged apps. --- apps/electron-backend/src/app/events/epg.events.ts | 7 ++++++- package.json | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 3f13fa26e..554e3e0c0 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -97,12 +97,17 @@ export default class EpgEvents { } return new Promise((resolve, reject) => { - const workerPath = path.join( + let workerPath = path.join( __dirname, 'workers', 'epg-parser.worker.js' ); + // Handle asar unpacked files in production + if (workerPath.includes('app.asar')) { + workerPath = workerPath.replace('app.asar', 'app.asar.unpacked'); + } + console.log(this.loggerLabel, 'Creating worker for:', url); console.log(this.loggerLabel, 'Worker path:', workerPath); diff --git a/package.json b/package.json index f80c824d2..c70d7b87c 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ "appId": "com.fourgray.iptvnator", "productName": "IPTVnator", "artifactName": "${name}-${version}-${os}-${arch}.${ext}", + "asarUnpack": [ + "**/workers/**" + ], "mac": { "target": { "target": "dmg", From 1b4954e20b0d1f2053a47d6083dec41bc5741212 Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:36:29 +0000 Subject: [PATCH 05/13] feat(epg): update worker path handling for production environment --- .../src/app/events/epg.events.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 554e3e0c0..4008183c7 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -1,7 +1,8 @@ -import { ipcMain } from 'electron'; +import { app, ipcMain } from 'electron'; import * as path from 'path'; import { EpgChannelWithPrograms, EpgData, EpgProgram } from 'shared-interfaces'; import { Worker } from 'worker_threads'; +import { pathToFileURL } from 'url'; /** * EPG Events Handler @@ -97,23 +98,24 @@ export default class EpgEvents { } return new Promise((resolve, reject) => { - let workerPath = path.join( - __dirname, + // Get the proper worker path following Electron's recommended approach + // https://www.electronjs.org/docs/latest/tutorial/multithreading + const workerPath = path.join( + app.getAppPath().replace('app.asar', 'app.asar.unpacked'), + 'electron-backend', 'workers', 'epg-parser.worker.js' ); - // Handle asar unpacked files in production - if (workerPath.includes('app.asar')) { - workerPath = workerPath.replace('app.asar', 'app.asar.unpacked'); - } - console.log(this.loggerLabel, 'Creating worker for:', url); console.log(this.loggerLabel, 'Worker path:', workerPath); + console.log(this.loggerLabel, 'App path:', app.getAppPath()); let worker: Worker; try { - worker = new Worker(workerPath); + // Worker threads require file:// URLs in packaged apps + const workerURL = pathToFileURL(workerPath).href; + worker = new Worker(workerURL); console.log(this.loggerLabel, 'Worker created successfully'); } catch (error) { console.error( From 682b040aecf086624d1d3640b00f157578aab62c Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:53:10 +0000 Subject: [PATCH 06/13] fix(epg): update worker URL handling for packaged apps --- apps/electron-backend/src/app/events/epg.events.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 4008183c7..d73c066cd 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -113,8 +113,8 @@ export default class EpgEvents { let worker: Worker; try { - // Worker threads require file:// URLs in packaged apps - const workerURL = pathToFileURL(workerPath).href; + // Worker threads require file:// URLs wrapped in URL object for packaged apps + const workerURL = pathToFileURL(workerPath); worker = new Worker(workerURL); console.log(this.loggerLabel, 'Worker created successfully'); } catch (error) { From 6b40287faeb974ab18dcf841d987162122a341b1 Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:08:05 +0000 Subject: [PATCH 07/13] feat(epg): differentiate worker path for packaged and development environments --- .../src/app/events/epg.events.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index d73c066cd..325772333 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -100,16 +100,24 @@ export default class EpgEvents { return new Promise((resolve, reject) => { // Get the proper worker path following Electron's recommended approach // https://www.electronjs.org/docs/latest/tutorial/multithreading - const workerPath = path.join( - app.getAppPath().replace('app.asar', 'app.asar.unpacked'), - 'electron-backend', - 'workers', - 'epg-parser.worker.js' - ); + let workerPath: string; + + if (app.isPackaged) { + // In packaged app: Resources/app.asar.unpacked/workers/epg-parser.worker.js + workerPath = path.join( + app.getAppPath().replace('app.asar', 'app.asar.unpacked'), + 'workers', + 'epg-parser.worker.js' + ); + } else { + // In development: dist/apps/electron-backend/workers/epg-parser.worker.js + workerPath = path.join(__dirname, 'workers', 'epg-parser.worker.js'); + } console.log(this.loggerLabel, 'Creating worker for:', url); console.log(this.loggerLabel, 'Worker path:', workerPath); console.log(this.loggerLabel, 'App path:', app.getAppPath()); + console.log(this.loggerLabel, 'Is packaged:', app.isPackaged); let worker: Worker; try { From 64afc2901eaba94a5acf04e2bb091a6b47b4597e Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:21:00 +0000 Subject: [PATCH 08/13] feat(epg): enhance worker path handling and add fallback for missing worker files --- .../src/app/events/epg.events.ts | 33 ++++++++++++++++--- package.json | 6 +++- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 325772333..293580e8d 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -104,11 +104,9 @@ export default class EpgEvents { if (app.isPackaged) { // In packaged app: Resources/app.asar.unpacked/workers/epg-parser.worker.js - workerPath = path.join( - app.getAppPath().replace('app.asar', 'app.asar.unpacked'), - 'workers', - 'epg-parser.worker.js' - ); + const appPath = app.getAppPath(); + const unpackedPath = appPath.replace('app.asar', 'app.asar.unpacked'); + workerPath = path.join(unpackedPath, 'workers', 'epg-parser.worker.js'); } else { // In development: dist/apps/electron-backend/workers/epg-parser.worker.js workerPath = path.join(__dirname, 'workers', 'epg-parser.worker.js'); @@ -118,6 +116,31 @@ export default class EpgEvents { console.log(this.loggerLabel, 'Worker path:', workerPath); console.log(this.loggerLabel, 'App path:', app.getAppPath()); console.log(this.loggerLabel, 'Is packaged:', app.isPackaged); + console.log(this.loggerLabel, '__dirname:', __dirname); + + // Check if file exists + const fs = require('fs'); + if (!fs.existsSync(workerPath)) { + console.error(this.loggerLabel, 'Worker file does not exist at:', workerPath); + console.error(this.loggerLabel, 'Trying alternate paths...'); + + // Try alternate path with electron-backend subdirectory + const alternatePath = path.join( + app.getAppPath().replace('app.asar', 'app.asar.unpacked'), + 'electron-backend', + 'workers', + 'epg-parser.worker.js' + ); + console.error(this.loggerLabel, 'Alternate path:', alternatePath); + + if (fs.existsSync(alternatePath)) { + workerPath = alternatePath; + console.log(this.loggerLabel, 'Using alternate path'); + } else { + reject(new Error(`Worker file not found at ${workerPath} or ${alternatePath}`)); + return; + } + } let worker: Worker; try { diff --git a/package.json b/package.json index c70d7b87c..ba6f6d415 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,12 @@ "appId": "com.fourgray.iptvnator", "productName": "IPTVnator", "artifactName": "${name}-${version}-${os}-${arch}.${ext}", + "files": [ + "**/*", + "!**/*.map" + ], "asarUnpack": [ - "**/workers/**" + "workers/**/*.js" ], "mac": { "target": { From 9f7995054de680a9432d176d93a48e5366d24231 Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:19:35 +0000 Subject: [PATCH 09/13] feat(epg): update worker path for packaged app and refine file inclusion in build --- .../src/app/events/epg.events.ts | 34 ++++--------------- package.json | 6 ++-- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 293580e8d..500b17327 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -103,10 +103,15 @@ export default class EpgEvents { let workerPath: string; if (app.isPackaged) { - // In packaged app: Resources/app.asar.unpacked/workers/epg-parser.worker.js + // In packaged app: Resources/app.asar.unpacked/electron-backend/workers/epg-parser.worker.js const appPath = app.getAppPath(); const unpackedPath = appPath.replace('app.asar', 'app.asar.unpacked'); - workerPath = path.join(unpackedPath, 'workers', 'epg-parser.worker.js'); + workerPath = path.join( + unpackedPath, + 'electron-backend', + 'workers', + 'epg-parser.worker.js' + ); } else { // In development: dist/apps/electron-backend/workers/epg-parser.worker.js workerPath = path.join(__dirname, 'workers', 'epg-parser.worker.js'); @@ -116,31 +121,6 @@ export default class EpgEvents { console.log(this.loggerLabel, 'Worker path:', workerPath); console.log(this.loggerLabel, 'App path:', app.getAppPath()); console.log(this.loggerLabel, 'Is packaged:', app.isPackaged); - console.log(this.loggerLabel, '__dirname:', __dirname); - - // Check if file exists - const fs = require('fs'); - if (!fs.existsSync(workerPath)) { - console.error(this.loggerLabel, 'Worker file does not exist at:', workerPath); - console.error(this.loggerLabel, 'Trying alternate paths...'); - - // Try alternate path with electron-backend subdirectory - const alternatePath = path.join( - app.getAppPath().replace('app.asar', 'app.asar.unpacked'), - 'electron-backend', - 'workers', - 'epg-parser.worker.js' - ); - console.error(this.loggerLabel, 'Alternate path:', alternatePath); - - if (fs.existsSync(alternatePath)) { - workerPath = alternatePath; - console.log(this.loggerLabel, 'Using alternate path'); - } else { - reject(new Error(`Worker file not found at ${workerPath} or ${alternatePath}`)); - return; - } - } let worker: Worker; try { diff --git a/package.json b/package.json index ba6f6d415..04c83a746 100644 --- a/package.json +++ b/package.json @@ -24,11 +24,13 @@ "productName": "IPTVnator", "artifactName": "${name}-${version}-${os}-${arch}.${ext}", "files": [ - "**/*", + "electron-backend/**/*", + "web/**/*", + "remote-control-web/**/*", "!**/*.map" ], "asarUnpack": [ - "workers/**/*.js" + "electron-backend/workers/**" ], "mac": { "target": { From b7109c16a2a0c2b8569a352c6878fe3dd748799d Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:40:48 +0000 Subject: [PATCH 10/13] feat(package): update build directories and refine file inclusion for packaging --- package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 04c83a746..2f9b6202c 100644 --- a/package.json +++ b/package.json @@ -23,14 +23,21 @@ "appId": "com.fourgray.iptvnator", "productName": "IPTVnator", "artifactName": "${name}-${version}-${os}-${arch}.${ext}", + "directories": { + "buildResources": "dist/apps", + "output": "dist/executables" + }, "files": [ "electron-backend/**/*", "web/**/*", "remote-control-web/**/*", "!**/*.map" ], + "extraMetadata": { + "main": "electron-backend/main.js" + }, "asarUnpack": [ - "electron-backend/workers/**" + "**/workers/**" ], "mac": { "target": { From a948ce026512a5d7b00ba340d6eee346c4e07fc0 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 24 Nov 2025 20:46:15 +0100 Subject: [PATCH 11/13] feat(electron): bundle worker assets and resolve worker path Add webpack config and include it in the electron backend build so worker scripts are correctly bundled for packaged apps. Move worker files to be packaged as extraResources instead of asar unpack patterns so the packaged app can load worker JS from Resources/dist/... at runtime. Fix worker path resolution in epg.events: compute resourcesPath from app.getAppPath() and point to dist/apps/electron-backend/workers when app.isPackaged. Remove verbose app path logging and update comments to reflect the actual packaged layout. Why: ensure webworker entry points are included in the renderer/backend bundle and accessible when the Electron app is packaged, preventing worker loading failures in production builds. --- .claude/settings.local.json | 9 +- apps/electron-backend/build-worker.js | 44 + apps/electron-backend/project.json | 24 +- .../src/app/events/epg.events.ts | 69 +- .../src/app/workers/epg-parser.worker.ts | 45 +- package-lock.json | 1659 ++++++++++++++++- package.json | 5 +- 7 files changed, 1636 insertions(+), 219 deletions(-) create mode 100644 apps/electron-backend/build-worker.js diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7d693d23c..483910551 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,13 +5,16 @@ "WebSearch", "WebFetch(domain:www.electronjs.org)", "Bash(npm run build:frontend:*)", - "Bash(cat:*)" + "Bash(cat:*)", + "Bash(npx asar:*)", + "Bash(npm run package:app:*)", + "Bash(npm run build:backend:*)" ], "deny": [], "ask": [] }, + "enableAllProjectMcpServers": true, "enabledMcpjsonServers": [ "nx-mcp" - ], - "enableAllProjectMcpServers": true + ] } diff --git a/apps/electron-backend/build-worker.js b/apps/electron-backend/build-worker.js new file mode 100644 index 000000000..5fd6b8413 --- /dev/null +++ b/apps/electron-backend/build-worker.js @@ -0,0 +1,44 @@ +const esbuild = require('esbuild'); +const path = require('path'); + +// Node.js built-in modules that should be externalized +const nodeBuiltins = [ + 'assert', 'async_hooks', 'buffer', 'child_process', 'cluster', + 'console', 'constants', 'crypto', 'dgram', 'dns', 'domain', + 'events', 'fs', 'http', 'http2', 'https', 'inspector', 'module', + 'net', 'os', 'path', 'perf_hooks', 'process', 'punycode', + 'querystring', 'readline', 'repl', 'stream', 'string_decoder', + 'sys', 'timers', 'tls', 'trace_events', 'tty', 'url', 'util', + 'v8', 'vm', 'worker_threads', 'zlib' +]; + +const isProduction = process.env.NODE_ENV === 'production'; + +async function buildWorker() { + try { + console.log(`Building EPG parser worker with esbuild (${isProduction ? 'production' : 'development'})...`); + + await esbuild.build({ + entryPoints: [path.join(__dirname, 'src/app/workers/epg-parser.worker.ts')], + bundle: true, + platform: 'node', + target: 'node18', + format: 'cjs', + outfile: path.join(__dirname, '../../dist/apps/electron-backend/workers/epg-parser.worker.js'), + external: nodeBuiltins.map(m => `node:${m}`).concat(nodeBuiltins), + sourcemap: !isProduction, + minify: isProduction, + // Resolve workspace libraries from tsconfig paths + alias: { + 'shared-interfaces': path.join(__dirname, '../../libs/shared/interfaces/src/index.ts'), + }, + }); + + console.log('✅ Worker built successfully!'); + } catch (error) { + console.error('❌ Worker build failed:', error); + process.exit(1); + } +} + +buildWorker(); diff --git a/apps/electron-backend/project.json b/apps/electron-backend/project.json index d03e3a92c..ee532cb86 100644 --- a/apps/electron-backend/project.json +++ b/apps/electron-backend/project.json @@ -4,8 +4,16 @@ "sourceRoot": "apps/electron-backend/src", "projectType": "application", "targets": { + "build-worker": { + "executor": "nx:run-commands", + "outputs": ["{workspaceRoot}/dist/apps/electron-backend/workers"], + "options": { + "command": "node apps/electron-backend/build-worker.js" + } + }, "build": { "dependsOn": [ + "electron-backend:build-worker", { "projects": ["web", "remote-control-web"], "target": "build" @@ -17,20 +25,7 @@ "outputPath": "dist/apps/electron-backend", "main": "apps/electron-backend/src/main.ts", "tsConfig": "apps/electron-backend/tsconfig.app.json", - "assets": [ - "apps/electron-backend/src/assets", - { - "input": "apps/electron-backend/src/app/workers", - "glob": "*.worker.ts", - "output": "workers" - } - ], - "additionalEntryPoints": [ - { - "entryName": "workers/epg-parser.worker", - "entryPath": "apps/electron-backend/src/app/workers/epg-parser.worker.ts" - } - ] + "assets": ["apps/electron-backend/src/assets"] }, "configurations": { "production": { @@ -54,7 +49,6 @@ "nx run electron-backend:serve-electron" ] } - }, "serve-electron": { "executor": "nx-electron:execute", diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts index 500b17327..79d738389 100644 --- a/apps/electron-backend/src/app/events/epg.events.ts +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -24,8 +24,6 @@ export default class EpgEvents { * Bootstrap EPG events */ static bootstrapEpgEvents(): Electron.IpcMain { - console.log('[EPG Events] Bootstrapping EPG events...'); - // Fetch EPG from URLs ipcMain.handle('FETCH_EPG', async (event, args: { url: string[] }) => { return await this.handleFetchEpg(args.url); @@ -79,7 +77,7 @@ export default class EpgEvents { await Promise.all(promises); return { success: true }; } catch (error) { - console.error('[EPG Events] Error fetching EPG:', error); + console.error(this.loggerLabel, 'Error fetching EPG:', error); return { success: false, message: error instanceof Error ? error.message : String(error), @@ -93,21 +91,19 @@ export default class EpgEvents { private static async fetchEpgFromUrl(url: string): Promise { // Skip if already fetched if (this.fetchedUrls.has(url)) { - console.log(this.loggerLabel, 'URL already fetched:', url); return; } return new Promise((resolve, reject) => { - // Get the proper worker path following Electron's recommended approach - // https://www.electronjs.org/docs/latest/tutorial/multithreading let workerPath: string; - + if (app.isPackaged) { - // In packaged app: Resources/app.asar.unpacked/electron-backend/workers/epg-parser.worker.js - const appPath = app.getAppPath(); - const unpackedPath = appPath.replace('app.asar', 'app.asar.unpacked'); + // In packaged app: Resources/dist/apps/electron-backend/workers/epg-parser.worker.js + const resourcesPath = path.dirname(app.getAppPath()); workerPath = path.join( - unpackedPath, + resourcesPath, + 'dist', + 'apps', 'electron-backend', 'workers', 'epg-parser.worker.js' @@ -117,17 +113,11 @@ export default class EpgEvents { workerPath = path.join(__dirname, 'workers', 'epg-parser.worker.js'); } - console.log(this.loggerLabel, 'Creating worker for:', url); - console.log(this.loggerLabel, 'Worker path:', workerPath); - console.log(this.loggerLabel, 'App path:', app.getAppPath()); - console.log(this.loggerLabel, 'Is packaged:', app.isPackaged); - let worker: Worker; try { // Worker threads require file:// URLs wrapped in URL object for packaged apps const workerURL = pathToFileURL(workerPath); worker = new Worker(workerURL); - console.log(this.loggerLabel, 'Worker created successfully'); } catch (error) { console.error( this.loggerLabel, @@ -149,16 +139,8 @@ export default class EpgEvents { url?: string; }) => { if (message.type === 'READY') { - console.log( - this.loggerLabel, - 'Worker ready, sending fetch command' - ); worker.postMessage({ type: 'FETCH_EPG', url }); } else if (message.type === 'EPG_PARSED') { - console.log( - this.loggerLabel, - 'EPG parsed in worker, merging data...' - ); if (message.data) { this.mergeEpgData(message.data); this.fetchedUrls.add(url); @@ -201,11 +183,6 @@ export default class EpgEvents { * Merge EPG data (optimized for large datasets) */ private static mergeEpgData(newData: EpgData): void { - console.log( - this.loggerLabel, - `Merging ${newData.channels.length} channels and ${newData.programs.length} programs...` - ); - // Merge channels (avoid duplicates) const existingChannelIds = new Set( this.epgData.channels.map((c) => c.id) @@ -226,11 +203,6 @@ export default class EpgEvents { // Rebuild merged data structure this.rebuildMergedData(); - - console.log( - this.loggerLabel, - `Merged EPG data: ${this.epgData.channels.length} channels, ${this.epgData.programs.length} programs` - ); } /** @@ -238,7 +210,6 @@ export default class EpgEvents { * Optimized for large datasets */ private static rebuildMergedData(): void { - console.log(this.loggerLabel, 'Rebuilding merged data structure...'); this.epgDataMerged.clear(); // Create channel lookup map for O(1) access @@ -265,31 +236,17 @@ export default class EpgEvents { }); } } - - console.log( - this.loggerLabel, - `Rebuild complete. ${this.epgDataMerged.size} channels with programs` - ); } /** * Get programs for a specific channel */ private static handleGetChannelPrograms(channelId: string): EpgProgram[] { - console.log('[EPG Events] Getting programs for channel:', channelId); - console.log( - '[EPG Events] Total merged channels:', - this.epgDataMerged.size - ); - // First try exact ID match let channelData = this.epgDataMerged.get(channelId); // If not found, try to find by display name if (!channelData) { - console.log( - '[EPG Events] No exact match, searching by display name...' - ); for (const [id, channel] of this.epgDataMerged.entries()) { const displayNames = channel.displayName.map((d) => d.value.toLowerCase() @@ -302,22 +259,12 @@ export default class EpgEvents { channelId.toLowerCase().includes(name) ) ) { - console.log( - '[EPG Events] Found match by name:', - id, - '→', - channel.displayName[0]?.value - ); channelData = channel; break; } } } - console.log( - '[EPG Events] Found programs:', - channelData?.programs?.length || 0 - ); return channelData?.programs || []; } @@ -343,7 +290,5 @@ export default class EpgEvents { // Terminate all workers this.workers.forEach((worker) => worker.terminate()); this.workers.clear(); - - console.log(this.loggerLabel, 'EPG data cleared'); } } diff --git a/apps/electron-backend/src/app/workers/epg-parser.worker.ts b/apps/electron-backend/src/app/workers/epg-parser.worker.ts index 52a2f33d2..cbf56a20e 100644 --- a/apps/electron-backend/src/app/workers/epg-parser.worker.ts +++ b/apps/electron-backend/src/app/workers/epg-parser.worker.ts @@ -1,4 +1,3 @@ -import axios from 'axios'; import { parse as parseEpg } from 'epg-parser'; import { EpgData, EpgProgram } from 'shared-interfaces'; import { parentPort } from 'worker_threads'; @@ -29,32 +28,28 @@ const loggerLabel = '[EPG Worker]'; */ async function fetchAndParseEpg(url: string): Promise { try { - console.log(loggerLabel, 'Fetching EPG from:', url); - const isGzipped = url.endsWith('.gz'); - const axiosConfig = isGzipped - ? { responseType: 'arraybuffer' as const } - : {}; - const response = await axios.get(url.trim(), axiosConfig); - console.log( - loggerLabel, - 'EPG data fetched, size:', - response.data.length - ); + // Use native fetch (available in Node.js 18+) + const response = await fetch(url.trim()); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } let xmlString: string; if (isGzipped) { - console.log(loggerLabel, 'Unzipping...'); - const buffer = Buffer.from(response.data); + // For gzipped files, get as ArrayBuffer + const arrayBuffer = await response.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); const decompressed = gunzipSync(buffer); xmlString = decompressed.toString('utf-8'); } else { - xmlString = response.data; + // For regular files, get as text + xmlString = await response.text(); } - console.log(loggerLabel, 'Parsing EPG XML...'); const parsed = parseEpg(xmlString); // Normalize data to match our interface @@ -89,11 +84,6 @@ async function fetchAndParseEpg(url: string): Promise { ) as EpgProgram[], }; - console.log( - loggerLabel, - `Parsed ${normalized.channels.length} channels and ${normalized.programs.length} programs` - ); - return normalized; } catch (error) { console.error( @@ -109,20 +99,12 @@ async function fetchAndParseEpg(url: string): Promise { * Worker message handler */ if (parentPort) { - console.log(loggerLabel, 'Worker initialized and ready'); - parentPort.on('message', async (message: WorkerMessage) => { - console.log(loggerLabel, 'Received message:', message.type); try { if ( message.type === 'FETCH_EPG' || message.type === 'FORCE_FETCH' ) { - console.log( - loggerLabel, - 'Starting EPG fetch for:', - message.url - ); const parsedData = await fetchAndParseEpg(message.url); const response: WorkerResponse = { @@ -131,10 +113,6 @@ if (parentPort) { url: message.url, }; - console.log( - loggerLabel, - 'Sending parsed data back to main thread' - ); parentPort?.postMessage(response); } } catch (error) { @@ -150,7 +128,6 @@ if (parentPort) { }); // Notify parent that worker is ready - console.log(loggerLabel, 'Sending READY message'); parentPort.postMessage({ type: 'READY' }); } else { console.error(loggerLabel, 'parentPort is not available!'); diff --git a/package-lock.json b/package-lock.json index 3c57daf19..c39cb15b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -112,6 +112,7 @@ "drizzle-kit": "0.31.5", "electron": "^39.0.0", "electron-builder": "^26.0.12", + "esbuild": "0.27.0", "eslint": "^9.8.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "2.32.0", @@ -5215,9 +5216,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", "cpu": [ "ppc64" ], @@ -5283,9 +5284,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", "cpu": [ "arm64" ], @@ -5504,9 +5505,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", "cpu": [ "arm64" ], @@ -5538,9 +5539,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", "cpu": [ "arm64" ], @@ -7653,6 +7654,472 @@ "esbuild": "0.25.5" } }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@modern-js/node-bundle-require/node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, "node_modules/@modern-js/utils": { "version": "2.68.2", "resolved": "https://registry.npmjs.org/@modern-js/utils/-/utils-2.68.2.tgz", @@ -18241,6 +18708,490 @@ "drizzle-kit": "bin.cjs" } }, + "node_modules/drizzle-kit/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/drizzle-kit/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, "node_modules/drizzle-orm": { "version": "0.44.6", "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.44.6.tgz", @@ -19119,9 +20070,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -19132,31 +20083,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" } }, "node_modules/esbuild-register": { @@ -19186,9 +20138,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", "cpu": [ "arm" ], @@ -19203,9 +20155,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", "cpu": [ "arm64" ], @@ -19220,9 +20172,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", "cpu": [ "x64" ], @@ -19237,9 +20189,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", "cpu": [ "x64" ], @@ -19254,9 +20206,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", "cpu": [ "arm64" ], @@ -19271,9 +20223,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", "cpu": [ "x64" ], @@ -19288,9 +20240,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", "cpu": [ "arm" ], @@ -19305,9 +20257,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", "cpu": [ "arm64" ], @@ -19322,9 +20274,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", "cpu": [ "ia32" ], @@ -19339,9 +20291,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", "cpu": [ "loong64" ], @@ -19356,9 +20308,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", "cpu": [ "mips64el" ], @@ -19373,9 +20325,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", "cpu": [ "ppc64" ], @@ -19390,9 +20342,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", "cpu": [ "riscv64" ], @@ -19407,9 +20359,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", "cpu": [ "s390x" ], @@ -19424,9 +20376,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", "cpu": [ "x64" ], @@ -19441,9 +20393,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", "cpu": [ "x64" ], @@ -19458,9 +20410,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", "cpu": [ "x64" ], @@ -19474,10 +20426,27 @@ "node": ">=18" } }, + "node_modules/esbuild/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", "cpu": [ "x64" ], @@ -19492,9 +20461,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", "cpu": [ "arm64" ], @@ -19509,9 +20478,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", "cpu": [ "ia32" ], @@ -19526,9 +20495,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", "cpu": [ "x64" ], @@ -38306,6 +39275,490 @@ } } }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", diff --git a/package.json b/package.json index 2f9b6202c..72e106562 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "extraMetadata": { "main": "electron-backend/main.js" }, - "asarUnpack": [ - "**/workers/**" + "extraResources": [ + "dist/apps/electron-backend/workers" ], "mac": { "target": { @@ -201,6 +201,7 @@ "drizzle-kit": "0.31.5", "electron": "^39.0.0", "electron-builder": "^26.0.12", + "esbuild": "0.27.0", "eslint": "^9.8.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "2.32.0", From 7918c4849d21a4b3c0e1a1568e31ff251a2ad9b3 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 24 Nov 2025 21:25:10 +0100 Subject: [PATCH 12/13] fix: suppress snackbar for portal status checks and log them Refactor error handling for Xtream requests to avoid showing user snackbars when the request is a portal status check (get_account_info). Instead of treating these errors as full failures, log them with console.log to indicate the portal may be unavailable and return early. Key changes: - Introduce isStatusCheck detection in electron and pwa services. - Replace console.error + snackbar with console.log for status checks. - Only display snackbars for non-status-check errors. - Add a console.log when pwa response has no payload for status checks. This prevents unnecessary user-facing error popups for routine portal health/status checks while keeping errors surfaced for other requests. --- apps/web/src/app/services/electron.service.ts | 32 +++++++++++++------ apps/web/src/app/services/pwa.service.ts | 15 +++++++-- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/apps/web/src/app/services/electron.service.ts b/apps/web/src/app/services/electron.service.ts index 5b6cc0135..cee7b310f 100644 --- a/apps/web/src/app/services/electron.service.ts +++ b/apps/web/src/app/services/electron.service.ts @@ -226,16 +226,28 @@ export class ElectronService extends DataService { window.postMessage(result); return result; } catch (error: any) { - console.error('Xtream request error:', error.message); - this.snackBar.open( - `Error: ${error.message ?? 'Failed to connect to Xtream server'}, status: ${ - error.status ?? 500 - }`, - 'Close', - { - duration: 5000, - } - ); + const isStatusCheck = payload.params?.action === 'get_account_info'; + + // Log error to console + if (isStatusCheck) { + console.log('Portal status check failed - portal may be unavailable:', error.message || error); + } else { + console.error('Xtream request error:', error.message); + } + + // Only show snackbar for non-status-check requests + if (!isStatusCheck) { + this.snackBar.open( + `Error: ${error.message ?? 'Failed to connect to Xtream server'}, status: ${ + error.status ?? 500 + }`, + 'Close', + { + duration: 5000, + } + ); + } + return { type: ERROR, status: error.status ?? 500, diff --git a/apps/web/src/app/services/pwa.service.ts b/apps/web/src/app/services/pwa.service.ts index 000bfdda8..e4535f2e0 100644 --- a/apps/web/src/app/services/pwa.service.ts +++ b/apps/web/src/app/services/pwa.service.ts @@ -186,7 +186,10 @@ export class PwaService extends DataService { ); if (!(response as any).payload) { - if (payload.params.action === 'get_account_info') return; + if (payload.params.action === 'get_account_info') { + console.log('Portal status check failed - portal may be unavailable:', (response as any).message || 'No payload received'); + return; + } result = { type: ERROR, @@ -204,7 +207,15 @@ export class PwaService extends DataService { } return result; } catch (error: any) { - if (payload.params.action === 'get_account_info') return; + const isStatusCheck = payload.params.action === 'get_account_info'; + + // Log error to console + if (isStatusCheck) { + console.log('Portal status check failed - portal may be unavailable:', error.message || error); + return; + } + + console.error('Xtream request error:', error.message); this.snackBar.open( `Error: ${error.message ?? ' Unknown error'}, status: ${ error.status ?? 500 From 008f267808ce39a279312d498a7a4f8f31fb0edd Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 24 Nov 2025 22:29:42 +0100 Subject: [PATCH 13/13] feat(ui/epg-list): replace mat-list with custom markup and add progress Refactor EPG list template to remove Material selection list and dividers, replacing them with plain markup and CSS-friendly elements. Key changes: - Replace with .header-divider for consistent styling. - Replace mat-selection-list/mat-list-option with plain divs (.program-item, .program-meta, .program-title) to allow richer DOM structure and avoid Material selection semantics. - Use track $index in ngFor to stabilize rendering and avoid using program start/stop concatenation as key. - Render live progress bar inside program items when a program is playing, using calculateProgress(program) to set width. - Convert empty-state

to .epg-not-available div for layout consistency. - Add clickable class and active class binding to interactive items. Code changes and cleanup: - Update component imports to use ChangeDetectionStrategy and ChangeDetectorRef and remove unused Material imports (MatDivider, MatListModule) from the component file. - Adjust template bindings: use [innerHTML] and class bindings instead of matList directives. Why: - Remove heavy dependency on Material selection list to gain finer control over DOM and styles, enable custom progress UI and clickable behavior, and simplify template for better performance and maintainability. --- .../epg-list-item.component.scss | 104 ++++++++-- .../src/lib/epg-list/epg-list.component.html | 62 +++--- .../src/lib/epg-list/epg-list.component.scss | 181 +++++++++++++++--- .../src/lib/epg-list/epg-list.component.ts | 41 +++- 4 files changed, 317 insertions(+), 71 deletions(-) diff --git a/libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.scss b/libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.scss index 62700d796..fb8d24679 100644 --- a/libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.scss +++ b/libs/ui/components/src/lib/epg-list/epg-list-item/epg-list-item.component.scss @@ -1,30 +1,106 @@ +:host { + display: flex; + align-items: center; + gap: 8px; + width: 100%; +} + .time { - color: #666; - border-bottom: 1px solid #ccc; - font-size: 0.8em; - display: inline-block; - margin-bottom: 5px; - margin-left: 5px; + font-family: 'DM Sans', sans-serif; + font-size: 0.7rem; + opacity: 0.6; + letter-spacing: 0.02em; + line-height: 1; + white-space: nowrap; } .badge { - border-radius: 2px; - padding: 2px 6px; - color: #fff; + border-radius: 4px; + padding: 3px 8px; + color: white; text-transform: uppercase; - margin-left: 6px; - font-size: 0.8em; + font-size: 10px; + font-weight: 600; + letter-spacing: 0.08em; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 40px; + transition: all 0.2s ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } .live { - background-color: red; + background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + animation: livePulse 2s ease-in-out infinite; + box-shadow: 0 0 12px rgba(239, 68, 68, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3); + + &::after { + content: '●'; + margin-left: 4px; + animation: blink 1.5s ease-in-out infinite; + } } .rec { - background-color: grey; + background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); + box-shadow: 0 0 12px rgba(139, 92, 246, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3); + + &::after { + content: '◉'; + margin-left: 4px; + } } .description-icon { - float: right; + margin-left: auto; cursor: pointer; + opacity: 0.6; + transition: all 0.2s ease; + padding: 4px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + + mat-icon { + font-size: 18px; + width: 18px; + height: 18px; + } + + &:hover { + opacity: 1; + background: rgba(0, 0, 0, 0.04); + } + + &:active { + transform: scale(0.95); + } +} + +// Dark theme support +::ng-deep .dark-theme { + .description-icon:hover { + background: rgba(255, 255, 255, 0.04); + } +} + +// Animations +@keyframes livePulse { + 0%, 100% { + box-shadow: 0 0 12px rgba(239, 68, 68, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3); + } + 50% { + box-shadow: 0 0 20px rgba(239, 68, 68, 0.8), 0 2px 12px rgba(0, 0, 0, 0.4); + } +} + +@keyframes blink { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.3; + } } diff --git a/libs/ui/components/src/lib/epg-list/epg-list.component.html b/libs/ui/components/src/lib/epg-list/epg-list.component.html index 260047d49..58cfeb869 100644 --- a/libs/ui/components/src/lib/epg-list/epg-list.component.html +++ b/libs/ui/components/src/lib/epg-list/epg-list.component.html @@ -23,7 +23,7 @@