stricter ESLint configuration, linebreak on stylistic per deprecation by ESLint, fixed changes. add attibutes to prevent blockade.

This commit is contained in:
theofficialomega
2025-07-28 22:28:48 +02:00
parent 88652ab1ae
commit e3c7a372f2
41 changed files with 8471 additions and 8424 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Enforce the usage of CRLF in GitHub Actions per ESLint configuration.
* text eol=crlf

View File

@@ -1,4 +1,5 @@
import typescriptEslint from '@typescript-eslint/eslint-plugin'
import stylistic from '@stylistic/eslint-plugin'
import globals from 'globals'
import tsParser from '@typescript-eslint/parser'
import path from 'node:path'
@@ -15,10 +16,11 @@ const compat = new FlatCompat({
})
export default [
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'),
...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/strict', 'plugin:@typescript-eslint/stylistic', 'prettier'),
{
plugins: {
'@typescript-eslint': typescriptEslint
'@typescript-eslint': typescriptEslint,
'@stylistic': stylistic
},
languageOptions: {
@@ -36,7 +38,7 @@ export default [
'@typescript-eslint/no-require-imports': 'off',
'@typescript-eslint/no-var-requires': 'off',
'no-case-declarations': 'off',
'linebreak-style': ['error', process.env.CI ? 'unix' : 'windows'],
'@stylistic/linebreak-style': ['error', 'windows'],
quotes: [
'error',

45
package-lock.json generated
View File

@@ -18,6 +18,7 @@
"@octokit/core": "^7.0.3",
"@octokit/plugin-paginate-rest": "^13.1.1",
"@octokit/plugin-rest-endpoint-methods": "^16.0.0",
"@stylistic/eslint-plugin": "^5.2.2",
"@swc/core": "^1.13.2",
"@swc/jest": "^0.2.39",
"@types/cli-progress": "^3.11.6",
@@ -3146,6 +3147,50 @@
"@sinonjs/commons": "^3.0.1"
}
},
"node_modules/@stylistic/eslint-plugin": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.2.tgz",
"integrity": "sha512-bE2DUjruqXlHYP3Q2Gpqiuj2bHq7/88FnuaS0FjeGGLCy+X6a07bGVuwtiOYnPSLHR6jmx5Bwdv+j7l8H+G97A==",
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/types": "^8.37.0",
"eslint-visitor-keys": "^4.2.1",
"espree": "^10.4.0",
"estraverse": "^5.3.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"peerDependencies": {
"eslint": ">=9.0.0"
}
},
"node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@swc/core": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.2.tgz",

View File

@@ -46,6 +46,7 @@
"@octokit/core": "^7.0.3",
"@octokit/plugin-paginate-rest": "^13.1.1",
"@octokit/plugin-rest-endpoint-methods": "^16.0.0",
"@stylistic/eslint-plugin": "^5.2.2",
"@swc/core": "^1.13.2",
"@swc/jest": "^0.2.39",
"@types/cli-progress": "^3.11.6",

View File

@@ -13,8 +13,8 @@ import epgGrabber from 'epg-grabber'
import { Command } from 'commander'
import readline from 'readline'
type ChoiceValue = { type: string; value?: Feed | Channel }
type Choice = { name: string; short?: string; value: ChoiceValue; default?: boolean }
interface ChoiceValue { type: string; value?: Feed | Channel }
interface Choice { name: string; short?: string; value: ChoiceValue; default?: boolean }
if (process.platform === 'win32') {
readline

View File

@@ -12,7 +12,7 @@ program
.option('-o, --output <output>', 'Output file')
.parse(process.argv)
type ParseOptions = {
interface ParseOptions {
config: string
set?: string
output?: string
@@ -43,9 +43,7 @@ async function main() {
channelList = await parser.parse(outputFilepath)
}
const args: {
[key: string]: string
} = {}
const args: Record<string, string> = {}
if (Array.isArray(options.set)) {
options.set.forEach((arg: string) => {

View File

@@ -11,7 +11,7 @@ import langs from 'langs'
program.argument('[filepath...]', 'Path to *.channels.xml files to validate').parse(process.argv)
type ValidationError = {
interface ValidationError {
type: 'duplicate' | 'wrong_channel_id' | 'wrong_feed_id' | 'wrong_lang'
name: string
lang?: string

View File

@@ -48,7 +48,7 @@ program
.addOption(new Option('--curl', 'Display each request as CURL').default(false).env('CURL'))
.parse()
export type GrabOptions = {
export interface GrabOptions {
site?: string
channels?: string
output: string

View File

@@ -2,7 +2,7 @@ import { parseChannels } from 'epg-grabber'
import { Storage } from '@freearhey/core'
import { ChannelList } from '../models'
type ChannelsParserProps = {
interface ChannelsParserProps {
storage: Storage
}

View File

@@ -3,7 +3,6 @@ import { DataLoaderData } from '../types/dataLoader'
import { Collection } from '@freearhey/core'
export class DataProcessor {
constructor() {}
process(data: DataLoaderData) {
let channels = new Collection(data.channels).map(data => new Channel(data))

View File

@@ -5,7 +5,7 @@ import { GrabOptions } from '../commands/epg/grab'
import { TaskQueue, PromisyClass } from 'cwait'
import { SocksProxyAgent } from 'socks-proxy-agent'
type GrabberProps = {
interface GrabberProps {
logger: Logger
queue: Queue
options: GrabOptions

View File

@@ -8,7 +8,7 @@ import { DataLoaderData } from '../types/dataLoader'
import { DataProcessorData } from '../types/dataProcessor'
import { DATA_DIR } from '../constants'
type GuideManagerProps = {
interface GuideManagerProps {
options: OptionValues
logger: Logger
channels: Collection

View File

@@ -1,4 +1,4 @@
type Column = {
interface Column {
name: string
nowrap?: boolean
align?: string

View File

@@ -2,7 +2,7 @@ import { Logger } from '@freearhey/core'
import { Queue, Grabber, GuideManager } from '.'
import { GrabOptions } from '../commands/epg/grab'
type JobProps = {
interface JobProps {
options: GrabOptions
logger: Logger
queue: Queue

View File

@@ -1,6 +1,6 @@
import { URL } from 'node:url'
type ProxyParserResult = {
interface ProxyParserResult {
protocol: string | null
auth?: {
username?: string

View File

@@ -1,7 +1,7 @@
import { Dictionary } from '@freearhey/core'
import { SiteConfig, Channel } from 'epg-grabber'
export type QueueItem = {
export interface QueueItem {
channel: Channel
date: string
config: SiteConfig

View File

@@ -5,7 +5,7 @@ import { ConfigLoader, Queue } from './'
import { SiteConfig } from 'epg-grabber'
import path from 'path'
type QueueCreatorProps = {
interface QueueCreatorProps {
logger: Logger
options: GrabOptions
channels: Collection

View File

@@ -28,10 +28,10 @@ export const sortBy = <T>(arr: T[], fn: (item: T) => number | string): T[] =>
* // [{name: 'bob', age: 30}, {name: 'john', age: 30}, {name: 'jane', age: 25}]
*/
export const orderBy = (
arr: Array<unknown>,
fns: Array<(item: unknown) => string | number>,
orders: Array<string> = []
): Array<unknown> =>
arr: unknown[],
fns: ((item: unknown) => string | number)[],
orders: string[] = []
): unknown[] =>
[...arr].sort((a, b) =>
fns.reduce(
(acc, fn, i) =>

View File

@@ -12,7 +12,7 @@ export class Channel {
subdivisionCode?: string
cityName?: string
categoryIds?: Collection
isNSFW: boolean = false
isNSFW = false
launched?: string
closed?: string
replacedBy?: string
@@ -116,7 +116,7 @@ export class Channel {
}
function format(logo: Logo): number {
const levelByFormat: { [key: string]: number } = {
const levelByFormat: Record<string, number> = {
SVG: 0,
PNG: 3,
APNG: 1,

View File

@@ -29,7 +29,7 @@ export class ChannelList {
}
toString() {
function escapeString(value: string, defaultValue: string = '') {
function escapeString(value: string, defaultValue = '') {
if (!value) return defaultValue
const regex = new RegExp(

View File

@@ -87,7 +87,7 @@ export class Feed {
getLogos(): Collection {
function format(logo: Logo): number {
const levelByFormat: { [key: string]: number } = {
const levelByFormat: Record<string, number> = {
SVG: 0,
PNG: 3,
APNG: 1,

View File

@@ -1,7 +1,7 @@
import { Collection, DateTime } from '@freearhey/core'
import { generateXMLTV } from 'epg-grabber'
type GuideData = {
interface GuideData {
channels: Collection
programs: Collection
filepath: string

View File

@@ -1,7 +1,7 @@
import { Dictionary } from '@freearhey/core'
import { OWNER, REPO } from '../constants'
type IssueProps = {
interface IssueProps {
number: number
labels: string[]
data: Dictionary

View File

@@ -7,8 +7,8 @@ export class Logo {
feedId?: string
feed?: Feed
tags: Collection = new Collection()
width: number = 0
height: number = 0
width = 0
height = 0
format?: string
url?: string

View File

@@ -7,12 +7,12 @@ enum StatusCode {
OK = 'ok'
}
type Status = {
interface Status {
code: StatusCode
emoji: string
}
type SiteProps = {
interface SiteProps {
domain: string
totalChannels?: number
markedChannels?: number

View File

@@ -16,8 +16,8 @@ export class Stream {
isInterlaced?: boolean
referrer?: string
userAgent?: string
groupTitle: string = 'Undefined'
removed: boolean = false
groupTitle = 'Undefined'
removed = false
constructor(data: StreamData) {
const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel

View File

@@ -1,6 +1,6 @@
import { Collection } from '@freearhey/core'
export type ChannelData = {
export interface ChannelData {
id: string
name: string
alt_names: string[]
@@ -17,7 +17,7 @@ export type ChannelData = {
website: string
}
export type ChannelSearchableData = {
export interface ChannelSearchableData {
id: string
name: string
altNames: string[]

View File

@@ -1,10 +1,10 @@
import { Storage } from '@freearhey/core'
export type DataLoaderProps = {
export interface DataLoaderProps {
storage: Storage
}
export type DataLoaderData = {
export interface DataLoaderData {
countries: object | object[]
regions: object | object[]
subdivisions: object | object[]

View File

@@ -1,6 +1,6 @@
import { Collection, Dictionary } from '@freearhey/core'
export type DataProcessorData = {
export interface DataProcessorData {
guideChannelsGroupedByStreamId: Dictionary
feedsGroupedByChannelId: Dictionary
logosGroupedByChannelId: Dictionary

View File

@@ -1,6 +1,6 @@
import { Collection } from '@freearhey/core'
export type FeedData = {
export interface FeedData {
channel: string
id: string
name: string

View File

@@ -1,4 +1,4 @@
export type GuideData = {
export interface GuideData {
channel: string
feed: string
site: string

View File

@@ -1,4 +1,4 @@
export type LogoData = {
export interface LogoData {
channel: string
feed: string | null
tags: string[]

View File

@@ -1,4 +1,4 @@
export type StreamData = {
export interface StreamData {
channel: string | null
feed: string | null
name?: string

View File

@@ -1,6 +1,6 @@
import { execSync } from 'child_process'
type ExecError = {
interface ExecError {
status: number
stdout: string
}

View File

@@ -1,6 +1,6 @@
import { execSync } from 'child_process'
type ExecError = {
interface ExecError {
status: number
stdout: string
}