Merge pull request #751 from 4gray/fix/epg-keep-expired-items

Fix/epg-keep-expired-items
This commit is contained in:
4gray authored and GitHub committed 2026-02-03 07:49:43 +01:00
commit b101dfaf91
6 files changed
+141 -647

No files matched your search

@@ -128,12 +128,8 @@ ipcMain.handle(
async (_event, channelId: string, fromTime?: string, toTime?: string) => {
try {
const db = await getDatabase();
const now = new Date().toISOString();
let query = db
.select()
.from(schema.epgPrograms)
.where(eq(schema.epgPrograms.channelId, channelId));
let query;
// Apply time filters if provided
if (fromTime && toTime) {
@@ -148,16 +144,11 @@ ipcMain.handle(
)
);
} else {
// Default: from now onwards
// Return all programs for this channel
query = db
.select()
.from(schema.epgPrograms)
.where(
and(
eq(schema.epgPrograms.channelId, channelId),
gte(schema.epgPrograms.stop, now)
)
);
.where(eq(schema.epgPrograms.channelId, channelId));
}
const results = await query.orderBy(schema.epgPrograms.start);
@@ -176,29 +167,32 @@ ipcMain.handle(
/**
* Get current program for a channel (what's on now)
*/
ipcMain.handle('EPG_DB_GET_CURRENT_PROGRAM', async (_event, channelId: string) => {
try {
const db = await getDatabase();
const now = new Date().toISOString();
ipcMain.handle(
'EPG_DB_GET_CURRENT_PROGRAM',
async (_event, channelId: string) => {
try {
const db = await getDatabase();
const now = new Date().toISOString();
const result = await db
.select()
.from(schema.epgPrograms)
.where(
and(
eq(schema.epgPrograms.channelId, channelId),
lte(schema.epgPrograms.start, now),
gte(schema.epgPrograms.stop, now)
const result = await db
.select()
.from(schema.epgPrograms)
.where(
and(
eq(schema.epgPrograms.channelId, channelId),
lte(schema.epgPrograms.start, now),
gte(schema.epgPrograms.stop, now)
)
)
)
.limit(1);
.limit(1);
return result[0] || null;
} catch (error) {
console.error(loggerLabel, 'Error getting current program:', error);
throw error;
return result[0] || null;
} catch (error) {
console.error(loggerLabel, 'Error getting current program:', error);
throw error;
}
}
});
);
/**
* Full-text search EPG programs using FTS5 with LIKE fallback
@@ -210,7 +204,6 @@ ipcMain.handle(
async (_event, searchTerm: string, limit = 50) => {
try {
const db = await getDatabase();
const now = new Date().toISOString();
const trimmedTerm = searchTerm.trim();
if (!trimmedTerm) {
@@ -222,6 +215,7 @@ ipcMain.handle(
const likePattern = `%${trimmedTerm}%`;
// JOIN with epg_channels to get channel display name
// Include all programs (past and future) for catchup/archive feature
const results = await db.all(sql`
SELECT
p.*,
@@ -233,7 +227,6 @@ ipcMain.handle(
OR p.description LIKE ${likePattern}
OR p.category LIKE ${likePattern}
)
AND p.stop >= ${now}
ORDER BY p.start
LIMIT ${limit}
`);
@@ -266,59 +259,37 @@ ipcMain.handle('EPG_DB_GET_CHANNELS', async () => {
/**
* Get channel by ID or display name
*/
ipcMain.handle('EPG_DB_GET_CHANNEL', async (_event, channelIdOrName: string) => {
try {
const db = await getDatabase();
ipcMain.handle(
'EPG_DB_GET_CHANNEL',
async (_event, channelIdOrName: string) => {
try {
const db = await getDatabase();
// Try exact ID match first
let result = await db
.select()
.from(schema.epgChannels)
.where(eq(schema.epgChannels.id, channelIdOrName))
.limit(1);
// Try exact ID match first
let result = await db
.select()
.from(schema.epgChannels)
.where(eq(schema.epgChannels.id, channelIdOrName))
.limit(1);
if (result.length > 0) return result[0];
if (result.length > 0) return result[0];
// Try display name match (case-insensitive)
result = await db
.select()
.from(schema.epgChannels)
.where(
sql`LOWER(${schema.epgChannels.displayName}) = LOWER(${channelIdOrName})`
)
.limit(1);
// Try display name match (case-insensitive)
result = await db
.select()
.from(schema.epgChannels)
.where(
sql`LOWER(${schema.epgChannels.displayName}) = LOWER(${channelIdOrName})`
)
.limit(1);
return result[0] || null;
} catch (error) {
console.error(loggerLabel, 'Error getting EPG channel:', error);
throw error;
return result[0] || null;
} catch (error) {
console.error(loggerLabel, 'Error getting EPG channel:', error);
throw error;
}
}
});
/**
* Cleanup expired programs (older than specified hours)
*/
ipcMain.handle('EPG_DB_CLEANUP_EXPIRED', async (_event, hoursToKeep = 24) => {
try {
const db = await getDatabase();
const cutoff = new Date(
Date.now() - hoursToKeep * 60 * 60 * 1000
).toISOString();
const result = await db
.delete(schema.epgPrograms)
.where(lte(schema.epgPrograms.stop, cutoff));
console.log(
loggerLabel,
`Cleaned up expired programs (older than ${hoursToKeep}h)`
);
return { success: true };
} catch (error) {
console.error(loggerLabel, 'Error cleaning up EPG programs:', error);
throw error;
}
});
);
/**
* Clear all EPG data for a specific source URL
@@ -1,4 +1,4 @@
import { and, eq, gte, sql } from 'drizzle-orm';
import { eq, sql } from 'drizzle-orm';
import { app, BrowserWindow, ipcMain } from 'electron';
import * as path from 'path';
import { EpgProgram } from 'shared-interfaces';
@@ -75,14 +75,6 @@ export default class EpgEvents {
return await this.handleFetchEpg([url]);
});
// Cleanup expired programs (uses worker thread)
ipcMain.handle(
'EPG_CLEANUP_EXPIRED',
async (_event, hoursToKeep?: number) => {
return this.runCleanupInWorker(hoursToKeep ?? 24);
}
);
// Clear all EPG data
ipcMain.handle('EPG_CLEAR_ALL', async () => {
await this.clearEpgData();
@@ -280,7 +272,11 @@ export default class EpgEvents {
// In packaged app, native modules are in app.asar.unpacked/node_modules
// which is separate from the worker location in extraResources
const nativeModulesPath = app.isPackaged
? path.join(path.dirname(app.getAppPath()), 'app.asar.unpacked', 'node_modules')
? path.join(
path.dirname(app.getAppPath()),
'app.asar.unpacked',
'node_modules'
)
: undefined;
worker = new Worker(workerURL, {
resourceLimits: {
@@ -348,18 +344,6 @@ export default class EpgEvents {
message.stats
);
this.fetchedUrls.add(url);
// Trigger cleanup in worker thread (non-blocking)
worker.postMessage({
type: 'CLEANUP_EXPIRED',
hoursToKeep: 24,
});
break;
case 'CLEANUP_COMPLETE':
console.log(
this.loggerLabel,
'Cleanup complete, terminating worker'
);
worker.terminate();
this.workers.delete(url);
resolve();
@@ -450,20 +434,14 @@ export default class EpgEvents {
): Promise<EpgProgram[]> {
try {
const db = await getDatabase();
const now = new Date().toISOString();
// Try exact channel ID match first
let results = await db
.select()
.from(schema.epgPrograms)
.where(
and(
eq(schema.epgPrograms.channelId, channelId),
gte(schema.epgPrograms.stop, now)
)
)
.where(eq(schema.epgPrograms.channelId, channelId))
.orderBy(schema.epgPrograms.start)
.limit(100);
.limit(500);
if (results.length > 0) {
return results.map(this.transformDbRowToEpgProgram);
@@ -482,14 +460,9 @@ export default class EpgEvents {
results = await db
.select()
.from(schema.epgPrograms)
.where(
and(
eq(schema.epgPrograms.channelId, channel[0].id),
gte(schema.epgPrograms.stop, now)
)
)
.where(eq(schema.epgPrograms.channelId, channel[0].id))
.orderBy(schema.epgPrograms.start)
.limit(100);
.limit(500);
return results.map(this.transformDbRowToEpgProgram);
}
@@ -587,88 +560,6 @@ export default class EpgEvents {
}
}
/**
* Run cleanup in worker thread to avoid blocking main thread
*/
private static async runCleanupInWorker(
hoursToKeep: number
): Promise<{ success: boolean }> {
return new Promise((resolve, reject) => {
let workerPath: string;
if (app.isPackaged) {
const resourcesPath = path.dirname(app.getAppPath());
workerPath = path.join(
resourcesPath,
'dist',
'apps',
'electron-backend',
'workers',
'epg-parser.worker.js'
);
} else {
workerPath = path.join(
__dirname,
'workers',
'epg-parser.worker.js'
);
}
let worker: Worker;
try {
const workerURL = pathToFileURL(workerPath);
// In packaged app, native modules are in app.asar.unpacked/node_modules
const nativeModulesPath = app.isPackaged
? path.join(path.dirname(app.getAppPath()), 'app.asar.unpacked', 'node_modules')
: undefined;
worker = new Worker(workerURL, {
workerData: { nativeModulesPath },
});
} catch (error) {
console.error(
this.loggerLabel,
'Failed to create worker for cleanup:',
error
);
reject(error);
return;
}
worker.on(
'message',
(message: { type: string; error?: string }) => {
if (message.type === 'READY') {
worker.postMessage({
type: 'CLEANUP_EXPIRED',
hoursToKeep,
});
} else if (message.type === 'CLEANUP_COMPLETE') {
worker.terminate();
resolve({ success: true });
} else if (message.type === 'EPG_ERROR') {
console.error(
this.loggerLabel,
'Worker cleanup error:',
message.error
);
worker.terminate();
reject(new Error(message.error || 'Cleanup failed'));
}
}
);
worker.on('error', (error) => {
console.error(
this.loggerLabel,
'Worker error during cleanup:',
error
);
worker.terminate();
reject(error);
});
});
}
/**
* Clear all EPG data using worker thread to avoid blocking main thread
*/
@@ -699,7 +590,11 @@ export default class EpgEvents {
const workerURL = pathToFileURL(workerPath);
// In packaged app, native modules are in app.asar.unpacked/node_modules
const nativeModulesPath = app.isPackaged
? path.join(path.dirname(app.getAppPath()), 'app.asar.unpacked', 'node_modules')
? path.join(
path.dirname(app.getAppPath()),
'app.asar.unpacked',
'node_modules'
)
: undefined;
worker = new Worker(workerURL, {
workerData: { nativeModulesPath },
@@ -1,12 +1,12 @@
import { parentPort, workerData } from 'worker_threads';
import { createGunzip } from 'zlib';
import type BetterSqlite3 from 'better-sqlite3';
import { existsSync, mkdirSync } from 'fs';
import { createRequire } from 'module';
import { homedir } from 'os';
import { join } from 'path';
import { SaxesParser, SaxesTagPlain } from 'saxes';
import { Readable } from 'stream';
import { existsSync, mkdirSync } from 'fs';
import { homedir } from 'os';
import { join, dirname } from 'path';
import { createRequire } from 'module';
import type BetterSqlite3 from 'better-sqlite3';
import { parentPort, workerData } from 'worker_threads';
import { createGunzip } from 'zlib';
// In packaged app, native modules are in app.asar.unpacked/node_modules
// which is separate from the worker location in extraResources
@@ -14,25 +14,46 @@ let Database: typeof BetterSqlite3;
function loadBetterSqlite3(): typeof BetterSqlite3 {
// Try workerData path first (passed from main process)
if (workerData?.nativeModulesPath && existsSync(workerData.nativeModulesPath)) {
if (
workerData?.nativeModulesPath &&
existsSync(workerData.nativeModulesPath)
) {
try {
const nativeRequire = createRequire(join(workerData.nativeModulesPath, 'index.js'));
const nativeRequire = createRequire(
join(workerData.nativeModulesPath, 'index.js')
);
return nativeRequire('better-sqlite3');
} catch (e) {
console.error('[EPG Worker] Failed to load from workerData path:', e);
console.error(
'[EPG Worker] Failed to load from workerData path:',
e
);
}
}
// Try process.resourcesPath (available in packaged Electron apps)
if ((process as NodeJS.Process & { resourcesPath?: string }).resourcesPath) {
const resourcesPath = (process as NodeJS.Process & { resourcesPath?: string }).resourcesPath!;
const unpackedPath = join(resourcesPath, 'app.asar.unpacked', 'node_modules');
if (
(process as NodeJS.Process & { resourcesPath?: string }).resourcesPath
) {
const resourcesPath = (
process as NodeJS.Process & { resourcesPath?: string }
).resourcesPath!;
const unpackedPath = join(
resourcesPath,
'app.asar.unpacked',
'node_modules'
);
if (existsSync(unpackedPath)) {
try {
const nativeRequire = createRequire(join(unpackedPath, 'index.js'));
const nativeRequire = createRequire(
join(unpackedPath, 'index.js')
);
return nativeRequire('better-sqlite3');
} catch (e) {
console.error('[EPG Worker] Failed to load from resourcesPath:', e);
console.error(
'[EPG Worker] Failed to load from resourcesPath:',
e
);
}
}
}
@@ -97,9 +118,8 @@ interface ParsedProgram {
*/
interface WorkerMessage {
type: 'FETCH_EPG' | 'FORCE_FETCH' | 'CLEAR_EPG' | 'CLEANUP_EXPIRED';
type: 'FETCH_EPG' | 'FORCE_FETCH' | 'CLEAR_EPG';
url?: string;
hoursToKeep?: number;
}
interface WorkerResponse {
@@ -108,7 +128,6 @@ interface WorkerResponse {
| 'EPG_ERROR'
| 'EPG_PROGRESS'
| 'CLEAR_COMPLETE'
| 'CLEANUP_COMPLETE'
| 'READY';
error?: string;
url?: string;
@@ -124,34 +143,6 @@ const loggerLabel = '[EPG Worker]';
const CHANNEL_BATCH_SIZE = 100;
const PROGRAM_BATCH_SIZE = 1000;
// Skip programs that ended more than this many hours ago
const SKIP_PROGRAMS_OLDER_THAN_HOURS = 2;
/**
* Calculate the cutoff time for filtering old programs
* Programs that ended before this time will be skipped
*/
function getProgramCutoffTime(): Date {
return new Date(Date.now() - SKIP_PROGRAMS_OLDER_THAN_HOURS * 60 * 60 * 1000);
}
/**
* Check if a program has already ended (is expired)
* Handles timezone-aware ISO date strings
*/
function isProgramExpired(stopTime: string, cutoff: Date): boolean {
if (!stopTime) return true; // Skip programs without stop time
try {
const stopDate = new Date(stopTime);
// Check if the date is valid
if (isNaN(stopDate.getTime())) return false; // Don't skip if we can't parse
return stopDate < cutoff;
} catch {
return false; // Don't skip if parsing fails
}
}
/**
* Get database file path (same as main app)
*/
@@ -220,7 +211,8 @@ class EpgDatabase {
insertChannels(channels: ParsedChannel[], sourceUrl: string): void {
const insertMany = this.db.transaction((channels: ParsedChannel[]) => {
for (const channel of channels) {
const displayName = channel.displayName?.[0]?.value || channel.id;
const displayName =
channel.displayName?.[0]?.value || channel.id;
const iconUrl = channel.icon?.[0]?.src || null;
const url = channel.url?.[0] || null;
@@ -323,10 +315,6 @@ class StreamingEpgParser {
private programs: ParsedProgram[] = [];
private totalChannels = 0;
private totalPrograms = 0;
private skippedPrograms = 0;
// Cutoff time for filtering old programs (calculated once at start)
private readonly cutoffTime: Date;
// Current element being parsed
private currentChannel: Partial<ParsedChannel> | null = null;
@@ -343,7 +331,6 @@ class StreamingEpgParser {
private onProgress: (channels: number, programs: number) => void
) {
this.parser = new SaxesParser();
this.cutoffTime = getProgramCutoffTime();
this.setupParser();
}
@@ -452,7 +439,9 @@ class StreamingEpgParser {
if (text) this.currentChannel.url!.push(text);
break;
case 'channel':
this.channels.push(this.currentChannel as ParsedChannel);
this.channels.push(
this.currentChannel as ParsedChannel
);
this.totalChannels++;
this.currentChannel = null;
@@ -504,16 +493,13 @@ class StreamingEpgParser {
}
break;
case 'programme':
// Skip programs that have already ended
if (isProgramExpired(this.currentProgram.stop!, this.cutoffTime)) {
this.skippedPrograms++;
} else {
this.programs.push(this.currentProgram as ParsedProgram);
this.totalPrograms++;
this.programs.push(
this.currentProgram as ParsedProgram
);
this.totalPrograms++;
if (this.programs.length >= PROGRAM_BATCH_SIZE) {
this.flushPrograms();
}
if (this.programs.length >= PROGRAM_BATCH_SIZE) {
this.flushPrograms();
}
this.currentProgram = null;
break;
@@ -549,22 +535,14 @@ class StreamingEpgParser {
this.parser.write(chunk);
}
finish(): { totalChannels: number; totalPrograms: number; skippedPrograms: number } {
finish(): { totalChannels: number; totalPrograms: number } {
this.parser.close();
this.flushChannels();
this.flushPrograms();
if (this.skippedPrograms > 0) {
console.log(
loggerLabel,
`Skipped ${this.skippedPrograms} expired programs (ended more than ${SKIP_PROGRAMS_OLDER_THAN_HOURS}h ago)`
);
}
return {
totalChannels: this.totalChannels,
totalPrograms: this.totalPrograms,
skippedPrograms: this.skippedPrograms,
};
}
}
@@ -650,10 +628,7 @@ async function fetchAndParseEpgStreaming(url: string): Promise<void> {
const stats = parser.finish();
console.log(
loggerLabel,
`Parsing complete: ${stats.totalChannels} channels, ${stats.totalPrograms} programs` +
(stats.skippedPrograms > 0
? ` (skipped ${stats.skippedPrograms} expired)`
: '')
`Parsing complete: ${stats.totalChannels} channels, ${stats.totalPrograms} programs`
);
// Close database connection
@@ -719,40 +694,6 @@ function clearAllEpgData(): void {
}
}
/**
* Cleans up expired EPG programs from the database
* Runs in worker thread to avoid blocking main thread
*/
function cleanupExpiredPrograms(hoursToKeep: number): void {
const dbPath = getDatabasePath();
const db = new Database(dbPath);
try {
const cutoff = new Date(
Date.now() - hoursToKeep * 60 * 60 * 1000
).toISOString();
console.log(loggerLabel, `Cleaning up programs older than ${hoursToKeep}h (before ${cutoff})...`);
const stmt = db.prepare('DELETE FROM epg_programs WHERE stop <= ?');
const result = stmt.run(cutoff);
console.log(loggerLabel, `Cleaned up ${result.changes} expired programs`);
const response: WorkerResponse = { type: 'CLEANUP_COMPLETE' };
parentPort?.postMessage(response);
} catch (error) {
console.error(loggerLabel, 'Error cleaning up expired programs:', error);
const errorResponse: WorkerResponse = {
type: 'EPG_ERROR',
error: error instanceof Error ? error.message : String(error),
};
parentPort?.postMessage(errorResponse);
} finally {
db.close();
}
}
/**
* Worker message handler
*/
@@ -766,8 +707,6 @@ if (parentPort) {
await fetchAndParseEpgStreaming(message.url!);
} else if (message.type === 'CLEAR_EPG') {
clearAllEpgData();
} else if (message.type === 'CLEANUP_EXPIRED') {
cleanupExpiredPrograms(message.hoursToKeep ?? 24);
}
} catch (error) {
console.error(loggerLabel, 'Worker error:', error);
+23 -197
View File
@@ -28,8 +28,6 @@
"@ngrx/store": "20.0.0",
"@ngrx/store-devtools": "20.0.0",
"@ngx-pwa/local-storage": "20.0.0",
"@rx-angular/cdk": "20.0.0",
"@rx-angular/template": "20.0.0",
"@videojs/http-streaming": "2.15.0",
"@yangkghjh/videojs-aspect-ratio-panel": "0.0.1",
"angularx-qrcode": "21.0.4",
@@ -7816,6 +7814,7 @@
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
@@ -7829,6 +7828,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -7838,6 +7838,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
@@ -10840,35 +10841,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@rx-angular/cdk": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@rx-angular/cdk/-/cdk-20.0.0.tgz",
"integrity": "sha512-8ulzp1P3I7ijtA+0rgo6ZowUtIJikQ4Z25ViTv+mPP3v8hO+Fj6gindXEj1OHoVmVwD0BtUDTUj+clb+yvK/KQ==",
"license": "MIT",
"dependencies": {
"ng-morph": "^4.0.3",
"tslib": "^2.4.1"
},
"peerDependencies": {
"@angular/core": "^20.0.0",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@rx-angular/template": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@rx-angular/template/-/template-20.0.0.tgz",
"integrity": "sha512-HYWlHNZuyM7kZj/TZp/5JqcZ7FIyWsw+cSemyPFOK+LuI6OBmyEwzsLhJvad9OLozzQHSfgbQfmV9rWKehD8PQ==",
"license": "MIT",
"dependencies": {
"ng-morph": "^4.0.3",
"tslib": "^2.4.1"
},
"peerDependencies": {
"@angular/core": "^20.0.0",
"@rx-angular/cdk": "^20.0.0",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@schematics/angular": {
"version": "20.1.6",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.1.6.tgz",
@@ -12158,57 +12130,6 @@
"node": ">=10.13.0"
}
},
"node_modules/@ts-morph/common": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.24.0.tgz",
"integrity": "sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==",
"license": "MIT",
"dependencies": {
"fast-glob": "^3.3.2",
"minimatch": "^9.0.4",
"mkdirp": "^3.0.1",
"path-browserify": "^1.0.1"
}
},
"node_modules/@ts-morph/common/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@ts-morph/common/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@ts-morph/common/node_modules/mkdirp": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
"license": "MIT",
"bin": {
"mkdirp": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
@@ -12621,12 +12542,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/minimatch": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
"license": "MIT"
},
"node_modules/@types/mocha": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz",
@@ -14493,15 +14408,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array-differ": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
"integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -14634,15 +14540,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/arrify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/artplayer": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/artplayer/-/artplayer-5.3.0.tgz",
@@ -15005,6 +14902,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
"license": "MIT"
},
"node_modules/base64-js": {
@@ -15235,6 +15133,7 @@
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -15245,6 +15144,7 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -16081,12 +15981,6 @@
"node": ">= 0.12.0"
}
},
"node_modules/code-block-writer": {
"version": "13.0.3",
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
"integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
"license": "MIT"
},
"node_modules/collect-v8-coverage": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
@@ -16291,6 +16185,7 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true,
"license": "MIT"
},
"node_modules/config-chain": {
@@ -20056,6 +19951,7 @@
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@@ -20072,6 +19968,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
@@ -20114,6 +20011,7 @@
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
@@ -20252,6 +20150,7 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -22483,6 +22382,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -22553,6 +22453,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -22692,6 +22593,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
@@ -24116,6 +24018,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
"integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
"dev": true,
"license": "MIT"
},
"node_modules/jsonfile": {
@@ -25449,6 +25352,7 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -25468,6 +25372,7 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
@@ -25481,6 +25386,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -25600,6 +25506,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -25939,34 +25846,6 @@
"multicast-dns": "cli.js"
}
},
"node_modules/multimatch": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
"integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
"license": "MIT",
"dependencies": {
"@types/minimatch": "^3.0.3",
"array-differ": "^3.0.0",
"array-union": "^2.1.0",
"arrify": "^2.0.1",
"minimatch": "^3.0.4"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/multimatch/node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/mute-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
@@ -26126,47 +26005,6 @@
"@angular/platform-browser": "5.0.0-alpha - 5 || 6.0.0-alpha - 6 || 7.0.0-alpha - 7 || 8.0.0-alpha - 8 || 9.0.0-alpha - 9 || 10.0.0-alpha - 10 || 11.0.0-alpha - 11 || 12.0.0-alpha - 12 || 13.0.0-alpha - 13 || 14.0.0-alpha - 14 || 15.0.0-alpha - 15 || 16.0.0-alpha - 16 || 17.0.0-alpha - 17 || 18.0.0-alpha - 18 || 19.0.0-alpha - 19 || 20.0.0-alpha - 20"
}
},
"node_modules/ng-morph": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/ng-morph/-/ng-morph-4.8.4.tgz",
"integrity": "sha512-XwL53wCOhyaAxvoekN74ONbWUK30huzp+GpZYyC01RfaG2AX9l7YlC1mGG/l7Rx7YXtFAk85VFnNJqn2e46K8g==",
"license": "Apache-2.0",
"dependencies": {
"jsonc-parser": "3.3.1",
"minimatch": "10.0.1",
"multimatch": "5.0.0",
"ts-morph": "23.0.0"
},
"peerDependencies": {
"@angular-devkit/core": ">=16.0.0",
"@angular-devkit/schematics": ">=16.0.0",
"tslib": "^2.7.0"
}
},
"node_modules/ng-morph/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/ng-morph/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/ngx-indexed-db": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/ngx-indexed-db/-/ngx-indexed-db-21.0.0.tgz",
@@ -31768,12 +31606,6 @@
"node": ">= 0.8"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
"license": "MIT"
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -33208,6 +33040,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
"type": "github",
@@ -33775,6 +33608,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
@@ -33929,6 +33763,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
{
"type": "github",
@@ -37118,6 +36953,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -37446,16 +37282,6 @@
"webpack": "^5.0.0"
}
},
"node_modules/ts-morph": {
"version": "23.0.0",
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-23.0.0.tgz",
"integrity": "sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==",
"license": "MIT",
"dependencies": {
"@ts-morph/common": "~0.24.0",
"code-block-writer": "^13.0.1"
}
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+1 -3
View File
@@ -52,8 +52,6 @@
"@ngrx/store": "20.0.0",
"@ngrx/store-devtools": "20.0.0",
"@ngx-pwa/local-storage": "20.0.0",
"@rx-angular/cdk": "20.0.0",
"@rx-angular/template": "20.0.0",
"@videojs/http-streaming": "2.15.0",
"@yangkghjh/videojs-aspect-ratio-panel": "0.0.1",
"angularx-qrcode": "21.0.4",
@@ -162,4 +160,4 @@
"typescript": "5.9.3",
"typescript-eslint": "^8.46.2"
}
}
}
-135
View File
@@ -62,12 +62,6 @@ importers:
'@ngx-pwa/local-storage':
specifier: 20.0.0
version: 20.0.0(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@rx-angular/cdk':
specifier: 20.0.0
version: 20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
'@rx-angular/template':
specifier: 20.0.0
version: 20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@rx-angular/cdk@20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(rxjs@7.8.2)
'@videojs/http-streaming':
specifier: 2.15.0
version: 2.15.0(video.js@8.23.4)
@@ -3400,19 +3394,6 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
'@rx-angular/cdk@20.0.0':
resolution: {integrity: sha512-8ulzp1P3I7ijtA+0rgo6ZowUtIJikQ4Z25ViTv+mPP3v8hO+Fj6gindXEj1OHoVmVwD0BtUDTUj+clb+yvK/KQ==}
peerDependencies:
'@angular/core': ^20.0.0
rxjs: ^6.5.3 || ^7.4.0
'@rx-angular/template@20.0.0':
resolution: {integrity: sha512-HYWlHNZuyM7kZj/TZp/5JqcZ7FIyWsw+cSemyPFOK+LuI6OBmyEwzsLhJvad9OLozzQHSfgbQfmV9rWKehD8PQ==}
peerDependencies:
'@angular/core': ^20.0.0
'@rx-angular/cdk': ^20.0.0
rxjs: ^6.5.3 || ^7.4.0
'@schematics/angular@20.1.6':
resolution: {integrity: sha512-1dE+GkpSZbsQxnir/S24g3+pA5sE0XOMxa4Wxhon0dxArP/gH72hsinoVaLDfcQkYOtbbTw/Q8VV41uWBI9eGg==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
@@ -3628,9 +3609,6 @@ packages:
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
engines: {node: '>=10.13.0'}
'@ts-morph/common@0.24.0':
resolution: {integrity: sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==}
'@tsconfig/node10@1.0.12':
resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==}
@@ -3747,9 +3725,6 @@ packages:
'@types/mime@1.3.5':
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
'@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
'@types/mocha@9.0.0':
resolution: {integrity: sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==}
@@ -4321,10 +4296,6 @@ packages:
resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
engines: {node: '>= 0.4'}
array-differ@3.0.0:
resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==}
engines: {node: '>=8'}
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
@@ -4335,10 +4306,6 @@ packages:
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
engines: {node: '>= 0.4'}
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
array-union@3.0.1:
resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==}
engines: {node: '>=12'}
@@ -4359,10 +4326,6 @@ packages:
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
engines: {node: '>= 0.4'}
arrify@2.0.1:
resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
engines: {node: '>=8'}
artplayer@5.3.0:
resolution: {integrity: sha512-yExO39MpEg4P+bxgChxx1eJfiUPE4q1QQRLCmqGhlsj+ANuaoEkR8hF93LdI5ZyrAcIbJkuEndxEiUoKobifDw==}
@@ -4784,9 +4747,6 @@ packages:
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
code-block-writer@13.0.3:
resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
collect-v8-coverage@1.0.3:
resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==}
@@ -7511,10 +7471,6 @@ packages:
minimalistic-assert@1.0.1:
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
minimatch@10.0.1:
resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==}
engines: {node: 20 || >=22}
minimatch@10.1.1:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
@@ -7593,11 +7549,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
hasBin: true
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
@@ -7634,10 +7585,6 @@ packages:
resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==}
hasBin: true
multimatch@5.0.0:
resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==}
engines: {node: '>=10'}
mute-stream@2.0.0:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0}
@@ -7702,13 +7649,6 @@ packages:
'@angular/forms': 5.0.0-alpha - 5 || 6.0.0-alpha - 6 || 7.0.0-alpha - 7 || 8.0.0-alpha - 8 || 9.0.0-alpha - 9 || 10.0.0-alpha - 10 || 11.0.0-alpha - 11 || 12.0.0-alpha - 12 || 13.0.0-alpha - 13 || 14.0.0-alpha - 14 || 15.0.0-alpha - 15 || 16.0.0-alpha - 16 || 17.0.0-alpha - 17 || 18.0.0-alpha - 18 || 19.0.0-alpha - 19 || 20.0.0-alpha - 20
'@angular/platform-browser': 5.0.0-alpha - 5 || 6.0.0-alpha - 6 || 7.0.0-alpha - 7 || 8.0.0-alpha - 8 || 9.0.0-alpha - 9 || 10.0.0-alpha - 10 || 11.0.0-alpha - 11 || 12.0.0-alpha - 12 || 13.0.0-alpha - 13 || 14.0.0-alpha - 14 || 15.0.0-alpha - 15 || 16.0.0-alpha - 16 || 17.0.0-alpha - 17 || 18.0.0-alpha - 18 || 19.0.0-alpha - 19 || 20.0.0-alpha - 20
ng-morph@4.8.4:
resolution: {integrity: sha512-XwL53wCOhyaAxvoekN74ONbWUK30huzp+GpZYyC01RfaG2AX9l7YlC1mGG/l7Rx7YXtFAk85VFnNJqn2e46K8g==}
peerDependencies:
'@angular-devkit/core': '>=16.0.0'
'@angular-devkit/schematics': '>=16.0.0'
tslib: ^2.7.0
ngx-indexed-db@21.0.0:
resolution: {integrity: sha512-781n0P4ZWt0CegInpvQ7WB2Z9Z9A4Pi3GKOUuAfsKFof4ZSv85g05+IXkSx+h3jBIibCuNWcQd77VLj84xLBQA==}
peerDependencies:
@@ -8197,9 +8137,6 @@ packages:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
path-exists@3.0.0:
resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
engines: {node: '>=4'}
@@ -9722,9 +9659,6 @@ packages:
typescript: '*'
webpack: ^5.0.0
ts-morph@23.0.0:
resolution: {integrity: sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==}
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
@@ -13947,27 +13881,6 @@ snapshots:
'@rtsao/scc@1.1.0': {}
'@rx-angular/cdk@20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)':
dependencies:
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
ng-morph: 4.8.4(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(tslib@2.8.1)
rxjs: 7.8.2
tslib: 2.8.1
transitivePeerDependencies:
- '@angular-devkit/core'
- '@angular-devkit/schematics'
'@rx-angular/template@20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@rx-angular/cdk@20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(rxjs@7.8.2)':
dependencies:
'@angular/core': 20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)
'@rx-angular/cdk': 20.0.0(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
ng-morph: 4.8.4(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(tslib@2.8.1)
rxjs: 7.8.2
tslib: 2.8.1
transitivePeerDependencies:
- '@angular-devkit/core'
- '@angular-devkit/schematics'
'@schematics/angular@20.1.6(chokidar@4.0.3)':
dependencies:
'@angular-devkit/core': 20.1.6(chokidar@4.0.3)
@@ -14237,13 +14150,6 @@ snapshots:
'@trysound/sax@0.2.0': {}
'@ts-morph/common@0.24.0':
dependencies:
fast-glob: 3.3.3
minimatch: 9.0.5
mkdirp: 3.0.1
path-browserify: 1.0.1
'@tsconfig/node10@1.0.12': {}
'@tsconfig/node12@1.0.11': {}
@@ -14393,8 +14299,6 @@ snapshots:
'@types/mime@1.3.5': {}
'@types/minimatch@3.0.5': {}
'@types/mocha@9.0.0': {}
'@types/ms@2.1.0': {}
@@ -15081,8 +14985,6 @@ snapshots:
call-bound: 1.0.4
is-array-buffer: 3.0.5
array-differ@3.0.0: {}
array-flatten@1.1.1: {}
array-ify@1.0.0: {}
@@ -15098,8 +15000,6 @@ snapshots:
is-string: 1.1.1
math-intrinsics: 1.1.0
array-union@2.1.0: {}
array-union@3.0.1: {}
array.prototype.findlastindex@1.2.6:
@@ -15136,8 +15036,6 @@ snapshots:
get-intrinsic: 1.3.0
is-array-buffer: 3.0.5
arrify@2.0.1: {}
artplayer@5.3.0:
dependencies:
option-validator: 2.0.6
@@ -15704,8 +15602,6 @@ snapshots:
co@4.6.0: {}
code-block-writer@13.0.3: {}
collect-v8-coverage@1.0.3: {}
color-convert@1.9.3:
@@ -18958,10 +18854,6 @@ snapshots:
minimalistic-assert@1.0.1: {}
minimatch@10.0.1:
dependencies:
brace-expansion: 2.0.2
minimatch@10.1.1:
dependencies:
'@isaacs/brace-expansion': 5.0.0
@@ -19041,8 +18933,6 @@ snapshots:
mkdirp@1.0.4: {}
mkdirp@3.0.1: {}
moment@2.30.1: {}
mpd-parser@0.22.0:
@@ -19094,14 +18984,6 @@ snapshots:
dns-packet: 5.6.1
thunky: 1.1.0
multimatch@5.0.0:
dependencies:
'@types/minimatch': 3.0.5
array-differ: 3.0.0
array-union: 2.1.0
arrify: 2.0.1
minimatch: 3.1.2
mute-stream@2.0.0: {}
mux.js@6.0.1:
@@ -19151,16 +19033,6 @@ snapshots:
'@angular/forms': 20.3.15(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)
'@angular/platform-browser': 20.3.15(@angular/animations@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))
ng-morph@4.8.4(@angular-devkit/core@20.3.13(chokidar@4.0.3))(@angular-devkit/schematics@20.3.13(chokidar@4.0.3))(tslib@2.8.1):
dependencies:
'@angular-devkit/core': 20.3.13(chokidar@4.0.3)
'@angular-devkit/schematics': 20.3.13(chokidar@4.0.3)
jsonc-parser: 3.3.1
minimatch: 10.0.1
multimatch: 5.0.0
ts-morph: 23.0.0
tslib: 2.8.1
ngx-indexed-db@21.0.0(@angular/common@20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1)):
dependencies:
'@angular/common': 20.3.15(@angular/core@20.3.15(@angular/compiler@20.3.15)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)
@@ -19714,8 +19586,6 @@ snapshots:
parseurl@1.3.3: {}
path-browserify@1.0.1: {}
path-exists@3.0.0: {}
path-exists@4.0.0: {}
@@ -21328,11 +21198,6 @@ snapshots:
typescript: 5.9.3
webpack: 5.104.1(@swc/core@1.5.29(@swc/helpers@0.5.18))(esbuild@0.27.0)
ts-morph@23.0.0:
dependencies:
'@ts-morph/common': 0.24.0
code-block-writer: 13.0.3
ts-node@10.9.2(@swc/core@1.5.29(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1