From 204fe5165812b51a6470f6b47a94bb4a986526ba Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 01:51:22 +0000 Subject: [PATCH 01/55] Rewritten repository in typescript --- src/node/consumer/package-lock.json | 70 +++- src/node/consumer/package.json | 11 +- src/node/consumer/src/index.js | 4 +- src/node/consumer/src/jobs/processTorrents.js | 2 +- src/node/consumer/src/lib/cache.js | 2 +- src/node/consumer/src/lib/config.js | 2 +- src/node/consumer/src/lib/ingestedTorrent.js | 2 +- .../consumer/src/lib/{logger.js => logger.ts} | 0 src/node/consumer/src/lib/repository.js | 382 ------------------ src/node/consumer/src/lib/torrentEntries.js | 4 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- src/node/consumer/src/lib/trackerService.js | 2 +- .../src/repository/database_repository.ts | 259 ++++++++++++ .../interfaces/content_attributes.ts | 11 + .../repository/interfaces/file_attributes.ts | 19 + .../interfaces/ingested_page_attributes.ts | 6 + .../interfaces/ingested_torrent_attributes.ts | 16 + .../interfaces/provider_attributes.ts | 10 + .../interfaces/skip_torrent_attributes.ts | 8 + .../interfaces/subtitle_attributes.ts | 12 + .../interfaces/torrent_attributes.ts | 26 ++ .../consumer/src/repository/models/content.ts | 22 + .../consumer/src/repository/models/file.ts | 60 +++ .../src/repository/models/ingestedPage.ts | 16 + .../src/repository/models/ingestedTorrent.ts | 40 ++ .../src/repository/models/provider.ts | 15 + .../src/repository/models/skipTorrent.ts | 10 + .../src/repository/models/subtitle.ts | 39 ++ .../consumer/src/repository/models/torrent.ts | 56 +++ .../consumer/{jsconfig.json => tsconfig.json} | 9 +- 30 files changed, 700 insertions(+), 417 deletions(-) rename src/node/consumer/src/lib/{logger.js => logger.ts} (100%) delete mode 100644 src/node/consumer/src/lib/repository.js create mode 100644 src/node/consumer/src/repository/database_repository.ts create mode 100644 src/node/consumer/src/repository/interfaces/content_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/file_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/provider_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/subtitle_attributes.ts create mode 100644 src/node/consumer/src/repository/interfaces/torrent_attributes.ts create mode 100644 src/node/consumer/src/repository/models/content.ts create mode 100644 src/node/consumer/src/repository/models/file.ts create mode 100644 src/node/consumer/src/repository/models/ingestedPage.ts create mode 100644 src/node/consumer/src/repository/models/ingestedTorrent.ts create mode 100644 src/node/consumer/src/repository/models/provider.ts create mode 100644 src/node/consumer/src/repository/models/skipTorrent.ts create mode 100644 src/node/consumer/src/repository/models/subtitle.ts create mode 100644 src/node/consumer/src/repository/models/torrent.ts rename src/node/consumer/{jsconfig.json => tsconfig.json} (64%) diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index f6408a3..9a34802 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -14,24 +14,25 @@ "axios": "^1.6.1", "bottleneck": "^2.19.5", "cache-manager": "^5.4.0", - "dotenv": "^16.4.1", "google-sr": "^3.2.1", "jaro-winkler": "^0.2.8", "magnet-uri": "^6.2.0", "moment": "^2.30.1", - "mongodb": "^6.3.0", "name-to-imdb": "^3.0.4", "parse-torrent-title": "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", "pg": "^8.11.3", "pg-hstore": "^2.3.4", "pino": "^8.18.0", - "sequelize": "^6.31.1", + "reflect-metadata": "^0.2.1", + "sequelize": "^6.36.0", + "sequelize-typescript": "^2.1.6", "torrent-stream": "^1.2.1", "user-agents": "^1.0.1444" }, "devDependencies": { - "@types/node": "^20.11.6", + "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", + "@types/validator": "^13.11.8", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", @@ -581,7 +582,8 @@ }, "node_modules/@types/node": { "version": "20.11.16", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -597,7 +599,8 @@ }, "node_modules/@types/validator": { "version": "13.11.8", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", @@ -1409,17 +1412,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dotenv": { - "version": "16.4.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", - "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, "node_modules/dottie": { "version": "2.0.6", "license": "MIT" @@ -3776,6 +3768,11 @@ "node": ">= 12.13.0" } }, + "node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "dev": true, @@ -3965,13 +3962,14 @@ }, "node_modules/sequelize": { "version": "6.36.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", + "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", "funding": [ { "type": "opencollective", "url": "https://opencollective.com/sequelize" } ], - "license": "MIT", "dependencies": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", @@ -4030,6 +4028,42 @@ "node": ">= 10.0.0" } }, + "node_modules/sequelize-typescript": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz", + "integrity": "sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ==", + "dependencies": { + "glob": "7.2.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "@types/validator": "*", + "reflect-metadata": "*", + "sequelize": ">=6.20.1" + } + }, + "node_modules/sequelize-typescript/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sequelize/node_modules/semver": { "version": "7.5.4", "license": "ISC", diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 9678cfc..2639881 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -24,18 +24,21 @@ "pg": "^8.11.3", "pg-hstore": "^2.3.4", "pino": "^8.18.0", - "sequelize": "^6.31.1", + "reflect-metadata": "^0.2.1", + "sequelize": "^6.36.0", + "sequelize-typescript": "^2.1.6", "torrent-stream": "^1.2.1", "user-agents": "^1.0.1444" }, "devDependencies": { - "@types/node": "^20.11.6", + "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", + "@types/validator": "^13.11.8", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", - "tsx": "^4.7.0", - "pino-pretty": "^10.3.1" + "pino-pretty": "^10.3.1", + "tsx": "^4.7.0" } } diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.js index ac1dd83..e3ac0b7 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.js @@ -1,9 +1,9 @@ import { listenToQueue } from './jobs/processTorrents.js'; -import { connect } from './lib/repository.js'; +import { repository } from "./repository/database_repository"; import { getTrackers } from "./lib/trackerService.js"; (async () => { await getTrackers(); - await connect(); + await repository.connect(); await listenToQueue(); })(); \ No newline at end of file diff --git a/src/node/consumer/src/jobs/processTorrents.js b/src/node/consumer/src/jobs/processTorrents.js index 23d9701..1dd50b2 100644 --- a/src/node/consumer/src/jobs/processTorrents.js +++ b/src/node/consumer/src/jobs/processTorrents.js @@ -1,7 +1,7 @@ import amqp from 'amqplib' import { rabbitConfig, jobConfig } from '../lib/config.js' import { processTorrentRecord } from "../lib/ingestedTorrent.js"; -import {logger} from "../lib/logger.js"; +import {logger} from "../lib/logger"; const assertQueueOptions = { durable: true } const consumeQueueOptions = { noAck: false } diff --git a/src/node/consumer/src/lib/cache.js b/src/node/consumer/src/lib/cache.js index 7b9be26..a7c1128 100644 --- a/src/node/consumer/src/lib/cache.js +++ b/src/node/consumer/src/lib/cache.js @@ -1,7 +1,7 @@ import { createCache, memoryStore} from 'cache-manager'; import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' import { cacheConfig } from './config.js'; -import { logger } from './logger.js'; +import { logger } from './logger'; import { CacheType } from "./types.js"; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; diff --git a/src/node/consumer/src/lib/config.js b/src/node/consumer/src/lib/config.js index a63f093..69769ea 100644 --- a/src/node/consumer/src/lib/config.js +++ b/src/node/consumer/src/lib/config.js @@ -1,4 +1,4 @@ -export const rabbitConfig = { +export const rabbitConfig = { URI: process.env.RABBIT_URI || 'amqp://localhost', QUEUE_NAME: process.env.QUEUE_NAME || 'test-queue' } diff --git a/src/node/consumer/src/lib/ingestedTorrent.js b/src/node/consumer/src/lib/ingestedTorrent.js index 4948173..fe8705d 100644 --- a/src/node/consumer/src/lib/ingestedTorrent.js +++ b/src/node/consumer/src/lib/ingestedTorrent.js @@ -1,7 +1,7 @@ import { createTorrentEntry, checkAndUpdateTorrent } from './torrentEntries.js'; import {getTrackers} from "./trackerService.js"; import { TorrentType } from './types.js'; -import {logger} from "./logger.js"; +import {logger} from "./logger"; export async function processTorrentRecord(torrent) { const {category} = torrent; diff --git a/src/node/consumer/src/lib/logger.js b/src/node/consumer/src/lib/logger.ts similarity index 100% rename from src/node/consumer/src/lib/logger.js rename to src/node/consumer/src/lib/logger.ts diff --git a/src/node/consumer/src/lib/repository.js b/src/node/consumer/src/lib/repository.js deleted file mode 100644 index 34c2b8c..0000000 --- a/src/node/consumer/src/lib/repository.js +++ /dev/null @@ -1,382 +0,0 @@ -import moment from 'moment'; -import { Sequelize, Op, DataTypes, fn, col, literal } from 'sequelize'; -import { databaseConfig } from './config.js'; -import { logger } from "./logger.js"; -import * as Promises from './promises.js'; - -const database = new Sequelize( - databaseConfig.POSTGRES_URI, - { - logging: false - } -); - -const Provider = database.define('provider', { - name: { type: DataTypes.STRING(32), primaryKey: true }, - lastScraped: { type: DataTypes.DATE }, - lastScrapedId: { type: DataTypes.STRING(128) } -}); - -const IngestedTorrent = database.define('ingested_torrent', { - id: { type: DataTypes.BIGINT, autoIncrement: true, primaryKey: true }, - name: DataTypes.STRING, - source: DataTypes.STRING, - category: DataTypes.STRING, - info_hash: DataTypes.STRING, - size: DataTypes.STRING, - seeders: DataTypes.INTEGER, - leechers: DataTypes.INTEGER, - imdb: DataTypes.STRING, - processed: { - type: DataTypes.BOOLEAN, - defaultValue: false - } -}, - { - indexes: [ - { - unique: true, - fields: ['source', 'info_hash'] - } - ] - }) - -/* eslint-disable no-unused-vars */ -const IngestedPage = database.define('ingested_page', { - id: { type: DataTypes.BIGINT, autoIncrement: true, primaryKey: true }, - url: { type: DataTypes.STRING, allowNull: false }, -}, - { - indexes: [ - { - unique: true, - fields: ['url'] - } - ] - }) -/* eslint-enable no-unused-vars */ - -const Torrent = database.define('torrent', - { - infoHash: { type: DataTypes.STRING(64), primaryKey: true }, - provider: { type: DataTypes.STRING(32), allowNull: false }, - torrentId: { type: DataTypes.STRING(512) }, - title: { type: DataTypes.STRING(512), allowNull: false }, - size: { type: DataTypes.BIGINT }, - type: { type: DataTypes.STRING(16), allowNull: false }, - uploadDate: { type: DataTypes.DATE, allowNull: false }, - seeders: { type: DataTypes.SMALLINT }, - trackers: { type: DataTypes.STRING(8000) }, - languages: { type: DataTypes.STRING(4096) }, - resolution: { type: DataTypes.STRING(16) }, - reviewed: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, - opened: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false } - } -); - -const File = database.define('file', - { - id: { type: DataTypes.BIGINT, autoIncrement: true, primaryKey: true }, - infoHash: { - type: DataTypes.STRING(64), - allowNull: false, - references: { model: Torrent, key: 'infoHash' }, - onDelete: 'CASCADE' - }, - fileIndex: { type: DataTypes.INTEGER }, - title: { type: DataTypes.STRING(512), allowNull: false }, - size: { type: DataTypes.BIGINT }, - imdbId: { type: DataTypes.STRING(32) }, - imdbSeason: { type: DataTypes.INTEGER }, - imdbEpisode: { type: DataTypes.INTEGER }, - kitsuId: { type: DataTypes.INTEGER }, - kitsuEpisode: { type: DataTypes.INTEGER } - }, - { - indexes: [ - { - unique: true, - name: 'files_unique_file_constraint', - fields: [ - col('infoHash'), - fn('COALESCE', (col('fileIndex')), -1), - fn('COALESCE', (col('imdbId')), 'null'), - fn('COALESCE', (col('imdbSeason')), -1), - fn('COALESCE', (col('imdbEpisode')), -1), - fn('COALESCE', (col('kitsuId')), -1), - fn('COALESCE', (col('kitsuEpisode')), -1) - ] - }, - { unique: false, fields: ['imdbId', 'imdbSeason', 'imdbEpisode'] }, - { unique: false, fields: ['kitsuId', 'kitsuEpisode'] } - ] - } -); - -const Subtitle = database.define('subtitle', - { - infoHash: { - type: DataTypes.STRING(64), - allowNull: false, - references: { model: Torrent, key: 'infoHash' }, - onDelete: 'CASCADE' - }, - fileIndex: { - type: DataTypes.INTEGER, - allowNull: false - }, - fileId: { - type: DataTypes.BIGINT, - allowNull: true, - references: { model: File, key: 'id' }, - onDelete: 'SET NULL' - }, - title: { type: DataTypes.STRING(512), allowNull: false }, - }, - { - timestamps: false, - indexes: [ - { - unique: true, - name: 'subtitles_unique_subtitle_constraint', - fields: [ - col('infoHash'), - col('fileIndex'), - fn('COALESCE', (col('fileId')), -1) - ] - }, - { unique: false, fields: ['fileId'] } - ] - } -); - -const Content = database.define('content', - { - infoHash: { - type: DataTypes.STRING(64), - primaryKey: true, - allowNull: false, - references: { model: Torrent, key: 'infoHash' }, - onDelete: 'CASCADE' - }, - fileIndex: { - type: DataTypes.INTEGER, - primaryKey: true, - allowNull: false - }, - path: { type: DataTypes.STRING(512), allowNull: false }, - size: { type: DataTypes.BIGINT }, - }, - { - timestamps: false, - } -); - -const SkipTorrent = database.define('skip_torrent', { - infoHash: { type: DataTypes.STRING(64), primaryKey: true }, -}); - -Torrent.hasMany(File, { foreignKey: 'infoHash', constraints: false }); -File.belongsTo(Torrent, { foreignKey: 'infoHash', constraints: false }); -Torrent.hasMany(Content, { foreignKey: 'infoHash', constraints: false }); -Content.belongsTo(Torrent, { foreignKey: 'infoHash', constraints: false }); -File.hasMany(Subtitle, { foreignKey: 'fileId', constraints: false }); -Subtitle.belongsTo(File, { foreignKey: 'fileId', constraints: false }); - -export function connect() { - return database.sync({ alter: databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS }) - .catch(error => { - console.error('Failed syncing database: ', error.message); - throw error; - }); - // I'm not convinced this code is needed. If anyone can see where it leads, or what it does, please inform me. - // For now, I'm commenting it out. I don't think we ever reach this at the moment anyway as the previous ENABLE_SYNC - // was always on. - // return Promise.resolve(); -} - -export function getProvider(provider) { - return Provider.findOrCreate({ where: { name: { [Op.eq]: provider.name } }, defaults: provider }) - .then((result) => result[0]) - .catch(() => provider); -} - -export function getTorrent(torrent) { - const where = torrent.infoHash - ? { infoHash: torrent.infoHash } - : { provider: torrent.provider, torrentId: torrent.torrentId } - return Torrent.findOne({ where: where }); -} - -export function getTorrentsBasedOnTitle(titleQuery, type) { - return getTorrentsBasedOnQuery({ title: { [Op.regexp]: `${titleQuery}` }, type: type }); -} - -export function getTorrentsBasedOnQuery(where) { - return Torrent.findAll({ where: where }); -} - -export function getFilesBasedOnQuery(where) { - return File.findAll({ where: where }); -} - -export function getUnprocessedIngestedTorrents() { - return IngestedTorrent.findAll({ - where: { - processed: false, - category: { - [Op.or]: ['tv', 'movies'] - } - }, - - }); -} - -export function setIngestedTorrentsProcessed(ingestedTorrents) { - return Promises.sequence(ingestedTorrents - .map(ingestedTorrent => () => { - ingestedTorrent.processed = true; - return ingestedTorrent.save(); - })); -} - -export function getTorrentsWithoutSize() { - return Torrent.findAll({ - where: literal( - 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), - order: [ - ['seeders', 'DESC'] - ] - }); -} - -export function getUpdateSeedersTorrents(limit = 50) { - const until = moment().subtract(7, 'days').format('YYYY-MM-DD'); - return Torrent.findAll({ - where: literal(`torrent."updatedAt" < '${until}'`), - limit: limit, - order: [ - ['seeders', 'DESC'], - ['updatedAt', 'ASC'] - ] - }); -} - -export function getUpdateSeedersNewTorrents(limit = 50) { - const lastUpdate = moment().subtract(12, 'hours').format('YYYY-MM-DD'); - const createdAfter = moment().subtract(4, 'days').format('YYYY-MM-DD'); - return Torrent.findAll({ - where: literal(`torrent."updatedAt" < '${lastUpdate}' AND torrent."createdAt" > '${createdAfter}'`), - limit: limit, - order: [ - ['seeders', 'ASC'], - ['updatedAt', 'ASC'] - ] - }); -} - -export function getNoContentsTorrents() { - return Torrent.findAll({ - where: { opened: false, seeders: { [Op.gte]: 1 } }, - limit: 500, - order: [[fn('RANDOM')]] - }); -} - -export function createTorrent(torrent) { - return Torrent.upsert(torrent) - .then(() => createContents(torrent.infoHash, torrent.contents)) - .then(() => createSubtitles(torrent.infoHash, torrent.subtitles)); -} - -export function setTorrentSeeders(torrent, seeders) { - const where = torrent.infoHash - ? { infoHash: torrent.infoHash } - : { provider: torrent.provider, torrentId: torrent.torrentId } - return Torrent.update( - { seeders: seeders }, - { where: where } - ); -} - -export function deleteTorrent(torrent) { - return Torrent.destroy({ where: { infoHash: torrent.infoHash } }) -} - -export function createFile(file) { - if (file.id) { - return (file.dataValues ? file.save() : File.upsert(file)) - .then(() => upsertSubtitles(file, file.subtitles)); - } - if (file.subtitles && file.subtitles.length) { - file.subtitles = file.subtitles.map(subtitle => ({ infoHash: file.infoHash, title: subtitle.path, ...subtitle })); - } - return File.create(file, { include: [Subtitle], ignoreDuplicates: true }); -} - -export function getFiles(torrent) { - return File.findAll({ where: { infoHash: torrent.infoHash } }); -} - -export function getFilesBasedOnTitle(titleQuery) { - return File.findAll({ where: { title: { [Op.regexp]: `${titleQuery}` } } }); -} - -export function deleteFile(file) { - return File.destroy({ where: { id: file.id } }) -} - -export function createSubtitles(infoHash, subtitles) { - if (subtitles && subtitles.length) { - return Subtitle.bulkCreate(subtitles.map(subtitle => ({ infoHash, title: subtitle.path, ...subtitle }))); - } - return Promise.resolve(); -} - -export function upsertSubtitles(file, subtitles) { - if (file.id && subtitles && subtitles.length) { - return Promises.sequence(subtitles - .map(subtitle => { - subtitle.fileId = file.id; - subtitle.infoHash = subtitle.infoHash || file.infoHash; - subtitle.title = subtitle.title || subtitle.path; - return subtitle; - }) - .map(subtitle => () => subtitle.dataValues ? subtitle.save() : Subtitle.create(subtitle))); - } - return Promise.resolve(); -} - -export function getSubtitles(torrent) { - return Subtitle.findAll({ where: { infoHash: torrent.infoHash } }); -} - -export function getUnassignedSubtitles() { - return Subtitle.findAll({ where: { fileId: null } }); -} - -export function createContents(infoHash, contents) { - if (contents && contents.length) { - return Content.bulkCreate(contents.map(content => ({ infoHash, ...content })), { ignoreDuplicates: true }) - .then(() => Torrent.update({ opened: true }, { where: { infoHash: infoHash }, silent: true })); - } - return Promise.resolve(); -} - -export function getContents(torrent) { - return Content.findAll({ where: { infoHash: torrent.infoHash } }); -} - -export function getSkipTorrent(torrent) { - return SkipTorrent.findByPk(torrent.infoHash) - .then((result) => { - if (!result) { - throw new Error(`torrent not found: ${torrent.infoHash}`); - } - return result.dataValues; - }) -} - -export function createSkipTorrent(torrent) { - return SkipTorrent.upsert({ infoHash: torrent.infoHash }); -} diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 998b92e..9fb18a2 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -2,11 +2,11 @@ import { parse } from 'parse-torrent-title'; import { getImdbId, getKitsuId } from './metadata.js'; import { isPackTorrent } from './parseHelper.js'; import * as Promises from './promises.js'; -import * as repository from './repository.js'; +import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; import { assignSubtitles } from './torrentSubtitles.js'; import { TorrentType } from './types.js'; -import {logger} from "./logger.js"; +import {logger} from "./logger"; export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 0ac9ea9..68913f9 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -9,7 +9,7 @@ import { parseSeriesVideos, isPackTorrent } from './parseHelper.js'; import * as Promises from './promises.js'; import {torrentFiles} from "./torrent.js"; import { TorrentType } from './types.js'; -import {logger} from "./logger.js"; +import {logger} from "./logger"; const MIN_SIZE = 5 * 1024 * 1024; // 5 MB const imdb_limiter = new Bottleneck({ maxConcurrent: metadataConfig.IMDB_CONCURRENT, minTime: metadataConfig.IMDB_INTERVAL_MS }); diff --git a/src/node/consumer/src/lib/trackerService.js b/src/node/consumer/src/lib/trackerService.js index 1af9b13..736630d 100644 --- a/src/node/consumer/src/lib/trackerService.js +++ b/src/node/consumer/src/lib/trackerService.js @@ -1,7 +1,7 @@ import axios from 'axios'; import {cacheTrackers} from "./cache.js"; import { trackerConfig } from './config.js'; -import {logger} from "./logger.js"; +import {logger} from "./logger"; const downloadTrackers = async () => { const response = await axios.get(trackerConfig.TRACKERS_URL); diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts new file mode 100644 index 0000000..7aabd04 --- /dev/null +++ b/src/node/consumer/src/repository/database_repository.ts @@ -0,0 +1,259 @@ +import moment from 'moment'; +import {literal, Op, WhereOptions} from "sequelize"; +import {Model, Sequelize} from 'sequelize-typescript'; +import {databaseConfig} from '../lib/config'; +import * as Promises from '../lib/promises.js'; +import {Provider} from "./models/provider"; +import {File} from "./models/file"; +import {Torrent} from "./models/torrent"; +import {IngestedTorrent} from "./models/ingestedTorrent"; +import {Subtitle} from "./models/subtitle"; +import {Content} from "./models/content"; +import {SkipTorrent} from "./models/skipTorrent"; +import {FileAttributes} from "./interfaces/file_attributes"; +import {TorrentAttributes} from "./interfaces/torrent_attributes"; +import {IngestedPage} from "./models/ingestedPage"; +import {logger} from "../lib/logger"; + +class DatabaseRepository { + private readonly database: Sequelize; + + private models = [ + Torrent, + Provider, + File, + Subtitle, + Content, + SkipTorrent, + IngestedTorrent, + IngestedPage]; + + constructor() { + this.database = this.createDatabase(); + } + + public async connect(): Promise { + try { + await this.database.authenticate(); + logger.info('Database connection has been established successfully.'); + await this.database.sync({alter: true}); + } catch (error) { + logger.error('Failed syncing database: ', error); + throw error; + } + } + + public async getProvider(provider: Provider): Promise { + try { + const [result] = await Provider.findOrCreate({ where: { name: { [Op.eq]: provider.name } }, defaults: provider }); + return result; + } catch { + return provider as Provider; + } + } + + public async getTorrent(torrent: Torrent): Promise { + const where = torrent.infoHash + ? { infoHash: torrent.infoHash } + : { provider: torrent.provider, torrentId: torrent.torrentId }; + return await Torrent.findOne({ where }); + } + + public async getTorrentsBasedOnTitle(titleQuery: string, type: string): Promise { + return this.getTorrentsBasedOnQuery({ title: { [Op.regexp]: `${titleQuery}` }, type }); + } + + public async getTorrentsBasedOnQuery(where: WhereOptions): Promise { + return await Torrent.findAll({ where }); + } + + public async getFilesBasedOnQuery(where: WhereOptions): Promise { + return await File.findAll({ where }); + } + + public async getUnprocessedIngestedTorrents(): Promise { + return await IngestedTorrent.findAll({ + where: { + processed: false, + category: { + [Op.or]: ['tv', 'movies'] + } + }, + }); + } + + public async setIngestedTorrentsProcessed(ingestedTorrents: IngestedTorrent[]): Promise { + await Promises.sequence(ingestedTorrents + .map(ingestedTorrent => async () => { + ingestedTorrent.processed = true; + await ingestedTorrent.save(); + })); + } + + public async getTorrentsWithoutSize(): Promise { + return await Torrent.findAll({ + where: literal( + 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), + order: [ + ['seeders', 'DESC'] + ] + }); + } + + public async getUpdateSeedersTorrents(limit = 50): Promise { + const until = moment().subtract(7, 'days').format('YYYY-MM-DD'); + return await Torrent.findAll({ + where: literal(`torrent."updatedAt" < '${until}'`), + limit: limit, + order: [ + ['seeders', 'DESC'], + ['updatedAt', 'ASC'] + ] + }); + } + + public async getUpdateSeedersNewTorrents(limit = 50): Promise { + const lastUpdate = moment().subtract(12, 'hours').format('YYYY-MM-DD'); + const createdAfter = moment().subtract(4, 'days').format('YYYY-MM-DD'); + return await Torrent.findAll({ + where: literal(`torrent."updatedAt" < '${lastUpdate}' AND torrent."createdAt" > '${createdAfter}'`), + limit: limit, + order: [ + ['seeders', 'ASC'], + ['updatedAt', 'ASC'] + ] + }); + } + + public async getNoContentsTorrents(): Promise { + return await Torrent.findAll({ + where: { opened: false, seeders: { [Op.gte]: 1 } }, + limit: 500, + order: literal('random()') + }); + } + + public async createTorrent(torrent: Torrent): Promise { + await Torrent.upsert(torrent); + await this.createContents(torrent.infoHash, torrent.contents); + await this.createSubtitles(torrent.infoHash, torrent.subtitles); + } + + public async setTorrentSeeders(torrent: TorrentAttributes, seeders: number): Promise<[number]> { + const where = torrent.infoHash + ? { infoHash: torrent.infoHash } + : { provider: torrent.provider, torrentId: torrent.torrentId }; + + return await Torrent.update( + { seeders: seeders }, + { where: where } + ); + } + + public async deleteTorrent(torrent: TorrentAttributes): Promise { + return await Torrent.destroy({ where: { infoHash: torrent.infoHash } }); + } + + public async createFile(file: File): Promise { + if (file.id) { + if (file.dataValues) { + await file.save(); + } else { + await File.upsert(file); + } + await this.upsertSubtitles(file, file.subtitles); + } else { + if (file.subtitles && file.subtitles.length) { + file.subtitles = file.subtitles.map(subtitle => { + subtitle.title = subtitle.path; + return subtitle; + }); + } + await File.create(file, { include: [Subtitle], ignoreDuplicates: true }); + } + } + + public async getFiles(torrent: Torrent): Promise { + return File.findAll({ where: { infoHash: torrent.infoHash } }); + } + + public async getFilesBasedOnTitle(titleQuery: string): Promise { + return File.findAll({ where: { title: { [Op.regexp]: `${titleQuery}` } } }); + } + + public async deleteFile(file: File): Promise { + return File.destroy({ where: { id: file.id } }); + } + + public async createSubtitles(infoHash: string, subtitles: Subtitle[]): Promise[]> { + if (subtitles && subtitles.length) { + return Subtitle.bulkCreate(subtitles.map(subtitle => ({ infoHash, title: subtitle.path, ...subtitle }))); + } + return Promise.resolve(); + } + + public async upsertSubtitles(file: File, subtitles: Subtitle[]): Promise { + if (file.id && subtitles && subtitles.length) { + await Promises.sequence(subtitles + .map(subtitle => { + subtitle.fileId = file.id; + subtitle.infoHash = subtitle.infoHash || file.infoHash; + subtitle.title = subtitle.title || subtitle.path; + return subtitle; + }) + .map(subtitle => async () => { + if (subtitle.dataValues) { + await subtitle.save(); + } else { + await Subtitle.create(subtitle); + } + })); + } + } + + public async getSubtitles(torrent: Torrent): Promise { + return Subtitle.findAll({ where: { infoHash: torrent.infoHash } }); + } + + public async getUnassignedSubtitles(): Promise { + return Subtitle.findAll({ where: { fileId: null } }); + } + + public async createContents(infoHash: string, contents: Content[]): Promise { + if (contents && contents.length) { + await Content.bulkCreate(contents.map(content => ({ infoHash, ...content })), { ignoreDuplicates: true }); + await Torrent.update({ opened: true }, { where: { infoHash: infoHash }, silent: true }); + } + } + + public async getContents(torrent: Torrent): Promise { + return Content.findAll({ where: { infoHash: torrent.infoHash } }); + } + + public async getSkipTorrent(torrent: Torrent): Promise { + const result = await SkipTorrent.findByPk(torrent.infoHash); + if (!result) { + throw new Error(`torrent not found: ${torrent.infoHash}`); + } + return result.dataValues as SkipTorrent; + } + + public async createSkipTorrent(torrent: Torrent): Promise<[SkipTorrent, boolean]> { + return SkipTorrent.upsert({ infoHash: torrent.infoHash }); + } + + private createDatabase(): Sequelize { + const newDatabase = new Sequelize( + databaseConfig.POSTGRES_URI, + { + logging: false + } + ); + + newDatabase.addModels(this.models); + + return newDatabase; + } +} + +export const repository = new DatabaseRepository(); diff --git a/src/node/consumer/src/repository/interfaces/content_attributes.ts b/src/node/consumer/src/repository/interfaces/content_attributes.ts new file mode 100644 index 0000000..c7d8e85 --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/content_attributes.ts @@ -0,0 +1,11 @@ +import {Optional} from "sequelize"; + +export interface ContentAttributes { + infoHash: string; + fileIndex: number; + path: string; + size: number; +} + +export interface ContentCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/file_attributes.ts b/src/node/consumer/src/repository/interfaces/file_attributes.ts new file mode 100644 index 0000000..4cb68ea --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/file_attributes.ts @@ -0,0 +1,19 @@ +import {Optional} from "sequelize"; +import {SubtitleAttributes} from "./subtitle_attributes"; + +export interface FileAttributes { + id?: number; + infoHash: string; + fileIndex: number; + title: string; + size: number; + imdbId: string; + imdbSeason: number; + imdbEpisode: number; + kitsuId: number; + kitsuEpisode: number; + subtitles?: SubtitleAttributes[]; +} + +export interface FileCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts new file mode 100644 index 0000000..21bf9a6 --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts @@ -0,0 +1,6 @@ +export interface IngestedPageAttributes { + url: string; +} + +export interface IngestedPageCreationAttributes extends IngestedPageAttributes { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts new file mode 100644 index 0000000..9dbe491 --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts @@ -0,0 +1,16 @@ +import {Optional} from "sequelize"; + +export interface IngestedTorrentAttributes { + name: string; + source: string; + category: string; + info_hash: string; + size: string; + seeders: number; + leechers: number; + imdb: string; + processed: boolean; +} + +export interface IngestedTorrentCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/provider_attributes.ts b/src/node/consumer/src/repository/interfaces/provider_attributes.ts new file mode 100644 index 0000000..c175caa --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/provider_attributes.ts @@ -0,0 +1,10 @@ +import {Optional} from "sequelize"; + +export interface ProviderAttributes { + name: string; + lastScraped: Date; + lastScrapedId: string; +} + +export interface ProviderCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts new file mode 100644 index 0000000..9b843da --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts @@ -0,0 +1,8 @@ +import {Optional} from "sequelize"; + +export interface SkipTorrentAttributes { + infoHash: string; +} + +export interface SkipTorrentCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts b/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts new file mode 100644 index 0000000..6e4a28b --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts @@ -0,0 +1,12 @@ +import {Optional} from "sequelize"; + +export interface SubtitleAttributes { + infoHash: string; + fileIndex: number; + fileId?: number; + title: string; + path: string; +} + +export interface SubtitleCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts new file mode 100644 index 0000000..0fcef0b --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts @@ -0,0 +1,26 @@ +import {Optional} from "sequelize"; +import {ContentAttributes} from "./content_attributes"; +import {SubtitleAttributes} from "./subtitle_attributes"; +import {FileAttributes} from "./file_attributes"; + +export interface TorrentAttributes { + infoHash: string; + provider: string; + torrentId: string; + title: string; + size: number; + type: string; + uploadDate: Date; + seeders: number; + trackers: string; + languages: string; + resolution: string; + reviewed: boolean; + opened: boolean; + contents: ContentAttributes[]; + files: FileAttributes[]; + subtitles?: SubtitleAttributes[]; +} + +export interface TorrentCreationAttributes extends Optional { +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/content.ts b/src/node/consumer/src/repository/models/content.ts new file mode 100644 index 0000000..7e70d7e --- /dev/null +++ b/src/node/consumer/src/repository/models/content.ts @@ -0,0 +1,22 @@ +import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {ContentAttributes, ContentCreationAttributes} from "../interfaces/content_attributes"; +import {Torrent} from "./torrent"; + +@Table({modelName: 'content', timestamps: false}) +export class Content extends Model { + @Column({ type: DataType.STRING(64), primaryKey: true, allowNull: false, onDelete: 'CASCADE' }) + @ForeignKey(() => Torrent) + declare infoHash: string; + + @Column({ type: DataType.INTEGER, primaryKey: true, allowNull: false }) + declare fileIndex: number; + + @Column({ type: DataType.STRING(512), allowNull: false }) + declare path: string; + + @Column({ type: DataType.BIGINT }) + declare size: number; + + @BelongsTo(() => Torrent, { constraints: false, foreignKey: 'infoHash' }) + torrent: Torrent; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/file.ts b/src/node/consumer/src/repository/models/file.ts new file mode 100644 index 0000000..2383a78 --- /dev/null +++ b/src/node/consumer/src/repository/models/file.ts @@ -0,0 +1,60 @@ +import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {FileAttributes, FileCreationAttributes} from "../interfaces/file_attributes"; +import {Torrent} from "./torrent"; +import {Subtitle} from "./subtitle"; +import {SubtitleAttributes} from "../interfaces/subtitle_attributes"; + +const indexes = [ + { + unique: true, + name: 'files_unique_file_constraint', + fields: [ + 'infoHash', + 'fileIndex', + 'imdbId', + 'imdbSeason', + 'imdbEpisode', + 'kitsuId', + 'kitsuEpisode' + ] + }, + { unique: false, fields: ['imdbId', 'imdbSeason', 'imdbEpisode'] }, + { unique: false, fields: ['kitsuId', 'kitsuEpisode'] } +]; + +@Table({modelName: 'file', timestamps: true, indexes: indexes }) +export class File extends Model { + @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) + @ForeignKey(() => Torrent) + declare infoHash: string; + + @Column({ type: DataType.INTEGER}) + declare fileIndex: number; + + @Column({ type: DataType.STRING(512), allowNull: false }) + declare title: string; + + @Column({ type: DataType.BIGINT }) + declare size: number; + + @Column({ type: DataType.STRING(32) }) + declare imdbId: string; + + @Column({ type: DataType.INTEGER }) + declare imdbSeason: number; + + @Column({ type: DataType.INTEGER }) + declare imdbEpisode: number; + + @Column({ type: DataType.INTEGER }) + declare kitsuId: number; + + @Column({ type: DataType.INTEGER }) + declare kitsuEpisode: number; + + @HasMany(() => Subtitle, { constraints: false, foreignKey: 'fileId'}) + declare subtitles?: Subtitle[]; + + @BelongsTo(() => Torrent, { constraints: false, foreignKey: 'infoHash' }) + torrent: Torrent; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedPage.ts b/src/node/consumer/src/repository/models/ingestedPage.ts new file mode 100644 index 0000000..6504344 --- /dev/null +++ b/src/node/consumer/src/repository/models/ingestedPage.ts @@ -0,0 +1,16 @@ +import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {IngestedPageAttributes, IngestedPageCreationAttributes} from "../interfaces/ingested_page_attributes"; + +const indexes = [ + { + unique: true, + name: 'ingested_page_unique_url_constraint', + fields: ['url'] + } +]; + +@Table({modelName: 'ingested_page', timestamps: true, indexes: indexes}) +export class IngestedPage extends Model { + @Column({ type: DataType.STRING(512), allowNull: false }) + declare url: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedTorrent.ts b/src/node/consumer/src/repository/models/ingestedTorrent.ts new file mode 100644 index 0000000..5a21a4a --- /dev/null +++ b/src/node/consumer/src/repository/models/ingestedTorrent.ts @@ -0,0 +1,40 @@ +import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {IngestedTorrentAttributes, IngestedTorrentCreationAttributes} from "../interfaces/ingested_torrent_attributes"; + +const indexes = [ + { + unique: true, + name: 'ingested_torrent_unique_source_info_hash_constraint', + fields: ['source', 'info_hash'] + } +]; + +@Table({modelName: 'ingested_torrent', timestamps: true, indexes: indexes}) +export class IngestedTorrent extends Model { + @Column({ type: DataType.STRING(512) }) + declare name: string; + + @Column({ type: DataType.STRING(512) }) + declare source: string; + + @Column({ type: DataType.STRING(32) }) + declare category: string; + + @Column({ type: DataType.STRING(64) }) + declare info_hash: string; + + @Column({ type: DataType.STRING(32) }) + declare size: string; + + @Column({ type: DataType.INTEGER }) + declare seeders: number; + + @Column({ type: DataType.INTEGER }) + declare leechers: number; + + @Column({ type: DataType.STRING(32) }) + declare imdb: string; + + @Column({ type: DataType.BOOLEAN, defaultValue: false }) + declare processed: boolean; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/provider.ts b/src/node/consumer/src/repository/models/provider.ts new file mode 100644 index 0000000..26a8bfc --- /dev/null +++ b/src/node/consumer/src/repository/models/provider.ts @@ -0,0 +1,15 @@ +import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {ProviderAttributes, ProviderCreationAttributes} from "../interfaces/provider_attributes"; + +@Table({modelName: 'provider', timestamps: false}) +export class Provider extends Model { + + @Column({ type: DataType.STRING(32), primaryKey: true }) + declare name: string; + + @Column({ type: DataType.DATE }) + declare lastScraped: Date; + + @Column({ type: DataType.STRING(128) }) + declare lastScrapedId: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/skipTorrent.ts b/src/node/consumer/src/repository/models/skipTorrent.ts new file mode 100644 index 0000000..101ce68 --- /dev/null +++ b/src/node/consumer/src/repository/models/skipTorrent.ts @@ -0,0 +1,10 @@ +import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {SkipTorrentAttributes, SkipTorrentCreationAttributes} from "../interfaces/skip_torrent_attributes"; + + +@Table({modelName: 'skip_torrent', timestamps: false}) +export class SkipTorrent extends Model { + + @Column({ type: DataType.STRING(64), primaryKey: true }) + declare infoHash: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/subtitle.ts b/src/node/consumer/src/repository/models/subtitle.ts new file mode 100644 index 0000000..0a4157c --- /dev/null +++ b/src/node/consumer/src/repository/models/subtitle.ts @@ -0,0 +1,39 @@ +import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {SubtitleAttributes, SubtitleCreationAttributes} from "../interfaces/subtitle_attributes"; +import {File} from "./file"; +import {Torrent} from "./torrent"; + +const indexes = [ + { + unique: true, + name: 'subtitles_unique_subtitle_constraint', + fields: [ + 'infoHash', + 'fileIndex', + 'fileId' + ] + }, + { unique: false, fields: ['fileId'] } +]; + +@Table({modelName: 'subtitle', timestamps: false, indexes: indexes}) +export class Subtitle extends Model { + + @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) + declare infoHash: string; + + @Column({ type: DataType.INTEGER, allowNull: false }) + declare fileIndex: number; + + @Column({ type: DataType.BIGINT, allowNull: true, onDelete: 'SET NULL' }) + @ForeignKey(() => File) + declare fileId?: number | null; + + @Column({ type: DataType.STRING(512), allowNull: false }) + declare title: string; + + @BelongsTo(() => File, { constraints: false, foreignKey: 'fileId' }) + file: File; + + path: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/torrent.ts b/src/node/consumer/src/repository/models/torrent.ts new file mode 100644 index 0000000..b6b7a80 --- /dev/null +++ b/src/node/consumer/src/repository/models/torrent.ts @@ -0,0 +1,56 @@ +import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {TorrentAttributes, TorrentCreationAttributes} from "../interfaces/torrent_attributes"; +import {Content} from "./content"; +import {File} from "./file"; +import {Subtitle} from "./subtitle"; + +@Table({modelName: 'torrent', timestamps: true}) + +export class Torrent extends Model { + @Column({type: DataType.STRING(64), primaryKey: true}) + declare infoHash: string; + + @Column({type: DataType.STRING(32), allowNull: false}) + declare provider: string; + + @Column({type: DataType.STRING(512)}) + declare torrentId: string; + + @Column({type: DataType.STRING(512), allowNull: false}) + declare title: string; + + @Column({type: DataType.BIGINT}) + declare size: number; + + @Column({type: DataType.STRING(16), allowNull: false}) + declare type: string; + + @Column({type: DataType.DATE, allowNull: false}) + declare uploadDate: Date; + + @Column({type: DataType.SMALLINT}) + declare seeders: number; + + @Column({type: DataType.STRING(8000)}) + declare trackers: string; + + @Column({type: DataType.STRING(4096)}) + declare languages: string; + + @Column({type: DataType.STRING(16)}) + declare resolution: string; + + @Column({type: DataType.BOOLEAN, allowNull: false, defaultValue: false}) + declare reviewed: boolean; + + @Column({type: DataType.BOOLEAN, allowNull: false, defaultValue: false}) + declare opened: boolean; + + @HasMany(() => Content, { foreignKey: 'infoHash', constraints: false }) + contents?: Content[]; + + @HasMany(() => File, { foreignKey: 'infoHash', constraints: false }) + files?: File[]; + + subtitles?: Subtitle[]; +} \ No newline at end of file diff --git a/src/node/consumer/jsconfig.json b/src/node/consumer/tsconfig.json similarity index 64% rename from src/node/consumer/jsconfig.json rename to src/node/consumer/tsconfig.json index 6b1c407..c6f83d1 100644 --- a/src/node/consumer/jsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -3,7 +3,7 @@ "baseUrl": "./src", "checkJs": true, "isolatedModules": true, - "lib": ["es6"], + "lib": ["ESNext"], "module": "ESNext", "moduleResolution": "node", "outDir": "./dist", @@ -13,9 +13,12 @@ "rootDir": "./src", "skipLibCheck": true, "sourceMap": true, - "target": "ES6", + "target": "ESNext", "types": ["node"], - "typeRoots": ["node_modules/@types", "src/@types"] + "typeRoots": ["node_modules/@types", "src/@types"], + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "allowSyntheticDefaultImports": true }, "exclude": ["node_modules"] } \ No newline at end of file From cf25f32cb619c209382d4b5663f8a029bfbe592c Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 03:35:52 +0000 Subject: [PATCH 02/55] Torrent processing orchestrator now typescript too Will start to tackle some of the other services after work tomorrow. --- src/node/consumer/package-lock.json | 10 ++++ src/node/consumer/package.json | 1 + src/node/consumer/src/index.js | 2 +- src/node/consumer/src/jobs/processTorrents.js | 37 ------------ src/node/consumer/src/jobs/processTorrents.ts | 56 +++++++++++++++++++ src/node/consumer/src/lib/cache.js | 2 +- .../consumer/src/lib/enums/cache_types.ts | 4 ++ .../consumer/src/lib/enums/torrent_types.ts | 6 ++ src/node/consumer/src/lib/ingestedTorrent.js | 46 --------------- .../lib/interfaces/ingested_rabbit_message.ts | 15 +++++ .../src/lib/interfaces/torrent_info.ts | 12 ++++ src/node/consumer/src/lib/metadata.js | 2 +- src/node/consumer/src/lib/parseHelper.js | 2 +- src/node/consumer/src/lib/torrentEntries.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- .../consumer/src/lib/torrent_processor.ts | 49 ++++++++++++++++ src/node/consumer/src/lib/types.js | 11 ---- .../interfaces/ingested_torrent_attributes.ts | 1 + 18 files changed, 160 insertions(+), 100 deletions(-) delete mode 100644 src/node/consumer/src/jobs/processTorrents.js create mode 100644 src/node/consumer/src/jobs/processTorrents.ts create mode 100644 src/node/consumer/src/lib/enums/cache_types.ts create mode 100644 src/node/consumer/src/lib/enums/torrent_types.ts delete mode 100644 src/node/consumer/src/lib/ingestedTorrent.js create mode 100644 src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_info.ts create mode 100644 src/node/consumer/src/lib/torrent_processor.ts delete mode 100644 src/node/consumer/src/lib/types.js diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 9a34802..3ad7ee7 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -30,6 +30,7 @@ "user-agents": "^1.0.1444" }, "devDependencies": { + "@types/amqplib": "^0.10.4", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", "@types/validator": "^13.11.8", @@ -564,6 +565,15 @@ "url": "https://github.com/sponsors/tirke" } }, + "node_modules/@types/amqplib": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz", + "integrity": "sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "license": "MIT", diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 2639881..0c86906 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -31,6 +31,7 @@ "user-agents": "^1.0.1444" }, "devDependencies": { + "@types/amqplib": "^0.10.4", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", "@types/validator": "^13.11.8", diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.js index e3ac0b7..92f994d 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.js @@ -1,4 +1,4 @@ -import { listenToQueue } from './jobs/processTorrents.js'; +import { listenToQueue } from './jobs/processTorrents'; import { repository } from "./repository/database_repository"; import { getTrackers } from "./lib/trackerService.js"; diff --git a/src/node/consumer/src/jobs/processTorrents.js b/src/node/consumer/src/jobs/processTorrents.js deleted file mode 100644 index 1dd50b2..0000000 --- a/src/node/consumer/src/jobs/processTorrents.js +++ /dev/null @@ -1,37 +0,0 @@ -import amqp from 'amqplib' -import { rabbitConfig, jobConfig } from '../lib/config.js' -import { processTorrentRecord } from "../lib/ingestedTorrent.js"; -import {logger} from "../lib/logger"; - -const assertQueueOptions = { durable: true } -const consumeQueueOptions = { noAck: false } - -const processMessage = msg => processTorrentRecord(getMessageAsJson(msg)); - -const getMessageAsJson = msg => - JSON.parse(msg.content.toString()).message; - -const assertAndConsumeQueue = async channel => { - logger.info('Worker is running! Waiting for new torrents...') - - const ackMsg = msg => - processMessage(msg) - .then(() => channel.ack(msg)) - .catch(error => logger.error('Failed processing torrent', error)); - - channel.assertQueue(rabbitConfig.QUEUE_NAME, assertQueueOptions) - .then(() => channel.prefetch(jobConfig.JOB_CONCURRENCY)) - .then(() => channel.consume(rabbitConfig.QUEUE_NAME, ackMsg, consumeQueueOptions)) - .catch(error => logger.error('Failed to setup channel', error)); -} - -export const listenToQueue = async () => { - if (!jobConfig.JOBS_ENABLED) { - return; - } - - return amqp.connect(rabbitConfig.URI) - .then(connection => connection.createChannel()) - .then(channel => assertAndConsumeQueue(channel)) - .catch(error => logger.error('Failed to connect and setup channel', error)); - }; \ No newline at end of file diff --git a/src/node/consumer/src/jobs/processTorrents.ts b/src/node/consumer/src/jobs/processTorrents.ts new file mode 100644 index 0000000..200d84c --- /dev/null +++ b/src/node/consumer/src/jobs/processTorrents.ts @@ -0,0 +1,56 @@ +import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' +import {jobConfig, rabbitConfig} from '../lib/config.js'; +import {processTorrentRecord} from '../lib/torrent_processor'; +import {logger} from '../lib/logger'; +import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; +import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; + +const assertQueueOptions: Options.AssertQueue = { durable: true }; +const consumeQueueOptions: Options.Consume = { noAck: false }; + +const processMessage = (msg: ConsumeMessage | null): Promise => { + const ingestedTorrent: IngestedTorrentAttributes = getMessageAsJson(msg); + return processTorrentRecord(ingestedTorrent); +}; + +const getMessageAsJson = (msg: ConsumeMessage | null): IngestedTorrentAttributes => { + const content = msg ? msg?.content.toString('utf8') : "{}"; + const receivedObject: IngestedRabbitMessage = JSON.parse(content) as IngestedRabbitMessage; + const receivedTorrent:IngestedRabbitTorrent = receivedObject.message; + const mappedObject: any = {...receivedTorrent, info_hash: receivedTorrent.infoHash}; + delete mappedObject.infoHash; + + return mappedObject as IngestedTorrentAttributes; +}; + +const assertAndConsumeQueue = async (channel: Channel): Promise => { + logger.info('Worker is running! Waiting for new torrents...'); + + const ackMsg = (msg: ConsumeMessage): void => { + processMessage(msg) + .then(() => channel.ack(msg)) + .catch((error: Error) => logger.error('Failed processing torrent', error)); + } + + try { + await channel.assertQueue(rabbitConfig.QUEUE_NAME, assertQueueOptions); + await channel.prefetch(jobConfig.JOB_CONCURRENCY); + await channel.consume(rabbitConfig.QUEUE_NAME, ackMsg, consumeQueueOptions); + } catch(error) { + logger.error('Failed to setup channel', error); + } +} + +export const listenToQueue = async (): Promise => { + if (!jobConfig.JOBS_ENABLED) { + return; + } + + try { + const connection: Connection = await client.connect(rabbitConfig.URI); + const channel: Channel = await connection.createChannel(); + await assertAndConsumeQueue(channel); + } catch (error) { + logger.error('Failed to connect and setup channel', error); + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/cache.js b/src/node/consumer/src/lib/cache.js index a7c1128..3c9d69d 100644 --- a/src/node/consumer/src/lib/cache.js +++ b/src/node/consumer/src/lib/cache.js @@ -2,7 +2,7 @@ import { createCache, memoryStore} from 'cache-manager'; import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' import { cacheConfig } from './config.js'; import { logger } from './logger'; -import { CacheType } from "./types.js"; +import { CacheType } from "./enums/cache_types"; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; diff --git a/src/node/consumer/src/lib/enums/cache_types.ts b/src/node/consumer/src/lib/enums/cache_types.ts new file mode 100644 index 0000000..989f6bd --- /dev/null +++ b/src/node/consumer/src/lib/enums/cache_types.ts @@ -0,0 +1,4 @@ +export enum CacheType { + MEMORY = 'memory', + MONGODB = 'mongodb' +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/enums/torrent_types.ts b/src/node/consumer/src/lib/enums/torrent_types.ts new file mode 100644 index 0000000..7a20693 --- /dev/null +++ b/src/node/consumer/src/lib/enums/torrent_types.ts @@ -0,0 +1,6 @@ +export enum TorrentType { + SERIES = 'SERIES', + MOVIE = 'MOVIE', + ANIME = 'anime', + PORN = 'xxx', +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/ingestedTorrent.js b/src/node/consumer/src/lib/ingestedTorrent.js deleted file mode 100644 index fe8705d..0000000 --- a/src/node/consumer/src/lib/ingestedTorrent.js +++ /dev/null @@ -1,46 +0,0 @@ -import { createTorrentEntry, checkAndUpdateTorrent } from './torrentEntries.js'; -import {getTrackers} from "./trackerService.js"; -import { TorrentType } from './types.js'; -import {logger} from "./logger"; - -export async function processTorrentRecord(torrent) { - const {category} = torrent; - const type = category === 'tv' ? TorrentType.SERIES : TorrentType.MOVIE; - const torrentInfo = await parseTorrent(torrent, type); - logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`) - - if (await checkAndUpdateTorrent(torrentInfo)) { - return torrentInfo; - } - - return createTorrentEntry(torrentInfo); -} - -async function assignTorrentTrackers() { - const trackers = await getTrackers(); - return trackers.join(','); -} - -async function parseTorrent(torrent, category) { - const infoHash = torrent.infoHash?.trim().toLowerCase() - return { - title: torrent.name, - torrentId: `${torrent.name}_${infoHash}`, - infoHash: infoHash, - seeders: 100, - size: torrent.size, - uploadDate: torrent.createdAt, - imdbId: parseImdbId(torrent), - type: category, - provider: torrent.source, - trackers: await assignTorrentTrackers(), - } -} - -function parseImdbId(torrent) { - if (torrent.imdb === undefined || torrent.imdb === null) { - return undefined; - } - - return torrent.imdb; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts b/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts new file mode 100644 index 0000000..28ef21c --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts @@ -0,0 +1,15 @@ +export interface IngestedRabbitTorrent { + name: string; + source: string; + category: string; + infoHash: string; + size: string; + seeders: number; + leechers: number; + imdb: string; + processed: boolean; +} + +export interface IngestedRabbitMessage { + message: IngestedRabbitTorrent; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_info.ts b/src/node/consumer/src/lib/interfaces/torrent_info.ts new file mode 100644 index 0000000..31895bd --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_info.ts @@ -0,0 +1,12 @@ +export interface TorrentInfo { + title: string | null; + torrentId: string; + infoHash: string | null; + seeders: number; + size: string | null; + uploadDate: Date; + imdbId: string | undefined; + type: string; + provider: string | null; + trackers: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/metadata.js b/src/node/consumer/src/lib/metadata.js index 874decb..09da123 100644 --- a/src/node/consumer/src/lib/metadata.js +++ b/src/node/consumer/src/lib/metadata.js @@ -2,7 +2,7 @@ import axios from 'axios'; import { search } from 'google-sr'; import nameToImdb from 'name-to-imdb'; import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache.js'; -import { TorrentType } from './types.js'; +import { TorrentType } from './enums/torrent_types'; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; diff --git a/src/node/consumer/src/lib/parseHelper.js b/src/node/consumer/src/lib/parseHelper.js index b088687..131e4f0 100644 --- a/src/node/consumer/src/lib/parseHelper.js +++ b/src/node/consumer/src/lib/parseHelper.js @@ -1,5 +1,5 @@ import { parse } from 'parse-torrent-title'; -import { TorrentType } from './types.js'; +import { TorrentType } from './enums/torrent_types'; const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 9fb18a2..d5a629d 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -5,7 +5,7 @@ import * as Promises from './promises.js'; import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; import { assignSubtitles } from './torrentSubtitles.js'; -import { TorrentType } from './types.js'; +import { TorrentType } from './enums/torrent_types'; import {logger} from "./logger"; export async function createTorrentEntry(torrent, overwrite = false) { diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 68913f9..0a59c56 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -8,7 +8,7 @@ import { getMetadata, getImdbId, getKitsuId } from './metadata.js'; import { parseSeriesVideos, isPackTorrent } from './parseHelper.js'; import * as Promises from './promises.js'; import {torrentFiles} from "./torrent.js"; -import { TorrentType } from './types.js'; +import { TorrentType } from './enums/torrent_types'; import {logger} from "./logger"; const MIN_SIZE = 5 * 1024 * 1024; // 5 MB diff --git a/src/node/consumer/src/lib/torrent_processor.ts b/src/node/consumer/src/lib/torrent_processor.ts new file mode 100644 index 0000000..49f842a --- /dev/null +++ b/src/node/consumer/src/lib/torrent_processor.ts @@ -0,0 +1,49 @@ +import {TorrentInfo} from "./interfaces/torrent_info"; +import {TorrentType} from "./enums/torrent_types"; +import {logger} from "./logger"; +import {checkAndUpdateTorrent, createTorrentEntry} from "./torrentEntries.js"; +import {getTrackers} from "./trackerService.js"; +import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; + +export async function processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { + const { category } = torrent; + const type = category === 'tv' ? TorrentType.SERIES : TorrentType.MOVIE; + const torrentInfo: TorrentInfo = await parseTorrent(torrent, type); + + logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); + + if (await checkAndUpdateTorrent(torrentInfo)) { + return; + } + + return createTorrentEntry(torrentInfo); +} + +async function assignTorrentTrackers(): Promise { + const trackers = await getTrackers(); + return trackers.join(','); +} + +async function parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { + const infoHash = torrent.info_hash?.trim().toLowerCase() + return { + title: torrent.name, + torrentId: `${torrent.name}_${infoHash}`, + infoHash: infoHash, + seeders: 100, + size: torrent.size, + uploadDate: torrent.createdAt, + imdbId: parseImdbId(torrent), + type: category, + provider: torrent.source, + trackers: await assignTorrentTrackers(), + } +} + +function parseImdbId(torrent: IngestedTorrentAttributes): string | undefined { + if (torrent.imdb === undefined || torrent.imdb === null) { + return undefined; + } + + return torrent.imdb; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/types.js b/src/node/consumer/src/lib/types.js deleted file mode 100644 index 17d37dc..0000000 --- a/src/node/consumer/src/lib/types.js +++ /dev/null @@ -1,11 +0,0 @@ -export const TorrentType = { - MOVIE: 'movie', - SERIES: 'series', - ANIME: 'anime', - PORN: 'xxx', -}; - -export const CacheType = { - MEMORY: 'memory', - MONGODB: 'mongodb', -}; \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts index 9dbe491..b54eec1 100644 --- a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts @@ -10,6 +10,7 @@ export interface IngestedTorrentAttributes { leechers: number; imdb: string; processed: boolean; + createdAt: Date; } export interface IngestedTorrentCreationAttributes extends Optional { From 948cb8e03733c3085ec8673bf0b4121465f5dede Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 04:57:04 +0000 Subject: [PATCH 03/55] metadata service now ts --- .../src/lib/interfaces/cinemeta_metadata.ts | 80 +++++++ .../lib/interfaces/common_video_metadata.ts | 4 + .../lib/interfaces/kitsu_catalog_metadata.ts | 23 ++ .../src/lib/interfaces/kitsu_metadata.ts | 49 ++++ .../src/lib/interfaces/metadata_query.ts | 8 + .../src/lib/interfaces/metadata_response.ts | 13 ++ src/node/consumer/src/lib/metadata.js | 165 ------------- src/node/consumer/src/lib/metadata.ts | 216 ++++++++++++++++++ src/node/consumer/src/lib/torrentEntries.js | 16 +- src/node/consumer/src/lib/torrentFiles.js | 19 +- 10 files changed, 422 insertions(+), 171 deletions(-) create mode 100644 src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts create mode 100644 src/node/consumer/src/lib/interfaces/common_video_metadata.ts create mode 100644 src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts create mode 100644 src/node/consumer/src/lib/interfaces/kitsu_metadata.ts create mode 100644 src/node/consumer/src/lib/interfaces/metadata_query.ts create mode 100644 src/node/consumer/src/lib/interfaces/metadata_response.ts delete mode 100644 src/node/consumer/src/lib/metadata.js create mode 100644 src/node/consumer/src/lib/metadata.ts diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts new file mode 100644 index 0000000..48cdc8a --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -0,0 +1,80 @@ +import {CommonVideoMetadata} from "./common_video_metadata"; + +export interface CinemetaJsonResponse { + meta?: CinemetaMetaData; + trailerStreams?: CinemetaTrailerStream[]; + links?: CinemetaLink[]; + behaviorHints?: CinemetaBehaviorHints; +} +export interface CinemetaMetaData { + awards?: string; + cast?: string[]; + country?: string; + description?: string; + director?: null; + dvdRelease?: null; + genre?: string[]; + imdbRating?: string; + imdb_id?: string; + name?: string; + popularity?: number; + poster?: string; + released?: string; + runtime?: string; + status?: string; + tvdb_id?: number; + type?: string; + writer?: string[]; + year?: string; + background?: string; + logo?: string; + popularities?: CinemetaPopularities; + moviedb_id?: number; + slug?: string; + trailers?: CinemetaTrailer[]; + id?: string; + genres?: string[]; + releaseInfo?: string; + videos?: CinemetaVideo[]; +} +export interface CinemetaPopularities { + PXS_TEST?: number; + PXS?: number; + SCM?: number; + EXMD?: number; + ALLIANCE?: number; + EJD?: number; + moviedb?: number; + trakt?: number; + stremio?: number; + stremio_lib?: number; +} +export interface CinemetaTrailer { + source?: string; + type?: string; +} +export interface CinemetaVideo extends CommonVideoMetadata { + name?: string; + number?: number; + firstAired?: string; + tvdb_id?: number; + rating?: string; + overview?: string; + thumbnail?: string; + id?: string; + released?: string; + description?: string; +} +export interface CinemetaTrailerStream { + title?: string; + ytId?: string; +} +export interface CinemetaLink { + name?: string; + category?: string; + url?: string; +} +export interface CinemetaBehaviorHints { + defaultVideoId?: null; + hasScheduledVideos?: boolean; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts new file mode 100644 index 0000000..4383417 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts @@ -0,0 +1,4 @@ +export interface CommonVideoMetadata { + season?: number; + episode?: number; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts new file mode 100644 index 0000000..42ac1bd --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts @@ -0,0 +1,23 @@ +import {KitsuLink, KitsuTrailer} from "./kitsu_metadata"; + +export interface KitsuCatalogJsonResponse { + metas: KitsuCatalogMetaData[]; +} + +export interface KitsuCatalogMetaData { + id: string; + type: string; + animeType: string; + name: string; + aliases: string[]; + description: string; + releaseInfo: string; + runtime: string; + imdbRating: string; + genres: string[]; + logo?: string; + poster: string; + background: string; + trailers: KitsuTrailer[]; + links: KitsuLink[]; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts new file mode 100644 index 0000000..fc63293 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -0,0 +1,49 @@ +import {CommonVideoMetadata} from "./common_video_metadata"; + +export interface KitsuJsonResponse { + cacheMaxAge?: number; + meta?: KitsuMeta; +} +export interface KitsuMeta { + aliases?: string[]; + animeType?: string; + background?: string; + description?: string; + country?: string; + genres?: string[]; + id?: string; + imdbRating?: string; + imdb_id?: string; + kitsu_id?: string; + links?: KitsuLink[]; + logo?: string; + name?: string; + poster?: string; + releaseInfo?: string; + runtime?: string; + slug?: string; + status?: string; + trailers?: KitsuTrailer[]; + type?: string; + userCount?: number; + videos?: KitsuVideo[]; + year?: string; +} +export interface KitsuVideo extends CommonVideoMetadata { + id?: string; + imdbEpisode?: number; + imdbSeason?: number; + imdb_id?: string; + released?: string; + thumbnail?: string; + title?: string; +} +export interface KitsuTrailer { + source?: string; + type?: string; +} +export interface KitsuLink { + name?: string; + category?: string; + url?: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_query.ts b/src/node/consumer/src/lib/interfaces/metadata_query.ts new file mode 100644 index 0000000..ecb85ea --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/metadata_query.ts @@ -0,0 +1,8 @@ +export interface MetaDataQuery { + title?: string + type?: string + year?: number | string + date?: string + season?: number + episode?: number +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_response.ts b/src/node/consumer/src/lib/interfaces/metadata_response.ts new file mode 100644 index 0000000..e1509c5 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/metadata_response.ts @@ -0,0 +1,13 @@ +export interface MetadataResponse { + kitsuId?: number; + imdbId?: number; + type?: string; + title?: string; + year?: number; + country?: string; + genres?: string[]; + status?: string; + videos?: any[]; + episodeCount?: number[]; + totalCount?: number; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/metadata.js b/src/node/consumer/src/lib/metadata.js deleted file mode 100644 index 09da123..0000000 --- a/src/node/consumer/src/lib/metadata.js +++ /dev/null @@ -1,165 +0,0 @@ -import axios from 'axios'; -import { search } from 'google-sr'; -import nameToImdb from 'name-to-imdb'; -import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache.js'; -import { TorrentType } from './enums/torrent_types'; - -const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; -const KITSU_URL = 'https://anime-kitsu.strem.fun'; -const TIMEOUT = 20000; - -export function getMetadata(id, type = TorrentType.SERIES) { - if (!id) { - return Promise.reject("no valid id provided"); - } - - const key = Number.isInteger(id) || id.match(/^\d+$/) ? `kitsu:${id}` : id; - const metaType = type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; - return cacheWrapMetadata(key, () => _requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) - .catch(() => _requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) - .catch(() => { - // try different type in case there was a mismatch - const otherType = metaType === TorrentType.MOVIE ? TorrentType.SERIES : TorrentType.MOVIE; - return _requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) - }) - .catch((error) => { - throw new Error(`failed metadata query ${key} due: ${error.message}`); - })); -} - -function _requestMetadata(url) { - return axios.get(url, { timeout: TIMEOUT }) - .then((response) => { - const body = response.data; - if (body && body.meta && (body.meta.imdb_id || body.meta.kitsu_id)) { - return { - kitsuId: body.meta.kitsu_id, - imdbId: body.meta.imdb_id, - type: body.meta.type, - title: body.meta.name, - year: body.meta.year, - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: (body.meta.videos || []) - .map((video) => Number.isInteger(video.imdbSeason) - ? { - name: video.name || video.title, - season: video.season, - episode: video.episode, - imdbSeason: video.imdbSeason, - imdbEpisode: video.imdbEpisode - } - : { - name: video.name || video.title, - season: video.season, - episode: video.episode, - kitsuId: video.kitsu_id, - kitsuEpisode: video.kitsuEpisode, - released: video.released - } - ), - episodeCount: Object.values((body.meta.videos || []) - .filter((entry) => entry.season !== 0 && entry.episode !== 0) - .sort((a, b) => a.season - b.season) - .reduce((map, next) => { - map[next.season] = map[next.season] + 1 || 1; - return map; - }, {})), - totalCount: body.meta.videos && body.meta.videos - .filter((entry) => entry.season !== 0 && entry.episode !== 0).length - }; - } else { - throw new Error('No search results'); - } - }); -} - -export function escapeTitle(title) { - return title.toLowerCase() - .normalize('NFKD') // normalize non-ASCII characters - .replace(/[\u0300-\u036F]/g, '') - .replace(/&/g, 'and') - .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces - .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars - .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering - .replace(/\s{2,}/, ' ') // replace multiple spaces - .trim(); -} - -export async function getImdbId(info, type) { - const name = escapeTitle(info.title); - const year = info.year || (info.date && info.date.slice(0, 4)); - const key = `${name}_${year || 'NA'}_${type}`; - const query = `${name} ${year || ''} ${type} imdb`; - const fallbackQuery = `${name} ${type} imdb`; - const googleQuery = year ? query : fallbackQuery; - - try { - const imdbId = await cacheWrapImdbId(key, - () => getIMDbIdFromNameToImdb(name, info.year, type) - ); - return imdbId && 'tt' + imdbId.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); - } catch (error) { - const imdbIdFallback = await getIMDbIdFromGoogle(googleQuery); - return imdbIdFallback && 'tt' + imdbIdFallback.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); - } -} - -function getIMDbIdFromNameToImdb(name, year, type) { - return new Promise((resolve, reject) => { - nameToImdb({ name, year, type }, function(err, res) { - if (res) { - resolve(res); - } else { - reject(err || new Error('Failed IMDbId search')); - } - }); - }); -} - -async function getIMDbIdFromGoogle(query) { - try { - const searchResults = await search({ query: query }); - for (const result of searchResults) { - if (result.link.includes('imdb.com/title/')) { - const match = result.link.match(/imdb\.com\/title\/(tt\d+)/); - if (match) { - return match[1]; - } - } - } - return undefined; - } - catch (error) { - throw new Error('Failed to find IMDb ID from Google search'); - } -} - -export async function getKitsuId(info) { - const title = escapeTitle(info.title.replace(/\s\|\s.*/, '')); - const year = info.year ? ` ${info.year}` : ''; - const season = info.season > 1 ? ` S${info.season}` : ''; - const key = `${title}${year}${season}`; - const query = encodeURIComponent(key); - - return cacheWrapKitsuId(key, - () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, { timeout: 60000 }) - .then((response) => { - const body = response.data; - if (body && body.metas && body.metas.length) { - return body.metas[0].id.replace('kitsu:', ''); - } else { - throw new Error('No search results'); - } - })); -} - -export async function isEpisodeImdbId(imdbId) { - if (!imdbId) { - return false; - } - return axios.get(`https://www.imdb.com/title/${imdbId}/`, { timeout: 10000 }) - .then(response => !!(response.data && response.data.includes('video.episode'))) - .catch(() => false); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/metadata.ts b/src/node/consumer/src/lib/metadata.ts new file mode 100644 index 0000000..e29e80b --- /dev/null +++ b/src/node/consumer/src/lib/metadata.ts @@ -0,0 +1,216 @@ +import axios, {AxiosResponse} from 'axios'; +import {search, ResultTypes} from 'google-sr'; +import nameToImdb from 'name-to-imdb'; +import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache.js'; +import { TorrentType } from './enums/torrent_types'; +import {MetadataResponse} from "./interfaces/metadata_response"; +import {CinemetaJsonResponse} from "./interfaces/cinemeta_metadata"; +import {CommonVideoMetadata} from "./interfaces/common_video_metadata"; +import {KitsuJsonResponse} from "./interfaces/kitsu_metadata"; +import {MetaDataQuery} from "./interfaces/metadata_query"; +import {KitsuCatalogJsonResponse} from "./interfaces/kitsu_catalog_metadata"; + +const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; +const KITSU_URL = 'https://anime-kitsu.strem.fun'; +const TIMEOUT = 20000; + +async function _requestMetadata(url: string): Promise { + let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); + let result : MetadataResponse; + const body = response.data; + if ('kitsu_id' in body.meta) { + result = handleKitsuResponse(body as KitsuJsonResponse); + } + else if ('imdb_id' in body.meta) { + result = handleCinemetaResponse(body as CinemetaJsonResponse); + } + else { + throw new Error('No valid metadata'); + } + + return result; +} + +function handleCinemetaResponse(body: CinemetaJsonResponse) : MetadataResponse { + return { + imdbId: parseInt(body.meta.imdb_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.name, + season: video.season, + episode: video.episode, + imdbSeason: video.season, + imdbEpisode: video.episode, + })) + : [], + episodeCount: body.meta.videos + ? getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }; +} + +function handleKitsuResponse(body: KitsuJsonResponse) : MetadataResponse { + return { + kitsuId: parseInt(body.meta.kitsu_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.title, + season: video.season, + episode: video.episode, + kitsuId: video.id, + kitsuEpisode: video.episode, + released: video.released, + })) + : [], + episodeCount: body.meta.videos + ? getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }; +} + +function getEpisodeCount(videos: CommonVideoMetadata[]) { + return Object.values( + videos + .filter(entry => entry.season !== 0 && entry.episode !== 0) + .sort((a, b) => a.season - b.season) + .reduce((map, next) => { + map[next.season] = map[next.season] + 1 || 1; + return map; + }, {}) + ); +} + + +export function escapeTitle(title: string): string { + return title.toLowerCase() + .normalize('NFKD') // normalize non-ASCII characters + .replace(/[\u0300-\u036F]/g, '') + .replace(/&/g, 'and') + .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces + .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars + .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering + .replace(/\s{2,}/, ' ') // replace multiple spaces + .trim(); +} + +function getIMDbIdFromNameToImdb(name: string, info: MetaDataQuery) : Promise { + const year = info.year; + const type = info.type; + return new Promise((resolve, reject) => { + nameToImdb({ name, year, type }, function(err: Error, res: string) { + if (res) { + resolve(res); + } else { + reject(err || new Error('Failed IMDbId search')); + } + }); + }); +} + +async function getIMDbIdFromGoogle(query: string): Promise{ + try { + const searchResults = await search({ query: query }); + for(const result of searchResults) { + if(result.type === ResultTypes.SearchResult) { + if(result.link.includes('imdb.com/title/')){ + const match = result.link.match(/imdb\.com\/title\/(tt\d+)/); + if(match){ + return match[1]; + } + } + } + } + return undefined; + } + catch (error) { + throw new Error('Failed to find IMDb ID from Google search'); + } +} + +export async function getKitsuId(info: MetaDataQuery): Promise { + const title = escapeTitle(info.title.replace(/\s\|\s.*/, '')); + const year = info.year ? ` ${info.year}` : ''; + const season = info.season > 1 ? ` S${info.season}` : ''; + const key = `${title}${year}${season}`; + const query = encodeURIComponent(key); + + return cacheWrapKitsuId(key, + () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, { timeout: 60000 }) + .then((response) => { + const body = response.data as KitsuCatalogJsonResponse; + if (body && body.metas && body.metas.length) { + return body.metas[0].id.replace('kitsu:', ''); + } else { + throw new Error('No search results'); + } + })); +} + +export async function getImdbId(info: MetaDataQuery): Promise { + const name = escapeTitle(info.title); + const year = info.year || (info.date && info.date.slice(0, 4)); + const key = `${name}_${year || 'NA'}_${info.type}`; + const query = `${name} ${year || ''} ${info.type} imdb`; + const fallbackQuery = `${name} ${info.type} imdb`; + const googleQuery = year ? query : fallbackQuery; + + try { + const imdbId = await cacheWrapImdbId(key, + () => getIMDbIdFromNameToImdb(name, info) + ); + return imdbId && 'tt' + imdbId.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); + } catch (error) { + const imdbIdFallback = await getIMDbIdFromGoogle(googleQuery); + return imdbIdFallback && 'tt' + imdbIdFallback.toString().replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); + } +} + +export function getMetadata(id: string | number, type: TorrentType = TorrentType.SERIES): Promise { + if (!id) { + return Promise.reject("no valid id provided"); + } + + const key = Number.isInteger(id) || id.toString().match(/^\d+$/) ? `kitsu:${id}` : id; + const metaType = type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; + return cacheWrapMetadata(key, () => _requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + .catch(() => _requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) + .catch(() => { + // try different type in case there was a mismatch + const otherType = metaType === TorrentType.MOVIE ? TorrentType.SERIES : TorrentType.MOVIE; + return _requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) + }) + .catch((error) => { + throw new Error(`failed metadata query ${key} due: ${error.message}`); + })); +} + +export async function isEpisodeImdbId(imdbId: string | undefined): Promise { + if (!imdbId) { + return false; + } + return axios.get(`https://www.imdb.com/title/${imdbId}/`, { timeout: 10000 }) + .then(response => !!(response.data && response.data.includes('video.episode'))) + .catch(() => false); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index d5a629d..18d4940 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,5 +1,5 @@ import { parse } from 'parse-torrent-title'; -import { getImdbId, getKitsuId } from './metadata.js'; +import { getImdbId, getKitsuId } from './metadata'; import { isPackTorrent } from './parseHelper.js'; import * as Promises from './promises.js'; import { repository } from '../repository/database_repository'; @@ -12,7 +12,12 @@ export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.ANIME) { - torrent.imdbId = await getImdbId(titleInfo, torrent.type) + const imdbQuery = { + title: titleInfo.title, + year: titleInfo.year, + type: torrent.type + }; + torrent.imdbId = await getImdbId(imdbQuery) .catch(() => undefined); } if (torrent.imdbId && torrent.imdbId.length < 9) { @@ -24,7 +29,12 @@ export async function createTorrentEntry(torrent, overwrite = false) { torrent.imdbId = torrent.imdbId.replace(/tt0+([0-9]{7,})$/, 'tt$1'); } if (!torrent.kitsuId && torrent.type === TorrentType.ANIME) { - torrent.kitsuId = await getKitsuId(titleInfo) + const kitsuQuery = { + title: titleInfo.title, + year: titleInfo.year, + season: titleInfo.season, + }; + torrent.kitsuId = await getKitsuId(kitsuQuery) .catch(() => undefined); } diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 0a59c56..31e8d98 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -4,7 +4,7 @@ import moment from 'moment'; import { parse } from 'parse-torrent-title'; import { metadataConfig } from './config.js'; import { isDisk } from './extension.js'; -import { getMetadata, getImdbId, getKitsuId } from './metadata.js'; +import { getMetadata, getImdbId, getKitsuId } from './metadata'; import { parseSeriesVideos, isPackTorrent } from './parseHelper.js'; import * as Promises from './promises.js'; import {torrentFiles} from "./torrent.js"; @@ -472,12 +472,25 @@ async function updateToCinemetaMetadata(metadata) { function findMovieImdbId(title) { const parsedTitle = typeof title === 'string' ? parse(title) : title; logger.debug(`Finding movie imdbId for ${title}`); - return imdb_limiter.schedule(() => getImdbId(parsedTitle, TorrentType.MOVIE).catch(() => undefined)); + return imdb_limiter.schedule(() => { + const imdbQuery = { + title: parsedTitle.title, + year: parsedTitle.year, + type: TorrentType.MOVIE + }; + return getImdbId(imdbQuery).catch(() => undefined); + }); } function findMovieKitsuId(title) { const parsedTitle = typeof title === 'string' ? parse(title) : title; - return getKitsuId(parsedTitle, TorrentType.MOVIE).catch(() => undefined); + const kitsuQuery = { + title: parsedTitle.title, + year: parsedTitle.year, + season: parsedTitle.season, + type: TorrentType.MOVIE + }; + return getKitsuId(kitsuQuery).catch(() => undefined); } function isDiskTorrent(contents) { From 9e9e928c8050e2b17076d0ec5b9452ad49d00591 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 05:02:41 +0000 Subject: [PATCH 04/55] promises helpers now ts --- src/node/consumer/src/lib/promises.js | 55 ------------------- src/node/consumer/src/lib/promises.ts | 52 ++++++++++++++++++ src/node/consumer/src/lib/torrentEntries.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- .../src/repository/database_repository.ts | 2 +- 5 files changed, 55 insertions(+), 58 deletions(-) delete mode 100644 src/node/consumer/src/lib/promises.js create mode 100644 src/node/consumer/src/lib/promises.ts diff --git a/src/node/consumer/src/lib/promises.js b/src/node/consumer/src/lib/promises.js deleted file mode 100644 index 33e3dae..0000000 --- a/src/node/consumer/src/lib/promises.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Execute promises in sequence one after another. - */ -export async function sequence(promises) { - return promises.reduce((promise, func) => - promise.then(result => func().then(Array.prototype.concat.bind(result))), Promise.resolve([])); -} - -/** - * Return first resolved promise as the result. - */ -export async function first(promises) { - return Promise.all(promises.map((p) => { - // If a request fails, count that as a resolution so it will keep - // waiting for other possible successes. If a request succeeds, - // treat it as a rejection so Promise.all immediately bails out. - return p.then( - (val) => Promise.reject(val), - (err) => Promise.resolve(err) - ); - })).then( - // If '.all' resolved, we've just got an array of errors. - (errors) => Promise.reject(errors), - // If '.all' rejected, we've got the result we wanted. - (val) => Promise.resolve(val) - ); -} - -/** - * Delay promise - */ -export async function delay(duration) { - return new Promise((resolve) => setTimeout(resolve, duration)); -} - -/** - * Timeout promise after a set time in ms - */ -export async function timeout(timeoutMs, promise, message = 'Timed out') { - return Promise.race([ - promise, - new Promise(function (resolve, reject) { - setTimeout(function () { - reject(message); - }, timeoutMs); - }) - ]); -} - -/** - * Return most common value from given array. - */ -export function mostCommonValue(array) { - return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/promises.ts b/src/node/consumer/src/lib/promises.ts new file mode 100644 index 0000000..f7a8dd3 --- /dev/null +++ b/src/node/consumer/src/lib/promises.ts @@ -0,0 +1,52 @@ +/** + * Execute promises in sequence one after another. + */ +export async function sequence(promises: Array<() => Promise>): Promise { + return promises.reduce((promise: Promise, func: () => Promise) => + promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); +} + +/** + * Return first resolved promise as the result. + */ +export async function first(promises: Array>): Promise { + return Promise.all(promises.map(p => { + // If a request fails, count that as a resolution so it will keep + // waiting for other possible successes. If a request succeeds, + // treat it as a rejection so Promise.all immediately bails out. + return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); + })).then( + // If '.all' resolved, we've just got an array of errors. + (errors) => Promise.reject(errors), + // If '.all' rejected, we've got the result we wanted. + (val) => Promise.resolve(val) + ); +} + +/** + * Delay promise + */ +export async function delay(duration: number): Promise { + return new Promise((resolve) => setTimeout(() => resolve(), duration)); +} + +/** + * Timeout promise after a set time in ms + */ +export async function timeout(timeoutMs: number, promise: Promise, message = 'Timed out'): Promise { + return Promise.race([ + promise, + new Promise(function (resolve, reject) { + setTimeout(function () { + reject(message); + }, timeoutMs); + }) + ]); +} + +/** + * Return most common value from given array. + */ +export function mostCommonValue(array: any[]): any { + return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 18d4940..3288126 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,7 +1,7 @@ import { parse } from 'parse-torrent-title'; import { getImdbId, getKitsuId } from './metadata'; import { isPackTorrent } from './parseHelper.js'; -import * as Promises from './promises.js'; +import * as Promises from './promises'; import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; import { assignSubtitles } from './torrentSubtitles.js'; diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 31e8d98..abef29c 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -6,7 +6,7 @@ import { metadataConfig } from './config.js'; import { isDisk } from './extension.js'; import { getMetadata, getImdbId, getKitsuId } from './metadata'; import { parseSeriesVideos, isPackTorrent } from './parseHelper.js'; -import * as Promises from './promises.js'; +import * as Promises from './promises'; import {torrentFiles} from "./torrent.js"; import { TorrentType } from './enums/torrent_types'; import {logger} from "./logger"; diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index 7aabd04..023aa4c 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -2,7 +2,7 @@ import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; import {Model, Sequelize} from 'sequelize-typescript'; import {databaseConfig} from '../lib/config'; -import * as Promises from '../lib/promises.js'; +import * as Promises from '../lib/promises'; import {Provider} from "./models/provider"; import {File} from "./models/file"; import {Torrent} from "./models/torrent"; From 9d918abef3b242cd2dd775cce07325528152c36e Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 05:06:46 +0000 Subject: [PATCH 05/55] tracker service ts --- src/node/consumer/src/index.js | 2 +- .../consumer/src/lib/torrent_processor.ts | 2 +- .../{trackerService.js => trackerService.ts} | 19 ++++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) rename src/node/consumer/src/lib/{trackerService.js => trackerService.ts} (57%) diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.js index 92f994d..3f7ef3a 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.js @@ -1,6 +1,6 @@ import { listenToQueue } from './jobs/processTorrents'; import { repository } from "./repository/database_repository"; -import { getTrackers } from "./lib/trackerService.js"; +import { getTrackers } from "./lib/trackerService"; (async () => { await getTrackers(); diff --git a/src/node/consumer/src/lib/torrent_processor.ts b/src/node/consumer/src/lib/torrent_processor.ts index 49f842a..97387d1 100644 --- a/src/node/consumer/src/lib/torrent_processor.ts +++ b/src/node/consumer/src/lib/torrent_processor.ts @@ -2,7 +2,7 @@ import {TorrentInfo} from "./interfaces/torrent_info"; import {TorrentType} from "./enums/torrent_types"; import {logger} from "./logger"; import {checkAndUpdateTorrent, createTorrentEntry} from "./torrentEntries.js"; -import {getTrackers} from "./trackerService.js"; +import {getTrackers} from "./trackerService"; import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; export async function processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { diff --git a/src/node/consumer/src/lib/trackerService.js b/src/node/consumer/src/lib/trackerService.ts similarity index 57% rename from src/node/consumer/src/lib/trackerService.js rename to src/node/consumer/src/lib/trackerService.ts index 736630d..f2310c0 100644 --- a/src/node/consumer/src/lib/trackerService.js +++ b/src/node/consumer/src/lib/trackerService.ts @@ -1,19 +1,20 @@ -import axios from 'axios'; -import {cacheTrackers} from "./cache.js"; +import axios, { AxiosResponse } from 'axios'; +import { cacheTrackers } from "./cache.js"; import { trackerConfig } from './config.js'; -import {logger} from "./logger"; +import { logger } from "./logger"; -const downloadTrackers = async () => { - const response = await axios.get(trackerConfig.TRACKERS_URL); - const trackersListText = response.data; +const downloadTrackers = async (): Promise => { + const response: AxiosResponse = await axios.get(trackerConfig.TRACKERS_URL); + const trackersListText: string = response.data; // Trackers are separated by a newline character let urlTrackers = trackersListText.split("\n"); // remove blank lines urlTrackers = urlTrackers.filter(line => line.trim() !== ''); - + if (!trackerConfig.UDP_ENABLED) { // remove any udp trackers - urlTrackers = urlTrackers.filter(line => !line.startsWith('udp://')); + urlTrackers = urlTrackers.filter(line => !line.startsWith('udp://')); + } logger.info(`Trackers updated at ${Date.now()}: ${urlTrackers.length} trackers`); @@ -21,6 +22,6 @@ const downloadTrackers = async () => { return urlTrackers; }; -export const getTrackers = async () => { +export const getTrackers = async (): Promise => { return cacheTrackers(downloadTrackers); }; \ No newline at end of file From b8ede8e71cd0f99a595bbde2be6631d4ab706cec Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 05:16:39 +0000 Subject: [PATCH 06/55] Title parser now ts --- .../src/lib/interfaces/parsable_torrent.ts | 9 ++ .../lib/interfaces/parsable_torrent_video.ts | 6 ++ .../interfaces/parse_torrent_title_result.ts | 31 ++++++ src/node/consumer/src/lib/parseHelper.js | 98 ----------------- src/node/consumer/src/lib/parseHelper.ts | 101 ++++++++++++++++++ src/node/consumer/src/lib/torrentEntries.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- 7 files changed, 149 insertions(+), 100 deletions(-) create mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent.ts create mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts create mode 100644 src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts delete mode 100644 src/node/consumer/src/lib/parseHelper.js create mode 100644 src/node/consumer/src/lib/parseHelper.ts diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent.ts new file mode 100644 index 0000000..20683c2 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/parsable_torrent.ts @@ -0,0 +1,9 @@ +import {TorrentType} from "../enums/torrent_types"; + +export interface ParsableTorrent { + title: string; + type: TorrentType; + size: number; + pack?: boolean; +} + diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts new file mode 100644 index 0000000..d57b7e7 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts @@ -0,0 +1,6 @@ +import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; + +export interface ParsableTorrentVideo extends ParseTorrentTitleResult { + name: string; + path: string; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts new file mode 100644 index 0000000..ea85e8e --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts @@ -0,0 +1,31 @@ +export interface ParseTorrentTitleResult { + title: string; + date?: string; + year?: number | string; + resolution?: string; + extended?: boolean; + unrated?: boolean; + proper?: boolean; + repack?: boolean; + convert?: boolean; + hardcoded?: boolean; + retail?: boolean; + remastered?: boolean; + complete?: boolean; + region?: string; + container?: string; + extension?: string; + source?: string; + codec?: string; + bitDepth?: string; + hdr?: Array; + audio?: string; + group?: string; + volumes?: Array; + seasons?: Array; + season?: number; + episodes?: Array; + episode?: number; + languages?: string; + dubbed?: boolean; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/parseHelper.js b/src/node/consumer/src/lib/parseHelper.js deleted file mode 100644 index 131e4f0..0000000 --- a/src/node/consumer/src/lib/parseHelper.js +++ /dev/null @@ -1,98 +0,0 @@ -import { parse } from 'parse-torrent-title'; -import { TorrentType } from './enums/torrent_types'; - -const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB - -export function parseSeriesVideos(torrent, videos) { - const parsedTorrentName = parse(torrent.title); - const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); - const parsedVideos = videos.map(video => parseSeriesVideo(video, parsedTorrentName)); - return parsedVideos.map(video => ({ ...video, isMovie: isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); -} - -function parseSeriesVideo(video, parsedTorrentName) { - const videoInfo = parse(video.name); - // the episode may be in a folder containing season number - if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { - const folders = video.path.split('/'); - const pathInfo = parse(folders[folders.length - 2]); - videoInfo.season = pathInfo.season; - } - if (!Number.isInteger(videoInfo.season) && parsedTorrentName.season) { - videoInfo.season = parsedTorrentName.season; - } - if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { - // in case single file was interpreted as having multiple seasons - videoInfo.season = videoInfo.seasons[0]; - } - if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && parsedTorrentName.seasons - && parsedTorrentName.seasons.length > 1) { - // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv - const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); - videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; - } - // sometimes video file does not have correct date format as in torrent title - if (!videoInfo.episodes && !videoInfo.date && parsedTorrentName.date) { - videoInfo.date = parsedTorrentName.date; - } - // limit number of episodes in case of incorrect parsing - if (videoInfo.episodes && videoInfo.episodes.length > 20) { - videoInfo.episodes = [videoInfo.episodes[0]]; - videoInfo.episode = videoInfo.episodes[0]; - } - // force episode to any found number if it was not parsed - if (!videoInfo.episodes && !videoInfo.date) { - const epMatcher = videoInfo.title.match( - /(? 3 - && otherVideos.filter(other => other.title === video.title && other.year === video.year) < 3; -} - -export function isPackTorrent(torrent) { - if (torrent.pack) { - return true; - } - const parsedInfo = parse(torrent.title); - if (torrent.type === TorrentType.MOVIE) { - return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); - } - const hasMultipleEpisodes = parsedInfo.complete || - torrent.size > MULTIPLE_FILES_SIZE || - (parsedInfo.seasons && parsedInfo.seasons.length > 1) || - (parsedInfo.episodes && parsedInfo.episodes.length > 1) || - (parsedInfo.seasons && !parsedInfo.episodes); - const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); - return hasMultipleEpisodes && !hasSingleEpisode; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/parseHelper.ts b/src/node/consumer/src/lib/parseHelper.ts new file mode 100644 index 0000000..d393186 --- /dev/null +++ b/src/node/consumer/src/lib/parseHelper.ts @@ -0,0 +1,101 @@ +import { parse } from 'parse-torrent-title'; +import { TorrentType } from './enums/torrent_types'; +import {ParseTorrentTitleResult} from "./interfaces/parse_torrent_title_result"; +import {ParsableTorrentVideo} from "./interfaces/parsable_torrent_video"; +import {ParsableTorrent} from "./interfaces/parsable_torrent"; + +const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB + +export function parseSeriesVideos(torrent: ParsableTorrent, videos: ParsableTorrentVideo[]): ParseTorrentTitleResult[] { + const parsedTorrentName = parse(torrent.title); + const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); + const parsedVideos = videos.map(video => parseSeriesVideo(video, parsedTorrentName)); + return parsedVideos.map(video => ({ ...video, isMovie: isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); +} + +function parseSeriesVideo(video: ParsableTorrentVideo, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { + const videoInfo = parse(video.name); + // the episode may be in a folder containing season number + if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { + const folders = video.path.split('/'); + const pathInfo = parse(folders[folders.length - 2]); + videoInfo.season = pathInfo.season; + } + if (!Number.isInteger(videoInfo.season) && parsedTorrentName.season) { + videoInfo.season = parsedTorrentName.season; + } + if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { + // in case single file was interpreted as having multiple seasons + videoInfo.season = videoInfo.seasons[0]; + } + if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && parsedTorrentName.seasons + && parsedTorrentName.seasons.length > 1) { + // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv + const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); + videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; + } + // sometimes video file does not have correct date format as in torrent title + if (!videoInfo.episodes && !videoInfo.date && parsedTorrentName.date) { + videoInfo.date = parsedTorrentName.date; + } + // limit number of episodes in case of incorrect parsing + if (videoInfo.episodes && videoInfo.episodes.length > 20) { + videoInfo.episodes = [videoInfo.episodes[0]]; + videoInfo.episode = videoInfo.episodes[0]; + } + // force episode to any found number if it was not parsed + if (!videoInfo.episodes && !videoInfo.date) { + const epMatcher = videoInfo.title.match( + /(? 3 + && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; +} + +export function isPackTorrent(torrent: ParsableTorrent): boolean { + if (torrent.pack) { + return true; + } + const parsedInfo = parse(torrent.title); + if (torrent.type === TorrentType.MOVIE) { + return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); + } + const hasMultipleEpisodes = parsedInfo.complete || + torrent.size > MULTIPLE_FILES_SIZE || + (parsedInfo.seasons && parsedInfo.seasons.length > 1) || + (parsedInfo.episodes && parsedInfo.episodes.length > 1) || + (parsedInfo.seasons && !parsedInfo.episodes); + const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); + return hasMultipleEpisodes && !hasSingleEpisode; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 3288126..f341192 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,6 +1,6 @@ import { parse } from 'parse-torrent-title'; import { getImdbId, getKitsuId } from './metadata'; -import { isPackTorrent } from './parseHelper.js'; +import { isPackTorrent } from './parseHelper'; import * as Promises from './promises'; import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index abef29c..27b8551 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -5,7 +5,7 @@ import { parse } from 'parse-torrent-title'; import { metadataConfig } from './config.js'; import { isDisk } from './extension.js'; import { getMetadata, getImdbId, getKitsuId } from './metadata'; -import { parseSeriesVideos, isPackTorrent } from './parseHelper.js'; +import { parseSeriesVideos, isPackTorrent } from './parseHelper'; import * as Promises from './promises'; import {torrentFiles} from "./torrent.js"; import { TorrentType } from './enums/torrent_types'; From 1431b57a490769e622fb1e58bf9281e74f8310be Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 05:17:48 +0000 Subject: [PATCH 07/55] extension now ts --- src/node/consumer/src/lib/extension.js | 62 ----------------------- src/node/consumer/src/lib/extension.ts | 62 +++++++++++++++++++++++ src/node/consumer/src/lib/torrent.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- 4 files changed, 64 insertions(+), 64 deletions(-) delete mode 100644 src/node/consumer/src/lib/extension.js create mode 100644 src/node/consumer/src/lib/extension.ts diff --git a/src/node/consumer/src/lib/extension.js b/src/node/consumer/src/lib/extension.js deleted file mode 100644 index 6c11617..0000000 --- a/src/node/consumer/src/lib/extension.js +++ /dev/null @@ -1,62 +0,0 @@ -const VIDEO_EXTENSIONS = [ - "3g2", - "3gp", - "avi", - "flv", - "mkv", - "mk3d", - "mov", - "mp2", - "mp4", - "m4v", - "mpe", - "mpeg", - "mpg", - "mpv", - "webm", - "wmv", - "ogm", - "divx" -]; -const SUBTITLE_EXTENSIONS = [ - "aqt", - "gsub", - "jss", - "sub", - "ttxt", - "pjs", - "psb", - "rt", - "smi", - "slt", - "ssf", - "srt", - "ssa", - "ass", - "usf", - "idx", - "vtt" -]; -const DISK_EXTENSIONS = [ - "iso", - "m2ts", - "ts", - "vob" -] - -export function isVideo(filename) { - return isExtension(filename, VIDEO_EXTENSIONS); -} - -export function isSubtitle(filename) { - return isExtension(filename, SUBTITLE_EXTENSIONS); -} - -export function isDisk(filename) { - return isExtension(filename, DISK_EXTENSIONS); -} - -export function isExtension(filename, extensions) { - const extensionMatch = filename.match(/\.(\w{2,4})$/); - return extensionMatch && extensions.includes(extensionMatch[1].toLowerCase()); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/extension.ts b/src/node/consumer/src/lib/extension.ts new file mode 100644 index 0000000..937dc35 --- /dev/null +++ b/src/node/consumer/src/lib/extension.ts @@ -0,0 +1,62 @@ +const VIDEO_EXTENSIONS: string[] = [ + "3g2", + "3gp", + "avi", + "flv", + "mkv", + "mk3d", + "mov", + "mp2", + "mp4", + "m4v", + "mpe", + "mpeg", + "mpg", + "mpv", + "webm", + "wmv", + "ogm", + "divx" +]; +const SUBTITLE_EXTENSIONS: string[] = [ + "aqt", + "gsub", + "jss", + "sub", + "ttxt", + "pjs", + "psb", + "rt", + "smi", + "slt", + "ssf", + "srt", + "ssa", + "ass", + "usf", + "idx", + "vtt" +]; +const DISK_EXTENSIONS: string[] = [ + "iso", + "m2ts", + "ts", + "vob" +] + +export function isVideo(filename: string): boolean { + return isExtension(filename, VIDEO_EXTENSIONS); +} + +export function isSubtitle(filename: string): boolean { + return isExtension(filename, SUBTITLE_EXTENSIONS); +} + +export function isDisk(filename: string): boolean { + return isExtension(filename, DISK_EXTENSIONS); +} + +export function isExtension(filename: string, extensions: string[]): boolean { + const extensionMatch = filename.match(/\.(\w{2,4})$/); + return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrent.js b/src/node/consumer/src/lib/torrent.js index 4253052..3a066b3 100644 --- a/src/node/consumer/src/lib/torrent.js +++ b/src/node/consumer/src/lib/torrent.js @@ -1,7 +1,7 @@ import { decode } from 'magnet-uri'; import torrentStream from 'torrent-stream'; import { torrentConfig } from './config.js'; -import {isSubtitle, isVideo} from './extension.js'; +import {isSubtitle, isVideo} from './extension'; export async function torrentFiles(torrent, timeout) { return filesFromTorrentStream(torrent, timeout) diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 27b8551..3a60556 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -3,7 +3,7 @@ import distance from 'jaro-winkler'; import moment from 'moment'; import { parse } from 'parse-torrent-title'; import { metadataConfig } from './config.js'; -import { isDisk } from './extension.js'; +import { isDisk } from './extension'; import { getMetadata, getImdbId, getKitsuId } from './metadata'; import { parseSeriesVideos, isPackTorrent } from './parseHelper'; import * as Promises from './promises'; From 5cc08e27d3d30022501595dfae9417041f19d7e3 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 05:26:41 +0000 Subject: [PATCH 08/55] cache now ts --- src/node/consumer/src/jobs/processTorrents.ts | 4 +- .../consumer/src/lib/{cache.js => cache.ts} | 57 +++++++++-------- src/node/consumer/src/lib/config.js | 63 ------------------- src/node/consumer/src/lib/config.ts | 51 +++++++++++++++ .../src/lib/interfaces/cache_options.ts | 3 + src/node/consumer/src/lib/metadata.ts | 2 +- src/node/consumer/src/lib/torrent.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 2 +- src/node/consumer/src/lib/trackerService.ts | 4 +- 9 files changed, 92 insertions(+), 96 deletions(-) rename src/node/consumer/src/lib/{cache.js => cache.ts} (58%) delete mode 100644 src/node/consumer/src/lib/config.js create mode 100644 src/node/consumer/src/lib/config.ts create mode 100644 src/node/consumer/src/lib/interfaces/cache_options.ts diff --git a/src/node/consumer/src/jobs/processTorrents.ts b/src/node/consumer/src/jobs/processTorrents.ts index 200d84c..6f43426 100644 --- a/src/node/consumer/src/jobs/processTorrents.ts +++ b/src/node/consumer/src/jobs/processTorrents.ts @@ -1,5 +1,5 @@ import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' -import {jobConfig, rabbitConfig} from '../lib/config.js'; +import {jobConfig, rabbitConfig} from '../lib/config'; import {processTorrentRecord} from '../lib/torrent_processor'; import {logger} from '../lib/logger'; import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; @@ -47,7 +47,7 @@ export const listenToQueue = async (): Promise => { } try { - const connection: Connection = await client.connect(rabbitConfig.URI); + const connection: Connection = await client.connect(rabbitConfig.RABBIT_URI); const channel: Channel = await connection.createChannel(); await assertAndConsumeQueue(channel); } catch (error) { diff --git a/src/node/consumer/src/lib/cache.js b/src/node/consumer/src/lib/cache.ts similarity index 58% rename from src/node/consumer/src/lib/cache.js rename to src/node/consumer/src/lib/cache.ts index 3c9d69d..d389257 100644 --- a/src/node/consumer/src/lib/cache.js +++ b/src/node/consumer/src/lib/cache.ts @@ -1,8 +1,9 @@ -import { createCache, memoryStore} from 'cache-manager'; +import {Cache, createCache, memoryStore} from 'cache-manager'; import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' -import { cacheConfig } from './config.js'; +import { cacheConfig } from './config'; import { logger } from './logger'; import { CacheType } from "./enums/cache_types"; +import {CacheOptions} from "./interfaces/cache_options"; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; @@ -10,40 +11,43 @@ const KITSU_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|kitsu_id`; const METADATA_PREFIX = `${GLOBAL_KEY_PREFIX}|metadata`; const TRACKERS_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|trackers`; -const GLOBAL_TTL = process.env.METADATA_TTL || 7 * 24 * 60 * 60; // 7 days -const MEMORY_TTL = process.env.METADATA_TTL || 2 * 60 * 60; // 2 hours -const TRACKERS_TTL = 2 * 24 * 60 * 60; // 2 days +const GLOBAL_TTL: number = Number(process.env.METADATA_TTL) || 7 * 24 * 60 * 60; // 7 days +const MEMORY_TTL: number = Number(process.env.METADATA_TTL) || 2 * 60 * 60; // 2 hours +const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days + +type CacheMethod = () => any; const initiateMemoryCache = () => createCache(memoryStore(), { - ttl: parseInt(MEMORY_TTL) - }); + ttl: MEMORY_TTL + }) as Cache; const initiateMongoCache = () => { const store = mongoDbStore({ collectionName: cacheConfig.COLLECTION_NAME, - ttl: parseInt(GLOBAL_TTL), + ttl: GLOBAL_TTL, url: cacheConfig.MONGO_URI, mongoConfig:{ socketTimeoutMS: 120000, appName: 'knightcrawler-consumer', } - }); - + }); + return createCache(store, { - ttl: parseInt(GLOBAL_TTL), + ttl: GLOBAL_TTL, }); } -const initiateRemoteCache = ()=> { +const initiateRemoteCache = (): Cache => { if (cacheConfig.NO_CACHE) { logger.debug('Cache is disabled'); return null; } + return cacheConfig.MONGO_URI ? initiateMongoCache() : initiateMemoryCache(); } -const getCacheType = (cacheType) => { +const getCacheType = (cacheType: CacheType): typeof memoryCache | null => { switch (cacheType) { case CacheType.MEMORY: return memoryCache; @@ -54,12 +58,13 @@ const getCacheType = (cacheType) => { } } -const memoryCache = initiateMemoryCache() -const remoteCache = initiateRemoteCache() +const memoryCache = initiateMemoryCache(); +const remoteCache = initiateRemoteCache(); -const cacheWrap = async (cacheType, key, method, options) => { +const cacheWrap = async ( + cacheType: CacheType, key: string, method: CacheMethod, options: CacheOptions): Promise => { const cache = getCacheType(cacheType); - + if (cacheConfig.NO_CACHE || !cache) { return method(); } @@ -67,18 +72,18 @@ const cacheWrap = async (cacheType, key, method, options) => { logger.debug(`Cache type: ${cacheType}`); logger.debug(`Cache key: ${key}`); logger.debug(`Cache options: ${JSON.stringify(options)}`); - + return cache.wrap(key, method, options.ttl); } -export const cacheWrapImdbId = (key, method) => - cacheWrap(CacheType.MONGODB, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: parseInt(GLOBAL_TTL) }); +export const cacheWrapImdbId = (key: string, method: CacheMethod): Promise => + cacheWrap(CacheType.MONGODB, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); -export const cacheWrapKitsuId = (key, method) => - cacheWrap(CacheType.MONGODB, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: parseInt(GLOBAL_TTL) }); +export const cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => + cacheWrap(CacheType.MONGODB, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); -export const cacheWrapMetadata = (id, method) => - cacheWrap(CacheType.MEMORY, `${METADATA_PREFIX}:${id}`, method, { ttl: parseInt(MEMORY_TTL) }); +export const cacheWrapMetadata = (id: string, method: CacheMethod): Promise => + cacheWrap(CacheType.MEMORY, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); -export const cacheTrackers = (method) => - cacheWrap(CacheType.MEMORY, `${TRACKERS_KEY_PREFIX}`, method, { ttl: parseInt(TRACKERS_TTL) }); \ No newline at end of file +export const cacheTrackers = (method: CacheMethod): Promise => + cacheWrap(CacheType.MEMORY, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); \ No newline at end of file diff --git a/src/node/consumer/src/lib/config.js b/src/node/consumer/src/lib/config.js deleted file mode 100644 index 69769ea..0000000 --- a/src/node/consumer/src/lib/config.js +++ /dev/null @@ -1,63 +0,0 @@ -export const rabbitConfig = { - URI: process.env.RABBIT_URI || 'amqp://localhost', - QUEUE_NAME: process.env.QUEUE_NAME || 'test-queue' -} - -export const cacheConfig = { - MONGODB_HOST: process.env.MONGODB_HOST || 'mongodb', - MONGODB_PORT: process.env.MONGODB_PORT || '27017', - MONGODB_DB: process.env.MONGODB_DB || 'knightcrawler', - MONGO_INITDB_ROOT_USERNAME: process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo', - MONGO_INITDB_ROOT_PASSWORD: process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo', - NO_CACHE: parseBool(process.env.NO_CACHE, false), - COLLECTION_NAME: process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection' -} - -// Combine the environment variables into a connection string -// The combined string will look something like: -// 'mongodb://mongo:mongo@localhost:27017/knightcrawler?authSource=admin' -cacheConfig.MONGO_URI = 'mongodb://' + cacheConfig.MONGO_INITDB_ROOT_USERNAME + ':' + cacheConfig.MONGO_INITDB_ROOT_PASSWORD + '@' + cacheConfig.MONGODB_HOST + ':' + cacheConfig.MONGODB_PORT + '/' + cacheConfig.MONGODB_DB + '?authSource=admin'; - -export const databaseConfig = { - POSTGRES_HOST: process.env.POSTGRES_HOST || 'postgres', - POSTGRES_PORT: process.env.POSTGRES_PORT || '5432', - POSTGRES_DB: process.env.POSTGRES_DB || 'knightcrawler', - POSTGRES_USER: process.env.POSTGRES_USER || 'postgres', - POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || 'postgres', - AUTO_CREATE_AND_APPLY_MIGRATIONS: parseBool(process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS, false) -} - -// Combine the environment variables into a connection string -// The combined string will look something like: -// 'postgres://postgres:postgres@localhost:5432/knightcrawler' -databaseConfig.POSTGRES_URI = 'postgres://' + databaseConfig.POSTGRES_USER + ':' + databaseConfig.POSTGRES_PASSWORD + '@' + databaseConfig.POSTGRES_HOST + ':' + databaseConfig.POSTGRES_PORT + '/' + databaseConfig.POSTGRES_DB; - -export const jobConfig = { - JOB_CONCURRENCY: parseInt(process.env.JOB_CONCURRENCY || 1), - JOBS_ENABLED: parseBool(process.env.JOBS_ENABLED || true) -} - -export const metadataConfig = { - IMDB_CONCURRENT: parseInt(process.env.IMDB_CONCURRENT || 1), - IMDB_INTERVAL_MS: parseInt(process.env.IMDB_INTERVAL_MS || 1000), -} - -export const trackerConfig = { - TRACKERS_URL: process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt', - UDP_ENABLED: parseBool(process.env.UDP_TRACKERS_ENABLED || false), -} - -export const torrentConfig = { - MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || 20), - TIMEOUT: parseInt(process.env.TORRENT_TIMEOUT || 30000), -} - -function parseBool(boolString, defaultValue) { - const isString = typeof boolString === 'string' || boolString instanceof String; - - if (!isString) { - return defaultValue; - } - - return boolString.toLowerCase() === 'true' ? true : defaultValue; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/config.ts b/src/node/consumer/src/lib/config.ts new file mode 100644 index 0000000..ddd31d0 --- /dev/null +++ b/src/node/consumer/src/lib/config.ts @@ -0,0 +1,51 @@ +const parseBool = (boolString: string | undefined, defaultValue: boolean): boolean => + boolString?.toLowerCase() === 'true' ? true : defaultValue; + +export const rabbitConfig = { + RABBIT_URI: process.env.RABBIT_URI || 'amqp://localhost', + QUEUE_NAME: process.env.QUEUE_NAME || 'test-queue' +} + +export const cacheConfig = { + MONGODB_HOST: process.env.MONGODB_HOST || 'mongodb', + MONGODB_PORT: process.env.MONGODB_PORT || '27017', + MONGODB_DB: process.env.MONGODB_DB || 'knightcrawler', + MONGO_INITDB_ROOT_USERNAME: process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo', + MONGO_INITDB_ROOT_PASSWORD: process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo', + NO_CACHE: parseBool(process.env.NO_CACHE, false), + COLLECTION_NAME: process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection', + MONGO_URI: '', +} + +cacheConfig.MONGO_URI = `mongodb://${cacheConfig.MONGO_INITDB_ROOT_USERNAME}:${cacheConfig.MONGO_INITDB_ROOT_PASSWORD}@${cacheConfig.MONGODB_HOST}:${cacheConfig.MONGODB_PORT}/${cacheConfig.MONGODB_DB}?authSource=admin`; + +export const databaseConfig = { + POSTGRES_HOST: process.env.POSTGRES_HOST || 'postgres', + POSTGRES_PORT: process.env.POSTGRES_PORT || '5432', + POSTGRES_DATABASE: process.env.POSTGRES_DATABASE || 'knightcrawler', + POSTGRES_USERNAME: process.env.POSTGRES_USERNAME || 'postgres', + POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || 'postgres', + POSTGRES_URI: '', +} + +databaseConfig.POSTGRES_URI = `postgres://${databaseConfig.POSTGRES_USERNAME}:${databaseConfig.POSTGRES_PASSWORD}@${databaseConfig.POSTGRES_HOST}:${databaseConfig.POSTGRES_PORT}/${databaseConfig.POSTGRES_DATABASE}`; + +export const jobConfig = { + JOB_CONCURRENCY: Number.parseInt(process.env.JOB_CONCURRENCY || "1", 10), + JOBS_ENABLED: parseBool(process.env.JOBS_ENABLED, true), +} + +export const metadataConfig = { + IMDB_CONCURRENT: Number.parseInt(process.env.IMDB_CONCURRENT || "1", 10), + IMDB_INTERVAL_MS: Number.parseInt(process.env.IMDB_INTERVAL_MS || "1000", 10), +} + +export const trackerConfig = { + TRACKERS_URL: process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt', + UDP_ENABLED: parseBool(process.env.UDP_TRACKERS_ENABLED, false), +} + +export const torrentConfig = { + MAX_CONNECTIONS_PER_TORRENT: Number.parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10), + TIMEOUT: Number.parseInt(process.env.TORRENT_TIMEOUT || "30000", 10), +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cache_options.ts b/src/node/consumer/src/lib/interfaces/cache_options.ts new file mode 100644 index 0000000..f8b25e6 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/cache_options.ts @@ -0,0 +1,3 @@ +export interface CacheOptions { + ttl: number; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/metadata.ts b/src/node/consumer/src/lib/metadata.ts index e29e80b..99ebc8d 100644 --- a/src/node/consumer/src/lib/metadata.ts +++ b/src/node/consumer/src/lib/metadata.ts @@ -1,7 +1,7 @@ import axios, {AxiosResponse} from 'axios'; import {search, ResultTypes} from 'google-sr'; import nameToImdb from 'name-to-imdb'; -import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache.js'; +import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache'; import { TorrentType } from './enums/torrent_types'; import {MetadataResponse} from "./interfaces/metadata_response"; import {CinemetaJsonResponse} from "./interfaces/cinemeta_metadata"; diff --git a/src/node/consumer/src/lib/torrent.js b/src/node/consumer/src/lib/torrent.js index 3a066b3..4f78d05 100644 --- a/src/node/consumer/src/lib/torrent.js +++ b/src/node/consumer/src/lib/torrent.js @@ -1,6 +1,6 @@ import { decode } from 'magnet-uri'; import torrentStream from 'torrent-stream'; -import { torrentConfig } from './config.js'; +import { torrentConfig } from './config'; import {isSubtitle, isVideo} from './extension'; export async function torrentFiles(torrent, timeout) { diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 3a60556..3539925 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -2,7 +2,7 @@ import Bottleneck from 'bottleneck'; import distance from 'jaro-winkler'; import moment from 'moment'; import { parse } from 'parse-torrent-title'; -import { metadataConfig } from './config.js'; +import { metadataConfig } from './config'; import { isDisk } from './extension'; import { getMetadata, getImdbId, getKitsuId } from './metadata'; import { parseSeriesVideos, isPackTorrent } from './parseHelper'; diff --git a/src/node/consumer/src/lib/trackerService.ts b/src/node/consumer/src/lib/trackerService.ts index f2310c0..f42e44e 100644 --- a/src/node/consumer/src/lib/trackerService.ts +++ b/src/node/consumer/src/lib/trackerService.ts @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios'; -import { cacheTrackers } from "./cache.js"; -import { trackerConfig } from './config.js'; +import { cacheTrackers } from "./cache"; +import { trackerConfig } from './config'; import { logger } from "./logger"; const downloadTrackers = async (): Promise => { From 29371b21926b5252ef7a333f85835a08194527d3 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 12:37:20 +0000 Subject: [PATCH 09/55] further lunchtime cleanup Three files left: torrentEntries, torrentFiles torrentSubtitles --- src/node/consumer/package-lock.json | 20 ++ src/node/consumer/package.json | 2 + src/node/consumer/src/index.js | 4 +- src/node/consumer/src/jobs/processTorrents.ts | 6 +- src/node/consumer/src/lib/cache.ts | 89 ------- src/node/consumer/src/lib/extension.ts | 62 ----- .../src/lib/helpers/promises_helpers.ts | 51 ++++ .../lib/interfaces/downloaded_torrent_file.ts | 3 + src/node/consumer/src/lib/logger.ts | 5 - src/node/consumer/src/lib/metadata.ts | 216 ----------------- src/node/consumer/src/lib/parseHelper.ts | 101 -------- src/node/consumer/src/lib/promises.ts | 52 ----- .../src/lib/services/cache_service.ts | 104 +++++++++ .../src/lib/services/extension_service.ts | 69 ++++++ .../src/lib/services/logging_service.ts | 26 +++ .../src/lib/services/metadata_service.ts | 217 ++++++++++++++++++ .../src/lib/services/parsing_service.ts | 106 +++++++++ .../lib/services/torrent_download_service.ts | 82 +++++++ .../services/torrent_processing_service.ts | 54 +++++ .../src/lib/services/tracker_service.ts | 32 +++ src/node/consumer/src/lib/torrent.js | 82 ------- src/node/consumer/src/lib/torrentEntries.js | 22 +- src/node/consumer/src/lib/torrentFiles.js | 32 +-- .../consumer/src/lib/torrent_processor.ts | 49 ---- src/node/consumer/src/lib/trackerService.ts | 27 --- .../src/repository/database_repository.ts | 8 +- 26 files changed, 802 insertions(+), 719 deletions(-) delete mode 100644 src/node/consumer/src/lib/cache.ts delete mode 100644 src/node/consumer/src/lib/extension.ts create mode 100644 src/node/consumer/src/lib/helpers/promises_helpers.ts create mode 100644 src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts delete mode 100644 src/node/consumer/src/lib/logger.ts delete mode 100644 src/node/consumer/src/lib/metadata.ts delete mode 100644 src/node/consumer/src/lib/parseHelper.ts delete mode 100644 src/node/consumer/src/lib/promises.ts create mode 100644 src/node/consumer/src/lib/services/cache_service.ts create mode 100644 src/node/consumer/src/lib/services/extension_service.ts create mode 100644 src/node/consumer/src/lib/services/logging_service.ts create mode 100644 src/node/consumer/src/lib/services/metadata_service.ts create mode 100644 src/node/consumer/src/lib/services/parsing_service.ts create mode 100644 src/node/consumer/src/lib/services/torrent_download_service.ts create mode 100644 src/node/consumer/src/lib/services/torrent_processing_service.ts create mode 100644 src/node/consumer/src/lib/services/tracker_service.ts delete mode 100644 src/node/consumer/src/lib/torrent.js delete mode 100644 src/node/consumer/src/lib/torrent_processor.ts delete mode 100644 src/node/consumer/src/lib/trackerService.ts diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 3ad7ee7..2898608 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -31,8 +31,10 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", + "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", + "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", "esbuild": "^0.20.0", "eslint": "^8.56.0", @@ -586,6 +588,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/magnet-uri": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", + "integrity": "sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ms": { "version": "0.7.34", "license": "MIT" @@ -607,6 +618,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/torrent-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/torrent-stream/-/torrent-stream-0.0.9.tgz", + "integrity": "sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/validator": { "version": "13.11.8", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 0c86906..f306029 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -32,8 +32,10 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", + "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", + "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", "esbuild": "^0.20.0", "eslint": "^8.56.0", diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.js index 3f7ef3a..7d3e675 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.js @@ -1,9 +1,9 @@ import { listenToQueue } from './jobs/processTorrents'; import { repository } from "./repository/database_repository"; -import { getTrackers } from "./lib/trackerService"; +import { trackerService } from "./lib/services/tracker_service.js"; (async () => { - await getTrackers(); + await trackerService.getTrackers(); await repository.connect(); await listenToQueue(); })(); \ No newline at end of file diff --git a/src/node/consumer/src/jobs/processTorrents.ts b/src/node/consumer/src/jobs/processTorrents.ts index 6f43426..54a3a6b 100644 --- a/src/node/consumer/src/jobs/processTorrents.ts +++ b/src/node/consumer/src/jobs/processTorrents.ts @@ -1,7 +1,7 @@ import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' import {jobConfig, rabbitConfig} from '../lib/config'; -import {processTorrentRecord} from '../lib/torrent_processor'; -import {logger} from '../lib/logger'; +import {torrentProcessingService} from '../lib/services/torrent_processing_service'; +import {logger} from '../lib/services/logging_service'; import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; @@ -10,7 +10,7 @@ const consumeQueueOptions: Options.Consume = { noAck: false }; const processMessage = (msg: ConsumeMessage | null): Promise => { const ingestedTorrent: IngestedTorrentAttributes = getMessageAsJson(msg); - return processTorrentRecord(ingestedTorrent); + return torrentProcessingService.processTorrentRecord(ingestedTorrent); }; const getMessageAsJson = (msg: ConsumeMessage | null): IngestedTorrentAttributes => { diff --git a/src/node/consumer/src/lib/cache.ts b/src/node/consumer/src/lib/cache.ts deleted file mode 100644 index d389257..0000000 --- a/src/node/consumer/src/lib/cache.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {Cache, createCache, memoryStore} from 'cache-manager'; -import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' -import { cacheConfig } from './config'; -import { logger } from './logger'; -import { CacheType } from "./enums/cache_types"; -import {CacheOptions} from "./interfaces/cache_options"; - -const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; -const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; -const KITSU_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|kitsu_id`; -const METADATA_PREFIX = `${GLOBAL_KEY_PREFIX}|metadata`; -const TRACKERS_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|trackers`; - -const GLOBAL_TTL: number = Number(process.env.METADATA_TTL) || 7 * 24 * 60 * 60; // 7 days -const MEMORY_TTL: number = Number(process.env.METADATA_TTL) || 2 * 60 * 60; // 2 hours -const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days - -type CacheMethod = () => any; - -const initiateMemoryCache = () => - createCache(memoryStore(), { - ttl: MEMORY_TTL - }) as Cache; - -const initiateMongoCache = () => { - const store = mongoDbStore({ - collectionName: cacheConfig.COLLECTION_NAME, - ttl: GLOBAL_TTL, - url: cacheConfig.MONGO_URI, - mongoConfig:{ - socketTimeoutMS: 120000, - appName: 'knightcrawler-consumer', - } - }); - - return createCache(store, { - ttl: GLOBAL_TTL, - }); -} - -const initiateRemoteCache = (): Cache => { - if (cacheConfig.NO_CACHE) { - logger.debug('Cache is disabled'); - return null; - } - - return cacheConfig.MONGO_URI ? initiateMongoCache() : initiateMemoryCache(); -} - -const getCacheType = (cacheType: CacheType): typeof memoryCache | null => { - switch (cacheType) { - case CacheType.MEMORY: - return memoryCache; - case CacheType.MONGODB: - return remoteCache; - default: - return null; - } -} - -const memoryCache = initiateMemoryCache(); -const remoteCache = initiateRemoteCache(); - -const cacheWrap = async ( - cacheType: CacheType, key: string, method: CacheMethod, options: CacheOptions): Promise => { - const cache = getCacheType(cacheType); - - if (cacheConfig.NO_CACHE || !cache) { - return method(); - } - - logger.debug(`Cache type: ${cacheType}`); - logger.debug(`Cache key: ${key}`); - logger.debug(`Cache options: ${JSON.stringify(options)}`); - - return cache.wrap(key, method, options.ttl); -} - -export const cacheWrapImdbId = (key: string, method: CacheMethod): Promise => - cacheWrap(CacheType.MONGODB, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); - -export const cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => - cacheWrap(CacheType.MONGODB, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); - -export const cacheWrapMetadata = (id: string, method: CacheMethod): Promise => - cacheWrap(CacheType.MEMORY, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); - -export const cacheTrackers = (method: CacheMethod): Promise => - cacheWrap(CacheType.MEMORY, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); \ No newline at end of file diff --git a/src/node/consumer/src/lib/extension.ts b/src/node/consumer/src/lib/extension.ts deleted file mode 100644 index 937dc35..0000000 --- a/src/node/consumer/src/lib/extension.ts +++ /dev/null @@ -1,62 +0,0 @@ -const VIDEO_EXTENSIONS: string[] = [ - "3g2", - "3gp", - "avi", - "flv", - "mkv", - "mk3d", - "mov", - "mp2", - "mp4", - "m4v", - "mpe", - "mpeg", - "mpg", - "mpv", - "webm", - "wmv", - "ogm", - "divx" -]; -const SUBTITLE_EXTENSIONS: string[] = [ - "aqt", - "gsub", - "jss", - "sub", - "ttxt", - "pjs", - "psb", - "rt", - "smi", - "slt", - "ssf", - "srt", - "ssa", - "ass", - "usf", - "idx", - "vtt" -]; -const DISK_EXTENSIONS: string[] = [ - "iso", - "m2ts", - "ts", - "vob" -] - -export function isVideo(filename: string): boolean { - return isExtension(filename, VIDEO_EXTENSIONS); -} - -export function isSubtitle(filename: string): boolean { - return isExtension(filename, SUBTITLE_EXTENSIONS); -} - -export function isDisk(filename: string): boolean { - return isExtension(filename, DISK_EXTENSIONS); -} - -export function isExtension(filename: string, extensions: string[]): boolean { - const extensionMatch = filename.match(/\.(\w{2,4})$/); - return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/helpers/promises_helpers.ts b/src/node/consumer/src/lib/helpers/promises_helpers.ts new file mode 100644 index 0000000..3837d19 --- /dev/null +++ b/src/node/consumer/src/lib/helpers/promises_helpers.ts @@ -0,0 +1,51 @@ +export class PromiseHelpers { + public static async sequence(promises: Array<() => Promise>): Promise { + return promises.reduce((promise: Promise, func: () => Promise) => + promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); + } + + /** + * Return first resolved promise as the result. + */ + public static async first(promises: Array>): Promise { + return Promise.all(promises.map(p => { + // If a request fails, count that as a resolution so it will keep + // waiting for other possible successes. If a request succeeds, + // treat it as a rejection so Promise.all immediately bails out. + return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); + })).then( + // If '.all' resolved, we've just got an array of errors. + (errors) => Promise.reject(errors), + // If '.all' rejected, we've got the result we wanted. + (val) => Promise.resolve(val) + ); + } + + /** + * Delay promise + */ + public static async delay(duration: number): Promise { + return new Promise((resolve) => setTimeout(() => resolve(), duration)); + } + + /** + * Timeout promise after a set time in ms + */ + public static async timeout(timeoutMs: number, promise: Promise, message = 'Timed out'): Promise { + return Promise.race([ + promise, + new Promise(function (resolve, reject) { + setTimeout(function () { + reject(message); + }, timeoutMs); + }) + ]); + } + + /** + * Return most common value from given array. + */ + public static mostCommonValue(array: any[]): any { + return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); + } +} diff --git a/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts b/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts new file mode 100644 index 0000000..4a0a5a5 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts @@ -0,0 +1,3 @@ +export interface DownloadedTorrentFile extends TorrentStream.TorrentFile { + fileIndex: number; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/logger.ts b/src/node/consumer/src/lib/logger.ts deleted file mode 100644 index 2ea0d7a..0000000 --- a/src/node/consumer/src/lib/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -import pino from 'pino'; - -export const logger = pino({ - level: process.env.LOG_LEVEL || 'info' -}); \ No newline at end of file diff --git a/src/node/consumer/src/lib/metadata.ts b/src/node/consumer/src/lib/metadata.ts deleted file mode 100644 index 99ebc8d..0000000 --- a/src/node/consumer/src/lib/metadata.ts +++ /dev/null @@ -1,216 +0,0 @@ -import axios, {AxiosResponse} from 'axios'; -import {search, ResultTypes} from 'google-sr'; -import nameToImdb from 'name-to-imdb'; -import { cacheWrapImdbId, cacheWrapKitsuId, cacheWrapMetadata } from './cache'; -import { TorrentType } from './enums/torrent_types'; -import {MetadataResponse} from "./interfaces/metadata_response"; -import {CinemetaJsonResponse} from "./interfaces/cinemeta_metadata"; -import {CommonVideoMetadata} from "./interfaces/common_video_metadata"; -import {KitsuJsonResponse} from "./interfaces/kitsu_metadata"; -import {MetaDataQuery} from "./interfaces/metadata_query"; -import {KitsuCatalogJsonResponse} from "./interfaces/kitsu_catalog_metadata"; - -const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; -const KITSU_URL = 'https://anime-kitsu.strem.fun'; -const TIMEOUT = 20000; - -async function _requestMetadata(url: string): Promise { - let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); - let result : MetadataResponse; - const body = response.data; - if ('kitsu_id' in body.meta) { - result = handleKitsuResponse(body as KitsuJsonResponse); - } - else if ('imdb_id' in body.meta) { - result = handleCinemetaResponse(body as CinemetaJsonResponse); - } - else { - throw new Error('No valid metadata'); - } - - return result; -} - -function handleCinemetaResponse(body: CinemetaJsonResponse) : MetadataResponse { - return { - imdbId: parseInt(body.meta.imdb_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos - ? body.meta.videos.map(video => ({ - name: video.name, - season: video.season, - episode: video.episode, - imdbSeason: video.season, - imdbEpisode: video.episode, - })) - : [], - episodeCount: body.meta.videos - ? getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }; -} - -function handleKitsuResponse(body: KitsuJsonResponse) : MetadataResponse { - return { - kitsuId: parseInt(body.meta.kitsu_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos - ? body.meta.videos.map(video => ({ - name: video.title, - season: video.season, - episode: video.episode, - kitsuId: video.id, - kitsuEpisode: video.episode, - released: video.released, - })) - : [], - episodeCount: body.meta.videos - ? getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }; -} - -function getEpisodeCount(videos: CommonVideoMetadata[]) { - return Object.values( - videos - .filter(entry => entry.season !== 0 && entry.episode !== 0) - .sort((a, b) => a.season - b.season) - .reduce((map, next) => { - map[next.season] = map[next.season] + 1 || 1; - return map; - }, {}) - ); -} - - -export function escapeTitle(title: string): string { - return title.toLowerCase() - .normalize('NFKD') // normalize non-ASCII characters - .replace(/[\u0300-\u036F]/g, '') - .replace(/&/g, 'and') - .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces - .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars - .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering - .replace(/\s{2,}/, ' ') // replace multiple spaces - .trim(); -} - -function getIMDbIdFromNameToImdb(name: string, info: MetaDataQuery) : Promise { - const year = info.year; - const type = info.type; - return new Promise((resolve, reject) => { - nameToImdb({ name, year, type }, function(err: Error, res: string) { - if (res) { - resolve(res); - } else { - reject(err || new Error('Failed IMDbId search')); - } - }); - }); -} - -async function getIMDbIdFromGoogle(query: string): Promise{ - try { - const searchResults = await search({ query: query }); - for(const result of searchResults) { - if(result.type === ResultTypes.SearchResult) { - if(result.link.includes('imdb.com/title/')){ - const match = result.link.match(/imdb\.com\/title\/(tt\d+)/); - if(match){ - return match[1]; - } - } - } - } - return undefined; - } - catch (error) { - throw new Error('Failed to find IMDb ID from Google search'); - } -} - -export async function getKitsuId(info: MetaDataQuery): Promise { - const title = escapeTitle(info.title.replace(/\s\|\s.*/, '')); - const year = info.year ? ` ${info.year}` : ''; - const season = info.season > 1 ? ` S${info.season}` : ''; - const key = `${title}${year}${season}`; - const query = encodeURIComponent(key); - - return cacheWrapKitsuId(key, - () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, { timeout: 60000 }) - .then((response) => { - const body = response.data as KitsuCatalogJsonResponse; - if (body && body.metas && body.metas.length) { - return body.metas[0].id.replace('kitsu:', ''); - } else { - throw new Error('No search results'); - } - })); -} - -export async function getImdbId(info: MetaDataQuery): Promise { - const name = escapeTitle(info.title); - const year = info.year || (info.date && info.date.slice(0, 4)); - const key = `${name}_${year || 'NA'}_${info.type}`; - const query = `${name} ${year || ''} ${info.type} imdb`; - const fallbackQuery = `${name} ${info.type} imdb`; - const googleQuery = year ? query : fallbackQuery; - - try { - const imdbId = await cacheWrapImdbId(key, - () => getIMDbIdFromNameToImdb(name, info) - ); - return imdbId && 'tt' + imdbId.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); - } catch (error) { - const imdbIdFallback = await getIMDbIdFromGoogle(googleQuery); - return imdbIdFallback && 'tt' + imdbIdFallback.toString().replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); - } -} - -export function getMetadata(id: string | number, type: TorrentType = TorrentType.SERIES): Promise { - if (!id) { - return Promise.reject("no valid id provided"); - } - - const key = Number.isInteger(id) || id.toString().match(/^\d+$/) ? `kitsu:${id}` : id; - const metaType = type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; - return cacheWrapMetadata(key, () => _requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) - .catch(() => _requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) - .catch(() => { - // try different type in case there was a mismatch - const otherType = metaType === TorrentType.MOVIE ? TorrentType.SERIES : TorrentType.MOVIE; - return _requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) - }) - .catch((error) => { - throw new Error(`failed metadata query ${key} due: ${error.message}`); - })); -} - -export async function isEpisodeImdbId(imdbId: string | undefined): Promise { - if (!imdbId) { - return false; - } - return axios.get(`https://www.imdb.com/title/${imdbId}/`, { timeout: 10000 }) - .then(response => !!(response.data && response.data.includes('video.episode'))) - .catch(() => false); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/parseHelper.ts b/src/node/consumer/src/lib/parseHelper.ts deleted file mode 100644 index d393186..0000000 --- a/src/node/consumer/src/lib/parseHelper.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { parse } from 'parse-torrent-title'; -import { TorrentType } from './enums/torrent_types'; -import {ParseTorrentTitleResult} from "./interfaces/parse_torrent_title_result"; -import {ParsableTorrentVideo} from "./interfaces/parsable_torrent_video"; -import {ParsableTorrent} from "./interfaces/parsable_torrent"; - -const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB - -export function parseSeriesVideos(torrent: ParsableTorrent, videos: ParsableTorrentVideo[]): ParseTorrentTitleResult[] { - const parsedTorrentName = parse(torrent.title); - const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); - const parsedVideos = videos.map(video => parseSeriesVideo(video, parsedTorrentName)); - return parsedVideos.map(video => ({ ...video, isMovie: isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); -} - -function parseSeriesVideo(video: ParsableTorrentVideo, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { - const videoInfo = parse(video.name); - // the episode may be in a folder containing season number - if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { - const folders = video.path.split('/'); - const pathInfo = parse(folders[folders.length - 2]); - videoInfo.season = pathInfo.season; - } - if (!Number.isInteger(videoInfo.season) && parsedTorrentName.season) { - videoInfo.season = parsedTorrentName.season; - } - if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { - // in case single file was interpreted as having multiple seasons - videoInfo.season = videoInfo.seasons[0]; - } - if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && parsedTorrentName.seasons - && parsedTorrentName.seasons.length > 1) { - // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv - const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); - videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; - } - // sometimes video file does not have correct date format as in torrent title - if (!videoInfo.episodes && !videoInfo.date && parsedTorrentName.date) { - videoInfo.date = parsedTorrentName.date; - } - // limit number of episodes in case of incorrect parsing - if (videoInfo.episodes && videoInfo.episodes.length > 20) { - videoInfo.episodes = [videoInfo.episodes[0]]; - videoInfo.episode = videoInfo.episodes[0]; - } - // force episode to any found number if it was not parsed - if (!videoInfo.episodes && !videoInfo.date) { - const epMatcher = videoInfo.title.match( - /(? 3 - && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; -} - -export function isPackTorrent(torrent: ParsableTorrent): boolean { - if (torrent.pack) { - return true; - } - const parsedInfo = parse(torrent.title); - if (torrent.type === TorrentType.MOVIE) { - return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); - } - const hasMultipleEpisodes = parsedInfo.complete || - torrent.size > MULTIPLE_FILES_SIZE || - (parsedInfo.seasons && parsedInfo.seasons.length > 1) || - (parsedInfo.episodes && parsedInfo.episodes.length > 1) || - (parsedInfo.seasons && !parsedInfo.episodes); - const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); - return hasMultipleEpisodes && !hasSingleEpisode; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/promises.ts b/src/node/consumer/src/lib/promises.ts deleted file mode 100644 index f7a8dd3..0000000 --- a/src/node/consumer/src/lib/promises.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Execute promises in sequence one after another. - */ -export async function sequence(promises: Array<() => Promise>): Promise { - return promises.reduce((promise: Promise, func: () => Promise) => - promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); -} - -/** - * Return first resolved promise as the result. - */ -export async function first(promises: Array>): Promise { - return Promise.all(promises.map(p => { - // If a request fails, count that as a resolution so it will keep - // waiting for other possible successes. If a request succeeds, - // treat it as a rejection so Promise.all immediately bails out. - return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); - })).then( - // If '.all' resolved, we've just got an array of errors. - (errors) => Promise.reject(errors), - // If '.all' rejected, we've got the result we wanted. - (val) => Promise.resolve(val) - ); -} - -/** - * Delay promise - */ -export async function delay(duration: number): Promise { - return new Promise((resolve) => setTimeout(() => resolve(), duration)); -} - -/** - * Timeout promise after a set time in ms - */ -export async function timeout(timeoutMs: number, promise: Promise, message = 'Timed out'): Promise { - return Promise.race([ - promise, - new Promise(function (resolve, reject) { - setTimeout(function () { - reject(message); - }, timeoutMs); - }) - ]); -} - -/** - * Return most common value from given array. - */ -export function mostCommonValue(array: any[]): any { - return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts new file mode 100644 index 0000000..5743d3c --- /dev/null +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -0,0 +1,104 @@ +import {Cache, createCache, memoryStore} from 'cache-manager'; +import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' +import { cacheConfig } from '../config'; +import { logger } from './logging_service'; +import { CacheType } from "../enums/cache_types"; +import {CacheOptions} from "../interfaces/cache_options"; + +const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; +const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; +const KITSU_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|kitsu_id`; +const METADATA_PREFIX = `${GLOBAL_KEY_PREFIX}|metadata`; +const TRACKERS_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|trackers`; + +const GLOBAL_TTL: number = Number(process.env.METADATA_TTL) || 7 * 24 * 60 * 60; // 7 days +const MEMORY_TTL: number = Number(process.env.METADATA_TTL) || 2 * 60 * 60; // 2 hours +const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days + +type CacheMethod = () => any; + +class CacheService { + constructor() { + if (!cacheConfig.NO_CACHE) { + logger.info('Cache is disabled'); + return; + } + + this.memoryCache = this.initiateMemoryCache(); + this.remoteCache = this.initiateRemoteCache(); + } + + public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => + this.cacheWrap(CacheType.MONGODB, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + + public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => + this.cacheWrap(CacheType.MONGODB, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + + public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => + this.cacheWrap(CacheType.MEMORY, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); + + public cacheTrackers = (method: CacheMethod): Promise => + this.cacheWrap(CacheType.MEMORY, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); + + private initiateMemoryCache = () => + createCache(memoryStore(), { + ttl: MEMORY_TTL + }) as Cache; + + private initiateMongoCache = () => { + const store = mongoDbStore({ + collectionName: cacheConfig.COLLECTION_NAME, + ttl: GLOBAL_TTL, + url: cacheConfig.MONGO_URI, + mongoConfig:{ + socketTimeoutMS: 120000, + appName: 'knightcrawler-consumer', + } + }); + + return createCache(store, { + ttl: GLOBAL_TTL, + }); + } + + private initiateRemoteCache = (): Cache => { + if (cacheConfig.NO_CACHE) { + logger.debug('Cache is disabled'); + return null; + } + + return cacheConfig.MONGO_URI ? this.initiateMongoCache() : this.initiateMemoryCache(); + } + + private getCacheType = (cacheType: CacheType): typeof this.memoryCache | null => { + switch (cacheType) { + case CacheType.MEMORY: + return this.memoryCache; + case CacheType.MONGODB: + return this.remoteCache; + default: + return null; + } + } + + private readonly memoryCache: Cache; + private readonly remoteCache: Cache; + + private cacheWrap = async ( + cacheType: CacheType, key: string, method: CacheMethod, options: CacheOptions): Promise => { + const cache = this.getCacheType(cacheType); + + if (cacheConfig.NO_CACHE || !cache) { + return method(); + } + + logger.debug(`Cache type: ${cacheType}`); + logger.debug(`Cache key: ${key}`); + logger.debug(`Cache options: ${JSON.stringify(options)}`); + + return cache.wrap(key, method, options.ttl); + } +} + +export const cacheService: CacheService = new CacheService(); + diff --git a/src/node/consumer/src/lib/services/extension_service.ts b/src/node/consumer/src/lib/services/extension_service.ts new file mode 100644 index 0000000..4e270ad --- /dev/null +++ b/src/node/consumer/src/lib/services/extension_service.ts @@ -0,0 +1,69 @@ +class ExtensionService { + private readonly VIDEO_EXTENSIONS: string[] = [ + "3g2", + "3gp", + "avi", + "flv", + "mkv", + "mk3d", + "mov", + "mp2", + "mp4", + "m4v", + "mpe", + "mpeg", + "mpg", + "mpv", + "webm", + "wmv", + "ogm", + "divx" + ]; + private readonly SUBTITLE_EXTENSIONS: string[] = [ + "aqt", + "gsub", + "jss", + "sub", + "ttxt", + "pjs", + "psb", + "rt", + "smi", + "slt", + "ssf", + "srt", + "ssa", + "ass", + "usf", + "idx", + "vtt" + ]; + private readonly DISK_EXTENSIONS: string[] = [ + "iso", + "m2ts", + "ts", + "vob" + ] + + public isVideo(filename: string): boolean { + return this.isExtension(filename, this.VIDEO_EXTENSIONS); + } + + public isSubtitle(filename: string): boolean { + return this.isExtension(filename, this.SUBTITLE_EXTENSIONS); + } + + public isDisk(filename: string): boolean { + return this.isExtension(filename, this.DISK_EXTENSIONS); + } + + public isExtension(filename: string, extensions: string[]): boolean { + const extensionMatch = filename.match(/\.(\w{2,4})$/); + return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); + } +} + +export const extensionService = new ExtensionService(); + + + diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts new file mode 100644 index 0000000..ac23ed8 --- /dev/null +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -0,0 +1,26 @@ +import {Logger, pino} from "pino"; + +class LoggingService { + public readonly logger: Logger = pino({ + level: process.env.LOG_LEVEL || 'info' + }); + + public info(message: string, ...args: any[]): void { + this.logger.info(message); + } + + public error(message: string, ...args: any[]): void { + this.logger.error(message); + } + + public debug(message: string, ...args: any[]): void { + this.logger.debug(message); + } + + public warn(message: string, ...args: any[]): void { + this.logger.warn(message); + } +} + +export const logger = new LoggingService(); + diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts new file mode 100644 index 0000000..5667bb8 --- /dev/null +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -0,0 +1,217 @@ +import axios, {AxiosResponse} from 'axios'; +import {search, ResultTypes} from 'google-sr'; +import nameToImdb from 'name-to-imdb'; +import { cacheService } from './cache_service'; +import { TorrentType } from '../enums/torrent_types'; +import {MetadataResponse} from "../interfaces/metadata_response"; +import {CinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; +import {CommonVideoMetadata} from "../interfaces/common_video_metadata"; +import {KitsuJsonResponse} from "../interfaces/kitsu_metadata"; +import {MetaDataQuery} from "../interfaces/metadata_query"; +import {KitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; + +const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; +const KITSU_URL = 'https://anime-kitsu.strem.fun'; +const TIMEOUT = 20000; + +class MetadataService { + public async getKitsuId(info: MetaDataQuery): Promise { + const title = this.escapeTitle(info.title.replace(/\s\|\s.*/, '')); + const year = info.year ? ` ${info.year}` : ''; + const season = info.season > 1 ? ` S${info.season}` : ''; + const key = `${title}${year}${season}`; + const query = encodeURIComponent(key); + + return cacheService.cacheWrapKitsuId(key, + () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, { timeout: 60000 }) + .then((response) => { + const body = response.data as KitsuCatalogJsonResponse; + if (body && body.metas && body.metas.length) { + return body.metas[0].id.replace('kitsu:', ''); + } else { + throw new Error('No search results'); + } + })); + } + + public async getImdbId(info: MetaDataQuery): Promise { + const name = this.escapeTitle(info.title); + const year = info.year || (info.date && info.date.slice(0, 4)); + const key = `${name}_${year || 'NA'}_${info.type}`; + const query = `${name} ${year || ''} ${info.type} imdb`; + const fallbackQuery = `${name} ${info.type} imdb`; + const googleQuery = year ? query : fallbackQuery; + + try { + const imdbId = await cacheService.cacheWrapImdbId(key, + () => this.getIMDbIdFromNameToImdb(name, info) + ); + return imdbId && 'tt' + imdbId.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); + } catch (error) { + const imdbIdFallback = await this.getIMDbIdFromGoogle(googleQuery); + return imdbIdFallback && 'tt' + imdbIdFallback.toString().replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); + } + } + + public getMetadata(id: string | number, type: TorrentType = TorrentType.SERIES): Promise { + if (!id) { + return Promise.reject("no valid id provided"); + } + + const key = Number.isInteger(id) || id.toString().match(/^\d+$/) ? `kitsu:${id}` : id; + const metaType = type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; + return cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + .catch(() => this.requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) + .catch(() => { + // try different type in case there was a mismatch + const otherType = metaType === TorrentType.MOVIE ? TorrentType.SERIES : TorrentType.MOVIE; + return this.requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) + }) + .catch((error) => { + throw new Error(`failed metadata query ${key} due: ${error.message}`); + })); + } + + public async isEpisodeImdbId(imdbId: string | undefined): Promise { + if (!imdbId) { + return false; + } + return axios.get(`https://www.imdb.com/title/${imdbId}/`, {timeout: 10000}) + .then(response => !!(response.data && response.data.includes('video.episode'))) + .catch(() => false); + } + + public escapeTitle(title: string): string { + return title.toLowerCase() + .normalize('NFKD') // normalize non-ASCII characters + .replace(/[\u0300-\u036F]/g, '') + .replace(/&/g, 'and') + .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces + .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars + .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering + .replace(/\s{2,}/, ' ') // replace multiple spaces + .trim(); + } + + private async requestMetadata(url: string): Promise { + let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); + let result: MetadataResponse; + const body = response.data; + if ('kitsu_id' in body.meta) { + result = this.handleKitsuResponse(body as KitsuJsonResponse); + } else if ('imdb_id' in body.meta) { + result = this.handleCinemetaResponse(body as CinemetaJsonResponse); + } else { + throw new Error('No valid metadata'); + } + + return result; + } + + private handleCinemetaResponse(body: CinemetaJsonResponse): MetadataResponse { + return { + imdbId: parseInt(body.meta.imdb_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.name, + season: video.season, + episode: video.episode, + imdbSeason: video.season, + imdbEpisode: video.episode, + })) + : [], + episodeCount: body.meta.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }; + } + + private handleKitsuResponse(body: KitsuJsonResponse): MetadataResponse { + return { + kitsuId: parseInt(body.meta.kitsu_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.title, + season: video.season, + episode: video.episode, + kitsuId: video.id, + kitsuEpisode: video.episode, + released: video.released, + })) + : [], + episodeCount: body.meta.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }; + } + + private getEpisodeCount(videos: CommonVideoMetadata[]) { + return Object.values( + videos + .filter(entry => entry.season !== 0 && entry.episode !== 0) + .sort((a, b) => a.season - b.season) + .reduce((map, next) => { + map[next.season] = map[next.season] + 1 || 1; + return map; + }, {}) + ); + } + + private getIMDbIdFromNameToImdb(name: string, info: MetaDataQuery): Promise { + const year = info.year; + const type = info.type; + return new Promise((resolve, reject) => { + nameToImdb({name, year, type}, function (err: Error, res: string) { + if (res) { + resolve(res); + } else { + reject(err || new Error('Failed IMDbId search')); + } + }); + }); + } + + private async getIMDbIdFromGoogle(query: string): Promise { + try { + const searchResults = await search({query: query}); + for (const result of searchResults) { + if (result.type === ResultTypes.SearchResult) { + if (result.link.includes('imdb.com/title/')) { + const match = result.link.match(/imdb\.com\/title\/(tt\d+)/); + if (match) { + return match[1]; + } + } + } + } + return undefined; + } catch (error) { + throw new Error('Failed to find IMDb ID from Google search'); + } + } +} + +export const metadataService: MetadataService = new MetadataService(); + diff --git a/src/node/consumer/src/lib/services/parsing_service.ts b/src/node/consumer/src/lib/services/parsing_service.ts new file mode 100644 index 0000000..28ea866 --- /dev/null +++ b/src/node/consumer/src/lib/services/parsing_service.ts @@ -0,0 +1,106 @@ +import { parse } from 'parse-torrent-title'; +import { TorrentType } from '../enums/torrent_types'; +import {ParseTorrentTitleResult} from "../interfaces/parse_torrent_title_result"; +import {ParsableTorrentVideo} from "../interfaces/parsable_torrent_video"; +import {ParsableTorrent} from "../interfaces/parsable_torrent"; + +class ParsingService { + private readonly MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB + + public parseSeriesVideos(torrent: ParsableTorrent, videos: ParsableTorrentVideo[]): ParseTorrentTitleResult[] { + const parsedTorrentName = parse(torrent.title); + const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); + const parsedVideos = videos.map(video => this.parseSeriesVideo(video, parsedTorrentName)); + return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); + } + + public isPackTorrent(torrent: ParsableTorrent): boolean { + if (torrent.pack) { + return true; + } + const parsedInfo = parse(torrent.title); + if (torrent.type === TorrentType.MOVIE) { + return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); + } + const hasMultipleEpisodes = parsedInfo.complete || + torrent.size > this.MULTIPLE_FILES_SIZE || + (parsedInfo.seasons && parsedInfo.seasons.length > 1) || + (parsedInfo.episodes && parsedInfo.episodes.length > 1) || + (parsedInfo.seasons && !parsedInfo.episodes); + const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); + return hasMultipleEpisodes && !hasSingleEpisode; + } + + private parseSeriesVideo(video: ParsableTorrentVideo, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { + const videoInfo = parse(video.name); + // the episode may be in a folder containing season number + if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { + const folders = video.path.split('/'); + const pathInfo = parse(folders[folders.length - 2]); + videoInfo.season = pathInfo.season; + } + if (!Number.isInteger(videoInfo.season) && parsedTorrentName.season) { + videoInfo.season = parsedTorrentName.season; + } + if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { + // in case single file was interpreted as having multiple seasons + videoInfo.season = videoInfo.seasons[0]; + } + if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && parsedTorrentName.seasons + && parsedTorrentName.seasons.length > 1) { + // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv + const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); + videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; + } + // sometimes video file does not have correct date format as in torrent title + if (!videoInfo.episodes && !videoInfo.date && parsedTorrentName.date) { + videoInfo.date = parsedTorrentName.date; + } + // limit number of episodes in case of incorrect parsing + if (videoInfo.episodes && videoInfo.episodes.length > 20) { + videoInfo.episodes = [videoInfo.episodes[0]]; + videoInfo.episode = videoInfo.episodes[0]; + } + // force episode to any found number if it was not parsed + if (!videoInfo.episodes && !videoInfo.date) { + const epMatcher = videoInfo.title.match( + /(? 3 + && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; + } +} + +export const parsingService = new ParsingService(); + diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts new file mode 100644 index 0000000..2cffccd --- /dev/null +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -0,0 +1,82 @@ +import { encode } from 'magnet-uri'; +import torrentStream from 'torrent-stream'; +import { torrentConfig } from '../config'; +import {extensionService} from './extension_service'; +import {TorrentInfo} from "../interfaces/torrent_info"; +import {DownloadedTorrentFile} from "../interfaces/downloaded_torrent_file"; + +class TorrentDownloadService { + private engineOptions: TorrentStream.TorrentEngineOptions = { + connections: torrentConfig.MAX_CONNECTIONS_PER_TORRENT, + uploads: 0, + verify: false, + dht: false, + tracker: true, + }; + + public async getTorrentFiles(torrent: TorrentInfo, timeout: number = 30000): Promise<{ contents: Array; videos: Array; subtitles: Array }> { + return this.filesFromTorrentStream(torrent, timeout) + .then((files: Array) => ({ + contents: files, + videos: this.filterVideos(files), + subtitles: this.filterSubtitles(files) + })); + } + + private async filesFromTorrentStream(torrent: TorrentInfo, timeout: number): Promise> { + if (!torrent.infoHash) { + return Promise.reject(new Error("No infoHash...")); + } + const magnet = encode({ infoHash: torrent.infoHash, announce: torrent.trackers.split(',') }); + + return new Promise((resolve, reject) => { + let engine: TorrentStream.TorrentEngine; + + const timeoutId = setTimeout(() => { + engine.destroy(() => {}); + reject(new Error('No available connections for torrent!')); + }, timeout); + + engine = torrentStream(magnet, this.engineOptions); + + engine.on("ready", () => { + const files: DownloadedTorrentFile[] = engine.files.map((file, fileId) => ({ ...file, fileIndex: fileId })); + resolve(files); + + engine.destroy(() => {}); + clearTimeout(timeoutId); + }); + }); + } + + private filterVideos(files: Array): Array { + if (files.length === 1 && !Number.isInteger(files[0].fileIndex)) { + return files; + } + const videos = files.filter(file => extensionService.isVideo(file.path || '')); + const maxSize = Math.max(...videos.map((video: DownloadedTorrentFile) => video.length)); + const minSampleRatio = videos.length <= 3 ? 3 : 10; + const minAnimeExtraRatio = 5; + const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; + const isSample = (video: DownloadedTorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.length.toString()) > minSampleRatio; + const isRedundant = (video: DownloadedTorrentFile) => maxSize / parseInt(video.length.toString()) > minRedundantRatio; + const isExtra = (video: DownloadedTorrentFile) => video.path?.match(/extras?\//i); + const isAnimeExtra = (video: DownloadedTorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; + const isWatermark = (video: DownloadedTorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio + return videos + .filter(video => !isSample(video)) + .filter(video => !isExtra(video)) + .filter(video => !isAnimeExtra(video)) + .filter(video => !isRedundant(video)) + .filter(video => !isWatermark(video)); + } + + private filterSubtitles(files: Array): Array { + return files.filter(file => extensionService.isSubtitle(file.path || '')); + } +} + +export const torrentDownloadService = new TorrentDownloadService(); + diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts new file mode 100644 index 0000000..3374881 --- /dev/null +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -0,0 +1,54 @@ +import {TorrentInfo} from "../interfaces/torrent_info"; +import {TorrentType} from "../enums/torrent_types"; +import {logger} from "./logging_service"; +import {checkAndUpdateTorrent, createTorrentEntry} from "../torrentEntries.js"; +import {trackerService} from "./tracker_service"; +import {IngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; + +class TorrentProcessingService { + public async processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { + const { category } = torrent; + const type = category === 'tv' ? TorrentType.SERIES : TorrentType.MOVIE; + const torrentInfo: TorrentInfo = await this.parseTorrent(torrent, type); + + logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); + + if (await checkAndUpdateTorrent(torrentInfo)) { + return; + } + + return createTorrentEntry(torrentInfo); + } + + private async assignTorrentTrackers(): Promise { + const trackers = await trackerService.getTrackers(); + return trackers.join(','); + } + + private async parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { + const infoHash = torrent.info_hash?.trim().toLowerCase() + return { + title: torrent.name, + torrentId: `${torrent.name}_${infoHash}`, + infoHash: infoHash, + seeders: 100, + size: torrent.size, + uploadDate: torrent.createdAt, + imdbId: this.parseImdbId(torrent), + type: category, + provider: torrent.source, + trackers: await this.assignTorrentTrackers(), + } + } + + private parseImdbId(torrent: IngestedTorrentAttributes): string | undefined { + if (torrent.imdb === undefined || torrent.imdb === null) { + return undefined; + } + + return torrent.imdb; + } +} + +export const torrentProcessingService = new TorrentProcessingService(); + diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts new file mode 100644 index 0000000..15438a5 --- /dev/null +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -0,0 +1,32 @@ +import axios, { AxiosResponse } from 'axios'; +import { cacheService } from "./cache_service"; +import { trackerConfig } from '../config'; +import { logger } from "./logging_service"; + +class TrackerService { + public async getTrackers() : Promise { + return cacheService.cacheTrackers(this.downloadTrackers); + }; + + private async downloadTrackers(): Promise { + const response: AxiosResponse = await axios.get(trackerConfig.TRACKERS_URL); + const trackersListText: string = response.data; + // Trackers are separated by a newline character + let urlTrackers = trackersListText.split("\n"); + // remove blank lines + urlTrackers = urlTrackers.filter(line => line.trim() !== ''); + + if (!trackerConfig.UDP_ENABLED) { + // remove any udp trackers + urlTrackers = urlTrackers.filter(line => !line.startsWith('udp://')); + + } + + logger.info(`Trackers updated at ${Date.now()}: ${urlTrackers.length} trackers`); + + return urlTrackers; + }; +} + +export const trackerService = new TrackerService(); + diff --git a/src/node/consumer/src/lib/torrent.js b/src/node/consumer/src/lib/torrent.js deleted file mode 100644 index 4f78d05..0000000 --- a/src/node/consumer/src/lib/torrent.js +++ /dev/null @@ -1,82 +0,0 @@ -import { decode } from 'magnet-uri'; -import torrentStream from 'torrent-stream'; -import { torrentConfig } from './config'; -import {isSubtitle, isVideo} from './extension'; - -export async function torrentFiles(torrent, timeout) { - return filesFromTorrentStream(torrent, timeout) - .then(files => ({ - contents: files, - videos: filterVideos(files), - subtitles: filterSubtitles(files) - })); -} - -async function filesFromTorrentStream(torrent, timeout) { - return filesAndSizeFromTorrentStream(torrent, timeout).then(result => result.files); -} - -const engineOptions = { - connections: torrentConfig.MAX_CONNECTIONS_PER_TORRENT, - uploads: 0, - verify: false, - dht: false, - tracker: true -} - -function filesAndSizeFromTorrentStream(torrent, timeout = 30000) { - if (!torrent.infoHash) { - return Promise.reject(new Error("no infoHash...")); - } - const magnet = decode.encode({ infoHash: torrent.infoHash, announce: torrent.trackers }); - return new Promise((resolve, rejected) => { - const timeoutId = setTimeout(() => { - engine.destroy(); - rejected(new Error('No available connections for torrent!')); - }, timeout); - - const engine = new torrentStream(magnet, engineOptions); - - engine.ready(() => { - const files = engine.files - .map((file, fileId) => ({ - fileIndex: fileId, - name: file.name, - path: file.path.replace(/^[^/]+\//, ''), - size: file.length - })); - const size = engine.torrent.length; - resolve({ files, size }); - engine.destroy(); - clearTimeout(timeoutId); - }); - }); -} - -function filterVideos(files) { - if (files.length === 1 && !Number.isInteger(files[0].fileIndex)) { - return files; - } - const videos = files.filter(file => isVideo(file.path)); - const maxSize = Math.max(...videos.map(video => video.size)); - const minSampleRatio = videos.length <= 3 ? 3 : 10; - const minAnimeExtraRatio = 5; - const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = video => video.path.match(/sample|bonus|promo/i) && maxSize / parseInt(video.size) > minSampleRatio; - const isRedundant = video => maxSize / parseInt(video.size) > minRedundantRatio; - const isExtra = video => video.path.match(/extras?\//i); - const isAnimeExtra = video => video.path.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) - && maxSize / parseInt(video.size) > minAnimeExtraRatio; - const isWatermark = video => video.path.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) - && maxSize / parseInt(video.size) > minAnimeExtraRatio - return videos - .filter(video => !isSample(video)) - .filter(video => !isExtra(video)) - .filter(video => !isAnimeExtra(video)) - .filter(video => !isRedundant(video)) - .filter(video => !isWatermark(video)); -} - -function filterSubtitles(files) { - return files.filter(file => isSubtitle(file.path)); -} diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index f341192..d4aeef2 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,12 +1,12 @@ import { parse } from 'parse-torrent-title'; -import { getImdbId, getKitsuId } from './metadata'; -import { isPackTorrent } from './parseHelper'; -import * as Promises from './promises'; +import { metadataService } from './services/metadata_service'; +import { parsingService } from './services/parsing_service'; +import {PromiseHelpers} from './helpers/promises_helpers.js'; import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; import { assignSubtitles } from './torrentSubtitles.js'; import { TorrentType } from './enums/torrent_types'; -import {logger} from "./logger"; +import {logger} from './services/logging_service'; export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); @@ -17,7 +17,7 @@ export async function createTorrentEntry(torrent, overwrite = false) { year: titleInfo.year, type: torrent.type }; - torrent.imdbId = await getImdbId(imdbQuery) + torrent.imdbId = await metadataService.getImdbId(imdbQuery) .catch(() => undefined); } if (torrent.imdbId && torrent.imdbId.length < 9) { @@ -34,11 +34,11 @@ export async function createTorrentEntry(torrent, overwrite = false) { year: titleInfo.year, season: titleInfo.season, }; - torrent.kitsuId = await getKitsuId(kitsuQuery) + torrent.kitsuId = await metadataService.getKitsuId(kitsuQuery) .catch(() => undefined); } - if (!torrent.imdbId && !torrent.kitsuId && !isPackTorrent(torrent)) { + if (!torrent.imdbId && !torrent.kitsuId && !parsingService.isPackTorrent(torrent)) { logger.warn(`imdbId or kitsuId not found: ${torrent.provider} ${torrent.title}`); return; } @@ -56,7 +56,7 @@ export async function createTorrentEntry(torrent, overwrite = false) { } return repository.createTorrent({ ...torrent, contents, subtitles }) - .then(() => Promises.sequence(videos.map(video => () => repository.createFile(video)))) + .then(() => PromiseHelpers.sequence(videos.map(video => () => repository.createFile(video)))) .then(() => logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); } @@ -132,8 +132,8 @@ export async function createTorrentContents(torrent) { return; } const notOpenedVideo = storedVideos.length === 1 && !Number.isInteger(storedVideos[0].fileIndex); - const imdbId = Promises.mostCommonValue(storedVideos.map(stored => stored.imdbId)); - const kitsuId = Promises.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); + const imdbId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); + const kitsuId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); const { contents, videos, subtitles } = await parseTorrentFiles({ ...torrent, imdbId, kitsuId }) .then(torrentContents => notOpenedVideo ? torrentContents : { ...torrentContents, videos: storedVideos }) @@ -165,7 +165,7 @@ export async function createTorrentContents(torrent) { } return Promise.resolve(); }) - .then(() => Promises.sequence(videos.map(video => () => repository.createFile(video)))) + .then(() => PromiseHelpers.sequence(videos.map(video => () => repository.createFile(video)))) .then(() => logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) .catch(error => logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); } diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 3539925..417f783 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -3,20 +3,20 @@ import distance from 'jaro-winkler'; import moment from 'moment'; import { parse } from 'parse-torrent-title'; import { metadataConfig } from './config'; -import { isDisk } from './extension'; -import { getMetadata, getImdbId, getKitsuId } from './metadata'; -import { parseSeriesVideos, isPackTorrent } from './parseHelper'; -import * as Promises from './promises'; -import {torrentFiles} from "./torrent.js"; +import { extensionService } from './services/extension_service'; +import { metadataService } from './services/metadata_service'; +import { parsingService } from './services/parsing_service'; +import {PromiseHelpers} from './helpers/promises_helpers.js'; +import {torrentDownloadService} from "./services/torrent_download_service"; import { TorrentType } from './enums/torrent_types'; -import {logger} from "./logger"; +import {logger} from "./services/logging_service"; const MIN_SIZE = 5 * 1024 * 1024; // 5 MB const imdb_limiter = new Bottleneck({ maxConcurrent: metadataConfig.IMDB_CONCURRENT, minTime: metadataConfig.IMDB_INTERVAL_MS }); export async function parseTorrentFiles(torrent) { const parsedTorrentName = parse(torrent.title); - const metadata = await getMetadata(torrent.kitsuId || torrent.imdbId, torrent.type || TorrentType.MOVIE) + const metadata = await metadataService.getMetadata(torrent.kitsuId || torrent.imdbId, torrent.type || TorrentType.MOVIE) .then(meta => Object.assign({}, meta)) .catch(() => undefined); @@ -53,7 +53,7 @@ async function parseMovieFiles(torrent, parsedName, metadata) { return { contents, videos: parsedVideos, subtitles }; } - const parsedVideos = await Promises.sequence(filteredVideos.map(video => () => isFeaturette(video) + const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => isFeaturette(video) ? Promise.resolve(video) : findMovieImdbId(video.name).then(imdbId => ({ ...video, imdbId })))) .then(videos => videos.map(video => ({ @@ -70,7 +70,7 @@ async function parseSeriesFiles(torrent, parsedName, metadata) { const { contents, videos, subtitles } = await getSeriesTorrentContent(torrent); const parsedVideos = await Promise.resolve(videos) .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) - .then(videos => parseSeriesVideos(torrent, videos)) + .then(videos => parsingService.parseSeriesVideos(torrent, videos)) .then(videos => decomposeEpisodes(torrent, videos, metadata)) .then(videos => assignKitsuOrImdbEpisodes(torrent, videos, metadata)) .then(videos => Promise.all(videos.map(video => video.isMovie @@ -97,9 +97,9 @@ async function getMoviesTorrentContent(torrent) { } async function getSeriesTorrentContent(torrent) { - return torrentFiles(torrent) + return torrentDownloadService.getTorrentFiles(torrent) .catch(error => { - if (!isPackTorrent(torrent)) { + if (!parsingService.isPackTorrent(torrent)) { return { videos: [{ name: torrent.title, path: torrent.title, size: torrent.size }] } } return Promise.reject(error); @@ -136,7 +136,7 @@ async function mapSeriesEpisode(file, torrent, files) { async function mapSeriesMovie(file, torrent) { const kitsuId = torrent.type === TorrentType.ANIME ? await findMovieKitsuId(file) : undefined; const imdbId = !kitsuId ? await findMovieImdbId(file) : undefined; - const metadata = await getMetadata(kitsuId || imdbId, TorrentType.MOVIE).catch(() => ({})); + const metadata = await metadataService.getMetadata(kitsuId || imdbId, TorrentType.MOVIE).catch(() => ({})); const hasEpisode = metadata.videos && metadata.videos.length && (file.episode || metadata.videos.length === 1); const episodeVideo = hasEpisode && metadata.videos[(file.episode || 1) - 1]; return [{ @@ -458,7 +458,7 @@ function needsCinemetaMetadataForAnime(files, metadata) { } async function updateToCinemetaMetadata(metadata) { - return getMetadata(metadata.imdbId, metadata.type) + return metadataService.getMetadata(metadata.imdbId, metadata.type) .then(newMetadata => !newMetadata.videos || !newMetadata.videos.length ? metadata : newMetadata) .then(newMetadata => { metadata.videos = newMetadata.videos; @@ -478,7 +478,7 @@ function findMovieImdbId(title) { year: parsedTitle.year, type: TorrentType.MOVIE }; - return getImdbId(imdbQuery).catch(() => undefined); + return metadataService.getImdbId(imdbQuery).catch(() => undefined); }); } @@ -490,11 +490,11 @@ function findMovieKitsuId(title) { season: parsedTitle.season, type: TorrentType.MOVIE }; - return getKitsuId(kitsuQuery).catch(() => undefined); + return metadataService.getKitsuId(kitsuQuery).catch(() => undefined); } function isDiskTorrent(contents) { - return contents.some(content => isDisk(content.path)); + return contents.some(content => extensionService.isDisk(content.path)); } function isSingleMovie(videos) { diff --git a/src/node/consumer/src/lib/torrent_processor.ts b/src/node/consumer/src/lib/torrent_processor.ts deleted file mode 100644 index 97387d1..0000000 --- a/src/node/consumer/src/lib/torrent_processor.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {TorrentInfo} from "./interfaces/torrent_info"; -import {TorrentType} from "./enums/torrent_types"; -import {logger} from "./logger"; -import {checkAndUpdateTorrent, createTorrentEntry} from "./torrentEntries.js"; -import {getTrackers} from "./trackerService"; -import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; - -export async function processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { - const { category } = torrent; - const type = category === 'tv' ? TorrentType.SERIES : TorrentType.MOVIE; - const torrentInfo: TorrentInfo = await parseTorrent(torrent, type); - - logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); - - if (await checkAndUpdateTorrent(torrentInfo)) { - return; - } - - return createTorrentEntry(torrentInfo); -} - -async function assignTorrentTrackers(): Promise { - const trackers = await getTrackers(); - return trackers.join(','); -} - -async function parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { - const infoHash = torrent.info_hash?.trim().toLowerCase() - return { - title: torrent.name, - torrentId: `${torrent.name}_${infoHash}`, - infoHash: infoHash, - seeders: 100, - size: torrent.size, - uploadDate: torrent.createdAt, - imdbId: parseImdbId(torrent), - type: category, - provider: torrent.source, - trackers: await assignTorrentTrackers(), - } -} - -function parseImdbId(torrent: IngestedTorrentAttributes): string | undefined { - if (torrent.imdb === undefined || torrent.imdb === null) { - return undefined; - } - - return torrent.imdb; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/trackerService.ts b/src/node/consumer/src/lib/trackerService.ts deleted file mode 100644 index f42e44e..0000000 --- a/src/node/consumer/src/lib/trackerService.ts +++ /dev/null @@ -1,27 +0,0 @@ -import axios, { AxiosResponse } from 'axios'; -import { cacheTrackers } from "./cache"; -import { trackerConfig } from './config'; -import { logger } from "./logger"; - -const downloadTrackers = async (): Promise => { - const response: AxiosResponse = await axios.get(trackerConfig.TRACKERS_URL); - const trackersListText: string = response.data; - // Trackers are separated by a newline character - let urlTrackers = trackersListText.split("\n"); - // remove blank lines - urlTrackers = urlTrackers.filter(line => line.trim() !== ''); - - if (!trackerConfig.UDP_ENABLED) { - // remove any udp trackers - urlTrackers = urlTrackers.filter(line => !line.startsWith('udp://')); - - } - - logger.info(`Trackers updated at ${Date.now()}: ${urlTrackers.length} trackers`); - - return urlTrackers; -}; - -export const getTrackers = async (): Promise => { - return cacheTrackers(downloadTrackers); -}; \ No newline at end of file diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index 023aa4c..c1772a2 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -2,7 +2,7 @@ import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; import {Model, Sequelize} from 'sequelize-typescript'; import {databaseConfig} from '../lib/config'; -import * as Promises from '../lib/promises'; +import {PromiseHelpers} from '../lib/helpers/promises_helpers'; import {Provider} from "./models/provider"; import {File} from "./models/file"; import {Torrent} from "./models/torrent"; @@ -13,7 +13,7 @@ import {SkipTorrent} from "./models/skipTorrent"; import {FileAttributes} from "./interfaces/file_attributes"; import {TorrentAttributes} from "./interfaces/torrent_attributes"; import {IngestedPage} from "./models/ingestedPage"; -import {logger} from "../lib/logger"; +import {logger} from "../lib/services/logging_service"; class DatabaseRepository { private readonly database: Sequelize; @@ -83,7 +83,7 @@ class DatabaseRepository { } public async setIngestedTorrentsProcessed(ingestedTorrents: IngestedTorrent[]): Promise { - await Promises.sequence(ingestedTorrents + await PromiseHelpers.sequence(ingestedTorrents .map(ingestedTorrent => async () => { ingestedTorrent.processed = true; await ingestedTorrent.save(); @@ -194,7 +194,7 @@ class DatabaseRepository { public async upsertSubtitles(file: File, subtitles: Subtitle[]): Promise { if (file.id && subtitles && subtitles.length) { - await Promises.sequence(subtitles + await PromiseHelpers.sequence(subtitles .map(subtitle => { subtitle.fileId = file.id; subtitle.infoHash = subtitle.infoHash || file.infoHash; From ff4edd5de472595350513006eaacc0210472ebef Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 13:07:44 +0000 Subject: [PATCH 10/55] configuration service now ts --- src/node/consumer/src/index.js | 2 +- src/node/consumer/src/jobs/processTorrents.ts | 12 ++--- src/node/consumer/src/lib/config.ts | 51 ------------------- .../src/lib/helpers/boolean_helpers.ts | 8 +++ .../lib/models/configuration/cache_config.ts | 15 ++++++ .../models/configuration/database_config.ts | 11 ++++ .../lib/models/configuration/job_config.ts | 6 +++ .../models/configuration/metadata_config.ts | 4 ++ .../lib/models/configuration/rabbit_config.ts | 4 ++ .../models/configuration/torrent_config.ts | 4 ++ .../models/configuration/tracker_config.ts | 6 +++ .../src/lib/services/cache_service.ts | 14 ++--- .../src/lib/services/configuration_service.ts | 19 +++++++ .../lib/services/torrent_download_service.ts | 4 +- .../src/lib/services/tracker_service.ts | 6 +-- src/node/consumer/src/lib/torrentEntries.js | 2 +- src/node/consumer/src/lib/torrentFiles.js | 6 +-- .../src/repository/database_repository.ts | 4 +- 18 files changed, 102 insertions(+), 76 deletions(-) delete mode 100644 src/node/consumer/src/lib/config.ts create mode 100644 src/node/consumer/src/lib/helpers/boolean_helpers.ts create mode 100644 src/node/consumer/src/lib/models/configuration/cache_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/database_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/job_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/metadata_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/rabbit_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/torrent_config.ts create mode 100644 src/node/consumer/src/lib/models/configuration/tracker_config.ts create mode 100644 src/node/consumer/src/lib/services/configuration_service.ts diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.js index 7d3e675..d4a163b 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.js @@ -1,6 +1,6 @@ import { listenToQueue } from './jobs/processTorrents'; import { repository } from "./repository/database_repository"; -import { trackerService } from "./lib/services/tracker_service.js"; +import { trackerService } from "./lib/services/tracker_service"; (async () => { await trackerService.getTrackers(); diff --git a/src/node/consumer/src/jobs/processTorrents.ts b/src/node/consumer/src/jobs/processTorrents.ts index 54a3a6b..9c7cd9b 100644 --- a/src/node/consumer/src/jobs/processTorrents.ts +++ b/src/node/consumer/src/jobs/processTorrents.ts @@ -1,5 +1,5 @@ import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' -import {jobConfig, rabbitConfig} from '../lib/config'; +import {configurationService} from '../lib/services/configuration_service'; import {torrentProcessingService} from '../lib/services/torrent_processing_service'; import {logger} from '../lib/services/logging_service'; import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; @@ -33,21 +33,21 @@ const assertAndConsumeQueue = async (channel: Channel): Promise => { } try { - await channel.assertQueue(rabbitConfig.QUEUE_NAME, assertQueueOptions); - await channel.prefetch(jobConfig.JOB_CONCURRENCY); - await channel.consume(rabbitConfig.QUEUE_NAME, ackMsg, consumeQueueOptions); + await channel.assertQueue(configurationService.rabbitConfig.QUEUE_NAME, assertQueueOptions); + await channel.prefetch(configurationService.jobConfig.JOB_CONCURRENCY); + await channel.consume(configurationService.rabbitConfig.QUEUE_NAME, ackMsg, consumeQueueOptions); } catch(error) { logger.error('Failed to setup channel', error); } } export const listenToQueue = async (): Promise => { - if (!jobConfig.JOBS_ENABLED) { + if (!configurationService.jobConfig.JOBS_ENABLED) { return; } try { - const connection: Connection = await client.connect(rabbitConfig.RABBIT_URI); + const connection: Connection = await client.connect(configurationService.rabbitConfig.RABBIT_URI); const channel: Channel = await connection.createChannel(); await assertAndConsumeQueue(channel); } catch (error) { diff --git a/src/node/consumer/src/lib/config.ts b/src/node/consumer/src/lib/config.ts deleted file mode 100644 index ddd31d0..0000000 --- a/src/node/consumer/src/lib/config.ts +++ /dev/null @@ -1,51 +0,0 @@ -const parseBool = (boolString: string | undefined, defaultValue: boolean): boolean => - boolString?.toLowerCase() === 'true' ? true : defaultValue; - -export const rabbitConfig = { - RABBIT_URI: process.env.RABBIT_URI || 'amqp://localhost', - QUEUE_NAME: process.env.QUEUE_NAME || 'test-queue' -} - -export const cacheConfig = { - MONGODB_HOST: process.env.MONGODB_HOST || 'mongodb', - MONGODB_PORT: process.env.MONGODB_PORT || '27017', - MONGODB_DB: process.env.MONGODB_DB || 'knightcrawler', - MONGO_INITDB_ROOT_USERNAME: process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo', - MONGO_INITDB_ROOT_PASSWORD: process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo', - NO_CACHE: parseBool(process.env.NO_CACHE, false), - COLLECTION_NAME: process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection', - MONGO_URI: '', -} - -cacheConfig.MONGO_URI = `mongodb://${cacheConfig.MONGO_INITDB_ROOT_USERNAME}:${cacheConfig.MONGO_INITDB_ROOT_PASSWORD}@${cacheConfig.MONGODB_HOST}:${cacheConfig.MONGODB_PORT}/${cacheConfig.MONGODB_DB}?authSource=admin`; - -export const databaseConfig = { - POSTGRES_HOST: process.env.POSTGRES_HOST || 'postgres', - POSTGRES_PORT: process.env.POSTGRES_PORT || '5432', - POSTGRES_DATABASE: process.env.POSTGRES_DATABASE || 'knightcrawler', - POSTGRES_USERNAME: process.env.POSTGRES_USERNAME || 'postgres', - POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || 'postgres', - POSTGRES_URI: '', -} - -databaseConfig.POSTGRES_URI = `postgres://${databaseConfig.POSTGRES_USERNAME}:${databaseConfig.POSTGRES_PASSWORD}@${databaseConfig.POSTGRES_HOST}:${databaseConfig.POSTGRES_PORT}/${databaseConfig.POSTGRES_DATABASE}`; - -export const jobConfig = { - JOB_CONCURRENCY: Number.parseInt(process.env.JOB_CONCURRENCY || "1", 10), - JOBS_ENABLED: parseBool(process.env.JOBS_ENABLED, true), -} - -export const metadataConfig = { - IMDB_CONCURRENT: Number.parseInt(process.env.IMDB_CONCURRENT || "1", 10), - IMDB_INTERVAL_MS: Number.parseInt(process.env.IMDB_INTERVAL_MS || "1000", 10), -} - -export const trackerConfig = { - TRACKERS_URL: process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt', - UDP_ENABLED: parseBool(process.env.UDP_TRACKERS_ENABLED, false), -} - -export const torrentConfig = { - MAX_CONNECTIONS_PER_TORRENT: Number.parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10), - TIMEOUT: Number.parseInt(process.env.TORRENT_TIMEOUT || "30000", 10), -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts new file mode 100644 index 0000000..9b608c0 --- /dev/null +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -0,0 +1,8 @@ +export class BooleanHelpers { + public static parseBool(value: string, defaultValue: boolean): boolean { + if (value === undefined) { + return defaultValue; + } + return value.toLowerCase() === 'true'; + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/cache_config.ts b/src/node/consumer/src/lib/models/configuration/cache_config.ts new file mode 100644 index 0000000..1ca735b --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/cache_config.ts @@ -0,0 +1,15 @@ +import {BooleanHelpers} from "../../helpers/boolean_helpers"; + +export class CacheConfig { + public MONGODB_HOST: string = process.env.MONGODB_HOST || 'mongodb'; + public MONGODB_PORT: string = process.env.MONGODB_PORT || '27017'; + public MONGODB_DB: string = process.env.MONGODB_DB || 'knightcrawler'; + public MONGO_INITDB_ROOT_USERNAME: string = process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo'; + public MONGO_INITDB_ROOT_PASSWORD: string = process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo'; + public NO_CACHE: boolean = BooleanHelpers.parseBool(process.env.NO_CACHE, false); + public COLLECTION_NAME: string = process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection'; + + public get MONGO_URI() { + return `mongodb://${this.MONGO_INITDB_ROOT_USERNAME}:${this.MONGO_INITDB_ROOT_PASSWORD}@${this.MONGODB_HOST}:${this.MONGODB_PORT}/${this.MONGODB_DB}?authSource=admin`; + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts new file mode 100644 index 0000000..bc47c9b --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -0,0 +1,11 @@ +export class DatabaseConfig { + public POSTGRES_HOST: string = process.env.POSTGRES_HOST || 'postgres'; + public POSTGRES_PORT: number = parseInt(process.env.POSTGRES_PORT || '5432'); + public POSTGRES_DATABASE: string = process.env.POSTGRES_DATABASE || 'knightcrawler'; + public POSTGRES_USER: string = process.env.POSTGRES_USER || 'postgres'; + public POSTGRES_PASSWORD: string = process.env.POSTGRES_PASSWORD || 'postgres'; + + public get POSTGRES_URI() { + return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DATABASE}`; + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/job_config.ts b/src/node/consumer/src/lib/models/configuration/job_config.ts new file mode 100644 index 0000000..9ebbf90 --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/job_config.ts @@ -0,0 +1,6 @@ +import {BooleanHelpers} from "../../helpers/boolean_helpers"; + +export class JobConfig { + public JOB_CONCURRENCY: number = parseInt(process.env.JOB_CONCURRENCY || "1", 10); + public JOBS_ENABLED: boolean = BooleanHelpers.parseBool(process.env.JOBS_ENABLED, true); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/metadata_config.ts b/src/node/consumer/src/lib/models/configuration/metadata_config.ts new file mode 100644 index 0000000..2debe48 --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/metadata_config.ts @@ -0,0 +1,4 @@ +export class MetadataConfig { + public IMDB_CONCURRENT: number = parseInt(process.env.IMDB_CONCURRENT || "1", 10); + public IMDB_INTERVAL_MS: number = parseInt(process.env.IMDB_INTERVAL_MS || "1000", 10); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/rabbit_config.ts b/src/node/consumer/src/lib/models/configuration/rabbit_config.ts new file mode 100644 index 0000000..d864f46 --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/rabbit_config.ts @@ -0,0 +1,4 @@ +export class RabbitConfig { + public RABBIT_URI: string = process.env.RABBIT_URI || 'amqp://localhost'; + public QUEUE_NAME: string = process.env.QUEUE_NAME || 'test-queue'; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/torrent_config.ts b/src/node/consumer/src/lib/models/configuration/torrent_config.ts new file mode 100644 index 0000000..5f0f6c7 --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/torrent_config.ts @@ -0,0 +1,4 @@ +export class TorrentConfig { + public MAX_CONNECTIONS_PER_TORRENT: number = parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10); + public TIMEOUT: number = parseInt(process.env.TORRENT_TIMEOUT || "30000", 10); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/tracker_config.ts b/src/node/consumer/src/lib/models/configuration/tracker_config.ts new file mode 100644 index 0000000..275dfa3 --- /dev/null +++ b/src/node/consumer/src/lib/models/configuration/tracker_config.ts @@ -0,0 +1,6 @@ +import {BooleanHelpers} from "../../helpers/boolean_helpers"; + +export class TrackerConfig { + public TRACKERS_URL: string = process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt'; + public UDP_ENABLED: boolean = BooleanHelpers.parseBool(process.env.UDP_TRACKERS_ENABLED, false); +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 5743d3c..88aad32 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,6 +1,6 @@ import {Cache, createCache, memoryStore} from 'cache-manager'; import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' -import { cacheConfig } from '../config'; +import { configurationService } from './configuration_service'; import { logger } from './logging_service'; import { CacheType } from "../enums/cache_types"; import {CacheOptions} from "../interfaces/cache_options"; @@ -19,7 +19,7 @@ type CacheMethod = () => any; class CacheService { constructor() { - if (!cacheConfig.NO_CACHE) { + if (!configurationService.cacheConfig.NO_CACHE) { logger.info('Cache is disabled'); return; } @@ -47,9 +47,9 @@ class CacheService { private initiateMongoCache = () => { const store = mongoDbStore({ - collectionName: cacheConfig.COLLECTION_NAME, + collectionName: configurationService.cacheConfig.COLLECTION_NAME, ttl: GLOBAL_TTL, - url: cacheConfig.MONGO_URI, + url: configurationService.cacheConfig.MONGO_URI, mongoConfig:{ socketTimeoutMS: 120000, appName: 'knightcrawler-consumer', @@ -62,12 +62,12 @@ class CacheService { } private initiateRemoteCache = (): Cache => { - if (cacheConfig.NO_CACHE) { + if (configurationService.cacheConfig.NO_CACHE) { logger.debug('Cache is disabled'); return null; } - return cacheConfig.MONGO_URI ? this.initiateMongoCache() : this.initiateMemoryCache(); + return configurationService.cacheConfig.MONGO_URI ? this.initiateMongoCache() : this.initiateMemoryCache(); } private getCacheType = (cacheType: CacheType): typeof this.memoryCache | null => { @@ -88,7 +88,7 @@ class CacheService { cacheType: CacheType, key: string, method: CacheMethod, options: CacheOptions): Promise => { const cache = this.getCacheType(cacheType); - if (cacheConfig.NO_CACHE || !cache) { + if (configurationService.cacheConfig.NO_CACHE || !cache) { return method(); } diff --git a/src/node/consumer/src/lib/services/configuration_service.ts b/src/node/consumer/src/lib/services/configuration_service.ts new file mode 100644 index 0000000..9bef6d3 --- /dev/null +++ b/src/node/consumer/src/lib/services/configuration_service.ts @@ -0,0 +1,19 @@ +import {RabbitConfig} from "../models/configuration/rabbit_config"; +import {CacheConfig} from "../models/configuration/cache_config"; +import {DatabaseConfig} from "../models/configuration/database_config"; +import {JobConfig} from "../models/configuration/job_config"; +import {MetadataConfig} from "../models/configuration/metadata_config"; +import {TrackerConfig} from "../models/configuration/tracker_config"; +import {TorrentConfig} from "../models/configuration/torrent_config"; + +class ConfigurationService { + public readonly rabbitConfig = new RabbitConfig(); + public readonly cacheConfig = new CacheConfig(); + public readonly databaseConfig = new DatabaseConfig(); + public readonly jobConfig = new JobConfig(); + public readonly metadataConfig = new MetadataConfig(); + public readonly trackerConfig = new TrackerConfig(); + public readonly torrentConfig = new TorrentConfig(); +} + +export const configurationService = new ConfigurationService(); diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 2cffccd..3af4a26 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,13 +1,13 @@ import { encode } from 'magnet-uri'; import torrentStream from 'torrent-stream'; -import { torrentConfig } from '../config'; +import { configurationService } from './configuration_service'; import {extensionService} from './extension_service'; import {TorrentInfo} from "../interfaces/torrent_info"; import {DownloadedTorrentFile} from "../interfaces/downloaded_torrent_file"; class TorrentDownloadService { private engineOptions: TorrentStream.TorrentEngineOptions = { - connections: torrentConfig.MAX_CONNECTIONS_PER_TORRENT, + connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, uploads: 0, verify: false, dht: false, diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index 15438a5..d17c7bb 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios'; import { cacheService } from "./cache_service"; -import { trackerConfig } from '../config'; +import { configurationService } from './configuration_service'; import { logger } from "./logging_service"; class TrackerService { @@ -9,14 +9,14 @@ class TrackerService { }; private async downloadTrackers(): Promise { - const response: AxiosResponse = await axios.get(trackerConfig.TRACKERS_URL); + const response: AxiosResponse = await axios.get(configurationService.trackerConfig.TRACKERS_URL); const trackersListText: string = response.data; // Trackers are separated by a newline character let urlTrackers = trackersListText.split("\n"); // remove blank lines urlTrackers = urlTrackers.filter(line => line.trim() !== ''); - if (!trackerConfig.UDP_ENABLED) { + if (!configurationService.trackerConfig.UDP_ENABLED) { // remove any udp trackers urlTrackers = urlTrackers.filter(line => !line.startsWith('udp://')); diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index d4aeef2..0212c1a 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,7 +1,7 @@ import { parse } from 'parse-torrent-title'; import { metadataService } from './services/metadata_service'; import { parsingService } from './services/parsing_service'; -import {PromiseHelpers} from './helpers/promises_helpers.js'; +import {PromiseHelpers} from './helpers/promises_helpers'; import { repository } from '../repository/database_repository'; import { parseTorrentFiles } from './torrentFiles.js'; import { assignSubtitles } from './torrentSubtitles.js'; diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js index 417f783..c2fda7c 100644 --- a/src/node/consumer/src/lib/torrentFiles.js +++ b/src/node/consumer/src/lib/torrentFiles.js @@ -2,17 +2,17 @@ import Bottleneck from 'bottleneck'; import distance from 'jaro-winkler'; import moment from 'moment'; import { parse } from 'parse-torrent-title'; -import { metadataConfig } from './config'; +import { configurationService } from './services/configuration_service'; import { extensionService } from './services/extension_service'; import { metadataService } from './services/metadata_service'; import { parsingService } from './services/parsing_service'; -import {PromiseHelpers} from './helpers/promises_helpers.js'; +import {PromiseHelpers} from './helpers/promises_helpers'; import {torrentDownloadService} from "./services/torrent_download_service"; import { TorrentType } from './enums/torrent_types'; import {logger} from "./services/logging_service"; const MIN_SIZE = 5 * 1024 * 1024; // 5 MB -const imdb_limiter = new Bottleneck({ maxConcurrent: metadataConfig.IMDB_CONCURRENT, minTime: metadataConfig.IMDB_INTERVAL_MS }); +const imdb_limiter = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); export async function parseTorrentFiles(torrent) { const parsedTorrentName = parse(torrent.title); diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index c1772a2..d6e4455 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -1,7 +1,7 @@ import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; import {Model, Sequelize} from 'sequelize-typescript'; -import {databaseConfig} from '../lib/config'; +import {configurationService} from '../lib/services/configuration_service'; import {PromiseHelpers} from '../lib/helpers/promises_helpers'; import {Provider} from "./models/provider"; import {File} from "./models/file"; @@ -244,7 +244,7 @@ class DatabaseRepository { private createDatabase(): Sequelize { const newDatabase = new Sequelize( - databaseConfig.POSTGRES_URI, + configurationService.databaseConfig.POSTGRES_URI, { logging: false } From aeebe88aca0a3d43ef1fd802e9c0c30780ffe1f8 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 13:09:36 +0000 Subject: [PATCH 11/55] postgres db --- .../consumer/src/lib/models/configuration/database_config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts index bc47c9b..fc5e8d3 100644 --- a/src/node/consumer/src/lib/models/configuration/database_config.ts +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -1,11 +1,11 @@ export class DatabaseConfig { public POSTGRES_HOST: string = process.env.POSTGRES_HOST || 'postgres'; public POSTGRES_PORT: number = parseInt(process.env.POSTGRES_PORT || '5432'); - public POSTGRES_DATABASE: string = process.env.POSTGRES_DATABASE || 'knightcrawler'; + public POSTGRES_DB: string = process.env.POSTGRES_DB || 'knightcrawler'; public POSTGRES_USER: string = process.env.POSTGRES_USER || 'postgres'; public POSTGRES_PASSWORD: string = process.env.POSTGRES_PASSWORD || 'postgres'; public get POSTGRES_URI() { - return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DATABASE}`; + return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DB}`; } } \ No newline at end of file From 3f8fee518e660805a1ad5a50a403c225a5b5ab02 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 15:09:31 +0000 Subject: [PATCH 12/55] torrent file service done - bound to be some issues in this.. --- src/node/consumer/package-lock.json | 7 + src/node/consumer/package.json | 1 + .../src/lib/interfaces/cinemeta_metadata.ts | 2 - .../lib/interfaces/common_video_metadata.ts | 6 +- .../lib/interfaces/downloaded_torrent_file.ts | 3 - .../src/lib/interfaces/kitsu_metadata.ts | 3 - .../src/lib/interfaces/metadata_query.ts | 1 + .../src/lib/interfaces/metadata_response.ts | 4 +- .../src/lib/interfaces/parsable_torrent.ts | 9 - .../lib/interfaces/parsable_torrent_file.ts | 12 + .../lib/interfaces/parsable_torrent_video.ts | 6 - .../interfaces/parse_torrent_title_result.ts | 2 +- .../lib/interfaces/torrent_file_collection.ts | 7 + .../src/lib/interfaces/torrent_info.ts | 12 +- .../src/lib/services/metadata_service.ts | 8 +- .../src/lib/services/parsing_service.ts | 10 +- .../lib/services/torrent_download_service.ts | 32 +- .../src/lib/services/torrent_file_service.ts | 589 ++++++++++++++++++ .../lib/services/torrent_subtitle_service.ts | 88 +++ src/node/consumer/src/lib/torrentEntries.js | 12 +- src/node/consumer/src/lib/torrentFiles.js | 526 ---------------- src/node/consumer/src/lib/torrentSubtitles.js | 89 --- 22 files changed, 756 insertions(+), 673 deletions(-) delete mode 100644 src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts delete mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent.ts create mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts delete mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_file_collection.ts create mode 100644 src/node/consumer/src/lib/services/torrent_file_service.ts create mode 100644 src/node/consumer/src/lib/services/torrent_subtitle_service.ts delete mode 100644 src/node/consumer/src/lib/torrentFiles.js delete mode 100644 src/node/consumer/src/lib/torrentSubtitles.js diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 2898608..3a41714 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", + "@types/jaro-winkler": "^0.2.3", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", @@ -583,6 +584,12 @@ "@types/ms": "*" } }, + "node_modules/@types/jaro-winkler": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@types/jaro-winkler/-/jaro-winkler-0.2.3.tgz", + "integrity": "sha512-W5qVYCDkBMP7hMM9szj4JvA52CYEyEqL/CKUy7EIulJmlzfqJy5cW0hkzOgJ50Yz8Egfo7MoLF+LUWHUxRZVrg==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "dev": true, diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index f306029..78c9826 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -32,6 +32,7 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", + "@types/jaro-winkler": "^0.2.3", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts index 48cdc8a..fc32250 100644 --- a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -61,8 +61,6 @@ export interface CinemetaVideo extends CommonVideoMetadata { rating?: string; overview?: string; thumbnail?: string; - id?: string; - released?: string; description?: string; } export interface CinemetaTrailerStream { diff --git a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts index 4383417..16df177 100644 --- a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts @@ -1,4 +1,8 @@ export interface CommonVideoMetadata { season?: number; - episode?: number; + episode?: number; + released?: string; + title?: string; + name?: string; + id?: string; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts b/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts deleted file mode 100644 index 4a0a5a5..0000000 --- a/src/node/consumer/src/lib/interfaces/downloaded_torrent_file.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface DownloadedTorrentFile extends TorrentStream.TorrentFile { - fileIndex: number; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts index fc63293..e789340 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -30,13 +30,10 @@ export interface KitsuMeta { year?: string; } export interface KitsuVideo extends CommonVideoMetadata { - id?: string; imdbEpisode?: number; imdbSeason?: number; imdb_id?: string; - released?: string; thumbnail?: string; - title?: string; } export interface KitsuTrailer { source?: string; diff --git a/src/node/consumer/src/lib/interfaces/metadata_query.ts b/src/node/consumer/src/lib/interfaces/metadata_query.ts index ecb85ea..2ae9c4e 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_query.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_query.ts @@ -5,4 +5,5 @@ export interface MetaDataQuery { date?: string season?: number episode?: number + id?: string | number } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_response.ts b/src/node/consumer/src/lib/interfaces/metadata_response.ts index e1509c5..ce9670e 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_response.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_response.ts @@ -1,3 +1,5 @@ +import {CommonVideoMetadata} from "./common_video_metadata"; + export interface MetadataResponse { kitsuId?: number; imdbId?: number; @@ -7,7 +9,7 @@ export interface MetadataResponse { country?: string; genres?: string[]; status?: string; - videos?: any[]; + videos?: CommonVideoMetadata[]; episodeCount?: number[]; totalCount?: number; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent.ts deleted file mode 100644 index 20683c2..0000000 --- a/src/node/consumer/src/lib/interfaces/parsable_torrent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {TorrentType} from "../enums/torrent_types"; - -export interface ParsableTorrent { - title: string; - type: TorrentType; - size: number; - pack?: boolean; -} - diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts new file mode 100644 index 0000000..394570f --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts @@ -0,0 +1,12 @@ +import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; + +export interface ParsableTorrentFile extends ParseTorrentTitleResult { + name?: string; + path?: string; + size?: number; + length?: number; + fileIndex?: number; + isMovie?: boolean; + imdbId?: string | number; + kitsuId?: number | string; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts deleted file mode 100644 index d57b7e7..0000000 --- a/src/node/consumer/src/lib/interfaces/parsable_torrent_video.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; - -export interface ParsableTorrentVideo extends ParseTorrentTitleResult { - name: string; - path: string; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts index ea85e8e..0cc445b 100644 --- a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts +++ b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts @@ -1,5 +1,5 @@ export interface ParseTorrentTitleResult { - title: string; + title?: string; date?: string; year?: number | string; resolution?: string; diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts new file mode 100644 index 0000000..500c5b0 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts @@ -0,0 +1,7 @@ +import {ParsableTorrentFile} from "./parsable_torrent_file"; + +export interface TorrentFileCollection { + contents?: ParsableTorrentFile[]; + videos?: ParsableTorrentFile[]; + subtitles?: ParsableTorrentFile[]; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_info.ts b/src/node/consumer/src/lib/interfaces/torrent_info.ts index 31895bd..93f7082 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_info.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_info.ts @@ -1,12 +1,16 @@ +import {TorrentType} from "../enums/torrent_types"; + export interface TorrentInfo { title: string | null; torrentId: string; infoHash: string | null; seeders: number; - size: string | null; uploadDate: Date; - imdbId: string | undefined; - type: string; - provider: string | null; + imdbId?: string; + kitsuId?: string; + type: TorrentType; + provider?: string | null; trackers: string; + size?: number; + pack?: boolean; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 5667bb8..e564de2 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -53,13 +53,13 @@ class MetadataService { } } - public getMetadata(id: string | number, type: TorrentType = TorrentType.SERIES): Promise { - if (!id) { + public getMetadata(query: MetaDataQuery): Promise { + if (!query.id) { return Promise.reject("no valid id provided"); } - const key = Number.isInteger(id) || id.toString().match(/^\d+$/) ? `kitsu:${id}` : id; - const metaType = type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; + const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; + const metaType = query.type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; return cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) .catch(() => this.requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) .catch(() => { diff --git a/src/node/consumer/src/lib/services/parsing_service.ts b/src/node/consumer/src/lib/services/parsing_service.ts index 28ea866..dc0b2a6 100644 --- a/src/node/consumer/src/lib/services/parsing_service.ts +++ b/src/node/consumer/src/lib/services/parsing_service.ts @@ -1,20 +1,20 @@ import { parse } from 'parse-torrent-title'; import { TorrentType } from '../enums/torrent_types'; import {ParseTorrentTitleResult} from "../interfaces/parse_torrent_title_result"; -import {ParsableTorrentVideo} from "../interfaces/parsable_torrent_video"; -import {ParsableTorrent} from "../interfaces/parsable_torrent"; +import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; +import {TorrentInfo} from "../interfaces/torrent_info"; class ParsingService { private readonly MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB - public parseSeriesVideos(torrent: ParsableTorrent, videos: ParsableTorrentVideo[]): ParseTorrentTitleResult[] { + public parseSeriesVideos(torrent: TorrentInfo, videos: ParsableTorrentFile[]): ParsableTorrentFile[] { const parsedTorrentName = parse(torrent.title); const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); const parsedVideos = videos.map(video => this.parseSeriesVideo(video, parsedTorrentName)); return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); } - public isPackTorrent(torrent: ParsableTorrent): boolean { + public isPackTorrent(torrent: TorrentInfo): boolean { if (torrent.pack) { return true; } @@ -31,7 +31,7 @@ class ParsingService { return hasMultipleEpisodes && !hasSingleEpisode; } - private parseSeriesVideo(video: ParsableTorrentVideo, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { + private parseSeriesVideo(video: ParsableTorrentFile, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { const videoInfo = parse(video.name); // the episode may be in a folder containing season number if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 3af4a26..58a7241 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -3,7 +3,8 @@ import torrentStream from 'torrent-stream'; import { configurationService } from './configuration_service'; import {extensionService} from './extension_service'; import {TorrentInfo} from "../interfaces/torrent_info"; -import {DownloadedTorrentFile} from "../interfaces/downloaded_torrent_file"; +import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; class TorrentDownloadService { private engineOptions: TorrentStream.TorrentEngineOptions = { @@ -14,16 +15,16 @@ class TorrentDownloadService { tracker: true, }; - public async getTorrentFiles(torrent: TorrentInfo, timeout: number = 30000): Promise<{ contents: Array; videos: Array; subtitles: Array }> { + public async getTorrentFiles(torrent: TorrentInfo, timeout: number = 30000): Promise { return this.filesFromTorrentStream(torrent, timeout) - .then((files: Array) => ({ + .then((files: Array) => ({ contents: files, videos: this.filterVideos(files), subtitles: this.filterSubtitles(files) })); } - private async filesFromTorrentStream(torrent: TorrentInfo, timeout: number): Promise> { + private async filesFromTorrentStream(torrent: TorrentInfo, timeout: number): Promise> { if (!torrent.infoHash) { return Promise.reject(new Error("No infoHash...")); } @@ -40,7 +41,12 @@ class TorrentDownloadService { engine = torrentStream(magnet, this.engineOptions); engine.on("ready", () => { - const files: DownloadedTorrentFile[] = engine.files.map((file, fileId) => ({ ...file, fileIndex: fileId })); + const files: ParsableTorrentFile[] = engine.files.map((file, fileId) => ({ + ...file, + fileIndex: fileId, + size: file.length, + title: file.name})); + resolve(files); engine.destroy(() => {}); @@ -49,21 +55,21 @@ class TorrentDownloadService { }); } - private filterVideos(files: Array): Array { + private filterVideos(files: Array): Array { if (files.length === 1 && !Number.isInteger(files[0].fileIndex)) { return files; } const videos = files.filter(file => extensionService.isVideo(file.path || '')); - const maxSize = Math.max(...videos.map((video: DownloadedTorrentFile) => video.length)); + const maxSize = Math.max(...videos.map((video: ParsableTorrentFile) => video.length)); const minSampleRatio = videos.length <= 3 ? 3 : 10; const minAnimeExtraRatio = 5; const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = (video: DownloadedTorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.length.toString()) > minSampleRatio; - const isRedundant = (video: DownloadedTorrentFile) => maxSize / parseInt(video.length.toString()) > minRedundantRatio; - const isExtra = (video: DownloadedTorrentFile) => video.path?.match(/extras?\//i); - const isAnimeExtra = (video: DownloadedTorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + const isSample = (video: ParsableTorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.length.toString()) > minSampleRatio; + const isRedundant = (video: ParsableTorrentFile) => maxSize / parseInt(video.length.toString()) > minRedundantRatio; + const isExtra = (video: ParsableTorrentFile) => video.path?.match(/extras?\//i); + const isAnimeExtra = (video: ParsableTorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; - const isWatermark = (video: DownloadedTorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + const isWatermark = (video: ParsableTorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio return videos .filter(video => !isSample(video)) @@ -73,7 +79,7 @@ class TorrentDownloadService { .filter(video => !isWatermark(video)); } - private filterSubtitles(files: Array): Array { + private filterSubtitles(files: Array): Array { return files.filter(file => extensionService.isSubtitle(file.path || '')); } } diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts new file mode 100644 index 0000000..6744d99 --- /dev/null +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -0,0 +1,589 @@ +import Bottleneck from 'bottleneck'; +import moment from 'moment'; +import { parse } from 'parse-torrent-title'; +import {PromiseHelpers} from '../helpers/promises_helpers'; +import { TorrentType } from '../enums/torrent_types'; +import {TorrentInfo} from "../interfaces/torrent_info"; +import { configurationService } from './configuration_service'; +import { extensionService } from './extension_service'; +import { metadataService } from './metadata_service'; +import { parsingService } from './parsing_service'; +import { torrentDownloadService } from "./torrent_download_service"; +import {logger} from "./logging_service"; +import {MetadataResponse} from "../interfaces/metadata_response"; +import {ParseTorrentTitleResult} from "../interfaces/parse_torrent_title_result"; +import {MetaDataQuery} from "../interfaces/metadata_query"; +import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; +import {CommonVideoMetadata} from "../interfaces/common_video_metadata"; +import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; + +class TorrentFileService { + private readonly MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB + private readonly imdb_limiter: Bottleneck = new Bottleneck({ + maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, + minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS + }); + + public async parseTorrentFiles(torrent: TorrentInfo) { + const parsedTorrentName = parse(torrent.title); + const query: MetaDataQuery = { + id: torrent.kitsuId || torrent.imdbId, + type: torrent.type || TorrentType.MOVIE, + }; + const metadata = await metadataService.getMetadata(query) + .then(meta => Object.assign({}, meta)) + .catch(() => undefined); + + if (torrent.type !== TorrentType.ANIME && metadata && metadata.type && metadata.type !== torrent.type) { + // it's actually a movie/series + torrent.type = metadata.type; + } + + if (torrent.type === TorrentType.MOVIE && (!parsedTorrentName.seasons || + parsedTorrentName.season === 5 && [1, 5].includes(parsedTorrentName.episode))) { + return this.parseMovieFiles(torrent, metadata); + } + + return this.parseSeriesFiles(torrent, metadata) + } + + private async parseMovieFiles(torrent: TorrentInfo, metadata: MetadataResponse): Promise { + const {contents, videos, subtitles} = await this.getMoviesTorrentContent(torrent); + const filteredVideos = videos + .filter(video => video.size > this.MIN_SIZE) + .filter(video => !this.isFeaturette(video)); + if (this.isSingleMovie(filteredVideos)) { + const parsedVideos = filteredVideos.map(video => ({ + infoHash: torrent.infoHash, + fileIndex: video.fileIndex, + title: video.path || torrent.title, + size: video.size || torrent.size, + imdbId: torrent.imdbId || metadata && metadata.imdbId, + kitsuId: torrent.kitsuId || metadata && metadata.kitsuId + })); + return {contents, videos: parsedVideos, subtitles}; + } + + const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => this.isFeaturette(video) + ? Promise.resolve(video) + : this.findMovieImdbId(video.name).then(imdbId => ({...video, imdbId})))) + .then(videos => videos.map(video => ({ + infoHash: torrent.infoHash, + fileIndex: video.fileIndex, + title: video.path || video.name, + size: video.size, + imdbId: video.imdbId, + }))); + return {contents, videos: parsedVideos, subtitles}; + } + + private async parseSeriesFiles(torrent: TorrentInfo, metadata: MetadataResponse) { + const {contents, videos, subtitles} = await this.getSeriesTorrentContent(torrent); + const parsedVideos = await Promise.resolve(videos) + .then(videos => videos.filter(video => videos.length === 1 || video.size > this.MIN_SIZE)) + .then(videos => parsingService.parseSeriesVideos(torrent, videos)) + .then(videos => this.decomposeEpisodes(torrent, videos, metadata)) + .then(videos => this.assignKitsuOrImdbEpisodes(torrent, videos, metadata)) + .then(videos => Promise.all(videos.map(video => video.isMovie + ? this.mapSeriesMovie(video, torrent) + : this.mapSeriesEpisode(video, torrent, videos)))) + .then(videos => videos + .map((video: ParsableTorrentFile) => this.isFeaturette(video) ? this.clearInfoFields(video) : video)) + return {contents, videos: parsedVideos, subtitles}; + } + + private async getMoviesTorrentContent(torrent: TorrentInfo) { + const files = await torrentDownloadService.getTorrentFiles(torrent) + .catch(error => { + if (!parsingService.isPackTorrent(torrent)) { + return { videos: [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}], contents:[], subtitles: []} + } + return Promise.reject(error); + }); + + if (files.contents && files.contents.length && !files.videos.length && this.isDiskTorrent(files.contents)) { + files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size}]; + } + return files; + } + + private async getSeriesTorrentContent(torrent: TorrentInfo) { + return torrentDownloadService.getTorrentFiles(torrent) + .catch(error => { + if (!parsingService.isPackTorrent(torrent)) { + return { videos: [{ name: torrent.title, path: torrent.title, size: torrent.size }], subtitles: [], contents: [] } + } + return Promise.reject(error); + }); + } + + private async mapSeriesEpisode(file: ParsableTorrentFile, torrent: TorrentInfo, files: ParsableTorrentFile[]) : Promise { + if (!file.episodes && !file.episodes) { + if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { + return Promise.resolve({ + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + title: file.path || file.name, + size: file.size, + imdbId: torrent.imdbId || file.imdbId, + }); + } + return Promise.resolve([]); + } + const episodeIndexes = [...(file.episodes || file.episodes).keys()]; + return Promise.resolve(episodeIndexes.map((index) => ({ + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + title: file.path || file.name, + size: file.size, + imdbId: file.imdbId || torrent.imdbId, + season: file.season, + episode: file.episodes && file.episodes[index], + episodes: file.episodes, + kitsuId: file.kitsuId || torrent.kitsuId, + }))) + } + + private async mapSeriesMovie(file: ParsableTorrentFile, torrent: TorrentInfo): Promise { + const kitsuId= torrent.type === TorrentType.ANIME ? await this.findMovieKitsuId(file) + .then(result => { + if (result instanceof Error) { + logger.warn(`Failed to retrieve kitsuId due to error: ${result.message}`); + return undefined; + } + return result; + }): undefined; + + const imdbId = !kitsuId ? await this.findMovieImdbId(file) : undefined; + + const query: MetaDataQuery = { + id: kitsuId || imdbId, + type: TorrentType.MOVIE + }; + + const metadataOrError = await metadataService.getMetadata(query); + if (metadataOrError instanceof Error) { + logger.warn(`Failed to retrieve metadata due to error: ${metadataOrError.message}`); + // return default result or throw error, depending on your use case + return [{ + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + title: file.path || file.name, + size: file.size, + imdbId: imdbId, + kitsuId: kitsuId, + episodes: undefined, + imdbSeason: undefined, + imdbEpisode: undefined, + kitsuEpisode: undefined + }]; + } + // at this point, TypeScript infers that metadataOrError is actually MetadataResponse + const metadata = metadataOrError; + const hasEpisode = metadata.videos && metadata.videos.length && (file.episode || metadata.videos.length === 1); + const episodeVideo = hasEpisode && metadata.videos[(file.episode || 1) - 1]; + return [{ + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + title: file.path || file.name, + size: file.size, + imdbId: metadata.imdbId || imdbId, + kitsuId: metadata.kitsuId || kitsuId, + season: episodeVideo && metadata.imdbId ? episodeVideo.season : undefined, + episode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, + }]; + } + + private async decomposeEpisodes(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse = { episodeCount: [] }) { + if (files.every(file => !file.episodes && !file.date)) { + return files; + } + + this.preprocessEpisodes(files); + + if (torrent.type === TorrentType.ANIME && torrent.kitsuId) { + if (this.needsCinemetaMetadataForAnime(files, metadata)) { + // In some cases anime could be resolved to wrong kitsuId + // because of imdb season naming/absolute per series naming/multiple seasons + // So in these cases we need to fetch cinemeta based metadata and decompose episodes using that + await this.updateToCinemetaMetadata(metadata); + if (files.some(file => Number.isInteger(file.season))) { + // sometimes multi season anime torrents don't include season 1 naming + files + .filter(file => !Number.isInteger(file.season) && file.episodes) + .forEach(file => file.season = 1); + } + } else { + // otherwise for anime type episodes are always absolute and for a single season + files + .filter(file => file.episodes && file.season !== 0) + .forEach(file => file.season = 1); + return files; + } + } + + const sortedEpisodes = files + .map(file => !file.isMovie && file.episodes || []) + .reduce((a, b) => a.concat(b), []) + .sort((a, b) => a - b); + + if (this.isConcatSeasonAndEpisodeFiles(files, sortedEpisodes, metadata)) { + this.decomposeConcatSeasonAndEpisodeFiles(files, metadata); + } else if (this.isDateEpisodeFiles(files, metadata)) { + this.decomposeDateEpisodeFiles(files, metadata); + } else if (this.isAbsoluteEpisodeFiles(torrent, files, metadata)) { + this.decomposeAbsoluteEpisodeFiles(torrent, files, metadata); + } + // decomposeEpisodeTitleFiles(torrent, files, metadata); + + return files; + } + + private preprocessEpisodes(files: ParsableTorrentFile[]) { + // reverse special episode naming when they named with 0 episode, ie. S02E00 + files + .filter(file => Number.isInteger(file.season) && file.episode === 0) + .forEach(file => { + file.episode = file.season + file.episodes = [file.season] + file.season = 0; + }) + } + + private isConcatSeasonAndEpisodeFiles(files: ParsableTorrentFile[], sortedEpisodes: number[], metadata: MetadataResponse) { + if (metadata.kitsuId !== undefined) { + // anime does not use this naming scheme in 99% of cases; + return false; + } + // decompose concat season and episode files (ex. 101=S01E01) in case: + // 1. file has a season, but individual files are concatenated with that season (ex. path Season 5/511 - Prize + // Fighters.avi) + // 2. file does not have a season and the episode does not go out of range for the concat season + // episode count + const thresholdAbove = Math.max(Math.ceil(files.length * 0.05), 5); + const thresholdSorted = Math.max(Math.ceil(files.length * 0.8), 8); + const threshold = Math.max(Math.ceil(files.length * 0.8), 5); + const sortedConcatEpisodes = sortedEpisodes + .filter(ep => ep > 100) + .filter(ep => metadata.episodeCount[this.div100(ep) - 1] < ep) + .filter(ep => metadata.episodeCount[this.div100(ep) - 1] >= this.mod100(ep)); + const concatFileEpisodes = files + .filter(file => !file.isMovie && file.episodes) + .filter(file => !file.season || file.episodes.every(ep => this.div100(ep) === file.season)); + const concatAboveTotalEpisodeCount = files + .filter(file => !file.isMovie && file.episodes && file.episodes.every(ep => ep > 100)) + .filter(file => file.episodes.every(ep => ep > metadata.totalCount)); + return sortedConcatEpisodes.length >= thresholdSorted && concatFileEpisodes.length >= threshold + || concatAboveTotalEpisodeCount.length >= thresholdAbove; + } + + private isDateEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + return files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); + } + + private isAbsoluteEpisodeFiles(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + const threshold = Math.ceil(files.length / 5); + const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; + const nonMovieEpisodes = files + .filter(file => !file.isMovie && file.episodes); + const absoluteEpisodes = files + .filter(file => file.season && file.episodes) + .filter(file => file.episodes.every(ep => metadata.episodeCount[file.season - 1] < ep)) + return nonMovieEpisodes.every(file => !file.season) + || (isAnime && nonMovieEpisodes.every(file => file.season > metadata.episodeCount.length)) + || absoluteEpisodes.length >= threshold; + } + + private isNewEpisodeNotInMetadata(torrent: TorrentInfo, file: ParsableTorrentFile, metadata: MetadataResponse) { + // new episode might not yet been indexed by cinemeta. + // detect this if episode number is larger than the last episode or season is larger than the last one + // only for non anime metas + const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; + return !isAnime && !file.isMovie && file.episodes && file.season !== 1 + && /continuing|current/i.test(metadata.status) + && file.season >= metadata.episodeCount.length + && file.episodes.every(ep => ep > (metadata.episodeCount[file.season - 1] || 0)); + } + + private decomposeConcatSeasonAndEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + files + .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) + .filter(file => metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) + .filter(file => file.season && file.episodes.every(ep => this.div100(ep) === file.season) || !file.season) + .forEach(file => { + file.season = this.div100(file.episodes[0]); + file.episodes = file.episodes.map(ep => this.mod100(ep)) + }); + + } + + private decomposeAbsoluteEpisodeFiles(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + if (metadata.episodeCount.length === 0) { + files + .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) + .forEach(file => { + file.season = 1; + }); + return; + } + files + .filter(file => file.episodes && !file.isMovie && file.season !== 0) + .filter(file => !this.isNewEpisodeNotInMetadata(torrent, file, metadata)) + .filter(file => !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]) + .forEach(file => { + const seasonIdx = ([...metadata.episodeCount.keys()] + .find((i) => metadata.episodeCount.slice(0, i + 1).reduce((a, b) => a + b) >= file.episodes[0]) + + 1 || metadata.episodeCount.length) - 1; + + file.season = seasonIdx + 1; + file.episodes = file.episodes + .map(ep => ep - metadata.episodeCount.slice(0, seasonIdx).reduce((a, b) => a + b, 0)) + }); + } + + private decomposeDateEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + if (!metadata || !metadata.videos || !metadata.videos.length) { + return; + } + + const timeZoneOffset = this.getTimeZoneOffset(metadata.country); + const offsetVideos = metadata.videos + .reduce((map, video) => { + const releaseDate = moment(video.released).utcOffset(timeZoneOffset).format('YYYY-MM-DD'); + map[releaseDate] = video; + return map; + }, {}); + + files + .filter(file => file.date) + .forEach(file => { + const video = offsetVideos[file.date]; + if (video) { + file.season = video.season; + file.episodes = [video.episode]; + } + }); + } + + private getTimeZoneOffset(country: string | undefined) { + switch (country) { + case 'United States': + case 'USA': + return '-08:00'; + default: + return '00:00'; + } + } + + private assignKitsuOrImdbEpisodes(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + if (!metadata || !metadata.videos || !metadata.videos.length) { + if (torrent.type === TorrentType.ANIME) { + // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping + files + .filter(file => file.season && file.episodes) + .forEach(file => { + file.season = undefined; + file.episodes = undefined; + }) + if (metadata.type === TorrentType.MOVIE && files.every(file => !file.imdbId)) { + // sometimes a movie has episode naming, thus not recognized as a movie and imdbId not assigned + files.forEach(file => file.imdbId = metadata.imdbId); + } + } + return files; + } + + const seriesMapping: CommonVideoMetadata = metadata.videos + .reduce((map, video) => { + const episodeMap = map[video.season] || {}; + episodeMap[video.episode] = video; + map[video.season] = episodeMap; + return map; + }, {}); + + if (metadata.videos.some(video => Number.isInteger(video.season)) || !metadata.imdbId) { + files.filter((file => Number.isInteger(file.season) && file.episodes)) + .map(file => { + const seasonMapping = seriesMapping[file.season]; + const episodeMapping = seasonMapping && seasonMapping[file.episodes[0]]; + if (episodeMapping && Number.isInteger(episodeMapping.imdbSeason)) { + file.imdbId = metadata.imdbId; + file.season = episodeMapping.imdbSeason; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].imdbEpisode); + } else { + // no imdb mapping available for episode + file.season = undefined; + file.episodes = undefined; + } + }); + } else if (metadata.videos.some(video => video.episode)) { + // imdb episode info is base + files + .filter(file => Number.isInteger(file.season) && file.episodes) + .forEach(file => { + if (seriesMapping[file.season]) { + const seasonMapping = seriesMapping[file.season]; + file.imdbId = metadata.imdbId; + file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + } else if (seriesMapping[file.season - 1]) { + // sometimes a second season might be a continuation of the previous season + const seasonMapping = seriesMapping[file.season - 1] as CommonVideoMetadata; + const episodes = Object.values(seasonMapping); + const firstKitsuId = episodes.length && episodes[0]; + const differentTitlesCount = new Set(episodes.map(ep => ep.id)).size + const skippedCount = episodes.filter(ep => ep.id === firstKitsuId).length; + const seasonEpisodes = files + .filter(otherFile => otherFile.season === file.season) + .reduce((a, b) => a.episodes.concat(b.episodes), []); + const isAbsoluteOrder = seasonEpisodes.episodes.every(ep => ep > skippedCount && ep <= episodes.length) + const isNormalOrder = seasonEpisodes.episodes.every(ep => ep + skippedCount <= episodes.length) + if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { + file.imdbId = metadata.imdbId; + file.season = file.season - 1; + file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); + file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + } + } else if (Object.values(seriesMapping).length === 1 && seriesMapping[1]) { + // sometimes series might be named with sequel season but it's not a season on imdb and a new title + const seasonMapping = seriesMapping[1]; + file.imdbId = metadata.imdbId; + file.season = 1; + file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + } + }); + } + return files; + } + + private needsCinemetaMetadataForAnime(files: ParsableTorrentFile[], metadata: MetadataResponse) { + if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { + return false; + } + + const minSeason = Math.min(...metadata.videos.map(video => video.season)) || Number.MAX_VALUE; + const maxSeason = Math.max(...metadata.videos.map(video => video.season)) || Number.MAX_VALUE; + const differentSeasons = new Set(metadata.videos + .map(video => video.season) + .filter(season => Number.isInteger(season))).size; + const total = metadata.totalCount || Number.MAX_VALUE; + return differentSeasons > 1 || files + .filter(file => !file.isMovie && file.episodes) + .some(file => file.season < minSeason || file.season > maxSeason || file.episodes.every(ep => ep > total)); + } + + private async updateToCinemetaMetadata(metadata: MetadataResponse) { + const query: MetaDataQuery = { + id: metadata.imdbId, + type: metadata.type + }; + + return await metadataService.getMetadata(query) + .then((newMetadataOrError) => { + if (newMetadataOrError instanceof Error) { + // handle error + logger.warn(`Failed ${metadata.imdbId} metadata cinemeta update due: ${newMetadataOrError.message}`); + return metadata; // or throw newMetadataOrError to propagate error up the call stack + } + // At this point TypeScript infers newMetadataOrError to be of type MetadataResponse + let newMetadata = newMetadataOrError; + if (!newMetadata.videos || !newMetadata.videos.length) { + return metadata; + } else { + metadata.videos = newMetadata.videos; + metadata.episodeCount = newMetadata.episodeCount; + metadata.totalCount = newMetadata.totalCount; + return metadata; + } + }) + } + + private findMovieImdbId(title: ParseTorrentTitleResult | string) { + const parsedTitle = typeof title === 'string' ? parse(title) : title; + logger.debug(`Finding movie imdbId for ${title}`); + return this.imdb_limiter.schedule(async () => { + const imdbQuery = { + title: parsedTitle.title, + year: parsedTitle.year, + type: TorrentType.MOVIE + }; + try { + return await metadataService.getImdbId(imdbQuery); + } catch (e) { + return undefined; + } + }); + } + + private async findMovieKitsuId(title: ParseTorrentTitleResult | string) { + const parsedTitle = typeof title === 'string' ? parse(title) : title; + const kitsuQuery = { + title: parsedTitle.title, + year: parsedTitle.year, + season: parsedTitle.season, + type: TorrentType.MOVIE + }; + try { + return await metadataService.getKitsuId(kitsuQuery); + } catch (e) { + return undefined; + } + } + + private isDiskTorrent(contents: ParsableTorrentFile[]) { + return contents.some(content => extensionService.isDisk(content.path)); + } + + private isSingleMovie(videos: ParsableTorrentFile[]) { + return videos.length === 1 || + (videos.length === 2 && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); + } + + private isFeaturette(video: ParsableTorrentFile) { + return /featurettes?\/|extras-grym/i.test(video.path); + } + + private clearInfoFields(video: ParsableTorrentFile) { + video.imdbId = undefined; + video.season = undefined; + video.episode = undefined; + video.kitsuId = undefined; + return video; + } + + private div100(episode: number) { + return (episode / 100 >> 0); // floor to nearest int + } + + private mod100(episode: number) { + return episode % 100; + } +} + +export const torrentFileService = new TorrentFileService(); + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts new file mode 100644 index 0000000..9cbe739 --- /dev/null +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -0,0 +1,88 @@ +import { parse } from 'parse-torrent-title'; + +class TorrentSubtitleService { + public assignSubtitles(contents: any, videos: any[], subtitles: any[]) { + if (videos && videos.length && subtitles && subtitles.length) { + if (videos.length === 1) { + videos[0].subtitles = subtitles; + return { contents, videos, subtitles: [] }; + } + + const parsedVideos = videos.map(video => this.parseVideo(video)); + const assignedSubs = subtitles.map(subtitle => ({ subtitle, videos: this.mostProbableSubtitleVideos(subtitle, parsedVideos) })); + const unassignedSubs = assignedSubs.filter(assignedSub => !assignedSub.videos).map(assignedSub => assignedSub.subtitle); + + assignedSubs + .filter(assignedSub => assignedSub.videos) + .forEach(assignedSub => assignedSub.videos.forEach(video => video.subtitles = (video.subtitles || []).concat(assignedSub.subtitle))); + return { contents, videos, subtitles: unassignedSubs }; + } + return { contents, videos, subtitles }; + } + + private parseVideo(video: any) { + const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); + const folderName = video.title.replace(/\/?[^/]+$/, ''); + return { + videoFile: video, + fileName: fileName, + folderName: folderName, + ...this.parseFilename(video.title) + }; + } + + private mostProbableSubtitleVideos(subtitle: any, parsedVideos: any[]) { + const subTitle = (subtitle.title || subtitle.path).split('/').pop().replace(/\.(\w{2,4})$/, ''); + const parsedSub = this.parsePath(subtitle.title || subtitle.path); + const byFileName = parsedVideos.filter(video => subTitle.includes(video.fileName)); + if (byFileName.length === 1) { + return byFileName.map(v => v.videoFile); + } + const byTitleSeasonEpisode = parsedVideos.filter(video => video.title === parsedSub.title + && this.arrayEquals(video.seasons, parsedSub.seasons) + && this.arrayEquals(video.episodes, parsedSub.episodes)); + if (this.singleVideoFile(byTitleSeasonEpisode)) { + return byTitleSeasonEpisode.map(v => v.videoFile); + } + const bySeasonEpisode = parsedVideos.filter(video => this.arrayEquals(video.seasons, parsedSub.seasons) + && this.arrayEquals(video.episodes, parsedSub.episodes)); + if (this.singleVideoFile(bySeasonEpisode)) { + return bySeasonEpisode.map(v => v.videoFile); + } + const byTitle = parsedVideos.filter(video => video.title && video.title === parsedSub.title); + if (this.singleVideoFile(byTitle)) { + return byTitle.map(v => v.videoFile); + } + const byEpisode = parsedVideos.filter(video => this.arrayEquals(video.episodes, parsedSub.episodes)); + if (this.singleVideoFile(byEpisode)) { + return byEpisode.map(v => v.videoFile); + } + return undefined; + } + + private singleVideoFile(videos: any[]) { + return new Set(videos.map(v => v.videoFile.fileIndex)).size === 1; + } + + private parsePath(path: string) { + const pathParts = path.split('/').map(part => this.parseFilename(part)); + const parsedWithEpisode = pathParts.find(parsed => parsed.season && parsed.episodes); + return parsedWithEpisode || pathParts[pathParts.length - 1]; + } + + private parseFilename(filename: string) { + const parsedInfo = parse(filename) + const titleEpisode = parsedInfo.title.match(/(\d+)$/); + if (!parsedInfo.episodes && titleEpisode) { + parsedInfo.episodes = [parseInt(titleEpisode[1], 10)]; + } + return parsedInfo; + } + + private arrayEquals(array1: any[], array2: any[]) { + if (!array1 || !array2) return array1 === array2; + return array1.length === array2.length && array1.every((value, index) => value === array2[index]) + } +} + +export const torrentSubtitleService = new TorrentSubtitleService(); diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 0212c1a..ed4933e 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -3,8 +3,8 @@ import { metadataService } from './services/metadata_service'; import { parsingService } from './services/parsing_service'; import {PromiseHelpers} from './helpers/promises_helpers'; import { repository } from '../repository/database_repository'; -import { parseTorrentFiles } from './torrentFiles.js'; -import { assignSubtitles } from './torrentSubtitles.js'; +import { torrentFileService } from './services/torrent_file_service'; +import { torrentSubtitleService } from './services/torrent_subtitle_service'; import { TorrentType } from './enums/torrent_types'; import {logger} from './services/logging_service'; @@ -43,9 +43,9 @@ export async function createTorrentEntry(torrent, overwrite = false) { return; } - const { contents, videos, subtitles } = await parseTorrentFiles(torrent) + const { contents, videos, subtitles } = await torrentFileService.parseTorrentFiles(torrent) .then(torrentContents => overwrite ? overwriteExistingFiles(torrent, torrentContents) : torrentContents) - .then(torrentContents => assignSubtitles(torrentContents)) + .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) .catch(error => { logger.warn(`Failed getting files for ${torrent.title}`, error.message); return {}; @@ -135,9 +135,9 @@ export async function createTorrentContents(torrent) { const imdbId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); const kitsuId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); - const { contents, videos, subtitles } = await parseTorrentFiles({ ...torrent, imdbId, kitsuId }) + const { contents, videos, subtitles } = await torrentFileService.parseTorrentFiles({ ...torrent, imdbId, kitsuId }) .then(torrentContents => notOpenedVideo ? torrentContents : { ...torrentContents, videos: storedVideos }) - .then(torrentContents => assignSubtitles(torrentContents)) + .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) .catch(error => { logger.warn(`Failed getting contents for [${torrent.infoHash}] ${torrent.title}`, error.message); return {}; diff --git a/src/node/consumer/src/lib/torrentFiles.js b/src/node/consumer/src/lib/torrentFiles.js deleted file mode 100644 index c2fda7c..0000000 --- a/src/node/consumer/src/lib/torrentFiles.js +++ /dev/null @@ -1,526 +0,0 @@ -import Bottleneck from 'bottleneck'; -import distance from 'jaro-winkler'; -import moment from 'moment'; -import { parse } from 'parse-torrent-title'; -import { configurationService } from './services/configuration_service'; -import { extensionService } from './services/extension_service'; -import { metadataService } from './services/metadata_service'; -import { parsingService } from './services/parsing_service'; -import {PromiseHelpers} from './helpers/promises_helpers'; -import {torrentDownloadService} from "./services/torrent_download_service"; -import { TorrentType } from './enums/torrent_types'; -import {logger} from "./services/logging_service"; - -const MIN_SIZE = 5 * 1024 * 1024; // 5 MB -const imdb_limiter = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); - -export async function parseTorrentFiles(torrent) { - const parsedTorrentName = parse(torrent.title); - const metadata = await metadataService.getMetadata(torrent.kitsuId || torrent.imdbId, torrent.type || TorrentType.MOVIE) - .then(meta => Object.assign({}, meta)) - .catch(() => undefined); - - // if (metadata && metadata.type !== torrent.type && torrent.type !== Type.ANIME) { - // throw new Error(`Mismatching entry type for ${torrent.name}: ${torrent.type}!=${metadata.type}`); - // } - if (torrent.type !== TorrentType.ANIME && metadata && metadata.type && metadata.type !== torrent.type) { - // it's actually a movie/series - torrent.type = metadata.type; - } - - if (torrent.type === TorrentType.MOVIE && (!parsedTorrentName.seasons || - parsedTorrentName.season === 5 && [1, 5].includes(parsedTorrentName.episode))) { - return parseMovieFiles(torrent, parsedTorrentName, metadata); - } - - return parseSeriesFiles(torrent, parsedTorrentName, metadata) -} - -async function parseMovieFiles(torrent, parsedName, metadata) { - const { contents, videos, subtitles } = await getMoviesTorrentContent(torrent); - const filteredVideos = videos - .filter(video => video.size > MIN_SIZE) - .filter(video => !isFeaturette(video)); - if (isSingleMovie(filteredVideos)) { - const parsedVideos = filteredVideos.map(video => ({ - infoHash: torrent.infoHash, - fileIndex: video.fileIndex, - title: video.path || torrent.title, - size: video.size || torrent.size, - imdbId: torrent.imdbId || metadata && metadata.imdbId, - kitsuId: torrent.kitsuId || metadata && metadata.kitsuId - })); - return { contents, videos: parsedVideos, subtitles }; - } - - const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => isFeaturette(video) - ? Promise.resolve(video) - : findMovieImdbId(video.name).then(imdbId => ({ ...video, imdbId })))) - .then(videos => videos.map(video => ({ - infoHash: torrent.infoHash, - fileIndex: video.fileIndex, - title: video.path || video.name, - size: video.size, - imdbId: video.imdbId, - }))); - return { contents, videos: parsedVideos, subtitles }; -} - -async function parseSeriesFiles(torrent, parsedName, metadata) { - const { contents, videos, subtitles } = await getSeriesTorrentContent(torrent); - const parsedVideos = await Promise.resolve(videos) - .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) - .then(videos => parsingService.parseSeriesVideos(torrent, videos)) - .then(videos => decomposeEpisodes(torrent, videos, metadata)) - .then(videos => assignKitsuOrImdbEpisodes(torrent, videos, metadata)) - .then(videos => Promise.all(videos.map(video => video.isMovie - ? mapSeriesMovie(video, torrent) - : mapSeriesEpisode(video, torrent, videos)))) - .then(videos => videos - .reduce((a, b) => a.concat(b), []) - .map(video => isFeaturette(video) ? clearInfoFields(video) : video)) - return { contents, videos: parsedVideos, subtitles }; -} - -async function getMoviesTorrentContent(torrent) { - const files = await torrentFiles(torrent) - .catch(error => { - if (!isPackTorrent(torrent)) { - return { videos: [{ name: torrent.title, path: torrent.title, size: torrent.size }] } - } - return Promise.reject(error); - }); - if (files.contents && files.contents.length && !files.videos.length && isDiskTorrent(files.contents)) { - files.videos = [{ name: torrent.title, path: torrent.title, size: torrent.size }]; - } - return files; -} - -async function getSeriesTorrentContent(torrent) { - return torrentDownloadService.getTorrentFiles(torrent) - .catch(error => { - if (!parsingService.isPackTorrent(torrent)) { - return { videos: [{ name: torrent.title, path: torrent.title, size: torrent.size }] } - } - return Promise.reject(error); - }); -} - -async function mapSeriesEpisode(file, torrent, files) { - if (!file.episodes && !file.kitsuEpisodes) { - if (files.length === 1 || files.some(f => f.episodes || f.kitsuEpisodes) || parse(torrent.title).seasons) { - return Promise.resolve({ - infoHash: torrent.infoHash, - fileIndex: file.fileIndex, - title: file.path || file.name, - size: file.size, - imdbId: torrent.imdbId || file.imdbId, - }); - } - return Promise.resolve([]); - } - const episodeIndexes = [...(file.episodes || file.kitsuEpisodes).keys()]; - return Promise.resolve(episodeIndexes.map((index) => ({ - infoHash: torrent.infoHash, - fileIndex: file.fileIndex, - title: file.path || file.name, - size: file.size, - imdbId: file.imdbId || torrent.imdbId, - imdbSeason: file.season, - imdbEpisode: file.episodes && file.episodes[index], - kitsuId: file.kitsuId || torrent.kitsuId, - kitsuEpisode: file.kitsuEpisodes && file.kitsuEpisodes[index] - }))) -} - -async function mapSeriesMovie(file, torrent) { - const kitsuId = torrent.type === TorrentType.ANIME ? await findMovieKitsuId(file) : undefined; - const imdbId = !kitsuId ? await findMovieImdbId(file) : undefined; - const metadata = await metadataService.getMetadata(kitsuId || imdbId, TorrentType.MOVIE).catch(() => ({})); - const hasEpisode = metadata.videos && metadata.videos.length && (file.episode || metadata.videos.length === 1); - const episodeVideo = hasEpisode && metadata.videos[(file.episode || 1) - 1]; - return [{ - infoHash: torrent.infoHash, - fileIndex: file.fileIndex, - title: file.path || file.name, - size: file.size, - imdbId: metadata.imdbId || imdbId, - kitsuId: metadata.kitsuId || kitsuId, - imdbSeason: episodeVideo && metadata.imdbId ? episodeVideo.imdbSeason : undefined, - imdbEpisode: episodeVideo && metadata.imdbId ? episodeVideo.imdbEpisode || episodeVideo.episode : undefined, - kitsuEpisode: episodeVideo && metadata.kitsuId ? episodeVideo.kitsuEpisode || episodeVideo.episode : undefined - }]; -} - -async function decomposeEpisodes(torrent, files, metadata = { episodeCount: [] }) { - if (files.every(file => !file.episodes && !file.date)) { - return files; - } - - preprocessEpisodes(files); - - if (torrent.type === TorrentType.ANIME && torrent.kitsuId) { - if (needsCinemetaMetadataForAnime(files, metadata)) { - // In some cases anime could be resolved to wrong kitsuId - // because of imdb season naming/absolute per series naming/multiple seasons - // So in these cases we need to fetch cinemeta based metadata and decompose episodes using that - await updateToCinemetaMetadata(metadata); - if (files.some(file => Number.isInteger(file.season))) { - // sometimes multi season anime torrents don't include season 1 naming - files - .filter(file => !Number.isInteger(file.season) && file.episodes) - .forEach(file => file.season = 1); - } - } else { - // otherwise for anime type episodes are always absolute and for a single season - files - .filter(file => file.episodes && file.season !== 0) - .forEach(file => file.season = 1); - return files; - } - } - - const sortedEpisodes = files - .map(file => !file.isMovie && file.episodes || []) - .reduce((a, b) => a.concat(b), []) - .sort((a, b) => a - b); - - if (isConcatSeasonAndEpisodeFiles(files, sortedEpisodes, metadata)) { - decomposeConcatSeasonAndEpisodeFiles(torrent, files, metadata); - } else if (isDateEpisodeFiles(files, metadata)) { - decomposeDateEpisodeFiles(torrent, files, metadata); - } else if (isAbsoluteEpisodeFiles(torrent, files, metadata)) { - decomposeAbsoluteEpisodeFiles(torrent, files, metadata); - } - // decomposeEpisodeTitleFiles(torrent, files, metadata); - - return files; -} - -function preprocessEpisodes(files) { - // reverse special episode naming when they named with 0 episode, ie. S02E00 - files - .filter(file => Number.isInteger(file.season) && file.episode === 0) - .forEach(file => { - file.episode = file.season - file.episodes = [file.season] - file.season = 0; - }) -} - -function isConcatSeasonAndEpisodeFiles(files, sortedEpisodes, metadata) { - if (metadata.kitsuId !== undefined) { - // anime does not use this naming scheme in 99% of cases; - return false; - } - // decompose concat season and episode files (ex. 101=S01E01) in case: - // 1. file has a season, but individual files are concatenated with that season (ex. path Season 5/511 - Prize - // Fighters.avi) - // 2. file does not have a season and the episode does not go out of range for the concat season - // episode count - const thresholdAbove = Math.max(Math.ceil(files.length * 0.05), 5); - const thresholdSorted = Math.max(Math.ceil(files.length * 0.8), 8); - const threshold = Math.max(Math.ceil(files.length * 0.8), 5); - const sortedConcatEpisodes = sortedEpisodes - .filter(ep => ep > 100) - .filter(ep => metadata.episodeCount[div100(ep) - 1] < ep) - .filter(ep => metadata.episodeCount[div100(ep) - 1] >= mod100(ep)); - const concatFileEpisodes = files - .filter(file => !file.isMovie && file.episodes) - .filter(file => !file.season || file.episodes.every(ep => div100(ep) === file.season)); - const concatAboveTotalEpisodeCount = files - .filter(file => !file.isMovie && file.episodes && file.episodes.every(ep => ep > 100)) - .filter(file => file.episodes.every(ep => ep > metadata.totalCount)); - return sortedConcatEpisodes.length >= thresholdSorted && concatFileEpisodes.length >= threshold - || concatAboveTotalEpisodeCount.length >= thresholdAbove; -} - -function isDateEpisodeFiles(files, metadata) { - return files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); -} - -function isAbsoluteEpisodeFiles(torrent, files, metadata) { - const threshold = Math.ceil(files.length / 5); - const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; - const nonMovieEpisodes = files - .filter(file => !file.isMovie && file.episodes); - const absoluteEpisodes = files - .filter(file => file.season && file.episodes) - .filter(file => file.episodes.every(ep => metadata.episodeCount[file.season - 1] < ep)) - return nonMovieEpisodes.every(file => !file.season) - || (isAnime && nonMovieEpisodes.every(file => file.season > metadata.episodeCount.length)) - || absoluteEpisodes.length >= threshold; -} - -function isNewEpisodeNotInMetadata(torrent, file, metadata) { - // new episode might not yet been indexed by cinemeta. - // detect this if episode number is larger than the last episode or season is larger than the last one - // only for non anime metas - const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; - return !isAnime && !file.isMovie && file.episodes && file.season !== 1 - && /continuing|current/i.test(metadata.status) - && file.season >= metadata.episodeCount.length - && file.episodes.every(ep => ep > (metadata.episodeCount[file.season - 1] || 0)); -} - -function decomposeConcatSeasonAndEpisodeFiles(torrent, files, metadata) { - files - .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) - .filter(file => metadata.episodeCount[(file.season || div100(file.episodes[0])) - 1] < 100) - .filter(file => file.season && file.episodes.every(ep => div100(ep) === file.season) || !file.season) - .forEach(file => { - file.season = div100(file.episodes[0]); - file.episodes = file.episodes.map(ep => mod100(ep)) - }); - -} - -function decomposeAbsoluteEpisodeFiles(torrent, files, metadata) { - if (metadata.episodeCount.length === 0) { - files - .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) - .forEach(file => { - file.season = 1; - }); - return; - } - files - .filter(file => file.episodes && !file.isMovie && file.season !== 0) - .filter(file => !isNewEpisodeNotInMetadata(torrent, file, metadata)) - .filter(file => !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]) - .forEach(file => { - const seasonIdx = ([...metadata.episodeCount.keys()] - .find((i) => metadata.episodeCount.slice(0, i + 1).reduce((a, b) => a + b) >= file.episodes[0]) - + 1 || metadata.episodeCount.length) - 1; - - file.season = seasonIdx + 1; - file.episodes = file.episodes - .map(ep => ep - metadata.episodeCount.slice(0, seasonIdx).reduce((a, b) => a + b, 0)) - }); -} - -function decomposeDateEpisodeFiles(torrent, files, metadata) { - if (!metadata || !metadata.videos || !metadata.videos.length) { - return; - } - - const timeZoneOffset = getTimeZoneOffset(metadata.country); - const offsetVideos = metadata.videos - .reduce((map, video) => { - const releaseDate = moment(video.released).utcOffset(timeZoneOffset).format('YYYY-MM-DD'); - map[releaseDate] = video; - return map; - }, {}); - - files - .filter(file => file.date) - .forEach(file => { - const video = offsetVideos[file.date]; - if (video) { - file.season = video.season; - file.episodes = [video.episode]; - } - }); -} - - -/* eslint-disable no-unused-vars */ -function decomposeEpisodeTitleFiles(torrent, files, metadata) { - files - // .filter(file => !file.season) - .map(file => { - const episodeTitle = file.name.replace('_', ' ') - .replace(/^.*(?:E\d+[abc]?|- )\s?(.+)\.\w{1,4}$/, '$1') - .trim(); - const foundEpisode = metadata.videos - .map(video => ({ ...video, distance: distance(episodeTitle, video.name) })) - .sort((a, b) => b.distance - a.distance)[0]; - if (foundEpisode) { - file.isMovie = false; - file.season = foundEpisode.season; - file.episodes = [foundEpisode.episode]; - } - }) -} -/* eslint-enable no-unused-vars */ - -function getTimeZoneOffset(country) { - switch (country) { - case 'United States': - case 'USA': - return '-08:00'; - default: - return '00:00'; - } -} - -function assignKitsuOrImdbEpisodes(torrent, files, metadata) { - if (!metadata || !metadata.videos || !metadata.videos.length) { - if (torrent.type === TorrentType.ANIME) { - // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping - files - .filter(file => file.season && file.episodes) - .forEach(file => { - file.kitsuEpisodes = file.episodes; - file.season = undefined; - file.episodes = undefined; - }) - if (metadata.type === TorrentType.MOVIE && files.every(file => !file.imdbId)) { - // sometimes a movie has episode naming, thus not recognized as a movie and imdbId not assigned - files.forEach(file => file.imdbId = metadata.imdbId); - } - } - return files; - } - - const seriesMapping = metadata.videos - .reduce((map, video) => { - const episodeMap = map[video.season] || {}; - episodeMap[video.episode] = video; - map[video.season] = episodeMap; - return map; - }, {}); - - if (metadata.videos.some(video => Number.isInteger(video.imdbSeason)) || !metadata.imdbId) { - // kitsu episode info is the base - files - .filter(file => Number.isInteger(file.season) && file.episodes) - .map(file => { - const seasonMapping = seriesMapping[file.season]; - const episodeMapping = seasonMapping && seasonMapping[file.episodes[0]]; - file.kitsuEpisodes = file.episodes; - if (episodeMapping && Number.isInteger(episodeMapping.imdbSeason)) { - file.imdbId = metadata.imdbId; - file.season = episodeMapping.imdbSeason; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].imdbEpisode); - } else { - // no imdb mapping available for episode - file.season = undefined; - file.episodes = undefined; - } - }); - } else if (metadata.videos.some(video => video.kitsuEpisode)) { - // imdb episode info is base - files - .filter(file => Number.isInteger(file.season) && file.episodes) - .forEach(file => { - if (seriesMapping[file.season]) { - const seasonMapping = seriesMapping[file.season]; - file.imdbId = metadata.imdbId; - file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId; - file.kitsuEpisodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); - } else if (seriesMapping[file.season - 1]) { - // sometimes a second season might be a continuation of the previous season - const seasonMapping = seriesMapping[file.season - 1]; - const episodes = Object.values(seasonMapping); - const firstKitsuId = episodes.length && episodes[0].kitsuId; - const differentTitlesCount = new Set(episodes.map(ep => ep.kitsuId)).size - const skippedCount = episodes.filter(ep => ep.kitsuId === firstKitsuId).length; - const seasonEpisodes = files - .filter(otherFile => otherFile.season === file.season) - .reduce((a, b) => a.concat(b.episodes), []); - const isAbsoluteOrder = seasonEpisodes.every(ep => ep > skippedCount && ep <= episodes.length) - const isNormalOrder = seasonEpisodes.every(ep => ep + skippedCount <= episodes.length) - if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { - file.imdbId = metadata.imdbId; - file.season = file.season - 1; - file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; - file.kitsuEpisodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); - } - } else if (Object.values(seriesMapping).length === 1 && seriesMapping[1]) { - // sometimes series might be named with sequel season but it's not a season on imdb and a new title - const seasonMapping = seriesMapping[1]; - file.imdbId = metadata.imdbId; - file.season = 1; - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; - file.kitsuEpisodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); - } - }); - } - return files; -} - -function needsCinemetaMetadataForAnime(files, metadata) { - if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { - return false; - } - - const minSeason = Math.min(...metadata.videos.map(video => video.imdbSeason)) || Number.MAX_VALUE; - const maxSeason = Math.max(...metadata.videos.map(video => video.imdbSeason)) || Number.MAX_VALUE; - const differentSeasons = new Set(metadata.videos - .map(video => video.imdbSeason) - .filter(season => Number.isInteger(season))).size; - const total = metadata.totalCount || Number.MAX_VALUE; - return differentSeasons > 1 || files - .filter(file => !file.isMovie && file.episodes) - .some(file => file.season < minSeason || file.season > maxSeason || file.episodes.every(ep => ep > total)); -} - -async function updateToCinemetaMetadata(metadata) { - return metadataService.getMetadata(metadata.imdbId, metadata.type) - .then(newMetadata => !newMetadata.videos || !newMetadata.videos.length ? metadata : newMetadata) - .then(newMetadata => { - metadata.videos = newMetadata.videos; - metadata.episodeCount = newMetadata.episodeCount; - metadata.totalCount = newMetadata.totalCount; - return metadata; - }) - .catch(error => logger.warn(`Failed ${metadata.imdbId} metadata cinemeta update due: ${error.message}`)); -} - -function findMovieImdbId(title) { - const parsedTitle = typeof title === 'string' ? parse(title) : title; - logger.debug(`Finding movie imdbId for ${title}`); - return imdb_limiter.schedule(() => { - const imdbQuery = { - title: parsedTitle.title, - year: parsedTitle.year, - type: TorrentType.MOVIE - }; - return metadataService.getImdbId(imdbQuery).catch(() => undefined); - }); -} - -function findMovieKitsuId(title) { - const parsedTitle = typeof title === 'string' ? parse(title) : title; - const kitsuQuery = { - title: parsedTitle.title, - year: parsedTitle.year, - season: parsedTitle.season, - type: TorrentType.MOVIE - }; - return metadataService.getKitsuId(kitsuQuery).catch(() => undefined); -} - -function isDiskTorrent(contents) { - return contents.some(content => extensionService.isDisk(content.path)); -} - -function isSingleMovie(videos) { - return videos.length === 1 || - (videos.length === 2 && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); -} - -function isFeaturette(video) { - return /featurettes?\/|extras-grym/i.test(video.path); -} - -function clearInfoFields(video) { - video.imdbId = undefined; - video.imdbSeason = undefined; - video.imdbEpisode = undefined; - video.kitsuId = undefined; - video.kitsuEpisode = undefined; - return video; -} - -function div100(episode) { - return (episode / 100 >> 0); // floor to nearest int -} - -function mod100(episode) { - return episode % 100; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentSubtitles.js b/src/node/consumer/src/lib/torrentSubtitles.js deleted file mode 100644 index 7bd9ab4..0000000 --- a/src/node/consumer/src/lib/torrentSubtitles.js +++ /dev/null @@ -1,89 +0,0 @@ -import { parse } from 'parse-torrent-title'; - -export function assignSubtitles({ contents, videos, subtitles }) { - if (videos && videos.length && subtitles && subtitles.length) { - if (videos.length === 1) { - videos[0].subtitles = subtitles; - return { contents, videos, subtitles: [] }; - } - - const parsedVideos = videos - .map(video => _parseVideo(video)); - const assignedSubs = subtitles - .map(subtitle => ({ subtitle, videos: _mostProbableSubtitleVideos(subtitle, parsedVideos) })); - const unassignedSubs = assignedSubs - .filter(assignedSub => !assignedSub.videos) - .map(assignedSub => assignedSub.subtitle); - - assignedSubs - .filter(assignedSub => assignedSub.videos) - .forEach(assignedSub => assignedSub.videos - .forEach(video => video.subtitles = (video.subtitles || []).concat(assignedSub.subtitle))); - return { contents, videos, subtitles: unassignedSubs }; - } - return { contents, videos, subtitles }; -} - -function _parseVideo(video) { - const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); - const folderName = video.title.replace(/\/?[^/]+$/, ''); - return { - videoFile: video, - fileName: fileName, - folderName: folderName, - ...parseFilename(video.title) - }; -} - -function _mostProbableSubtitleVideos(subtitle, parsedVideos) { - const subTitle = (subtitle.title || subtitle.path).split('/').pop().replace(/\.(\w{2,4})$/, ''); - const parsedSub = parsePath(subtitle.title || subtitle.path); - const byFileName = parsedVideos.filter(video => subTitle.includes(video.fileName)); - if (byFileName.length === 1) { - return byFileName.map(v => v.videoFile); - } - const byTitleSeasonEpisode = parsedVideos.filter(video => video.title === parsedSub.title - && arrayEquals(video.seasons, parsedSub.seasons) - && arrayEquals(video.episodes, parsedSub.episodes)); - if (singleVideoFile(byTitleSeasonEpisode)) { - return byTitleSeasonEpisode.map(v => v.videoFile); - } - const bySeasonEpisode = parsedVideos.filter(video => arrayEquals(video.seasons, parsedSub.seasons) - && arrayEquals(video.episodes, parsedSub.episodes)); - if (singleVideoFile(bySeasonEpisode)) { - return bySeasonEpisode.map(v => v.videoFile); - } - const byTitle = parsedVideos.filter(video => video.title && video.title === parsedSub.title); - if (singleVideoFile(byTitle)) { - return byTitle.map(v => v.videoFile); - } - const byEpisode = parsedVideos.filter(video => arrayEquals(video.episodes, parsedSub.episodes)); - if (singleVideoFile(byEpisode)) { - return byEpisode.map(v => v.videoFile); - } - return undefined; -} - -function singleVideoFile(videos) { - return new Set(videos.map(v => v.videoFile.fileIndex)).size === 1; -} - -function parsePath(path) { - const pathParts = path.split('/').map(part => parseFilename(part)); - const parsedWithEpisode = pathParts.find(parsed => parsed.season && parsed.episodes); - return parsedWithEpisode || pathParts[pathParts.length - 1]; -} - -function parseFilename(filename) { - const parsedInfo = parse(filename) - const titleEpisode = parsedInfo.title.match(/(\d+)$/); - if (!parsedInfo.episodes && titleEpisode) { - parsedInfo.episodes = [parseInt(titleEpisode[1], 10)]; - } - return parsedInfo; -} - -function arrayEquals(array1, array2) { - if (!array1 || !array2) return array1 === array2; - return array1.length === array2.length && array1.every((value, index) => value === array2[index]) -} \ No newline at end of file From 69fb088b62cad10635a458aa2a1bbad36f4ce876 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 5 Feb 2024 15:13:33 +0000 Subject: [PATCH 13/55] bring in config change for migrations --- .../consumer/src/lib/models/configuration/database_config.ts | 3 +++ src/node/consumer/src/repository/database_repository.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts index fc5e8d3..754cd85 100644 --- a/src/node/consumer/src/lib/models/configuration/database_config.ts +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -1,9 +1,12 @@ +import {BooleanHelpers} from "../../helpers/boolean_helpers"; + export class DatabaseConfig { public POSTGRES_HOST: string = process.env.POSTGRES_HOST || 'postgres'; public POSTGRES_PORT: number = parseInt(process.env.POSTGRES_PORT || '5432'); public POSTGRES_DB: string = process.env.POSTGRES_DB || 'knightcrawler'; public POSTGRES_USER: string = process.env.POSTGRES_USER || 'postgres'; public POSTGRES_PASSWORD: string = process.env.POSTGRES_PASSWORD || 'postgres'; + public AUTO_CREATE_AND_APPLY_MIGRATIONS : boolean = BooleanHelpers.parseBool(process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS, false); public get POSTGRES_URI() { return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DB}`; diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index d6e4455..a1b55d3 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -36,7 +36,7 @@ class DatabaseRepository { try { await this.database.authenticate(); logger.info('Database connection has been established successfully.'); - await this.database.sync({alter: true}); + await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); } catch (error) { logger.error('Failed syncing database: ', error); throw error; From a84ca68d9e4fbe2d40339c2331c9e99dee3ec500 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 09:28:55 +0000 Subject: [PATCH 14/55] some comment resolution - enums, process_torrents_job --- src/node/consumer/esbuild.js | 2 +- src/node/consumer/package.json | 2 +- src/node/consumer/src/{index.js => index.ts} | 4 +- src/node/consumer/src/jobs/processTorrents.ts | 56 ------------------ .../consumer/src/jobs/process_torrents_job.ts | 57 +++++++++++++++++++ .../consumer/src/lib/enums/cache_types.ts | 4 +- .../consumer/src/lib/enums/torrent_types.ts | 7 +-- .../src/lib/services/cache_service.ts | 12 ++-- .../src/lib/services/metadata_service.ts | 4 +- .../src/lib/services/parsing_service.ts | 4 +- .../src/lib/services/torrent_file_service.ts | 24 ++++---- .../services/torrent_processing_service.ts | 2 +- src/node/consumer/src/lib/torrentEntries.js | 4 +- .../interfaces/ingested_torrent_attributes.ts | 2 +- src/node/consumer/tsconfig.json | 1 + 15 files changed, 93 insertions(+), 92 deletions(-) rename src/node/consumer/src/{index.js => index.ts} (65%) delete mode 100644 src/node/consumer/src/jobs/processTorrents.ts create mode 100644 src/node/consumer/src/jobs/process_torrents_job.ts diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js index 63b1d16..9aea0be 100644 --- a/src/node/consumer/esbuild.js +++ b/src/node/consumer/esbuild.js @@ -13,7 +13,7 @@ try { build({ bundle: true, entryPoints: [ - "./src/index.js", + "./src/index.ts", ], external: [...(devDependencies && Object.keys(devDependencies))], keepNames: true, diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 78c9826..a1e5129 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "build": "node esbuild.js", - "dev": "tsx watch --ignore node_modules src/index.js | pino-pretty", + "dev": "tsx watch --ignore node_modules src/index.ts | pino-pretty", "start": "node dist/index.cjs", "lint": "eslint . --ext .ts,.js" }, diff --git a/src/node/consumer/src/index.js b/src/node/consumer/src/index.ts similarity index 65% rename from src/node/consumer/src/index.js rename to src/node/consumer/src/index.ts index d4a163b..f022264 100644 --- a/src/node/consumer/src/index.js +++ b/src/node/consumer/src/index.ts @@ -1,9 +1,9 @@ -import { listenToQueue } from './jobs/processTorrents'; +import { processTorrentsJob } from './jobs/process_torrents_job.js'; import { repository } from "./repository/database_repository"; import { trackerService } from "./lib/services/tracker_service"; (async () => { await trackerService.getTrackers(); await repository.connect(); - await listenToQueue(); + await processTorrentsJob.listenToQueue(); })(); \ No newline at end of file diff --git a/src/node/consumer/src/jobs/processTorrents.ts b/src/node/consumer/src/jobs/processTorrents.ts deleted file mode 100644 index 9c7cd9b..0000000 --- a/src/node/consumer/src/jobs/processTorrents.ts +++ /dev/null @@ -1,56 +0,0 @@ -import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' -import {configurationService} from '../lib/services/configuration_service'; -import {torrentProcessingService} from '../lib/services/torrent_processing_service'; -import {logger} from '../lib/services/logging_service'; -import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; -import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; - -const assertQueueOptions: Options.AssertQueue = { durable: true }; -const consumeQueueOptions: Options.Consume = { noAck: false }; - -const processMessage = (msg: ConsumeMessage | null): Promise => { - const ingestedTorrent: IngestedTorrentAttributes = getMessageAsJson(msg); - return torrentProcessingService.processTorrentRecord(ingestedTorrent); -}; - -const getMessageAsJson = (msg: ConsumeMessage | null): IngestedTorrentAttributes => { - const content = msg ? msg?.content.toString('utf8') : "{}"; - const receivedObject: IngestedRabbitMessage = JSON.parse(content) as IngestedRabbitMessage; - const receivedTorrent:IngestedRabbitTorrent = receivedObject.message; - const mappedObject: any = {...receivedTorrent, info_hash: receivedTorrent.infoHash}; - delete mappedObject.infoHash; - - return mappedObject as IngestedTorrentAttributes; -}; - -const assertAndConsumeQueue = async (channel: Channel): Promise => { - logger.info('Worker is running! Waiting for new torrents...'); - - const ackMsg = (msg: ConsumeMessage): void => { - processMessage(msg) - .then(() => channel.ack(msg)) - .catch((error: Error) => logger.error('Failed processing torrent', error)); - } - - try { - await channel.assertQueue(configurationService.rabbitConfig.QUEUE_NAME, assertQueueOptions); - await channel.prefetch(configurationService.jobConfig.JOB_CONCURRENCY); - await channel.consume(configurationService.rabbitConfig.QUEUE_NAME, ackMsg, consumeQueueOptions); - } catch(error) { - logger.error('Failed to setup channel', error); - } -} - -export const listenToQueue = async (): Promise => { - if (!configurationService.jobConfig.JOBS_ENABLED) { - return; - } - - try { - const connection: Connection = await client.connect(configurationService.rabbitConfig.RABBIT_URI); - const channel: Channel = await connection.createChannel(); - await assertAndConsumeQueue(channel); - } catch (error) { - logger.error('Failed to connect and setup channel', error); - } -} \ No newline at end of file diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/jobs/process_torrents_job.ts new file mode 100644 index 0000000..f655d31 --- /dev/null +++ b/src/node/consumer/src/jobs/process_torrents_job.ts @@ -0,0 +1,57 @@ +import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' +import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; +import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; +import {configurationService} from '../lib/services/configuration_service'; +import {torrentProcessingService} from '../lib/services/torrent_processing_service'; +import {logger} from '../lib/services/logging_service'; + +class ProcessTorrentsJob { + private readonly assertQueueOptions: Options.AssertQueue = {durable: true}; + private readonly consumeQueueOptions: Options.Consume = {noAck: false}; + + public listenToQueue = async (): Promise => { + if (!configurationService.jobConfig.JOBS_ENABLED) { + return; + } + + try { + const connection: Connection = await client.connect(configurationService.rabbitConfig.RABBIT_URI); + const channel: Channel = await connection.createChannel(); + await this.assertAndConsumeQueue(channel); + } catch (error) { + logger.error('Failed to connect and setup channel', error); + } + } + private processMessage = (msg: ConsumeMessage) => { + const ingestedTorrent: IngestedTorrentAttributes = this.getMessageAsJson(msg); + return torrentProcessingService.processTorrentRecord(ingestedTorrent); + }; + private getMessageAsJson = (msg: ConsumeMessage): IngestedTorrentAttributes => { + const content = msg?.content.toString('utf8') ?? "{}"; + const receivedObject: IngestedRabbitMessage = JSON.parse(content); + const receivedTorrent: IngestedRabbitTorrent = receivedObject.message; + return {...receivedTorrent, info_hash: receivedTorrent.infoHash}; + }; + private async assertAndConsumeQueue(channel: Channel) { + logger.info('Worker is running! Waiting for new torrents...'); + + const ackMsg = async (msg: ConsumeMessage) => { + try { + await this.processMessage(msg); + channel.ack(msg); + } catch (error) { + logger.error('Failed processing torrent', error); + } + } + + try { + await channel.assertQueue(configurationService.rabbitConfig.QUEUE_NAME, this.assertQueueOptions); + await channel.prefetch(configurationService.jobConfig.JOB_CONCURRENCY); + await channel.consume(configurationService.rabbitConfig.QUEUE_NAME, ackMsg, this.consumeQueueOptions); + } catch (error) { + logger.error('Failed to setup channel', error); + } + } +} + +export const processTorrentsJob = new ProcessTorrentsJob(); \ No newline at end of file diff --git a/src/node/consumer/src/lib/enums/cache_types.ts b/src/node/consumer/src/lib/enums/cache_types.ts index 989f6bd..d1cf197 100644 --- a/src/node/consumer/src/lib/enums/cache_types.ts +++ b/src/node/consumer/src/lib/enums/cache_types.ts @@ -1,4 +1,4 @@ export enum CacheType { - MEMORY = 'memory', - MONGODB = 'mongodb' + Memory = 'memory', + MongoDb = 'mongodb' } \ No newline at end of file diff --git a/src/node/consumer/src/lib/enums/torrent_types.ts b/src/node/consumer/src/lib/enums/torrent_types.ts index 7a20693..47743c6 100644 --- a/src/node/consumer/src/lib/enums/torrent_types.ts +++ b/src/node/consumer/src/lib/enums/torrent_types.ts @@ -1,6 +1,5 @@ export enum TorrentType { - SERIES = 'SERIES', - MOVIE = 'MOVIE', - ANIME = 'anime', - PORN = 'xxx', + Series = 'Series', + Movie = 'Movie', + Anime = 'anime', } \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 88aad32..1e1e673 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -29,16 +29,16 @@ class CacheService { } public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MONGODB, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MONGODB, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MEMORY, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); + this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); public cacheTrackers = (method: CacheMethod): Promise => - this.cacheWrap(CacheType.MEMORY, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); + this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); private initiateMemoryCache = () => createCache(memoryStore(), { @@ -72,9 +72,9 @@ class CacheService { private getCacheType = (cacheType: CacheType): typeof this.memoryCache | null => { switch (cacheType) { - case CacheType.MEMORY: + case CacheType.Memory: return this.memoryCache; - case CacheType.MONGODB: + case CacheType.MongoDb: return this.remoteCache; default: return null; diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index e564de2..3a14b23 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -59,12 +59,12 @@ class MetadataService { } const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; - const metaType = query.type === TorrentType.MOVIE ? TorrentType.MOVIE : TorrentType.SERIES; + const metaType = query.type === TorrentType.Movie ? TorrentType.Movie : TorrentType.Series; return cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) .catch(() => this.requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) .catch(() => { // try different type in case there was a mismatch - const otherType = metaType === TorrentType.MOVIE ? TorrentType.SERIES : TorrentType.MOVIE; + const otherType = metaType === TorrentType.Movie ? TorrentType.Series : TorrentType.Movie; return this.requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) }) .catch((error) => { diff --git a/src/node/consumer/src/lib/services/parsing_service.ts b/src/node/consumer/src/lib/services/parsing_service.ts index dc0b2a6..bb8da27 100644 --- a/src/node/consumer/src/lib/services/parsing_service.ts +++ b/src/node/consumer/src/lib/services/parsing_service.ts @@ -19,7 +19,7 @@ class ParsingService { return true; } const parsedInfo = parse(torrent.title); - if (torrent.type === TorrentType.MOVIE) { + if (torrent.type === TorrentType.Movie) { return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); } const hasMultipleEpisodes = parsedInfo.complete || @@ -86,7 +86,7 @@ class ParsingService { // movie if video explicitly has numbered movie keyword in the name, ie. 1 Movie or Movie 1 return true; } - if (!hasMovies && type !== TorrentType.ANIME) { + if (!hasMovies && type !== TorrentType.Anime) { // not movie if torrent name does not contain movies keyword or is not a pack torrent and is not anime return false; } diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 6744d99..29aa558 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -28,18 +28,18 @@ class TorrentFileService { const parsedTorrentName = parse(torrent.title); const query: MetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, - type: torrent.type || TorrentType.MOVIE, + type: torrent.type || TorrentType.Movie, }; const metadata = await metadataService.getMetadata(query) .then(meta => Object.assign({}, meta)) .catch(() => undefined); - if (torrent.type !== TorrentType.ANIME && metadata && metadata.type && metadata.type !== torrent.type) { + if (torrent.type !== TorrentType.Anime && metadata && metadata.type && metadata.type !== torrent.type) { // it's actually a movie/series torrent.type = metadata.type; } - if (torrent.type === TorrentType.MOVIE && (!parsedTorrentName.seasons || + if (torrent.type === TorrentType.Movie && (!parsedTorrentName.seasons || parsedTorrentName.season === 5 && [1, 5].includes(parsedTorrentName.episode))) { return this.parseMovieFiles(torrent, metadata); } @@ -145,7 +145,7 @@ class TorrentFileService { } private async mapSeriesMovie(file: ParsableTorrentFile, torrent: TorrentInfo): Promise { - const kitsuId= torrent.type === TorrentType.ANIME ? await this.findMovieKitsuId(file) + const kitsuId= torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) .then(result => { if (result instanceof Error) { logger.warn(`Failed to retrieve kitsuId due to error: ${result.message}`); @@ -158,7 +158,7 @@ class TorrentFileService { const query: MetaDataQuery = { id: kitsuId || imdbId, - type: TorrentType.MOVIE + type: TorrentType.Movie }; const metadataOrError = await metadataService.getMetadata(query); @@ -201,7 +201,7 @@ class TorrentFileService { this.preprocessEpisodes(files); - if (torrent.type === TorrentType.ANIME && torrent.kitsuId) { + if (torrent.type === TorrentType.Anime && torrent.kitsuId) { if (this.needsCinemetaMetadataForAnime(files, metadata)) { // In some cases anime could be resolved to wrong kitsuId // because of imdb season naming/absolute per series naming/multiple seasons @@ -283,7 +283,7 @@ class TorrentFileService { private isAbsoluteEpisodeFiles(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { const threshold = Math.ceil(files.length / 5); - const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; + const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; const nonMovieEpisodes = files .filter(file => !file.isMovie && file.episodes); const absoluteEpisodes = files @@ -298,7 +298,7 @@ class TorrentFileService { // new episode might not yet been indexed by cinemeta. // detect this if episode number is larger than the last episode or season is larger than the last one // only for non anime metas - const isAnime = torrent.type === TorrentType.ANIME && torrent.kitsuId; + const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; return !isAnime && !file.isMovie && file.episodes && file.season !== 1 && /continuing|current/i.test(metadata.status) && file.season >= metadata.episodeCount.length @@ -377,7 +377,7 @@ class TorrentFileService { private assignKitsuOrImdbEpisodes(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { if (!metadata || !metadata.videos || !metadata.videos.length) { - if (torrent.type === TorrentType.ANIME) { + if (torrent.type === TorrentType.Anime) { // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping files .filter(file => file.season && file.episodes) @@ -385,7 +385,7 @@ class TorrentFileService { file.season = undefined; file.episodes = undefined; }) - if (metadata.type === TorrentType.MOVIE && files.every(file => !file.imdbId)) { + if (metadata.type === TorrentType.Movie && files.every(file => !file.imdbId)) { // sometimes a movie has episode naming, thus not recognized as a movie and imdbId not assigned files.forEach(file => file.imdbId = metadata.imdbId); } @@ -507,7 +507,7 @@ class TorrentFileService { const imdbQuery = { title: parsedTitle.title, year: parsedTitle.year, - type: TorrentType.MOVIE + type: TorrentType.Movie }; try { return await metadataService.getImdbId(imdbQuery); @@ -523,7 +523,7 @@ class TorrentFileService { title: parsedTitle.title, year: parsedTitle.year, season: parsedTitle.season, - type: TorrentType.MOVIE + type: TorrentType.Movie }; try { return await metadataService.getKitsuId(kitsuQuery); diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index 3374881..c74a951 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -8,7 +8,7 @@ import {IngestedTorrentAttributes} from "../../repository/interfaces/ingested_to class TorrentProcessingService { public async processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { const { category } = torrent; - const type = category === 'tv' ? TorrentType.SERIES : TorrentType.MOVIE; + const type = category === 'tv' ? TorrentType.Series : TorrentType.Movie; const torrentInfo: TorrentInfo = await this.parseTorrent(torrent, type); logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index ed4933e..ec3b1ce 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -11,7 +11,7 @@ import {logger} from './services/logging_service'; export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); - if (!torrent.imdbId && torrent.type !== TorrentType.ANIME) { + if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { const imdbQuery = { title: titleInfo.title, year: titleInfo.year, @@ -28,7 +28,7 @@ export async function createTorrentEntry(torrent, overwrite = false) { // sanitize imdbId from redundant zeros torrent.imdbId = torrent.imdbId.replace(/tt0+([0-9]{7,})$/, 'tt$1'); } - if (!torrent.kitsuId && torrent.type === TorrentType.ANIME) { + if (!torrent.kitsuId && torrent.type === TorrentType.Anime) { const kitsuQuery = { title: titleInfo.title, year: titleInfo.year, diff --git a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts index b54eec1..c29ba9e 100644 --- a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts @@ -10,7 +10,7 @@ export interface IngestedTorrentAttributes { leechers: number; imdb: string; processed: boolean; - createdAt: Date; + createdAt?: Date; } export interface IngestedTorrentCreationAttributes extends Optional { diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index c6f83d1..3c3b81b 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "baseUrl": "./src", "checkJs": true, + "allowJs": true, "isolatedModules": true, "lib": ["ESNext"], "module": "ESNext", From 9982fc1093b321e27a63cc15590a25af6d42ac18 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 10:38:44 +0000 Subject: [PATCH 15/55] eslint cleanup - addded as const check tooo --- src/node/consumer/.eslintrc.cjs | 39 -- src/node/consumer/.eslintrc.json | 70 +++ src/node/consumer/esbuild.js | 3 + src/node/consumer/package-lock.json | 514 +++++++++++++++++- src/node/consumer/package.json | 9 +- .../consumer/src/jobs/process_torrents_job.ts | 6 +- src/node/consumer/src/lib/torrentEntries.js | 8 +- .../src/repository/database_repository.ts | 12 +- src/node/consumer/tsconfig.json | 16 +- 9 files changed, 598 insertions(+), 79 deletions(-) delete mode 100644 src/node/consumer/.eslintrc.cjs create mode 100644 src/node/consumer/.eslintrc.json diff --git a/src/node/consumer/.eslintrc.cjs b/src/node/consumer/.eslintrc.cjs deleted file mode 100644 index 1f703e1..0000000 --- a/src/node/consumer/.eslintrc.cjs +++ /dev/null @@ -1,39 +0,0 @@ -/** @type {import("eslint").ESLint.Options} */ -module.exports = { - env: { - es2024: true, - node: true, - }, - globals: { - Atomics: "readonly", - SharedArrayBuffer: "readonly", - }, - parserOptions: { - sourceType: "module", - }, - plugins: ["import", "import-helpers"], - rules: { - "default-case": "off", - "import/no-duplicates": "off", - "import/no-extraneous-dependencies": ["off", { devDependencies: ["backend", "frontend", "mobile"] }], - "import/order": "off", - "import-helpers/order-imports": [ - "warn", - { - alphabetize: { - order: "asc", - }, - }, - ], - "lines-between-class-members": ["error", "always", { exceptAfterSingleLine: true }], - "no-continue": "off", - "no-param-reassign": "off", - "no-plusplus": ["error", { allowForLoopAfterthoughts: true }], - "no-restricted-syntax": "off", - "no-unused-expressions": ["off", { allowShortCircuit: true }], - "no-unused-vars": "off", - "no-use-before-define": "off", - "one-var": ["error", { uninitialized: "consecutive" }], - "prefer-destructuring": "off", - }, -}; \ No newline at end of file diff --git a/src/node/consumer/.eslintrc.json b/src/node/consumer/.eslintrc.json new file mode 100644 index 0000000..784351f --- /dev/null +++ b/src/node/consumer/.eslintrc.json @@ -0,0 +1,70 @@ +{ + "root": true, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": [ + "./tsconfig.json" + ] + }, + "plugins": [ + "@typescript-eslint", + "import", + "import-helpers" + ], + "rules": { + "default-case": "off", + "import/no-duplicates": "error", + "import/no-extraneous-dependencies": "error", + "import/order": "off", + "import-helpers/order-imports": [ + "warn", + { + "alphabetize": { + "order": "asc" + } + } + ], + "lines-between-class-members": [ + "error", + "always", + { + "exceptAfterSingleLine": true + } + ], + "no-continue": "off", + "no-param-reassign": "off", + "no-plusplus": [ + "error", + { + "allowForLoopAfterthoughts": true + } + ], + "no-restricted-syntax": "off", + "no-unused-expressions": [ + "off", + { + "allowShortCircuit": true + } + ], + "no-unused-vars": "off", + "no-use-before-define": "off", + "one-var": [ + "error", + { + "uninitialized": "consecutive" + } + ], + "prefer-destructuring": "error", + "@typescript-eslint/consistent-type-assertions": [ + "error", + { + "assertionStyle": "as", + "objectLiteralTypeAssertions": "never" + } + ] + } +} \ No newline at end of file diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js index 9aea0be..82f9e58 100644 --- a/src/node/consumer/esbuild.js +++ b/src/node/consumer/esbuild.js @@ -43,9 +43,12 @@ try { ], }).then(() => { // biome-ignore lint/style/useTemplate: + // eslint-disable-next-line no-undef console.log("⚡ " + "\x1b[32m" + `Done in ${Date.now() - start}ms`); }); } catch (e) { + // eslint-disable-next-line no-undef console.log(e); + // eslint-disable-next-line no-undef process.exit(1); } \ No newline at end of file diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 3a41714..444d7f2 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -15,7 +15,6 @@ "bottleneck": "^2.19.5", "cache-manager": "^5.4.0", "google-sr": "^3.2.1", - "jaro-winkler": "^0.2.8", "magnet-uri": "^6.2.0", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", @@ -31,18 +30,20 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", - "@types/jaro-winkler": "^0.2.3", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", "pino-pretty": "^10.3.1", - "tsx": "^4.7.0" + "tsx": "^4.7.0", + "typescript": "^5.3.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -584,10 +585,10 @@ "@types/ms": "*" } }, - "node_modules/@types/jaro-winkler": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@types/jaro-winkler/-/jaro-winkler-0.2.3.tgz", - "integrity": "sha512-W5qVYCDkBMP7hMM9szj4JvA52CYEyEqL/CKUy7EIulJmlzfqJy5cW0hkzOgJ50Yz8Egfo7MoLF+LUWHUxRZVrg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/json5": { @@ -620,6 +621,12 @@ "version": "5.26.5", "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "node_modules/@types/stremio-addon-sdk": { "version": "1.6.11", "dev": true, @@ -650,6 +657,301 @@ "@types/webidl-conversions": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "dev": true, @@ -774,6 +1076,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.3", "dev": true, @@ -1010,6 +1321,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/bson": { "version": "6.3.0", "license": "Apache-2.0", @@ -1391,6 +1714,18 @@ "version": "1.3.0", "license": "MIT" }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "dev": true, @@ -1610,8 +1945,9 @@ }, "node_modules/eslint": { "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -1882,6 +2218,34 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "dev": true, @@ -1929,6 +2293,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "dev": true, @@ -2202,6 +2578,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/google-sr": { "version": "3.2.1", "license": "Apache-2.0", @@ -2562,6 +2958,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.0.7", "dev": true, @@ -2672,10 +3077,6 @@ "dev": true, "license": "ISC" }, - "node_modules/jaro-winkler": { - "version": "0.2.8", - "license": "MIT" - }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -2851,6 +3252,28 @@ "version": "1.5.0", "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "license": "MIT", @@ -3339,6 +3762,15 @@ "dev": true, "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/peer-wire-protocol": { "version": "0.7.1", "dependencies": { @@ -3456,6 +3888,18 @@ "split2": "^4.1.0" } }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pino": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", @@ -4334,6 +4778,15 @@ "version": "1.1.1", "license": "MIT" }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -4488,6 +4941,18 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/to-regex-range": { + "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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toposort-class": { "version": "1.0.1", "license": "MIT" @@ -4539,6 +5004,18 @@ "torrent-piece": "^1.0.0" } }, + "node_modules/ts-api-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", + "integrity": "sha512-d+3WxW4r8WQy2cZWpNRPPGExX8ffOLGcIhheUANKbL5Sqjbhkneki76fRAWeXkaslV2etTb4tSJBSxOsH5+CJw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "dev": true, @@ -5062,6 +5539,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/ultron": { "version": "1.0.2", "license": "MIT" diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index a1e5129..4b4fdb1 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -6,7 +6,7 @@ "build": "node esbuild.js", "dev": "tsx watch --ignore node_modules src/index.ts | pino-pretty", "start": "node dist/index.cjs", - "lint": "eslint . --ext .ts,.js" + "lint": "npx eslint ./src --ext .ts,.js" }, "license": "MIT", "dependencies": { @@ -16,7 +16,6 @@ "bottleneck": "^2.19.5", "cache-manager": "^5.4.0", "google-sr": "^3.2.1", - "jaro-winkler": "^0.2.8", "magnet-uri": "^6.2.0", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", @@ -32,17 +31,19 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", - "@types/jaro-winkler": "^0.2.3", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/stremio-addon-sdk": "^1.6.10", "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", "pino-pretty": "^10.3.1", - "tsx": "^4.7.0" + "tsx": "^4.7.0", + "typescript": "^5.3.3" } } diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/jobs/process_torrents_job.ts index f655d31..635df58 100644 --- a/src/node/consumer/src/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/jobs/process_torrents_job.ts @@ -9,7 +9,7 @@ class ProcessTorrentsJob { private readonly assertQueueOptions: Options.AssertQueue = {durable: true}; private readonly consumeQueueOptions: Options.Consume = {noAck: false}; - public listenToQueue = async (): Promise => { + public listenToQueue = async ()=> { if (!configurationService.jobConfig.JOBS_ENABLED) { return; } @@ -52,6 +52,10 @@ class ProcessTorrentsJob { logger.error('Failed to setup channel', error); } } + + private test() { + + } } export const processTorrentsJob = new ProcessTorrentsJob(); \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index ec3b1ce..69882db 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -1,12 +1,12 @@ import { parse } from 'parse-torrent-title'; +import { repository } from '../repository/database_repository'; +import { TorrentType } from './enums/torrent_types'; +import { PromiseHelpers } from './helpers/promises_helpers'; +import { logger } from './services/logging_service'; import { metadataService } from './services/metadata_service'; import { parsingService } from './services/parsing_service'; -import {PromiseHelpers} from './helpers/promises_helpers'; -import { repository } from '../repository/database_repository'; import { torrentFileService } from './services/torrent_file_service'; import { torrentSubtitleService } from './services/torrent_subtitle_service'; -import { TorrentType } from './enums/torrent_types'; -import {logger} from './services/logging_service'; export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index a1b55d3..35a11e1 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -32,18 +32,16 @@ class DatabaseRepository { this.database = this.createDatabase(); } - public async connect(): Promise { + public async connect() { try { - await this.database.authenticate(); - logger.info('Database connection has been established successfully.'); await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); - } catch (error) { - logger.error('Failed syncing database: ', error); - throw error; + } catch { + logger.error('Failed syncing database'); + process.exit(1); } } - public async getProvider(provider: Provider): Promise { + public async getProvider(provider: Provider) { try { const [result] = await Provider.findOrCreate({ where: { name: { [Op.eq]: provider.name } }, defaults: provider }); return result; diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index 3c3b81b..0003d53 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -1,22 +1,14 @@ { "compilerOptions": { - "baseUrl": "./src", - "checkJs": true, - "allowJs": true, - "isolatedModules": true, - "lib": ["ESNext"], - "module": "ESNext", + "module": "CommonJS", "moduleResolution": "node", - "outDir": "./dist", + "outDir": "dist", "pretty": true, "removeComments": true, - "resolveJsonModule": true, "rootDir": "./src", - "skipLibCheck": true, "sourceMap": true, - "target": "ESNext", - "types": ["node"], - "typeRoots": ["node_modules/@types", "src/@types"], + "target": "ES6", + "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "allowSyntheticDefaultImports": true From 969d956082d11fc9415baeb4c06a9ad6b7b6a1a5 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 10:42:26 +0000 Subject: [PATCH 16/55] extension_service formatting --- src/node/consumer/src/lib/services/extension_service.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/node/consumer/src/lib/services/extension_service.ts b/src/node/consumer/src/lib/services/extension_service.ts index 4e270ad..f80db1e 100644 --- a/src/node/consumer/src/lib/services/extension_service.ts +++ b/src/node/consumer/src/lib/services/extension_service.ts @@ -19,6 +19,7 @@ class ExtensionService { "ogm", "divx" ]; + private readonly SUBTITLE_EXTENSIONS: string[] = [ "aqt", "gsub", @@ -38,6 +39,7 @@ class ExtensionService { "idx", "vtt" ]; + private readonly DISK_EXTENSIONS: string[] = [ "iso", "m2ts", @@ -63,7 +65,4 @@ class ExtensionService { } } -export const extensionService = new ExtensionService(); - - - +export const extensionService = new ExtensionService(); \ No newline at end of file From 457df6b3269eeb231012ed09650d2cc3e52152b6 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 10:47:59 +0000 Subject: [PATCH 17/55] remove boolean helpers class --- src/node/consumer/src/lib/helpers/boolean_helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index 9b608c0..ff115f0 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,5 +1,5 @@ -export class BooleanHelpers { - public static parseBool(value: string, defaultValue: boolean): boolean { +export const BooleanHelpers = { + parseBool: function(value: string | undefined, defaultValue: boolean) { if (value === undefined) { return defaultValue; } From 7cb69a69d98b70c76096a80b10ac347ca8a742bf Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 11:00:29 +0000 Subject: [PATCH 18/55] to functional constants --- .../src/lib/helpers/promises_helpers.ts | 46 ++++++------------- .../lib/models/configuration/cache_config.ts | 22 ++++----- .../models/configuration/database_config.ts | 20 ++++---- .../lib/models/configuration/job_config.ts | 8 ++-- .../models/configuration/metadata_config.ts | 8 ++-- .../lib/models/configuration/rabbit_config.ts | 8 ++-- .../models/configuration/torrent_config.ts | 8 ++-- .../models/configuration/tracker_config.ts | 8 ++-- .../src/lib/services/configuration_service.ts | 34 +++++++------- 9 files changed, 72 insertions(+), 90 deletions(-) diff --git a/src/node/consumer/src/lib/helpers/promises_helpers.ts b/src/node/consumer/src/lib/helpers/promises_helpers.ts index 3837d19..366ec24 100644 --- a/src/node/consumer/src/lib/helpers/promises_helpers.ts +++ b/src/node/consumer/src/lib/helpers/promises_helpers.ts @@ -1,37 +1,24 @@ -export class PromiseHelpers { - public static async sequence(promises: Array<() => Promise>): Promise { - return promises.reduce((promise: Promise, func: () => Promise) => - promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); - } +export const PromiseHelpers = { - /** - * Return first resolved promise as the result. - */ - public static async first(promises: Array>): Promise { + sequence: async function(promises: (() => Promise)[]) { + return promises.reduce((promise, func) => + promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); + }, + + first: async function(promises) { return Promise.all(promises.map(p => { - // If a request fails, count that as a resolution so it will keep - // waiting for other possible successes. If a request succeeds, - // treat it as a rejection so Promise.all immediately bails out. return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); })).then( - // If '.all' resolved, we've just got an array of errors. (errors) => Promise.reject(errors), - // If '.all' rejected, we've got the result we wanted. (val) => Promise.resolve(val) ); - } + }, - /** - * Delay promise - */ - public static async delay(duration: number): Promise { - return new Promise((resolve) => setTimeout(() => resolve(), duration)); - } + delay: async function(duration: number) { + return new Promise(resolve => setTimeout(() => resolve(), duration)); + }, - /** - * Timeout promise after a set time in ms - */ - public static async timeout(timeoutMs: number, promise: Promise, message = 'Timed out'): Promise { + timeout: async function(timeoutMs: number, promise, message = 'Timed out') { return Promise.race([ promise, new Promise(function (resolve, reject) { @@ -40,12 +27,9 @@ export class PromiseHelpers { }, timeoutMs); }) ]); - } + }, - /** - * Return most common value from given array. - */ - public static mostCommonValue(array: any[]): any { + mostCommonValue: function(array) { return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); } -} +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/cache_config.ts b/src/node/consumer/src/lib/models/configuration/cache_config.ts index 1ca735b..0e2c927 100644 --- a/src/node/consumer/src/lib/models/configuration/cache_config.ts +++ b/src/node/consumer/src/lib/models/configuration/cache_config.ts @@ -1,15 +1,15 @@ import {BooleanHelpers} from "../../helpers/boolean_helpers"; -export class CacheConfig { - public MONGODB_HOST: string = process.env.MONGODB_HOST || 'mongodb'; - public MONGODB_PORT: string = process.env.MONGODB_PORT || '27017'; - public MONGODB_DB: string = process.env.MONGODB_DB || 'knightcrawler'; - public MONGO_INITDB_ROOT_USERNAME: string = process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo'; - public MONGO_INITDB_ROOT_PASSWORD: string = process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo'; - public NO_CACHE: boolean = BooleanHelpers.parseBool(process.env.NO_CACHE, false); - public COLLECTION_NAME: string = process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection'; - - public get MONGO_URI() { +export const cacheConfig = { + MONGODB_HOST: process.env.MONGODB_HOST || 'mongodb', + MONGODB_PORT: process.env.MONGODB_PORT || '27017', + MONGODB_DB: process.env.MONGODB_DB || 'knightcrawler', + MONGO_INITDB_ROOT_USERNAME: process.env.MONGO_INITDB_ROOT_USERNAME || 'mongo', + MONGO_INITDB_ROOT_PASSWORD: process.env.MONGO_INITDB_ROOT_PASSWORD || 'mongo', + NO_CACHE: BooleanHelpers.parseBool(process.env.NO_CACHE, false), + COLLECTION_NAME: process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection', + + get MONGO_URI() { return `mongodb://${this.MONGO_INITDB_ROOT_USERNAME}:${this.MONGO_INITDB_ROOT_PASSWORD}@${this.MONGODB_HOST}:${this.MONGODB_PORT}/${this.MONGODB_DB}?authSource=admin`; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts index 754cd85..8e5dccd 100644 --- a/src/node/consumer/src/lib/models/configuration/database_config.ts +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -1,14 +1,14 @@ import {BooleanHelpers} from "../../helpers/boolean_helpers"; -export class DatabaseConfig { - public POSTGRES_HOST: string = process.env.POSTGRES_HOST || 'postgres'; - public POSTGRES_PORT: number = parseInt(process.env.POSTGRES_PORT || '5432'); - public POSTGRES_DB: string = process.env.POSTGRES_DB || 'knightcrawler'; - public POSTGRES_USER: string = process.env.POSTGRES_USER || 'postgres'; - public POSTGRES_PASSWORD: string = process.env.POSTGRES_PASSWORD || 'postgres'; - public AUTO_CREATE_AND_APPLY_MIGRATIONS : boolean = BooleanHelpers.parseBool(process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS, false); - - public get POSTGRES_URI() { +export const databaseConfig = { + POSTGRES_HOST: process.env.POSTGRES_HOST || 'postgres', + POSTGRES_PORT: parseInt(process.env.POSTGRES_PORT || '5432'), + POSTGRES_DB: process.env.POSTGRES_DB || 'knightcrawler', + POSTGRES_USER: process.env.POSTGRES_USER || 'postgres', + POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || 'postgres', + AUTO_CREATE_AND_APPLY_MIGRATIONS: BooleanHelpers.parseBool(process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS, false), + + get POSTGRES_URI() { return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DB}`; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/job_config.ts b/src/node/consumer/src/lib/models/configuration/job_config.ts index 9ebbf90..57cb6ad 100644 --- a/src/node/consumer/src/lib/models/configuration/job_config.ts +++ b/src/node/consumer/src/lib/models/configuration/job_config.ts @@ -1,6 +1,6 @@ import {BooleanHelpers} from "../../helpers/boolean_helpers"; -export class JobConfig { - public JOB_CONCURRENCY: number = parseInt(process.env.JOB_CONCURRENCY || "1", 10); - public JOBS_ENABLED: boolean = BooleanHelpers.parseBool(process.env.JOBS_ENABLED, true); -} \ No newline at end of file +export const jobConfig = { + JOB_CONCURRENCY: parseInt(process.env.JOB_CONCURRENCY || "1", 10), + JOBS_ENABLED: BooleanHelpers.parseBool(process.env.JOBS_ENABLED, true) +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/metadata_config.ts b/src/node/consumer/src/lib/models/configuration/metadata_config.ts index 2debe48..32b4e33 100644 --- a/src/node/consumer/src/lib/models/configuration/metadata_config.ts +++ b/src/node/consumer/src/lib/models/configuration/metadata_config.ts @@ -1,4 +1,4 @@ -export class MetadataConfig { - public IMDB_CONCURRENT: number = parseInt(process.env.IMDB_CONCURRENT || "1", 10); - public IMDB_INTERVAL_MS: number = parseInt(process.env.IMDB_INTERVAL_MS || "1000", 10); -} \ No newline at end of file +export const metadataConfig = { + IMDB_CONCURRENT: parseInt(process.env.IMDB_CONCURRENT || "1", 10), + IMDB_INTERVAL_MS: parseInt(process.env.IMDB_INTERVAL_MS || "1000", 10) +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/rabbit_config.ts b/src/node/consumer/src/lib/models/configuration/rabbit_config.ts index d864f46..b06ff9f 100644 --- a/src/node/consumer/src/lib/models/configuration/rabbit_config.ts +++ b/src/node/consumer/src/lib/models/configuration/rabbit_config.ts @@ -1,4 +1,4 @@ -export class RabbitConfig { - public RABBIT_URI: string = process.env.RABBIT_URI || 'amqp://localhost'; - public QUEUE_NAME: string = process.env.QUEUE_NAME || 'test-queue'; -} \ No newline at end of file +export const rabbitConfig = { + RABBIT_URI: process.env.RABBIT_URI || 'amqp://localhost', + QUEUE_NAME: process.env.QUEUE_NAME || 'test-queue' +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/torrent_config.ts b/src/node/consumer/src/lib/models/configuration/torrent_config.ts index 5f0f6c7..33ea6c6 100644 --- a/src/node/consumer/src/lib/models/configuration/torrent_config.ts +++ b/src/node/consumer/src/lib/models/configuration/torrent_config.ts @@ -1,4 +1,4 @@ -export class TorrentConfig { - public MAX_CONNECTIONS_PER_TORRENT: number = parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10); - public TIMEOUT: number = parseInt(process.env.TORRENT_TIMEOUT || "30000", 10); -} \ No newline at end of file +export const torrentConfig = { + MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10), + TIMEOUT: parseInt(process.env.TORRENT_TIMEOUT || "30000", 10) +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/tracker_config.ts b/src/node/consumer/src/lib/models/configuration/tracker_config.ts index 275dfa3..8b31fff 100644 --- a/src/node/consumer/src/lib/models/configuration/tracker_config.ts +++ b/src/node/consumer/src/lib/models/configuration/tracker_config.ts @@ -1,6 +1,6 @@ import {BooleanHelpers} from "../../helpers/boolean_helpers"; -export class TrackerConfig { - public TRACKERS_URL: string = process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt'; - public UDP_ENABLED: boolean = BooleanHelpers.parseBool(process.env.UDP_TRACKERS_ENABLED, false); -} \ No newline at end of file +export const trackerConfig = { + TRACKERS_URL: process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt', + UDP_ENABLED: BooleanHelpers.parseBool(process.env.UDP_TRACKERS_ENABLED, false) +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/configuration_service.ts b/src/node/consumer/src/lib/services/configuration_service.ts index 9bef6d3..32b56ca 100644 --- a/src/node/consumer/src/lib/services/configuration_service.ts +++ b/src/node/consumer/src/lib/services/configuration_service.ts @@ -1,19 +1,17 @@ -import {RabbitConfig} from "../models/configuration/rabbit_config"; -import {CacheConfig} from "../models/configuration/cache_config"; -import {DatabaseConfig} from "../models/configuration/database_config"; -import {JobConfig} from "../models/configuration/job_config"; -import {MetadataConfig} from "../models/configuration/metadata_config"; -import {TrackerConfig} from "../models/configuration/tracker_config"; -import {TorrentConfig} from "../models/configuration/torrent_config"; +import {rabbitConfig} from "../models/configuration/rabbit_config"; +import {cacheConfig} from "../models/configuration/cache_config"; +import {databaseConfig} from "../models/configuration/database_config"; +import {jobConfig} from "../models/configuration/job_config"; +import {metadataConfig} from "../models/configuration/metadata_config"; +import {trackerConfig} from "../models/configuration/tracker_config"; +import {torrentConfig} from "../models/configuration/torrent_config"; -class ConfigurationService { - public readonly rabbitConfig = new RabbitConfig(); - public readonly cacheConfig = new CacheConfig(); - public readonly databaseConfig = new DatabaseConfig(); - public readonly jobConfig = new JobConfig(); - public readonly metadataConfig = new MetadataConfig(); - public readonly trackerConfig = new TrackerConfig(); - public readonly torrentConfig = new TorrentConfig(); -} - -export const configurationService = new ConfigurationService(); +export const configurationService = { + rabbitConfig: rabbitConfig, + cacheConfig: cacheConfig, + databaseConfig: databaseConfig, + jobConfig: jobConfig, + metadataConfig: metadataConfig, + trackerConfig: trackerConfig, + torrentConfig: torrentConfig +}; From 4e98e8f7b4a5b5ef9182ed69aca1073b51465764 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 11:06:09 +0000 Subject: [PATCH 19/55] once last js has gone - will move the overrides to rules --- src/node/consumer/.eslintrc.json | 24 +++++++++++++++------ src/node/consumer/src/lib/torrentEntries.js | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/node/consumer/.eslintrc.json b/src/node/consumer/.eslintrc.json index 784351f..85b3aad 100644 --- a/src/node/consumer/.eslintrc.json +++ b/src/node/consumer/.eslintrc.json @@ -59,12 +59,22 @@ } ], "prefer-destructuring": "error", - "@typescript-eslint/consistent-type-assertions": [ - "error", - { - "assertionStyle": "as", - "objectLiteralTypeAssertions": "never" + "@typescript-eslint/consistent-type-assertions": "off", + "@typescript-eslint/explicit-function-return-type": "off" + }, + "overrides": [ + { + "files": ["*.ts", "*.mts", "*.cts", "*.tsx"], + "rules": { + "@typescript-eslint/explicit-function-return-type": "error", + "@typescript-eslint/consistent-type-assertions": [ + "error", + { + "assertionStyle": "as", + "objectLiteralTypeAssertions": "never" + } + ] } - ] - } + } + ] } \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index 69882db..c72bb17 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -8,7 +8,7 @@ import { parsingService } from './services/parsing_service'; import { torrentFileService } from './services/torrent_file_service'; import { torrentSubtitleService } from './services/torrent_subtitle_service'; -export async function createTorrentEntry(torrent, overwrite = false) { +export async function createTorrentEntry(torrent, overwrite = false) : Promise { const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { From 815c70709d5fdb73b6ec27a464a09b5cf9704a75 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 11:12:05 +0000 Subject: [PATCH 20/55] add trim --- src/node/consumer/src/lib/helpers/boolean_helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index ff115f0..6d5d785 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -3,6 +3,6 @@ export const BooleanHelpers = { if (value === undefined) { return defaultValue; } - return value.toLowerCase() === 'true'; + return value.toLowerCase().trim() === 'true'; } } \ No newline at end of file From dcf62fe651497fe627021abe4c71a00ab3f6e55c Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 11:17:46 +0000 Subject: [PATCH 21/55] expand boolean helpers to support more than just true and false --- .../src/lib/helpers/boolean_helpers.ts | 40 +++++++++++++++++-- src/node/consumer/src/lib/torrentEntries.js | 2 +- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index 6d5d785..cd66b22 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,8 +1,40 @@ export const BooleanHelpers = { - parseBool: function(value: string | undefined, defaultValue: boolean) { - if (value === undefined) { - return defaultValue; + parseBool: function(value: string | number | undefined, defaultValue: boolean): boolean { + switch (typeof value) { + case 'string': + return parseStringToBool(value, defaultValue); + case 'boolean': + return value; + case 'number': + return parseNumberToBool(value, defaultValue); + default: + return defaultValue; } - return value.toLowerCase().trim() === 'true'; + } +} + +const parseStringToBool = (input: string, defaultVal: boolean): boolean => { + switch (input.toLowerCase().trim()) { + case 'true': + case 'yes': + case '1': + return true; + case 'false': + case 'no': + case '0': + return false; + default: + return defaultVal + } +} + +const parseNumberToBool = (input: number, defaultVal: boolean): boolean => { + switch (input) { + case 1: + return true; + case 0: + return false; + default: + return defaultVal; } } \ No newline at end of file diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js index c72bb17..0108e61 100644 --- a/src/node/consumer/src/lib/torrentEntries.js +++ b/src/node/consumer/src/lib/torrentEntries.js @@ -8,7 +8,7 @@ import { parsingService } from './services/parsing_service'; import { torrentFileService } from './services/torrent_file_service'; import { torrentSubtitleService } from './services/torrent_subtitle_service'; -export async function createTorrentEntry(torrent, overwrite = false) : Promise { +export async function createTorrentEntry(torrent, overwrite = false) { const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { From 555097d40b5ed069768e3236c5d2a448d7670a1a Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Tue, 6 Feb 2024 15:29:40 +0000 Subject: [PATCH 22/55] wip torrent_file_service, not completed yet --- .../lib/interfaces/parsable_torrent_file.ts | 12 - .../src/lib/interfaces/parsed_torrent.ts | 18 ++ .../lib/interfaces/torrent_file_collection.ts | 10 +- .../src/lib/interfaces/torrent_info.ts | 16 -- .../src/lib/services/parsing_service.ts | 106 -------- .../lib/services/torrent_download_service.ts | 125 ++++++--- .../lib/services/torrent_entries_service.ts | 233 ++++++++++++++++ .../src/lib/services/torrent_file_service.ts | 257 +++++++++++++----- .../services/torrent_processing_service.ts | 14 +- .../lib/services/torrent_subtitle_service.ts | 22 +- src/node/consumer/src/lib/torrentEntries.js | 183 ------------- .../src/repository/database_repository.ts | 47 +--- .../repository/interfaces/file_attributes.ts | 23 +- .../interfaces/torrent_attributes.ts | 28 +- 14 files changed, 592 insertions(+), 502 deletions(-) delete mode 100644 src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts create mode 100644 src/node/consumer/src/lib/interfaces/parsed_torrent.ts delete mode 100644 src/node/consumer/src/lib/interfaces/torrent_info.ts delete mode 100644 src/node/consumer/src/lib/services/parsing_service.ts create mode 100644 src/node/consumer/src/lib/services/torrent_entries_service.ts delete mode 100644 src/node/consumer/src/lib/torrentEntries.js diff --git a/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts b/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts deleted file mode 100644 index 394570f..0000000 --- a/src/node/consumer/src/lib/interfaces/parsable_torrent_file.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; - -export interface ParsableTorrentFile extends ParseTorrentTitleResult { - name?: string; - path?: string; - size?: number; - length?: number; - fileIndex?: number; - isMovie?: boolean; - imdbId?: string | number; - kitsuId?: number | string; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts new file mode 100644 index 0000000..fad6616 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts @@ -0,0 +1,18 @@ +import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; +import {TorrentType} from "../enums/torrent_types"; +import {TorrentFileCollection} from "./torrent_file_collection"; + +export interface ParsedTorrent extends ParseTorrentTitleResult { + size?: number; + isPack?: boolean; + imdbId?: string | number; + kitsuId?: string | number; + trackers?: string; + provider?: string | null; + infoHash: string | null; + type: string | TorrentType; + uploadDate?: Date; + seeders?: number; + torrentId?: string; + fileCollection?: TorrentFileCollection; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts index 500c5b0..1e00090 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts @@ -1,7 +1,9 @@ -import {ParsableTorrentFile} from "./parsable_torrent_file"; +import {ContentAttributes} from "../../repository/interfaces/content_attributes"; +import {FileAttributes} from "../../repository/interfaces/file_attributes"; +import {SubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; export interface TorrentFileCollection { - contents?: ParsableTorrentFile[]; - videos?: ParsableTorrentFile[]; - subtitles?: ParsableTorrentFile[]; + contents?: ContentAttributes[]; + videos?: FileAttributes[]; + subtitles?: SubtitleAttributes[]; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_info.ts b/src/node/consumer/src/lib/interfaces/torrent_info.ts deleted file mode 100644 index 93f7082..0000000 --- a/src/node/consumer/src/lib/interfaces/torrent_info.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {TorrentType} from "../enums/torrent_types"; - -export interface TorrentInfo { - title: string | null; - torrentId: string; - infoHash: string | null; - seeders: number; - uploadDate: Date; - imdbId?: string; - kitsuId?: string; - type: TorrentType; - provider?: string | null; - trackers: string; - size?: number; - pack?: boolean; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/parsing_service.ts b/src/node/consumer/src/lib/services/parsing_service.ts deleted file mode 100644 index bb8da27..0000000 --- a/src/node/consumer/src/lib/services/parsing_service.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { parse } from 'parse-torrent-title'; -import { TorrentType } from '../enums/torrent_types'; -import {ParseTorrentTitleResult} from "../interfaces/parse_torrent_title_result"; -import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; -import {TorrentInfo} from "../interfaces/torrent_info"; - -class ParsingService { - private readonly MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB - - public parseSeriesVideos(torrent: TorrentInfo, videos: ParsableTorrentFile[]): ParsableTorrentFile[] { - const parsedTorrentName = parse(torrent.title); - const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); - const parsedVideos = videos.map(video => this.parseSeriesVideo(video, parsedTorrentName)); - return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(video, parsedVideos, torrent.type, hasMovies) })); - } - - public isPackTorrent(torrent: TorrentInfo): boolean { - if (torrent.pack) { - return true; - } - const parsedInfo = parse(torrent.title); - if (torrent.type === TorrentType.Movie) { - return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); - } - const hasMultipleEpisodes = parsedInfo.complete || - torrent.size > this.MULTIPLE_FILES_SIZE || - (parsedInfo.seasons && parsedInfo.seasons.length > 1) || - (parsedInfo.episodes && parsedInfo.episodes.length > 1) || - (parsedInfo.seasons && !parsedInfo.episodes); - const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); - return hasMultipleEpisodes && !hasSingleEpisode; - } - - private parseSeriesVideo(video: ParsableTorrentFile, parsedTorrentName: ParseTorrentTitleResult): ParseTorrentTitleResult { - const videoInfo = parse(video.name); - // the episode may be in a folder containing season number - if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { - const folders = video.path.split('/'); - const pathInfo = parse(folders[folders.length - 2]); - videoInfo.season = pathInfo.season; - } - if (!Number.isInteger(videoInfo.season) && parsedTorrentName.season) { - videoInfo.season = parsedTorrentName.season; - } - if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { - // in case single file was interpreted as having multiple seasons - videoInfo.season = videoInfo.seasons[0]; - } - if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && parsedTorrentName.seasons - && parsedTorrentName.seasons.length > 1) { - // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv - const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); - videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; - } - // sometimes video file does not have correct date format as in torrent title - if (!videoInfo.episodes && !videoInfo.date && parsedTorrentName.date) { - videoInfo.date = parsedTorrentName.date; - } - // limit number of episodes in case of incorrect parsing - if (videoInfo.episodes && videoInfo.episodes.length > 20) { - videoInfo.episodes = [videoInfo.episodes[0]]; - videoInfo.episode = videoInfo.episodes[0]; - } - // force episode to any found number if it was not parsed - if (!videoInfo.episodes && !videoInfo.date) { - const epMatcher = videoInfo.title.match( - /(? 3 - && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; - } -} - -export const parsingService = new ParsingService(); - diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 58a7241..dae27e1 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,10 +1,20 @@ -import { encode } from 'magnet-uri'; +import {encode} from 'magnet-uri'; import torrentStream from 'torrent-stream'; -import { configurationService } from './configuration_service'; +import {configurationService} from './configuration_service'; import {extensionService} from './extension_service'; -import {TorrentInfo} from "../interfaces/torrent_info"; import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; +import {ParsedTorrent} from "../interfaces/parsed_torrent"; +import {FileAttributes} from "../../repository/interfaces/file_attributes"; +import {SubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; +import {ContentAttributes} from "../../repository/interfaces/content_attributes"; +import {parse} from "parse-torrent-title"; + +interface TorrentFile { + name: string; + path: string; + length: number; + fileIndex: number; +} class TorrentDownloadService { private engineOptions: TorrentStream.TorrentEngineOptions = { @@ -14,73 +24,124 @@ class TorrentDownloadService { dht: false, tracker: true, }; - - public async getTorrentFiles(torrent: TorrentInfo, timeout: number = 30000): Promise { - return this.filesFromTorrentStream(torrent, timeout) - .then((files: Array) => ({ - contents: files, - videos: this.filterVideos(files), - subtitles: this.filterSubtitles(files) - })); + + public async getTorrentFiles(torrent: ParsedTorrent, timeout: number = 30000): Promise { + const torrentFiles: TorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); + + const videos = this.filterVideos(torrent, torrentFiles); + const subtitles = this.filterSubtitles(torrent, torrentFiles); + const contents = this.createContent(torrent, torrentFiles); + + return { + contents: contents, + videos: videos, + subtitles: subtitles, + }; } - private async filesFromTorrentStream(torrent: TorrentInfo, timeout: number): Promise> { + private async filesFromTorrentStream(torrent: ParsedTorrent, timeout: number): Promise { if (!torrent.infoHash) { return Promise.reject(new Error("No infoHash...")); } - const magnet = encode({ infoHash: torrent.infoHash, announce: torrent.trackers.split(',') }); + const magnet = encode({infoHash: torrent.infoHash, announce: torrent.trackers.split(',')}); return new Promise((resolve, reject) => { let engine: TorrentStream.TorrentEngine; const timeoutId = setTimeout(() => { - engine.destroy(() => {}); + engine.destroy(() => { + }); reject(new Error('No available connections for torrent!')); }, timeout); engine = torrentStream(magnet, this.engineOptions); engine.on("ready", () => { - const files: ParsableTorrentFile[] = engine.files.map((file, fileId) => ({ + const files: TorrentFile[] = engine.files.map((file, fileId) => ({ ...file, fileIndex: fileId, size: file.length, - title: file.name})); - + title: file.name + })); + resolve(files); - engine.destroy(() => {}); + engine.destroy(() => { + }); clearTimeout(timeoutId); }); }); } - private filterVideos(files: Array): Array { - if (files.length === 1 && !Number.isInteger(files[0].fileIndex)) { - return files; + private filterVideos(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): FileAttributes[] { + if (torrentFiles.length === 1 && !Number.isInteger(torrentFiles[0].fileIndex)) { + return [this.mapTorrentFileToFileAttributes(torrent, torrentFiles[0])]; } - const videos = files.filter(file => extensionService.isVideo(file.path || '')); - const maxSize = Math.max(...videos.map((video: ParsableTorrentFile) => video.length)); + const videos = torrentFiles.filter(file => extensionService.isVideo(file.path || '')); + const maxSize = Math.max(...videos.map((video: TorrentFile) => video.length)); const minSampleRatio = videos.length <= 3 ? 3 : 10; const minAnimeExtraRatio = 5; const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = (video: ParsableTorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.length.toString()) > minSampleRatio; - const isRedundant = (video: ParsableTorrentFile) => maxSize / parseInt(video.length.toString()) > minRedundantRatio; - const isExtra = (video: ParsableTorrentFile) => video.path?.match(/extras?\//i); - const isAnimeExtra = (video: ParsableTorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + + const isSample = (video: TorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.path.toString()) > minSampleRatio; + const isRedundant = (video: TorrentFile) => maxSize / parseInt(video.path.toString()) > minRedundantRatio; + const isExtra = (video: TorrentFile) => video.path?.match(/extras?\//i); + const isAnimeExtra = (video: TorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; - const isWatermark = (video: ParsableTorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + const isWatermark = (video: TorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio + return videos .filter(video => !isSample(video)) .filter(video => !isExtra(video)) .filter(video => !isAnimeExtra(video)) .filter(video => !isRedundant(video)) - .filter(video => !isWatermark(video)); + .filter(video => !isWatermark(video)) + .map(video => this.mapTorrentFileToFileAttributes(torrent, video)); } - private filterSubtitles(files: Array): Array { - return files.filter(file => extensionService.isSubtitle(file.path || '')); + private filterSubtitles(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): SubtitleAttributes[] { + return torrentFiles.filter(file => extensionService.isSubtitle(file.name || '')) + .map(file => this.mapTorrentFileToSubtitleAttributes(torrent, file)); + } + + private createContent(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): ContentAttributes[] { + return torrentFiles.map(file => this.mapTorrentFileToContentAttributes(torrent, file)); + } + + private mapTorrentFileToFileAttributes(torrent: ParsedTorrent, file: TorrentFile): FileAttributes { + const videoFile: FileAttributes = { + title: file.name, + size: file.length, + fileIndex: file.fileIndex || 0, + infoHash: torrent.infoHash, + imdbId: torrent.imdbId.toString(), + imdbSeason: torrent.season || 0, + imdbEpisode: torrent.episode || 0, + kitsuId: parseInt(torrent.kitsuId.toString()) || 0, + kitsuEpisode: torrent.episode || 0 + }; + + return {...videoFile, ...parse(file.name)}; + } + + private mapTorrentFileToSubtitleAttributes(torrent: ParsedTorrent, file: TorrentFile): SubtitleAttributes { + return { + title: file.name, + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + fileId: file.fileIndex, + path: file.path, + }; + } + + private mapTorrentFileToContentAttributes(torrent: ParsedTorrent, file: TorrentFile): ContentAttributes { + return { + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + path: file.path, + size: file.length, + }; } } diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts new file mode 100644 index 0000000..c4b9fcc --- /dev/null +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -0,0 +1,233 @@ +import {parse} from 'parse-torrent-title'; +import {ParsedTorrent} from "../interfaces/parsed_torrent"; +import {repository} from '../../repository/database_repository'; +import {TorrentType} from '../enums/torrent_types'; +import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {Torrent} from "../../repository/models/torrent"; +import {PromiseHelpers} from '../helpers/promises_helpers'; +import {logger} from './logging_service'; +import {metadataService} from './metadata_service'; +import {torrentFileService} from './torrent_file_service'; +import {torrentSubtitleService} from './torrent_subtitle_service'; +import {TorrentAttributes} from "../../repository/interfaces/torrent_attributes"; +import {File} from "../../repository/models/file"; +import {Subtitle} from "../../repository/models/subtitle"; + +class TorrentEntriesService { + public async createTorrentEntry(torrent: ParsedTorrent, overwrite = false): Promise { + const titleInfo = parse(torrent.title); + + if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { + const imdbQuery = { + title: titleInfo.title, + year: titleInfo.year, + type: torrent.type + }; + torrent.imdbId = await metadataService.getImdbId(imdbQuery) + .catch(() => undefined); + } + if (torrent.imdbId && torrent.imdbId.toString().length < 9) { + // pad zeros to imdbId if missing + torrent.imdbId = 'tt' + torrent.imdbId.toString().replace('tt', '').padStart(7, '0'); + } + if (torrent.imdbId && torrent.imdbId.toString().length > 9 && torrent.imdbId.toString().startsWith('tt0')) { + // sanitize imdbId from redundant zeros + torrent.imdbId = torrent.imdbId.toString().replace(/tt0+([0-9]{7,})$/, 'tt$1'); + } + if (!torrent.kitsuId && torrent.type === TorrentType.Anime) { + const kitsuQuery = { + title: titleInfo.title, + year: titleInfo.year, + season: titleInfo.season, + }; + torrent.kitsuId = await metadataService.getKitsuId(kitsuQuery) + .catch(() => undefined); + } + + if (!torrent.imdbId && !torrent.kitsuId && !torrentFileService.isPackTorrent(torrent)) { + logger.warn(`imdbId or kitsuId not found: ${torrent.provider} ${torrent.title}`); + return; + } + + const fileCollection: TorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + .then((torrentContents: TorrentFileCollection) => overwrite ? this.overwriteExistingFiles(torrent, torrentContents) : torrentContents) + .then((torrentContents: TorrentFileCollection) => torrentSubtitleService.assignSubtitles(torrentContents)) + .catch(error => { + logger.warn(`Failed getting files for ${torrent.title}`, error.message); + return {}; + }); + + if (!fileCollection.videos || !fileCollection.videos.length) { + logger.warn(`no video files found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); + return; + } + + const newTorrent: Torrent = Torrent.build({ + ...torrent, + contents: fileCollection.contents, + subtitles: fileCollection.subtitles + }); + + return repository.createTorrent(newTorrent) + .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { + const newVideo = File.build(video); + return repository.createFile(newVideo) + }))) + .then(() => logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); + } + + public async createSkipTorrentEntry(torrent: Torrent) { + return repository.createSkipTorrent(torrent); + } + + public async getStoredTorrentEntry(torrent: Torrent) { + return repository.getSkipTorrent(torrent.infoHash) + .catch(() => repository.getTorrent(torrent)) + .catch(() => undefined); + } + + public async checkAndUpdateTorrent(torrent: ParsedTorrent): Promise { + const query: TorrentAttributes = { + infoHash: torrent.infoHash, + provider: torrent.provider, + } + + const existingTorrent = await repository.getTorrent(query).catch(() => undefined); + + if (!existingTorrent) { + return false; + } + + if (existingTorrent.provider === 'RARBG') { + return true; + } + if (existingTorrent.provider === 'KickassTorrents' && torrent.provider) { + existingTorrent.provider = torrent.provider; + existingTorrent.torrentId = torrent.torrentId; + } + + if (!existingTorrent.languages && torrent.languages && existingTorrent.provider !== 'RARBG') { + existingTorrent.languages = torrent.languages; + await existingTorrent.save(); + logger.debug(`Updated [${existingTorrent.infoHash}] ${existingTorrent.title} language to ${torrent.languages}`); + } + return this.createTorrentContents(existingTorrent) + .then(() => this.updateTorrentSeeders(existingTorrent)); + } + + public async createTorrentContents(torrent: Torrent) { + if (torrent.opened) { + return; + } + + const storedVideos: File[] = await repository.getFiles(torrent.infoHash).catch(() => []); + if (!storedVideos || !storedVideos.length) { + return; + } + const notOpenedVideo = storedVideos.length === 1 && !Number.isInteger(storedVideos[0].fileIndex); + const imdbId: string | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); + const kitsuId: number | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); + + const fileCollection: TorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos}) + .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) + .then(torrentContents => this.assignMetaIds(torrentContents, imdbId, kitsuId)) + .catch(error => { + logger.warn(`Failed getting contents for [${torrent.infoHash}] ${torrent.title}`, error.message); + return {}; + }); + + this.assignMetaIds(fileCollection, imdbId, kitsuId); + + if (!fileCollection.contents || !fileCollection.contents.length) { + return; + } + + if (notOpenedVideo && fileCollection.videos.length === 1) { + // if both have a single video and stored one was not opened, update stored one to true metadata and use that + storedVideos[0].fileIndex = fileCollection.videos[0].fileIndex; + storedVideos[0].title = fileCollection.videos[0].title; + storedVideos[0].size = fileCollection.videos[0].size; + storedVideos[0].subtitles = fileCollection.videos[0].subtitles.map(subtitle => Subtitle.build(subtitle)); + fileCollection.videos[0] = storedVideos[0]; + } + // no videos available or more than one new videos were in the torrent + const shouldDeleteOld = notOpenedVideo && fileCollection.videos.every(video => !video.id); + + const newTorrent: Torrent = Torrent.build({ + ...torrent, + contents: fileCollection.contents, + subtitles: fileCollection.subtitles + }); + + return repository.createTorrent(newTorrent) + .then(() => { + if (shouldDeleteOld) { + logger.debug(`Deleting old video for [${torrent.infoHash}] ${torrent.title}`) + return storedVideos[0].destroy(); + } + return Promise.resolve(); + }) + .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { + const newVideo = File.build(video); + return repository.createFile(newVideo) + }))) + .then(() => logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) + .catch(error => logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); + } + + public async updateTorrentSeeders(torrent: TorrentAttributes) { + if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { + return torrent; + } + + return repository.setTorrentSeeders(torrent, torrent.seeders) + .catch(error => { + logger.warn('Failed updating seeders:', error); + return undefined; + }); + } + + private assignMetaIds(fileCollection: TorrentFileCollection, imdbId: string, kitsuId: number): TorrentFileCollection { + if (fileCollection.videos && fileCollection.videos.length) { + fileCollection.videos.forEach(video => { + video.imdbId = imdbId; + video.kitsuId = kitsuId; + }); + } + + return fileCollection; + } + + private async overwriteExistingFiles(torrent: ParsedTorrent, torrentContents: TorrentFileCollection) { + const videos = torrentContents && torrentContents.videos; + if (videos && videos.length) { + const existingFiles = await repository.getFiles(torrent.infoHash) + .then((existing) => existing + .reduce((map, next) => { + const fileIndex = next.fileIndex !== undefined ? next.fileIndex : null; + map[fileIndex] = (map[fileIndex] || []).concat(next); + return map; + }, {})) + .catch(() => undefined); + if (existingFiles && Object.keys(existingFiles).length) { + const overwrittenVideos = videos + .map(file => { + const mapping = videos.length === 1 && Object.keys(existingFiles).length === 1 + ? Object.values(existingFiles)[0] + : existingFiles[file.fileIndex !== undefined ? file.fileIndex : null]; + if (mapping) { + const originalFile = mapping.shift(); + return {id: originalFile.id, ...file}; + } + return file; + }); + return {...torrentContents, videos: overwrittenVideos}; + } + return torrentContents; + } + return Promise.reject(`No video files found for: ${torrent.title}`); + } +} + +export const torrentEntriesService = new TorrentEntriesService(); \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 29aa558..4d00026 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -1,30 +1,32 @@ import Bottleneck from 'bottleneck'; import moment from 'moment'; -import { parse } from 'parse-torrent-title'; +import {parse} from 'parse-torrent-title'; import {PromiseHelpers} from '../helpers/promises_helpers'; -import { TorrentType } from '../enums/torrent_types'; -import {TorrentInfo} from "../interfaces/torrent_info"; -import { configurationService } from './configuration_service'; -import { extensionService } from './extension_service'; -import { metadataService } from './metadata_service'; -import { parsingService } from './parsing_service'; -import { torrentDownloadService } from "./torrent_download_service"; +import {TorrentType} from '../enums/torrent_types'; +import {configurationService} from './configuration_service'; +import {extensionService} from './extension_service'; +import {metadataService} from './metadata_service'; +import {torrentDownloadService} from "./torrent_download_service"; import {logger} from "./logging_service"; import {MetadataResponse} from "../interfaces/metadata_response"; -import {ParseTorrentTitleResult} from "../interfaces/parse_torrent_title_result"; import {MetaDataQuery} from "../interfaces/metadata_query"; -import {ParsableTorrentFile} from "../interfaces/parsable_torrent_file"; import {CommonVideoMetadata} from "../interfaces/common_video_metadata"; import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {ParsedTorrent} from "../interfaces/parsed_torrent"; +import {FileAttributes} from "../../repository/interfaces/file_attributes"; +import {ContentAttributes} from "../../repository/interfaces/content_attributes"; class TorrentFileService { private readonly MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB + + private readonly MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB + private readonly imdb_limiter: Bottleneck = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); - public async parseTorrentFiles(torrent: TorrentInfo) { + public async parseTorrentFiles(torrent: ParsedTorrent): Promise { const parsedTorrentName = parse(torrent.title); const query: MetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, @@ -47,7 +49,32 @@ class TorrentFileService { return this.parseSeriesFiles(torrent, metadata) } - private async parseMovieFiles(torrent: TorrentInfo, metadata: MetadataResponse): Promise { + public isPackTorrent(torrent: ParsedTorrent): boolean { + if (torrent.isPack) { + return true; + } + const parsedInfo = parse(torrent.title); + if (torrent.type === TorrentType.Movie) { + return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); + } + const hasMultipleEpisodes = parsedInfo.complete || + torrent.size > this.MULTIPLE_FILES_SIZE || + (parsedInfo.seasons && parsedInfo.seasons.length > 1) || + (parsedInfo.episodes && parsedInfo.episodes.length > 1) || + (parsedInfo.seasons && !parsedInfo.episodes); + const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); + return hasMultipleEpisodes && !hasSingleEpisode; + } + + private parseSeriesVideos(torrent: ParsedTorrent): FileAttributes[] { + const parsedTorrentName = parse(torrent.title); + const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); + const parsedVideos = torrent.fileCollection.videos.map(video => this.parseSeriesVideo(video)); + + return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies) })); + } + + private async parseMovieFiles(torrent: ParsedTorrent, metadata: MetadataResponse): Promise { const {contents, videos, subtitles} = await this.getMoviesTorrentContent(torrent); const filteredVideos = videos .filter(video => video.size > this.MIN_SIZE) @@ -66,7 +93,7 @@ class TorrentFileService { const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => this.isFeaturette(video) ? Promise.resolve(video) - : this.findMovieImdbId(video.name).then(imdbId => ({...video, imdbId})))) + : this.findMovieImdbId(video.title).then(imdbId => ({...video, imdbId})))) .then(videos => videos.map(video => ({ infoHash: torrent.infoHash, fileIndex: video.fileIndex, @@ -77,53 +104,58 @@ class TorrentFileService { return {contents, videos: parsedVideos, subtitles}; } - private async parseSeriesFiles(torrent: TorrentInfo, metadata: MetadataResponse) { - const {contents, videos, subtitles} = await this.getSeriesTorrentContent(torrent); - const parsedVideos = await Promise.resolve(videos) + private async parseSeriesFiles(torrent: ParsedTorrent, metadata: MetadataResponse): TorrentFileCollection { + const fileCollection: TorrentFileCollection = await this.getSeriesTorrentContent(torrent); + const parsedVideos: FileAttributes[] = await Promise.resolve(fileCollection.videos) .then(videos => videos.filter(video => videos.length === 1 || video.size > this.MIN_SIZE)) - .then(videos => parsingService.parseSeriesVideos(torrent, videos)) - .then(videos => this.decomposeEpisodes(torrent, videos, metadata)) - .then(videos => this.assignKitsuOrImdbEpisodes(torrent, videos, metadata)) + .then(videos => this.parseSeriesVideos(torrent)) + .then(videos => this.decomposeEpisodes(torrent, metadata)) + .then(videos => this.assignKitsuOrImdbEpisodes(torrent, fileCollection.videos, metadata)) .then(videos => Promise.all(videos.map(video => video.isMovie ? this.mapSeriesMovie(video, torrent) : this.mapSeriesEpisode(video, torrent, videos)))) .then(videos => videos - .map((video: ParsableTorrentFile) => this.isFeaturette(video) ? this.clearInfoFields(video) : video)) - return {contents, videos: parsedVideos, subtitles}; + .map((video: ParsedTorrent) => this.isFeaturette(video) ? this.clearInfoFields(video) : video)) + return {...torrent.fileCollection, videos: parsedVideos}; } - private async getMoviesTorrentContent(torrent: TorrentInfo) { + private async getMoviesTorrentContent(torrent: ParsedTorrent) { const files = await torrentDownloadService.getTorrentFiles(torrent) .catch(error => { - if (!parsingService.isPackTorrent(torrent)) { - return { videos: [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}], contents:[], subtitles: []} + if (!this.isPackTorrent(torrent)) { + const entries = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; + return { videos: entries, contents:[], subtitles: [], files: entries} } return Promise.reject(error); }); if (files.contents && files.contents.length && !files.videos.length && this.isDiskTorrent(files.contents)) { - files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size}]; + files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; } return files; } + + private getDefaultFileEntries(torrent: ParsedTorrent): FileAttributes[] { + return [{title: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; + } - private async getSeriesTorrentContent(torrent: TorrentInfo) { + private async getSeriesTorrentContent(torrent: ParsedTorrent): Promise { return torrentDownloadService.getTorrentFiles(torrent) .catch(error => { - if (!parsingService.isPackTorrent(torrent)) { - return { videos: [{ name: torrent.title, path: torrent.title, size: torrent.size }], subtitles: [], contents: [] } + if (!this.isPackTorrent(torrent)) { + return { videos: this.getDefaultFileEntries(torrent), subtitles: [], contents: [] } } return Promise.reject(error); }); } - private async mapSeriesEpisode(file: ParsableTorrentFile, torrent: TorrentInfo, files: ParsableTorrentFile[]) : Promise { + private async mapSeriesEpisode(file: FileAttributes, torrent: ParsedTorrent, files: ParsedTorrent[]) : Promise { if (!file.episodes && !file.episodes) { if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { return Promise.resolve({ infoHash: torrent.infoHash, fileIndex: file.fileIndex, - title: file.path || file.name, + title: file.path || file.title, size: file.size, imdbId: torrent.imdbId || file.imdbId, }); @@ -134,17 +166,20 @@ class TorrentFileService { return Promise.resolve(episodeIndexes.map((index) => ({ infoHash: torrent.infoHash, fileIndex: file.fileIndex, - title: file.path || file.name, + title: file.path || file.title, size: file.size, - imdbId: file.imdbId || torrent.imdbId, + imdbId: file.imdbId.toString() || torrent.imdbId.toString(), + imdbSeason: file.season, season: file.season, + imdbEpisode: file.episodes && file.episodes[index], episode: file.episodes && file.episodes[index], + kitsuEpisode: file.episodes && file.episodes[index], episodes: file.episodes, - kitsuId: file.kitsuId || torrent.kitsuId, + kitsuId: parseInt(file.kitsuId.toString() || torrent.kitsuId.toString()), }))) } - private async mapSeriesMovie(file: ParsableTorrentFile, torrent: TorrentInfo): Promise { + private async mapSeriesMovie(torrent: ParsedTorrent, file: FileAttributes): Promise { const kitsuId= torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) .then(result => { if (result instanceof Error) { @@ -168,10 +203,10 @@ class TorrentFileService { return [{ infoHash: torrent.infoHash, fileIndex: file.fileIndex, - title: file.path || file.name, + title: file.path || file.title, size: file.size, imdbId: imdbId, - kitsuId: kitsuId, + kitsuId: parseInt(kitsuId), episodes: undefined, imdbSeason: undefined, imdbEpisode: undefined, @@ -185,16 +220,17 @@ class TorrentFileService { return [{ infoHash: torrent.infoHash, fileIndex: file.fileIndex, - title: file.path || file.name, + title: file.path || file.title, size: file.size, - imdbId: metadata.imdbId || imdbId, - kitsuId: metadata.kitsuId || kitsuId, - season: episodeVideo && metadata.imdbId ? episodeVideo.season : undefined, - episode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, + imdbId: metadata.imdbId.toString() || imdbId, + kitsuId: parseInt(metadata.kitsuId.toString() || kitsuId), + imdbSeason: episodeVideo && metadata.imdbId ? episodeVideo.season : undefined, + imdbEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, + kitsuEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, }]; } - private async decomposeEpisodes(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse = { episodeCount: [] }) { + private async decomposeEpisodes(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse = { episodeCount: [] }) { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -239,7 +275,7 @@ class TorrentFileService { return files; } - private preprocessEpisodes(files: ParsableTorrentFile[]) { + private preprocessEpisodes(files: FileAttributes[]) { // reverse special episode naming when they named with 0 episode, ie. S02E00 files .filter(file => Number.isInteger(file.season) && file.episode === 0) @@ -250,7 +286,7 @@ class TorrentFileService { }) } - private isConcatSeasonAndEpisodeFiles(files: ParsableTorrentFile[], sortedEpisodes: number[], metadata: MetadataResponse) { + private isConcatSeasonAndEpisodeFiles(files: FileAttributes[], sortedEpisodes: number[], metadata: MetadataResponse) { if (metadata.kitsuId !== undefined) { // anime does not use this naming scheme in 99% of cases; return false; @@ -277,11 +313,11 @@ class TorrentFileService { || concatAboveTotalEpisodeCount.length >= thresholdAbove; } - private isDateEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + private isDateEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { return files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); } - private isAbsoluteEpisodeFiles(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + private isAbsoluteEpisodeFiles(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse) { const threshold = Math.ceil(files.length / 5); const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; const nonMovieEpisodes = files @@ -294,18 +330,18 @@ class TorrentFileService { || absoluteEpisodes.length >= threshold; } - private isNewEpisodeNotInMetadata(torrent: TorrentInfo, file: ParsableTorrentFile, metadata: MetadataResponse) { + private isNewEpisodeNotInMetadata(torrent: ParsedTorrent, video: FileAttributes, metadata: MetadataResponse) { // new episode might not yet been indexed by cinemeta. // detect this if episode number is larger than the last episode or season is larger than the last one // only for non anime metas const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; - return !isAnime && !file.isMovie && file.episodes && file.season !== 1 + return !isAnime && !video.isMovie && video.episodes && video.season !== 1 && /continuing|current/i.test(metadata.status) - && file.season >= metadata.episodeCount.length - && file.episodes.every(ep => ep > (metadata.episodeCount[file.season - 1] || 0)); + && video.season >= metadata.episodeCount.length + && video.episodes.every(ep => ep > (metadata.episodeCount[video.season - 1] || 0)); } - private decomposeConcatSeasonAndEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + private decomposeConcatSeasonAndEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { files .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) .filter(file => metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) @@ -317,16 +353,16 @@ class TorrentFileService { } - private decomposeAbsoluteEpisodeFiles(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + private decomposeAbsoluteEpisodeFiles(torrent: ParsedTorrent, videos: FileAttributes[], metadata: MetadataResponse) { if (metadata.episodeCount.length === 0) { - files + videos .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) .forEach(file => { file.season = 1; }); return; } - files + videos .filter(file => file.episodes && !file.isMovie && file.season !== 0) .filter(file => !this.isNewEpisodeNotInMetadata(torrent, file, metadata)) .filter(file => !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]) @@ -341,7 +377,7 @@ class TorrentFileService { }); } - private decomposeDateEpisodeFiles(files: ParsableTorrentFile[], metadata: MetadataResponse) { + private decomposeDateEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { if (!metadata || !metadata.videos || !metadata.videos.length) { return; } @@ -375,7 +411,7 @@ class TorrentFileService { } } - private assignKitsuOrImdbEpisodes(torrent: TorrentInfo, files: ParsableTorrentFile[], metadata: MetadataResponse) { + private assignKitsuOrImdbEpisodes(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse) { if (!metadata || !metadata.videos || !metadata.videos.length) { if (torrent.type === TorrentType.Anime) { // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping @@ -387,7 +423,7 @@ class TorrentFileService { }) if (metadata.type === TorrentType.Movie && files.every(file => !file.imdbId)) { // sometimes a movie has episode naming, thus not recognized as a movie and imdbId not assigned - files.forEach(file => file.imdbId = metadata.imdbId); + files.forEach(file => file.imdbId = metadata.imdbId.toString()); } } return files; @@ -402,14 +438,14 @@ class TorrentFileService { }, {}); if (metadata.videos.some(video => Number.isInteger(video.season)) || !metadata.imdbId) { - files.filter((file => Number.isInteger(file.season) && file.episodes)) + files.filter((file => Number.isInteger(torrent.season) && torrent.episodes)) .map(file => { const seasonMapping = seriesMapping[file.season]; const episodeMapping = seasonMapping && seasonMapping[file.episodes[0]]; - if (episodeMapping && Number.isInteger(episodeMapping.imdbSeason)) { - file.imdbId = metadata.imdbId; - file.season = episodeMapping.imdbSeason; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].imdbEpisode); + if (episodeMapping && Number.isInteger(episodeMapping.season)) { + file.imdbId = metadata.imdbId.toString(); + file.season = episodeMapping.season; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].episode); } else { // no imdb mapping available for episode file.season = undefined; @@ -423,7 +459,7 @@ class TorrentFileService { .forEach(file => { if (seriesMapping[file.season]) { const seasonMapping = seriesMapping[file.season]; - file.imdbId = metadata.imdbId; + file.imdbId = metadata.imdbId.toString(); file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); } else if (seriesMapping[file.season - 1]) { @@ -434,12 +470,12 @@ class TorrentFileService { const differentTitlesCount = new Set(episodes.map(ep => ep.id)).size const skippedCount = episodes.filter(ep => ep.id === firstKitsuId).length; const seasonEpisodes = files - .filter(otherFile => otherFile.season === file.season) + .filter((otherFile: FileAttributes) => otherFile.season === file.season) .reduce((a, b) => a.episodes.concat(b.episodes), []); const isAbsoluteOrder = seasonEpisodes.episodes.every(ep => ep > skippedCount && ep <= episodes.length) const isNormalOrder = seasonEpisodes.episodes.every(ep => ep + skippedCount <= episodes.length) if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { - file.imdbId = metadata.imdbId; + file.imdbId = metadata.imdbId.toString(); file.season = file.season - 1; file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; @@ -448,7 +484,7 @@ class TorrentFileService { } else if (Object.values(seriesMapping).length === 1 && seriesMapping[1]) { // sometimes series might be named with sequel season but it's not a season on imdb and a new title const seasonMapping = seriesMapping[1]; - file.imdbId = metadata.imdbId; + file.imdbId = metadata.imdbId.toString(); file.season = 1; file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); @@ -458,7 +494,7 @@ class TorrentFileService { return files; } - private needsCinemetaMetadataForAnime(files: ParsableTorrentFile[], metadata: MetadataResponse) { + private needsCinemetaMetadataForAnime(files: FileAttributes[], metadata: MetadataResponse) { if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { return false; } @@ -500,7 +536,7 @@ class TorrentFileService { }) } - private findMovieImdbId(title: ParseTorrentTitleResult | string) { + private findMovieImdbId(title: FileAttributes | string) { const parsedTitle = typeof title === 'string' ? parse(title) : title; logger.debug(`Finding movie imdbId for ${title}`); return this.imdb_limiter.schedule(async () => { @@ -517,7 +553,7 @@ class TorrentFileService { }); } - private async findMovieKitsuId(title: ParseTorrentTitleResult | string) { + private async findMovieKitsuId(title: FileAttributes | string) { const parsedTitle = typeof title === 'string' ? parse(title) : title; const kitsuQuery = { title: parsedTitle.title, @@ -532,26 +568,97 @@ class TorrentFileService { } } - private isDiskTorrent(contents: ParsableTorrentFile[]) { + private isDiskTorrent(contents: ContentAttributes[]) { return contents.some(content => extensionService.isDisk(content.path)); } - private isSingleMovie(videos: ParsableTorrentFile[]) { + private isSingleMovie(videos: FileAttributes[]) { return videos.length === 1 || (videos.length === 2 && videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); } - private isFeaturette(video: ParsableTorrentFile) { + private isFeaturette(video: FileAttributes) { return /featurettes?\/|extras-grym/i.test(video.path); } - private clearInfoFields(video: ParsableTorrentFile) { + private parseSeriesVideo(video: FileAttributes): FileAttributes { + const videoInfo = parse(video.title); + // the episode may be in a folder containing season number + if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { + const folders = video.path.split('/'); + const pathInfo = parse(folders[folders.length - 2]); + videoInfo.season = pathInfo.season; + } + if (!Number.isInteger(videoInfo.season) && video.season) { + videoInfo.season = video.season; + } + if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { + // in case single file was interpreted as having multiple seasons + videoInfo.season = videoInfo.seasons[0]; + } + if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && video.seasons + && video.seasons.length > 1) { + // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv + const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); + videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; + } + // sometimes video file does not have correct date format as in torrent title + if (!videoInfo.episodes && !videoInfo.date && video.date) { + videoInfo.date = video.date; + } + // limit number of episodes in case of incorrect parsing + if (videoInfo.episodes && videoInfo.episodes.length > 20) { + videoInfo.episodes = [videoInfo.episodes[0]]; + videoInfo.episode = videoInfo.episodes[0]; + } + // force episode to any found number if it was not parsed + if (!videoInfo.episodes && !videoInfo.date) { + const epMatcher = videoInfo.title.match( + /(? 3 + && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; + } + + private clearInfoFields(video: FileAttributes) { video.imdbId = undefined; - video.season = undefined; - video.episode = undefined; + video.imdbSeason = undefined; + video.imdbEpisode = undefined; video.kitsuId = undefined; + video.kitsuEpisode = undefined; return video; } diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index c74a951..9c59c39 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -1,23 +1,23 @@ -import {TorrentInfo} from "../interfaces/torrent_info"; import {TorrentType} from "../enums/torrent_types"; import {logger} from "./logging_service"; -import {checkAndUpdateTorrent, createTorrentEntry} from "../torrentEntries.js"; import {trackerService} from "./tracker_service"; +import {torrentEntriesService} from "./torrent_entries_service"; import {IngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; +import {ParsedTorrent} from "../interfaces/parsed_torrent"; class TorrentProcessingService { public async processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { const { category } = torrent; const type = category === 'tv' ? TorrentType.Series : TorrentType.Movie; - const torrentInfo: TorrentInfo = await this.parseTorrent(torrent, type); + const torrentInfo: ParsedTorrent = await this.parseTorrent(torrent, type); logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); - if (await checkAndUpdateTorrent(torrentInfo)) { + if (await torrentEntriesService.checkAndUpdateTorrent(torrentInfo)) { return; } - return createTorrentEntry(torrentInfo); + return torrentEntriesService.createTorrentEntry(torrentInfo); } private async assignTorrentTrackers(): Promise { @@ -25,14 +25,14 @@ class TorrentProcessingService { return trackers.join(','); } - private async parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { + private async parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { const infoHash = torrent.info_hash?.trim().toLowerCase() return { title: torrent.name, torrentId: `${torrent.name}_${infoHash}`, infoHash: infoHash, seeders: 100, - size: torrent.size, + size: parseInt(torrent.size), uploadDate: torrent.createdAt, imdbId: this.parseImdbId(torrent), type: category, diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 9cbe739..e0c52a1 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -1,26 +1,28 @@ import { parse } from 'parse-torrent-title'; +import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {FileAttributes} from "../../repository/interfaces/file_attributes"; class TorrentSubtitleService { - public assignSubtitles(contents: any, videos: any[], subtitles: any[]) { - if (videos && videos.length && subtitles && subtitles.length) { - if (videos.length === 1) { - videos[0].subtitles = subtitles; - return { contents, videos, subtitles: [] }; + public assignSubtitles(fileCollection: TorrentFileCollection) : TorrentFileCollection { + if (fileCollection.videos && fileCollection.videos.length && fileCollection.subtitles && fileCollection.subtitles.length) { + if (fileCollection.videos.length === 1) { + fileCollection.videos[0].subtitles = fileCollection.subtitles; + return { ...fileCollection, subtitles: [] }; } - const parsedVideos = videos.map(video => this.parseVideo(video)); - const assignedSubs = subtitles.map(subtitle => ({ subtitle, videos: this.mostProbableSubtitleVideos(subtitle, parsedVideos) })); + const parsedVideos = fileCollection.videos.map(video => this.parseVideo(video)); + const assignedSubs = fileCollection.subtitles.map(subtitle => ({ subtitle, videos: this.mostProbableSubtitleVideos(subtitle, parsedVideos) })); const unassignedSubs = assignedSubs.filter(assignedSub => !assignedSub.videos).map(assignedSub => assignedSub.subtitle); assignedSubs .filter(assignedSub => assignedSub.videos) .forEach(assignedSub => assignedSub.videos.forEach(video => video.subtitles = (video.subtitles || []).concat(assignedSub.subtitle))); - return { contents, videos, subtitles: unassignedSubs }; + return { ...fileCollection, subtitles: unassignedSubs }; } - return { contents, videos, subtitles }; + return fileCollection; } - private parseVideo(video: any) { + private parseVideo(video: FileAttributes) { const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); const folderName = video.title.replace(/\/?[^/]+$/, ''); return { diff --git a/src/node/consumer/src/lib/torrentEntries.js b/src/node/consumer/src/lib/torrentEntries.js deleted file mode 100644 index 0108e61..0000000 --- a/src/node/consumer/src/lib/torrentEntries.js +++ /dev/null @@ -1,183 +0,0 @@ -import { parse } from 'parse-torrent-title'; -import { repository } from '../repository/database_repository'; -import { TorrentType } from './enums/torrent_types'; -import { PromiseHelpers } from './helpers/promises_helpers'; -import { logger } from './services/logging_service'; -import { metadataService } from './services/metadata_service'; -import { parsingService } from './services/parsing_service'; -import { torrentFileService } from './services/torrent_file_service'; -import { torrentSubtitleService } from './services/torrent_subtitle_service'; - -export async function createTorrentEntry(torrent, overwrite = false) { - const titleInfo = parse(torrent.title); - - if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { - const imdbQuery = { - title: titleInfo.title, - year: titleInfo.year, - type: torrent.type - }; - torrent.imdbId = await metadataService.getImdbId(imdbQuery) - .catch(() => undefined); - } - if (torrent.imdbId && torrent.imdbId.length < 9) { - // pad zeros to imdbId if missing - torrent.imdbId = 'tt' + torrent.imdbId.replace('tt', '').padStart(7, '0'); - } - if (torrent.imdbId && torrent.imdbId.length > 9 && torrent.imdbId.startsWith('tt0')) { - // sanitize imdbId from redundant zeros - torrent.imdbId = torrent.imdbId.replace(/tt0+([0-9]{7,})$/, 'tt$1'); - } - if (!torrent.kitsuId && torrent.type === TorrentType.Anime) { - const kitsuQuery = { - title: titleInfo.title, - year: titleInfo.year, - season: titleInfo.season, - }; - torrent.kitsuId = await metadataService.getKitsuId(kitsuQuery) - .catch(() => undefined); - } - - if (!torrent.imdbId && !torrent.kitsuId && !parsingService.isPackTorrent(torrent)) { - logger.warn(`imdbId or kitsuId not found: ${torrent.provider} ${torrent.title}`); - return; - } - - const { contents, videos, subtitles } = await torrentFileService.parseTorrentFiles(torrent) - .then(torrentContents => overwrite ? overwriteExistingFiles(torrent, torrentContents) : torrentContents) - .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) - .catch(error => { - logger.warn(`Failed getting files for ${torrent.title}`, error.message); - return {}; - }); - if (!videos || !videos.length) { - logger.warn(`no video files found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); - return; - } - - return repository.createTorrent({ ...torrent, contents, subtitles }) - .then(() => PromiseHelpers.sequence(videos.map(video => () => repository.createFile(video)))) - .then(() => logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); -} - -async function overwriteExistingFiles(torrent, torrentContents) { - const videos = torrentContents && torrentContents.videos; - if (videos && videos.length) { - const existingFiles = await repository.getFiles({ infoHash: videos[0].infoHash }) - .then((existing) => existing - .reduce((map, next) => { - const fileIndex = next.fileIndex !== undefined ? next.fileIndex : null; - map[fileIndex] = (map[fileIndex] || []).concat(next); - return map; - }, {})) - .catch(() => undefined); - if (existingFiles && Object.keys(existingFiles).length) { - const overwrittenVideos = videos - .map(file => { - const mapping = videos.length === 1 && Object.keys(existingFiles).length === 1 - ? Object.values(existingFiles)[0] - : existingFiles[file.fileIndex !== undefined ? file.fileIndex : null]; - if (mapping) { - const originalFile = mapping.shift(); - return { id: originalFile.id, ...file }; - } - return file; - }); - return { ...torrentContents, videos: overwrittenVideos }; - } - return torrentContents; - } - return Promise.reject(`No video files found for: ${torrent.title}`); -} - -export async function createSkipTorrentEntry(torrent) { - return repository.createSkipTorrent(torrent); -} - -export async function getStoredTorrentEntry(torrent) { - return repository.getSkipTorrent(torrent) - .catch(() => repository.getTorrent(torrent)) - .catch(() => undefined); -} - -export async function checkAndUpdateTorrent(torrent) { - const storedTorrent = torrent.dataValues - ? torrent - : await repository.getTorrent(torrent).catch(() => undefined); - if (!storedTorrent) { - return false; - } - if (storedTorrent.provider === 'RARBG') { - return true; - } - if (storedTorrent.provider === 'KickassTorrents' && torrent.provider) { - storedTorrent.provider = torrent.provider; - storedTorrent.torrentId = torrent.torrentId; - } - if (!storedTorrent.languages && torrent.languages && storedTorrent.provider !== 'RARBG') { - storedTorrent.languages = torrent.languages; - await storedTorrent.save(); - logger.debug(`Updated [${storedTorrent.infoHash}] ${storedTorrent.title} language to ${torrent.languages}`); - } - return createTorrentContents({ ...storedTorrent.get(), torrentLink: torrent.torrentLink }) - .then(() => updateTorrentSeeders(torrent)); -} - -export async function createTorrentContents(torrent) { - if (torrent.opened) { - return; - } - const storedVideos = await repository.getFiles(torrent).catch(() => []); - if (!storedVideos || !storedVideos.length) { - return; - } - const notOpenedVideo = storedVideos.length === 1 && !Number.isInteger(storedVideos[0].fileIndex); - const imdbId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); - const kitsuId = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); - - const { contents, videos, subtitles } = await torrentFileService.parseTorrentFiles({ ...torrent, imdbId, kitsuId }) - .then(torrentContents => notOpenedVideo ? torrentContents : { ...torrentContents, videos: storedVideos }) - .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) - .catch(error => { - logger.warn(`Failed getting contents for [${torrent.infoHash}] ${torrent.title}`, error.message); - return {}; - }); - - if (!contents || !contents.length) { - return; - } - if (notOpenedVideo && videos.length === 1) { - // if both have a single video and stored one was not opened, update stored one to true metadata and use that - storedVideos[0].fileIndex = videos[0].fileIndex; - storedVideos[0].title = videos[0].title; - storedVideos[0].size = videos[0].size; - storedVideos[0].subtitles = videos[0].subtitles; - videos[0] = storedVideos[0]; - } - // no videos available or more than one new videos were in the torrent - const shouldDeleteOld = notOpenedVideo && videos.every(video => !video.id); - - return repository.createTorrent({ ...torrent, contents, subtitles }) - .then(() => { - if (shouldDeleteOld) { - logger.debug(`Deleting old video for [${torrent.infoHash}] ${torrent.title}`) - return storedVideos[0].destroy(); - } - return Promise.resolve(); - }) - .then(() => PromiseHelpers.sequence(videos.map(video => () => repository.createFile(video)))) - .then(() => logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) - .catch(error => logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); -} - -export async function updateTorrentSeeders(torrent) { - if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { - return torrent; - } - - return repository.setTorrentSeeders(torrent, torrent.seeders) - .catch(error => { - logger.warn('Failed updating seeders:', error); - return undefined; - }); -} diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index 35a11e1..51edac1 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -50,7 +50,7 @@ class DatabaseRepository { } } - public async getTorrent(torrent: Torrent): Promise { + public async getTorrent(torrent: TorrentAttributes): Promise { const where = torrent.infoHash ? { infoHash: torrent.infoHash } : { provider: torrent.provider, torrentId: torrent.torrentId }; @@ -69,25 +69,6 @@ class DatabaseRepository { return await File.findAll({ where }); } - public async getUnprocessedIngestedTorrents(): Promise { - return await IngestedTorrent.findAll({ - where: { - processed: false, - category: { - [Op.or]: ['tv', 'movies'] - } - }, - }); - } - - public async setIngestedTorrentsProcessed(ingestedTorrents: IngestedTorrent[]): Promise { - await PromiseHelpers.sequence(ingestedTorrents - .map(ingestedTorrent => async () => { - ingestedTorrent.processed = true; - await ingestedTorrent.save(); - })); - } - public async getTorrentsWithoutSize(): Promise { return await Torrent.findAll({ where: literal( @@ -148,8 +129,8 @@ class DatabaseRepository { ); } - public async deleteTorrent(torrent: TorrentAttributes): Promise { - return await Torrent.destroy({ where: { infoHash: torrent.infoHash } }); + public async deleteTorrent(infoHash: string): Promise { + return await Torrent.destroy({ where: { infoHash: infoHash } }); } public async createFile(file: File): Promise { @@ -171,16 +152,16 @@ class DatabaseRepository { } } - public async getFiles(torrent: Torrent): Promise { - return File.findAll({ where: { infoHash: torrent.infoHash } }); + public async getFiles(infoHash: string): Promise { + return File.findAll({ where: { infoHash: infoHash } }); } public async getFilesBasedOnTitle(titleQuery: string): Promise { return File.findAll({ where: { title: { [Op.regexp]: `${titleQuery}` } } }); } - public async deleteFile(file: File): Promise { - return File.destroy({ where: { id: file.id } }); + public async deleteFile(id: number): Promise { + return File.destroy({ where: { id: id } }); } public async createSubtitles(infoHash: string, subtitles: Subtitle[]): Promise[]> { @@ -209,8 +190,8 @@ class DatabaseRepository { } } - public async getSubtitles(torrent: Torrent): Promise { - return Subtitle.findAll({ where: { infoHash: torrent.infoHash } }); + public async getSubtitles(infoHash: string): Promise { + return Subtitle.findAll({ where: { infoHash: infoHash } }); } public async getUnassignedSubtitles(): Promise { @@ -224,14 +205,14 @@ class DatabaseRepository { } } - public async getContents(torrent: Torrent): Promise { - return Content.findAll({ where: { infoHash: torrent.infoHash } }); + public async getContents(infoHash: string): Promise { + return Content.findAll({ where: { infoHash: infoHash } }); } - public async getSkipTorrent(torrent: Torrent): Promise { - const result = await SkipTorrent.findByPk(torrent.infoHash); + public async getSkipTorrent(infoHash: string): Promise { + const result = await SkipTorrent.findByPk(infoHash); if (!result) { - throw new Error(`torrent not found: ${torrent.infoHash}`); + throw new Error(`torrent not found: ${infoHash}`); } return result.dataValues as SkipTorrent; } diff --git a/src/node/consumer/src/repository/interfaces/file_attributes.ts b/src/node/consumer/src/repository/interfaces/file_attributes.ts index 4cb68ea..7ae8469 100644 --- a/src/node/consumer/src/repository/interfaces/file_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/file_attributes.ts @@ -1,18 +1,21 @@ import {Optional} from "sequelize"; import {SubtitleAttributes} from "./subtitle_attributes"; +import {ParseTorrentTitleResult} from "../../lib/interfaces/parse_torrent_title_result"; -export interface FileAttributes { +export interface FileAttributes extends ParseTorrentTitleResult { id?: number; - infoHash: string; - fileIndex: number; - title: string; - size: number; - imdbId: string; - imdbSeason: number; - imdbEpisode: number; - kitsuId: number; - kitsuEpisode: number; + infoHash?: string; + fileIndex?: number; + title?: string; + size?: number; + imdbId?: string; + imdbSeason?: number; + imdbEpisode?: number; + kitsuId?: number; + kitsuEpisode?: number; subtitles?: SubtitleAttributes[]; + path?: string; + isMovie?: boolean; } export interface FileCreationAttributes extends Optional { diff --git a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts index 0fcef0b..60e4bb7 100644 --- a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts @@ -5,20 +5,20 @@ import {FileAttributes} from "./file_attributes"; export interface TorrentAttributes { infoHash: string; - provider: string; - torrentId: string; - title: string; - size: number; - type: string; - uploadDate: Date; - seeders: number; - trackers: string; - languages: string; - resolution: string; - reviewed: boolean; - opened: boolean; - contents: ContentAttributes[]; - files: FileAttributes[]; + provider?: string; + torrentId?: string; + title?: string; + size?: number; + type?: string; + uploadDate?: Date; + seeders?: number; + trackers?: string; + languages?: string; + resolution?: string; + reviewed?: boolean; + opened?: boolean; + contents?: ContentAttributes[]; + files?: FileAttributes[]; subtitles?: SubtitleAttributes[]; } From 2ca2c77b942dce2db7c0bb9b2ad20b978603792a Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 09:19:09 +0000 Subject: [PATCH 23/55] Initial pass before IOC --- .../consumer/{.eslintrc.json => .eslintrc} | 0 .../src/lib/interfaces/cache_service.ts | 0 .../src/lib/services/cache_service.ts | 2 +- .../src/lib/services/torrent_file_service.ts | 62 +++++++++---------- src/node/consumer/tsconfig.json | 5 +- 5 files changed, 35 insertions(+), 34 deletions(-) rename src/node/consumer/{.eslintrc.json => .eslintrc} (100%) create mode 100644 src/node/consumer/src/lib/interfaces/cache_service.ts diff --git a/src/node/consumer/.eslintrc.json b/src/node/consumer/.eslintrc similarity index 100% rename from src/node/consumer/.eslintrc.json rename to src/node/consumer/.eslintrc diff --git a/src/node/consumer/src/lib/interfaces/cache_service.ts b/src/node/consumer/src/lib/interfaces/cache_service.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 1e1e673..54117e4 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -15,7 +15,7 @@ const GLOBAL_TTL: number = Number(process.env.METADATA_TTL) || 7 * 24 * 60 * 60; const MEMORY_TTL: number = Number(process.env.METADATA_TTL) || 2 * 60 * 60; // 2 hours const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days -type CacheMethod = () => any; +export type CacheMethod = () => any; class CacheService { constructor() { diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 4d00026..e079bc5 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -16,11 +16,10 @@ import {ParsedTorrent} from "../interfaces/parsed_torrent"; import {FileAttributes} from "../../repository/interfaces/file_attributes"; import {ContentAttributes} from "../../repository/interfaces/content_attributes"; +const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB +const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB + class TorrentFileService { - private readonly MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB - - private readonly MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB - private readonly imdb_limiter: Bottleneck = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS @@ -58,7 +57,7 @@ class TorrentFileService { return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); } const hasMultipleEpisodes = parsedInfo.complete || - torrent.size > this.MULTIPLE_FILES_SIZE || + torrent.size > MULTIPLE_FILES_SIZE || (parsedInfo.seasons && parsedInfo.seasons.length > 1) || (parsedInfo.episodes && parsedInfo.episodes.length > 1) || (parsedInfo.seasons && !parsedInfo.episodes); @@ -66,18 +65,18 @@ class TorrentFileService { return hasMultipleEpisodes && !hasSingleEpisode; } - private parseSeriesVideos(torrent: ParsedTorrent): FileAttributes[] { + private parseSeriesVideos(torrent: ParsedTorrent, videos: FileAttributes[]): FileAttributes[] { const parsedTorrentName = parse(torrent.title); const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); - const parsedVideos = torrent.fileCollection.videos.map(video => this.parseSeriesVideo(video)); + const parsedVideos = videos.map(video => this.parseSeriesVideo(video)); return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies) })); } private async parseMovieFiles(torrent: ParsedTorrent, metadata: MetadataResponse): Promise { - const {contents, videos, subtitles} = await this.getMoviesTorrentContent(torrent); - const filteredVideos = videos - .filter(video => video.size > this.MIN_SIZE) + const fileCollection: TorrentFileCollection = await this.getMoviesTorrentContent(torrent); + const filteredVideos = fileCollection.videos + .filter(video => video.size > MIN_SIZE) .filter(video => !this.isFeaturette(video)); if (this.isSingleMovie(filteredVideos)) { const parsedVideos = filteredVideos.map(video => ({ @@ -85,10 +84,10 @@ class TorrentFileService { fileIndex: video.fileIndex, title: video.path || torrent.title, size: video.size || torrent.size, - imdbId: torrent.imdbId || metadata && metadata.imdbId, - kitsuId: torrent.kitsuId || metadata && metadata.kitsuId + imdbId: torrent.imdbId.toString() || metadata && metadata.imdbId.toString(), + kitsuId: parseInt(torrent.kitsuId.toString() || metadata && metadata.kitsuId.toString()) })); - return {contents, videos: parsedVideos, subtitles}; + return {...fileCollection, videos: parsedVideos}; } const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => this.isFeaturette(video) @@ -101,25 +100,26 @@ class TorrentFileService { size: video.size, imdbId: video.imdbId, }))); - return {contents, videos: parsedVideos, subtitles}; + return {...fileCollection, videos: parsedVideos}; } - private async parseSeriesFiles(torrent: ParsedTorrent, metadata: MetadataResponse): TorrentFileCollection { + private async parseSeriesFiles(torrent: ParsedTorrent, metadata: MetadataResponse): Promise { const fileCollection: TorrentFileCollection = await this.getSeriesTorrentContent(torrent); const parsedVideos: FileAttributes[] = await Promise.resolve(fileCollection.videos) - .then(videos => videos.filter(video => videos.length === 1 || video.size > this.MIN_SIZE)) - .then(videos => this.parseSeriesVideos(torrent)) - .then(videos => this.decomposeEpisodes(torrent, metadata)) - .then(videos => this.assignKitsuOrImdbEpisodes(torrent, fileCollection.videos, metadata)) + .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) + .then(videos => this.parseSeriesVideos(torrent, videos)) + .then(videos => this.decomposeEpisodes(torrent, videos, metadata)) + .then(videos => this.assignKitsuOrImdbEpisodes(torrent, videos, metadata)) .then(videos => Promise.all(videos.map(video => video.isMovie - ? this.mapSeriesMovie(video, torrent) - : this.mapSeriesEpisode(video, torrent, videos)))) + ? this.mapSeriesMovie(torrent, video) + : this.mapSeriesEpisode(torrent, video, videos)))) .then(videos => videos - .map((video: ParsedTorrent) => this.isFeaturette(video) ? this.clearInfoFields(video) : video)) + .reduce((a, b) => a.concat(b), []) + .map(video => this.isFeaturette(video) ? this.clearInfoFields(video) : video)); return {...torrent.fileCollection, videos: parsedVideos}; } - private async getMoviesTorrentContent(torrent: ParsedTorrent) { + private async getMoviesTorrentContent(torrent: ParsedTorrent): Promise { const files = await torrentDownloadService.getTorrentFiles(torrent) .catch(error => { if (!this.isPackTorrent(torrent)) { @@ -149,16 +149,16 @@ class TorrentFileService { }); } - private async mapSeriesEpisode(file: FileAttributes, torrent: ParsedTorrent, files: ParsedTorrent[]) : Promise { + private async mapSeriesEpisode(torrent: ParsedTorrent, file: FileAttributes, files: FileAttributes[]) : Promise { if (!file.episodes && !file.episodes) { if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { - return Promise.resolve({ + return Promise.resolve([{ infoHash: torrent.infoHash, fileIndex: file.fileIndex, title: file.path || file.title, size: file.size, - imdbId: torrent.imdbId || file.imdbId, - }); + imdbId: torrent.imdbId.toString() || file.imdbId.toString(), + }]); } return Promise.resolve([]); } @@ -438,7 +438,7 @@ class TorrentFileService { }, {}); if (metadata.videos.some(video => Number.isInteger(video.season)) || !metadata.imdbId) { - files.filter((file => Number.isInteger(torrent.season) && torrent.episodes)) + files.filter((file => Number.isInteger(file.season) && file.episodes)) .map(file => { const seasonMapping = seriesMapping[file.season]; const episodeMapping = seasonMapping && seasonMapping[file.episodes[0]]; @@ -471,9 +471,9 @@ class TorrentFileService { const skippedCount = episodes.filter(ep => ep.id === firstKitsuId).length; const seasonEpisodes = files .filter((otherFile: FileAttributes) => otherFile.season === file.season) - .reduce((a, b) => a.episodes.concat(b.episodes), []); - const isAbsoluteOrder = seasonEpisodes.episodes.every(ep => ep > skippedCount && ep <= episodes.length) - const isNormalOrder = seasonEpisodes.episodes.every(ep => ep + skippedCount <= episodes.length) + .reduce((a, b) => a.concat(b.episodes), []); + const isAbsoluteOrder = seasonEpisodes.every(ep => ep > skippedCount && ep <= episodes.length) + const isNormalOrder = seasonEpisodes.every(ep => ep + skippedCount <= episodes.length) if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { file.imdbId = metadata.imdbId.toString(); file.season = file.season - 1; diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index 0003d53..cd0f68d 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -8,10 +8,11 @@ "rootDir": "./src", "sourceMap": true, "target": "ES6", + "lib": ["es6"], + "types": ["node", "reflect-metadata"], "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "allowSyntheticDefaultImports": true - }, - "exclude": ["node_modules"] + } } \ No newline at end of file From b95f4333159afe936e59e32e1c2880c3b436b86e Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 09:48:32 +0000 Subject: [PATCH 24/55] interfaces normalized and extracted for services --- .../consumer/src/jobs/process_torrents_job.ts | 12 +-- .../src/lib/helpers/extension_helpers.ts | 66 +++++++++++++ .../src/lib/interfaces/cache_options.ts | 2 +- .../src/lib/interfaces/cache_service.ts | 8 ++ .../src/lib/interfaces/cinemeta_metadata.ts | 32 +++--- .../lib/interfaces/common_video_metadata.ts | 2 +- .../lib/interfaces/ingested_rabbit_message.ts | 6 +- .../lib/interfaces/kitsu_catalog_metadata.ts | 12 +-- .../src/lib/interfaces/kitsu_metadata.ts | 20 ++-- .../src/lib/interfaces/logging_service.ts | 6 ++ .../src/lib/interfaces/metadata_query.ts | 2 +- .../src/lib/interfaces/metadata_response.ts | 6 +- .../src/lib/interfaces/metadata_service.ts | 14 +++ .../interfaces/parse_torrent_title_result.ts | 2 +- .../src/lib/interfaces/parsed_torrent.ts | 8 +- .../interfaces/torrent_download_service.ts | 6 ++ .../lib/interfaces/torrent_entries_service.ts | 18 ++++ .../lib/interfaces/torrent_file_collection.ts | 14 +-- .../lib/interfaces/torrent_file_service.ts | 8 ++ .../interfaces/torrent_processing_service.ts | 5 + .../interfaces/torrent_subtitle_service.ts | 5 + .../src/lib/interfaces/tracker_service.ts | 3 + .../src/lib/services/cache_service.ts | 25 ++--- .../src/lib/services/extension_service.ts | 68 ------------- .../src/lib/services/logging_service.ts | 32 +++--- .../src/lib/services/metadata_service.ts | 47 ++++----- .../lib/services/torrent_download_service.ts | 55 ++++++----- .../lib/services/torrent_entries_service.ts | 29 +++--- .../src/lib/services/torrent_file_service.ts | 99 ++++++++++--------- .../services/torrent_processing_service.ts | 17 ++-- .../lib/services/torrent_subtitle_service.ts | 22 +++-- .../src/lib/services/tracker_service.ts | 15 +-- .../src/repository/database_repository.ts | 12 +-- .../interfaces/content_attributes.ts | 4 +- .../repository/interfaces/file_attributes.ts | 10 +- .../interfaces/ingested_page_attributes.ts | 4 +- .../interfaces/ingested_torrent_attributes.ts | 4 +- .../interfaces/provider_attributes.ts | 4 +- .../interfaces/skip_torrent_attributes.ts | 4 +- .../interfaces/subtitle_attributes.ts | 4 +- .../interfaces/torrent_attributes.ts | 16 +-- .../consumer/src/repository/models/content.ts | 4 +- .../consumer/src/repository/models/file.ts | 6 +- .../src/repository/models/ingestedPage.ts | 4 +- .../src/repository/models/ingestedTorrent.ts | 4 +- .../src/repository/models/provider.ts | 4 +- .../src/repository/models/skipTorrent.ts | 4 +- .../src/repository/models/subtitle.ts | 4 +- .../consumer/src/repository/models/torrent.ts | 4 +- 49 files changed, 424 insertions(+), 338 deletions(-) create mode 100644 src/node/consumer/src/lib/helpers/extension_helpers.ts create mode 100644 src/node/consumer/src/lib/interfaces/logging_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/metadata_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_download_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_entries_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_file_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_processing_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts create mode 100644 src/node/consumer/src/lib/interfaces/tracker_service.ts delete mode 100644 src/node/consumer/src/lib/services/extension_service.ts diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/jobs/process_torrents_job.ts index 635df58..93a6f24 100644 --- a/src/node/consumer/src/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/jobs/process_torrents_job.ts @@ -1,6 +1,6 @@ import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' -import {IngestedRabbitMessage, IngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; -import {IngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; +import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; +import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; import {configurationService} from '../lib/services/configuration_service'; import {torrentProcessingService} from '../lib/services/torrent_processing_service'; import {logger} from '../lib/services/logging_service'; @@ -23,13 +23,13 @@ class ProcessTorrentsJob { } } private processMessage = (msg: ConsumeMessage) => { - const ingestedTorrent: IngestedTorrentAttributes = this.getMessageAsJson(msg); + const ingestedTorrent: IIngestedTorrentAttributes = this.getMessageAsJson(msg); return torrentProcessingService.processTorrentRecord(ingestedTorrent); }; - private getMessageAsJson = (msg: ConsumeMessage): IngestedTorrentAttributes => { + private getMessageAsJson = (msg: ConsumeMessage): IIngestedTorrentAttributes => { const content = msg?.content.toString('utf8') ?? "{}"; - const receivedObject: IngestedRabbitMessage = JSON.parse(content); - const receivedTorrent: IngestedRabbitTorrent = receivedObject.message; + const receivedObject: IIngestedRabbitMessage = JSON.parse(content); + const receivedTorrent: IIngestedRabbitTorrent = receivedObject.message; return {...receivedTorrent, info_hash: receivedTorrent.infoHash}; }; private async assertAndConsumeQueue(channel: Channel) { diff --git a/src/node/consumer/src/lib/helpers/extension_helpers.ts b/src/node/consumer/src/lib/helpers/extension_helpers.ts new file mode 100644 index 0000000..b74933b --- /dev/null +++ b/src/node/consumer/src/lib/helpers/extension_helpers.ts @@ -0,0 +1,66 @@ +const VIDEO_EXTENSIONS = [ + "3g2", + "3gp", + "avi", + "flv", + "mkv", + "mk3d", + "mov", + "mp2", + "mp4", + "m4v", + "mpe", + "mpeg", + "mpg", + "mpv", + "webm", + "wmv", + "ogm", + "divx" +]; + +const SUBTITLE_EXTENSIONS = [ + "aqt", + "gsub", + "jss", + "sub", + "ttxt", + "pjs", + "psb", + "rt", + "smi", + "slt", + "ssf", + "srt", + "ssa", + "ass", + "usf", + "idx", + "vtt" +]; + +const DISK_EXTENSIONS = [ + "iso", + "m2ts", + "ts", + "vob" +]; + +export const ExtensionHelpers = { + isVideo(filename: string) { + return this.isExtension(filename, VIDEO_EXTENSIONS); + }, + + isSubtitle(filename: string) { + return this.isExtension(filename, SUBTITLE_EXTENSIONS); + }, + + isDisk(filename: string) { + return this.isExtension(filename, DISK_EXTENSIONS); + }, + + isExtension(filename: string, extensions: string[]) { + const extensionMatch = filename.match(/\.(\w{2,4})$/); + return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cache_options.ts b/src/node/consumer/src/lib/interfaces/cache_options.ts index f8b25e6..8613c41 100644 --- a/src/node/consumer/src/lib/interfaces/cache_options.ts +++ b/src/node/consumer/src/lib/interfaces/cache_options.ts @@ -1,3 +1,3 @@ -export interface CacheOptions { +export interface ICacheOptions { ttl: number; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cache_service.ts b/src/node/consumer/src/lib/interfaces/cache_service.ts index e69de29..3a94858 100644 --- a/src/node/consumer/src/lib/interfaces/cache_service.ts +++ b/src/node/consumer/src/lib/interfaces/cache_service.ts @@ -0,0 +1,8 @@ +import {CacheMethod} from "../services/cache_service"; + +export interface ICacheService { + cacheWrapImdbId: (key: string, method: CacheMethod) => Promise; + cacheWrapKitsuId: (key: string, method: CacheMethod) => Promise; + cacheWrapMetadata: (id: string, method: CacheMethod) => Promise; + cacheTrackers: (method: CacheMethod) => Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts index fc32250..ad3fc1f 100644 --- a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -1,12 +1,12 @@ -import {CommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "./common_video_metadata"; -export interface CinemetaJsonResponse { - meta?: CinemetaMetaData; - trailerStreams?: CinemetaTrailerStream[]; - links?: CinemetaLink[]; - behaviorHints?: CinemetaBehaviorHints; +export interface ICinemetaJsonResponse { + meta?: ICinemetaMetaData; + trailerStreams?: ICinemetaTrailerStream[]; + links?: ICinemetaLink[]; + behaviorHints?: ICinemetaBehaviorHints; } -export interface CinemetaMetaData { +export interface ICinemetaMetaData { awards?: string; cast?: string[]; country?: string; @@ -28,16 +28,16 @@ export interface CinemetaMetaData { year?: string; background?: string; logo?: string; - popularities?: CinemetaPopularities; + popularities?: ICinemetaPopularities; moviedb_id?: number; slug?: string; - trailers?: CinemetaTrailer[]; + trailers?: ICinemetaTrailer[]; id?: string; genres?: string[]; releaseInfo?: string; - videos?: CinemetaVideo[]; + videos?: ICinemetaVideo[]; } -export interface CinemetaPopularities { +export interface ICinemetaPopularities { PXS_TEST?: number; PXS?: number; SCM?: number; @@ -49,11 +49,11 @@ export interface CinemetaPopularities { stremio?: number; stremio_lib?: number; } -export interface CinemetaTrailer { +export interface ICinemetaTrailer { source?: string; type?: string; } -export interface CinemetaVideo extends CommonVideoMetadata { +export interface ICinemetaVideo extends ICommonVideoMetadata { name?: string; number?: number; firstAired?: string; @@ -63,16 +63,16 @@ export interface CinemetaVideo extends CommonVideoMetadata { thumbnail?: string; description?: string; } -export interface CinemetaTrailerStream { +export interface ICinemetaTrailerStream { title?: string; ytId?: string; } -export interface CinemetaLink { +export interface ICinemetaLink { name?: string; category?: string; url?: string; } -export interface CinemetaBehaviorHints { +export interface ICinemetaBehaviorHints { defaultVideoId?: null; hasScheduledVideos?: boolean; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts index 16df177..1a0faf7 100644 --- a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts @@ -1,4 +1,4 @@ -export interface CommonVideoMetadata { +export interface ICommonVideoMetadata { season?: number; episode?: number; released?: string; diff --git a/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts b/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts index 28ef21c..db25a2f 100644 --- a/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts +++ b/src/node/consumer/src/lib/interfaces/ingested_rabbit_message.ts @@ -1,4 +1,4 @@ -export interface IngestedRabbitTorrent { +export interface IIngestedRabbitTorrent { name: string; source: string; category: string; @@ -10,6 +10,6 @@ export interface IngestedRabbitTorrent { processed: boolean; } -export interface IngestedRabbitMessage { - message: IngestedRabbitTorrent; +export interface IIngestedRabbitMessage { + message: IIngestedRabbitTorrent; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts index 42ac1bd..a29f798 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts @@ -1,10 +1,10 @@ -import {KitsuLink, KitsuTrailer} from "./kitsu_metadata"; +import {IKitsuLink, IKitsuTrailer} from "./kitsu_metadata"; -export interface KitsuCatalogJsonResponse { - metas: KitsuCatalogMetaData[]; +export interface IKitsuCatalogJsonResponse { + metas: IKitsuCatalogMetaData[]; } -export interface KitsuCatalogMetaData { +export interface IKitsuCatalogMetaData { id: string; type: string; animeType: string; @@ -18,6 +18,6 @@ export interface KitsuCatalogMetaData { logo?: string; poster: string; background: string; - trailers: KitsuTrailer[]; - links: KitsuLink[]; + trailers: IKitsuTrailer[]; + links: IKitsuLink[]; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts index e789340..ea3f5d5 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -1,10 +1,10 @@ -import {CommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "./common_video_metadata"; -export interface KitsuJsonResponse { +export interface IKitsuJsonResponse { cacheMaxAge?: number; - meta?: KitsuMeta; + meta?: IKitsuMeta; } -export interface KitsuMeta { +export interface IKitsuMeta { aliases?: string[]; animeType?: string; background?: string; @@ -15,7 +15,7 @@ export interface KitsuMeta { imdbRating?: string; imdb_id?: string; kitsu_id?: string; - links?: KitsuLink[]; + links?: IKitsuLink[]; logo?: string; name?: string; poster?: string; @@ -23,23 +23,23 @@ export interface KitsuMeta { runtime?: string; slug?: string; status?: string; - trailers?: KitsuTrailer[]; + trailers?: IKitsuTrailer[]; type?: string; userCount?: number; - videos?: KitsuVideo[]; + videos?: IKitsuVideo[]; year?: string; } -export interface KitsuVideo extends CommonVideoMetadata { +export interface IKitsuVideo extends ICommonVideoMetadata { imdbEpisode?: number; imdbSeason?: number; imdb_id?: string; thumbnail?: string; } -export interface KitsuTrailer { +export interface IKitsuTrailer { source?: string; type?: string; } -export interface KitsuLink { +export interface IKitsuLink { name?: string; category?: string; url?: string; diff --git a/src/node/consumer/src/lib/interfaces/logging_service.ts b/src/node/consumer/src/lib/interfaces/logging_service.ts new file mode 100644 index 0000000..44e7c49 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/logging_service.ts @@ -0,0 +1,6 @@ +export interface ILoggingService { + info(message: string, ...args: any[]): void; + error(message: string, ...args: any[]): void; + debug(message: string, ...args: any[]): void; + warn(message: string, ...args: any[]): void; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_query.ts b/src/node/consumer/src/lib/interfaces/metadata_query.ts index 2ae9c4e..3d6932a 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_query.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_query.ts @@ -1,4 +1,4 @@ -export interface MetaDataQuery { +export interface IMetaDataQuery { title?: string type?: string year?: number | string diff --git a/src/node/consumer/src/lib/interfaces/metadata_response.ts b/src/node/consumer/src/lib/interfaces/metadata_response.ts index ce9670e..c3d481f 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_response.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_response.ts @@ -1,6 +1,6 @@ -import {CommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "./common_video_metadata"; -export interface MetadataResponse { +export interface IMetadataResponse { kitsuId?: number; imdbId?: number; type?: string; @@ -9,7 +9,7 @@ export interface MetadataResponse { country?: string; genres?: string[]; status?: string; - videos?: CommonVideoMetadata[]; + videos?: ICommonVideoMetadata[]; episodeCount?: number[]; totalCount?: number; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_service.ts b/src/node/consumer/src/lib/interfaces/metadata_service.ts new file mode 100644 index 0000000..71a1a2a --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/metadata_service.ts @@ -0,0 +1,14 @@ +import {IMetaDataQuery} from "./metadata_query"; +import {IMetadataResponse} from "./metadata_response"; + +export interface IMetadataService { + getKitsuId(info: IMetaDataQuery): Promise; + + getImdbId(info: IMetaDataQuery): Promise; + + getMetadata(query: IMetaDataQuery): Promise; + + isEpisodeImdbId(imdbId: string | undefined): Promise; + + escapeTitle(title: string): string; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts index 0cc445b..fcb9a61 100644 --- a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts +++ b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts @@ -1,4 +1,4 @@ -export interface ParseTorrentTitleResult { +export interface IParseTorrentTitleResult { title?: string; date?: string; year?: number | string; diff --git a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts index fad6616..8e227ef 100644 --- a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts +++ b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts @@ -1,8 +1,8 @@ -import {ParseTorrentTitleResult} from "./parse_torrent_title_result"; +import {IParseTorrentTitleResult} from "./parse_torrent_title_result"; import {TorrentType} from "../enums/torrent_types"; -import {TorrentFileCollection} from "./torrent_file_collection"; +import {ITorrentFileCollection} from "./torrent_file_collection"; -export interface ParsedTorrent extends ParseTorrentTitleResult { +export interface IParsedTorrent extends IParseTorrentTitleResult { size?: number; isPack?: boolean; imdbId?: string | number; @@ -14,5 +14,5 @@ export interface ParsedTorrent extends ParseTorrentTitleResult { uploadDate?: Date; seeders?: number; torrentId?: string; - fileCollection?: TorrentFileCollection; + fileCollection?: ITorrentFileCollection; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_download_service.ts b/src/node/consumer/src/lib/interfaces/torrent_download_service.ts new file mode 100644 index 0000000..980b354 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_download_service.ts @@ -0,0 +1,6 @@ +import {IParsedTorrent} from "./parsed_torrent"; +import {ITorrentFileCollection} from "./torrent_file_collection"; + +export interface ITorrentDownloadService { + getTorrentFiles(torrent: IParsedTorrent, timeout: number): Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts new file mode 100644 index 0000000..4d4696d --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts @@ -0,0 +1,18 @@ +import {IParsedTorrent} from "./parsed_torrent"; +import {Torrent} from "../../repository/models/torrent"; +import {ITorrentAttributes} from "../../repository/interfaces/torrent_attributes"; +import {SkipTorrent} from "../../repository/models/skipTorrent"; + +export interface ITorrentEntriesService { + createTorrentEntry(torrent: IParsedTorrent, overwrite): Promise; + + createSkipTorrentEntry(torrent: Torrent): Promise<[SkipTorrent, boolean]>; + + getStoredTorrentEntry(torrent: Torrent): Promise; + + checkAndUpdateTorrent(torrent: IParsedTorrent): Promise; + + createTorrentContents(torrent: Torrent): Promise; + + updateTorrentSeeders(torrent: ITorrentAttributes): Promise<[number] | ITorrentAttributes>; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts index 1e00090..5b9f824 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts @@ -1,9 +1,9 @@ -import {ContentAttributes} from "../../repository/interfaces/content_attributes"; -import {FileAttributes} from "../../repository/interfaces/file_attributes"; -import {SubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; +import {IContentAttributes} from "../../repository/interfaces/content_attributes"; +import {IFileAttributes} from "../../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; -export interface TorrentFileCollection { - contents?: ContentAttributes[]; - videos?: FileAttributes[]; - subtitles?: SubtitleAttributes[]; +export interface ITorrentFileCollection { + contents?: IContentAttributes[]; + videos?: IFileAttributes[]; + subtitles?: ISubtitleAttributes[]; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_service.ts b/src/node/consumer/src/lib/interfaces/torrent_file_service.ts new file mode 100644 index 0000000..f34218c --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_file_service.ts @@ -0,0 +1,8 @@ +import {IParsedTorrent} from "./parsed_torrent"; +import {ITorrentFileCollection} from "./torrent_file_collection"; + +export interface ITorrentFileService { + parseTorrentFiles(torrent: IParsedTorrent): Promise; + + isPackTorrent(torrent: IParsedTorrent): boolean; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts new file mode 100644 index 0000000..f4a1db7 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts @@ -0,0 +1,5 @@ +import {IIngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; + +export interface ITorrentProcessingService { + processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts b/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts new file mode 100644 index 0000000..66648b5 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts @@ -0,0 +1,5 @@ +import {ITorrentFileCollection} from "./torrent_file_collection"; + +export interface ITorrentSubtitleService { + assignSubtitles(fileCollection: ITorrentFileCollection): ITorrentFileCollection; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/tracker_service.ts b/src/node/consumer/src/lib/interfaces/tracker_service.ts new file mode 100644 index 0000000..cc15453 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/tracker_service.ts @@ -0,0 +1,3 @@ +export interface ITrackerService { + getTrackers(): Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 54117e4..144000e 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,9 +1,10 @@ import {Cache, createCache, memoryStore} from 'cache-manager'; -import { mongoDbStore } from '@tirke/node-cache-manager-mongodb' -import { configurationService } from './configuration_service'; -import { logger } from './logging_service'; -import { CacheType } from "../enums/cache_types"; -import {CacheOptions} from "../interfaces/cache_options"; +import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' +import {configurationService} from './configuration_service'; +import {logger} from './logging_service'; +import {CacheType} from "../enums/cache_types"; +import {ICacheOptions} from "../interfaces/cache_options"; +import {ICacheService} from "../interfaces/cache_service"; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; @@ -17,7 +18,7 @@ const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days export type CacheMethod = () => any; -class CacheService { +class CacheService implements ICacheService { constructor() { if (!configurationService.cacheConfig.NO_CACHE) { logger.info('Cache is disabled'); @@ -27,18 +28,18 @@ class CacheService { this.memoryCache = this.initiateMemoryCache(); this.remoteCache = this.initiateRemoteCache(); } - + public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, { ttl: GLOBAL_TTL }); + this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, { ttl: MEMORY_TTL }); + this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, {ttl: MEMORY_TTL}); public cacheTrackers = (method: CacheMethod): Promise => - this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, { ttl: TRACKERS_TTL }); + this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, {ttl: TRACKERS_TTL}); private initiateMemoryCache = () => createCache(memoryStore(), { @@ -85,7 +86,7 @@ class CacheService { private readonly remoteCache: Cache; private cacheWrap = async ( - cacheType: CacheType, key: string, method: CacheMethod, options: CacheOptions): Promise => { + cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { const cache = this.getCacheType(cacheType); if (configurationService.cacheConfig.NO_CACHE || !cache) { diff --git a/src/node/consumer/src/lib/services/extension_service.ts b/src/node/consumer/src/lib/services/extension_service.ts deleted file mode 100644 index f80db1e..0000000 --- a/src/node/consumer/src/lib/services/extension_service.ts +++ /dev/null @@ -1,68 +0,0 @@ -class ExtensionService { - private readonly VIDEO_EXTENSIONS: string[] = [ - "3g2", - "3gp", - "avi", - "flv", - "mkv", - "mk3d", - "mov", - "mp2", - "mp4", - "m4v", - "mpe", - "mpeg", - "mpg", - "mpv", - "webm", - "wmv", - "ogm", - "divx" - ]; - - private readonly SUBTITLE_EXTENSIONS: string[] = [ - "aqt", - "gsub", - "jss", - "sub", - "ttxt", - "pjs", - "psb", - "rt", - "smi", - "slt", - "ssf", - "srt", - "ssa", - "ass", - "usf", - "idx", - "vtt" - ]; - - private readonly DISK_EXTENSIONS: string[] = [ - "iso", - "m2ts", - "ts", - "vob" - ] - - public isVideo(filename: string): boolean { - return this.isExtension(filename, this.VIDEO_EXTENSIONS); - } - - public isSubtitle(filename: string): boolean { - return this.isExtension(filename, this.SUBTITLE_EXTENSIONS); - } - - public isDisk(filename: string): boolean { - return this.isExtension(filename, this.DISK_EXTENSIONS); - } - - public isExtension(filename: string, extensions: string[]): boolean { - const extensionMatch = filename.match(/\.(\w{2,4})$/); - return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); - } -} - -export const extensionService = new ExtensionService(); \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index ac23ed8..2d67911 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -1,26 +1,30 @@ import {Logger, pino} from "pino"; +import {ILoggingService} from "../interfaces/logging_service"; + +class LoggingService implements ILoggingService { + private readonly logger: Logger; + + constructor() { + this.logger = pino({ + level: process.env.LOG_LEVEL || 'info' + }); + } -class LoggingService { - public readonly logger: Logger = pino({ - level: process.env.LOG_LEVEL || 'info' - }); - public info(message: string, ...args: any[]): void { - this.logger.info(message); + this.logger.info(message, args); } - + public error(message: string, ...args: any[]): void { - this.logger.error(message); + this.logger.error(message, args); } - + public debug(message: string, ...args: any[]): void { - this.logger.debug(message); + this.logger.debug(message, args); } - + public warn(message: string, ...args: any[]): void { - this.logger.warn(message); + this.logger.warn(message, args); } } -export const logger = new LoggingService(); - +export const logger = new LoggingService(); \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 3a14b23..3b52d4f 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -1,21 +1,22 @@ import axios, {AxiosResponse} from 'axios'; -import {search, ResultTypes} from 'google-sr'; +import {ResultTypes, search} from 'google-sr'; import nameToImdb from 'name-to-imdb'; -import { cacheService } from './cache_service'; -import { TorrentType } from '../enums/torrent_types'; -import {MetadataResponse} from "../interfaces/metadata_response"; -import {CinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; -import {CommonVideoMetadata} from "../interfaces/common_video_metadata"; -import {KitsuJsonResponse} from "../interfaces/kitsu_metadata"; -import {MetaDataQuery} from "../interfaces/metadata_query"; -import {KitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; +import {cacheService} from './cache_service'; +import {TorrentType} from '../enums/torrent_types'; +import {IMetadataResponse} from "../interfaces/metadata_response"; +import {ICinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; +import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; +import {IKitsuJsonResponse} from "../interfaces/kitsu_metadata"; +import {IMetaDataQuery} from "../interfaces/metadata_query"; +import {IKitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; +import {IMetadataService} from "../interfaces/metadata_service"; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; const TIMEOUT = 20000; -class MetadataService { - public async getKitsuId(info: MetaDataQuery): Promise { +class MetadataService implements IMetadataService { + public async getKitsuId(info: IMetaDataQuery): Promise { const title = this.escapeTitle(info.title.replace(/\s\|\s.*/, '')); const year = info.year ? ` ${info.year}` : ''; const season = info.season > 1 ? ` S${info.season}` : ''; @@ -23,9 +24,9 @@ class MetadataService { const query = encodeURIComponent(key); return cacheService.cacheWrapKitsuId(key, - () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, { timeout: 60000 }) + () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, {timeout: 60000}) .then((response) => { - const body = response.data as KitsuCatalogJsonResponse; + const body = response.data as IKitsuCatalogJsonResponse; if (body && body.metas && body.metas.length) { return body.metas[0].id.replace('kitsu:', ''); } else { @@ -34,7 +35,7 @@ class MetadataService { })); } - public async getImdbId(info: MetaDataQuery): Promise { + public async getImdbId(info: IMetaDataQuery): Promise { const name = this.escapeTitle(info.title); const year = info.year || (info.date && info.date.slice(0, 4)); const key = `${name}_${year || 'NA'}_${info.type}`; @@ -53,7 +54,7 @@ class MetadataService { } } - public getMetadata(query: MetaDataQuery): Promise { + public getMetadata(query: IMetaDataQuery): Promise { if (!query.id) { return Promise.reject("no valid id provided"); } @@ -93,14 +94,14 @@ class MetadataService { .trim(); } - private async requestMetadata(url: string): Promise { + private async requestMetadata(url: string): Promise { let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); - let result: MetadataResponse; + let result: IMetadataResponse; const body = response.data; if ('kitsu_id' in body.meta) { - result = this.handleKitsuResponse(body as KitsuJsonResponse); + result = this.handleKitsuResponse(body as IKitsuJsonResponse); } else if ('imdb_id' in body.meta) { - result = this.handleCinemetaResponse(body as CinemetaJsonResponse); + result = this.handleCinemetaResponse(body as ICinemetaJsonResponse); } else { throw new Error('No valid metadata'); } @@ -108,7 +109,7 @@ class MetadataService { return result; } - private handleCinemetaResponse(body: CinemetaJsonResponse): MetadataResponse { + private handleCinemetaResponse(body: ICinemetaJsonResponse): IMetadataResponse { return { imdbId: parseInt(body.meta.imdb_id), type: body.meta.type, @@ -137,7 +138,7 @@ class MetadataService { }; } - private handleKitsuResponse(body: KitsuJsonResponse): MetadataResponse { + private handleKitsuResponse(body: IKitsuJsonResponse): IMetadataResponse { return { kitsuId: parseInt(body.meta.kitsu_id), type: body.meta.type, @@ -167,7 +168,7 @@ class MetadataService { }; } - private getEpisodeCount(videos: CommonVideoMetadata[]) { + private getEpisodeCount(videos: ICommonVideoMetadata[]) { return Object.values( videos .filter(entry => entry.season !== 0 && entry.episode !== 0) @@ -179,7 +180,7 @@ class MetadataService { ); } - private getIMDbIdFromNameToImdb(name: string, info: MetaDataQuery): Promise { + private getIMDbIdFromNameToImdb(name: string, info: IMetaDataQuery): Promise { const year = info.year; const type = info.type; return new Promise((resolve, reject) => { diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index dae27e1..dffcce2 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,22 +1,23 @@ import {encode} from 'magnet-uri'; import torrentStream from 'torrent-stream'; import {configurationService} from './configuration_service'; -import {extensionService} from './extension_service'; -import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ParsedTorrent} from "../interfaces/parsed_torrent"; -import {FileAttributes} from "../../repository/interfaces/file_attributes"; -import {SubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; -import {ContentAttributes} from "../../repository/interfaces/content_attributes"; +import {ExtensionHelpers} from '../helpers/extension_helpers'; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {IFileAttributes} from "../../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; +import {IContentAttributes} from "../../repository/interfaces/content_attributes"; import {parse} from "parse-torrent-title"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; -interface TorrentFile { +interface ITorrentFile { name: string; path: string; length: number; fileIndex: number; } -class TorrentDownloadService { +class TorrentDownloadService implements ITorrentDownloadService { private engineOptions: TorrentStream.TorrentEngineOptions = { connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, uploads: 0, @@ -25,8 +26,8 @@ class TorrentDownloadService { tracker: true, }; - public async getTorrentFiles(torrent: ParsedTorrent, timeout: number = 30000): Promise { - const torrentFiles: TorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); + public async getTorrentFiles(torrent: IParsedTorrent, timeout: number = 30000): Promise { + const torrentFiles: ITorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); const videos = this.filterVideos(torrent, torrentFiles); const subtitles = this.filterSubtitles(torrent, torrentFiles); @@ -39,7 +40,7 @@ class TorrentDownloadService { }; } - private async filesFromTorrentStream(torrent: ParsedTorrent, timeout: number): Promise { + private async filesFromTorrentStream(torrent: IParsedTorrent, timeout: number): Promise { if (!torrent.infoHash) { return Promise.reject(new Error("No infoHash...")); } @@ -57,7 +58,7 @@ class TorrentDownloadService { engine = torrentStream(magnet, this.engineOptions); engine.on("ready", () => { - const files: TorrentFile[] = engine.files.map((file, fileId) => ({ + const files: ITorrentFile[] = engine.files.map((file, fileId) => ({ ...file, fileIndex: fileId, size: file.length, @@ -73,22 +74,22 @@ class TorrentDownloadService { }); } - private filterVideos(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): FileAttributes[] { + private filterVideos(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IFileAttributes[] { if (torrentFiles.length === 1 && !Number.isInteger(torrentFiles[0].fileIndex)) { return [this.mapTorrentFileToFileAttributes(torrent, torrentFiles[0])]; } - const videos = torrentFiles.filter(file => extensionService.isVideo(file.path || '')); - const maxSize = Math.max(...videos.map((video: TorrentFile) => video.length)); + const videos = torrentFiles.filter(file => ExtensionHelpers.isVideo(file.path || '')); + const maxSize = Math.max(...videos.map((video: ITorrentFile) => video.length)); const minSampleRatio = videos.length <= 3 ? 3 : 10; const minAnimeExtraRatio = 5; const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = (video: TorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.path.toString()) > minSampleRatio; - const isRedundant = (video: TorrentFile) => maxSize / parseInt(video.path.toString()) > minRedundantRatio; - const isExtra = (video: TorrentFile) => video.path?.match(/extras?\//i); - const isAnimeExtra = (video: TorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + const isSample = (video: ITorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.path.toString()) > minSampleRatio; + const isRedundant = (video: ITorrentFile) => maxSize / parseInt(video.path.toString()) > minRedundantRatio; + const isExtra = (video: ITorrentFile) => video.path?.match(/extras?\//i); + const isAnimeExtra = (video: ITorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; - const isWatermark = (video: TorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + const isWatermark = (video: ITorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio return videos @@ -100,17 +101,17 @@ class TorrentDownloadService { .map(video => this.mapTorrentFileToFileAttributes(torrent, video)); } - private filterSubtitles(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): SubtitleAttributes[] { - return torrentFiles.filter(file => extensionService.isSubtitle(file.name || '')) + private filterSubtitles(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): ISubtitleAttributes[] { + return torrentFiles.filter(file => ExtensionHelpers.isSubtitle(file.name || '')) .map(file => this.mapTorrentFileToSubtitleAttributes(torrent, file)); } - private createContent(torrent: ParsedTorrent, torrentFiles: TorrentFile[]): ContentAttributes[] { + private createContent(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IContentAttributes[] { return torrentFiles.map(file => this.mapTorrentFileToContentAttributes(torrent, file)); } - private mapTorrentFileToFileAttributes(torrent: ParsedTorrent, file: TorrentFile): FileAttributes { - const videoFile: FileAttributes = { + private mapTorrentFileToFileAttributes(torrent: IParsedTorrent, file: ITorrentFile): IFileAttributes { + const videoFile: IFileAttributes = { title: file.name, size: file.length, fileIndex: file.fileIndex || 0, @@ -125,7 +126,7 @@ class TorrentDownloadService { return {...videoFile, ...parse(file.name)}; } - private mapTorrentFileToSubtitleAttributes(torrent: ParsedTorrent, file: TorrentFile): SubtitleAttributes { + private mapTorrentFileToSubtitleAttributes(torrent: IParsedTorrent, file: ITorrentFile): ISubtitleAttributes { return { title: file.name, infoHash: torrent.infoHash, @@ -135,7 +136,7 @@ class TorrentDownloadService { }; } - private mapTorrentFileToContentAttributes(torrent: ParsedTorrent, file: TorrentFile): ContentAttributes { + private mapTorrentFileToContentAttributes(torrent: IParsedTorrent, file: ITorrentFile): IContentAttributes { return { infoHash: torrent.infoHash, fileIndex: file.fileIndex, diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index c4b9fcc..32d5360 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -1,20 +1,21 @@ import {parse} from 'parse-torrent-title'; -import {ParsedTorrent} from "../interfaces/parsed_torrent"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; import {repository} from '../../repository/database_repository'; import {TorrentType} from '../enums/torrent_types'; -import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; import {Torrent} from "../../repository/models/torrent"; import {PromiseHelpers} from '../helpers/promises_helpers'; import {logger} from './logging_service'; import {metadataService} from './metadata_service'; import {torrentFileService} from './torrent_file_service'; import {torrentSubtitleService} from './torrent_subtitle_service'; -import {TorrentAttributes} from "../../repository/interfaces/torrent_attributes"; +import {ITorrentAttributes} from "../../repository/interfaces/torrent_attributes"; import {File} from "../../repository/models/file"; import {Subtitle} from "../../repository/models/subtitle"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; -class TorrentEntriesService { - public async createTorrentEntry(torrent: ParsedTorrent, overwrite = false): Promise { +class TorrentEntriesService implements ITorrentEntriesService { + public async createTorrentEntry(torrent: IParsedTorrent, overwrite = false): Promise { const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { @@ -49,9 +50,9 @@ class TorrentEntriesService { return; } - const fileCollection: TorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) - .then((torrentContents: TorrentFileCollection) => overwrite ? this.overwriteExistingFiles(torrent, torrentContents) : torrentContents) - .then((torrentContents: TorrentFileCollection) => torrentSubtitleService.assignSubtitles(torrentContents)) + const fileCollection: ITorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + .then((torrentContents: ITorrentFileCollection) => overwrite ? this.overwriteExistingFiles(torrent, torrentContents) : torrentContents) + .then((torrentContents: ITorrentFileCollection) => torrentSubtitleService.assignSubtitles(torrentContents)) .catch(error => { logger.warn(`Failed getting files for ${torrent.title}`, error.message); return {}; @@ -86,8 +87,8 @@ class TorrentEntriesService { .catch(() => undefined); } - public async checkAndUpdateTorrent(torrent: ParsedTorrent): Promise { - const query: TorrentAttributes = { + public async checkAndUpdateTorrent(torrent: IParsedTorrent): Promise { + const query: ITorrentAttributes = { infoHash: torrent.infoHash, provider: torrent.provider, } @@ -128,7 +129,7 @@ class TorrentEntriesService { const imdbId: string | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); const kitsuId: number | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); - const fileCollection: TorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + const fileCollection: ITorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos}) .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) .then(torrentContents => this.assignMetaIds(torrentContents, imdbId, kitsuId)) @@ -176,7 +177,7 @@ class TorrentEntriesService { .catch(error => logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); } - public async updateTorrentSeeders(torrent: TorrentAttributes) { + public async updateTorrentSeeders(torrent: ITorrentAttributes) { if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { return torrent; } @@ -188,7 +189,7 @@ class TorrentEntriesService { }); } - private assignMetaIds(fileCollection: TorrentFileCollection, imdbId: string, kitsuId: number): TorrentFileCollection { + private assignMetaIds(fileCollection: ITorrentFileCollection, imdbId: string, kitsuId: number): ITorrentFileCollection { if (fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { video.imdbId = imdbId; @@ -199,7 +200,7 @@ class TorrentEntriesService { return fileCollection; } - private async overwriteExistingFiles(torrent: ParsedTorrent, torrentContents: TorrentFileCollection) { + private async overwriteExistingFiles(torrent: IParsedTorrent, torrentContents: ITorrentFileCollection) { const videos = torrentContents && torrentContents.videos; if (videos && videos.length) { const existingFiles = await repository.getFiles(torrent.infoHash) diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index e079bc5..1ad6bcd 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -4,30 +4,31 @@ import {parse} from 'parse-torrent-title'; import {PromiseHelpers} from '../helpers/promises_helpers'; import {TorrentType} from '../enums/torrent_types'; import {configurationService} from './configuration_service'; -import {extensionService} from './extension_service'; +import {ExtensionHelpers} from '../helpers/extension_helpers'; import {metadataService} from './metadata_service'; import {torrentDownloadService} from "./torrent_download_service"; import {logger} from "./logging_service"; -import {MetadataResponse} from "../interfaces/metadata_response"; -import {MetaDataQuery} from "../interfaces/metadata_query"; -import {CommonVideoMetadata} from "../interfaces/common_video_metadata"; -import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ParsedTorrent} from "../interfaces/parsed_torrent"; -import {FileAttributes} from "../../repository/interfaces/file_attributes"; -import {ContentAttributes} from "../../repository/interfaces/content_attributes"; +import {IMetadataResponse} from "../interfaces/metadata_response"; +import {IMetaDataQuery} from "../interfaces/metadata_query"; +import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {IFileAttributes} from "../../repository/interfaces/file_attributes"; +import {IContentAttributes} from "../../repository/interfaces/content_attributes"; +import {ITorrentFileService} from "../interfaces/torrent_file_service"; const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB -class TorrentFileService { +class TorrentFileService implements ITorrentFileService { private readonly imdb_limiter: Bottleneck = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); - public async parseTorrentFiles(torrent: ParsedTorrent): Promise { + public async parseTorrentFiles(torrent: IParsedTorrent): Promise { const parsedTorrentName = parse(torrent.title); - const query: MetaDataQuery = { + const query: IMetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, type: torrent.type || TorrentType.Movie, }; @@ -48,7 +49,7 @@ class TorrentFileService { return this.parseSeriesFiles(torrent, metadata) } - public isPackTorrent(torrent: ParsedTorrent): boolean { + public isPackTorrent(torrent: IParsedTorrent): boolean { if (torrent.isPack) { return true; } @@ -65,7 +66,7 @@ class TorrentFileService { return hasMultipleEpisodes && !hasSingleEpisode; } - private parseSeriesVideos(torrent: ParsedTorrent, videos: FileAttributes[]): FileAttributes[] { + private parseSeriesVideos(torrent: IParsedTorrent, videos: IFileAttributes[]): IFileAttributes[] { const parsedTorrentName = parse(torrent.title); const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); const parsedVideos = videos.map(video => this.parseSeriesVideo(video)); @@ -73,8 +74,8 @@ class TorrentFileService { return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies) })); } - private async parseMovieFiles(torrent: ParsedTorrent, metadata: MetadataResponse): Promise { - const fileCollection: TorrentFileCollection = await this.getMoviesTorrentContent(torrent); + private async parseMovieFiles(torrent: IParsedTorrent, metadata: IMetadataResponse): Promise { + const fileCollection: ITorrentFileCollection = await this.getMoviesTorrentContent(torrent); const filteredVideos = fileCollection.videos .filter(video => video.size > MIN_SIZE) .filter(video => !this.isFeaturette(video)); @@ -103,9 +104,9 @@ class TorrentFileService { return {...fileCollection, videos: parsedVideos}; } - private async parseSeriesFiles(torrent: ParsedTorrent, metadata: MetadataResponse): Promise { - const fileCollection: TorrentFileCollection = await this.getSeriesTorrentContent(torrent); - const parsedVideos: FileAttributes[] = await Promise.resolve(fileCollection.videos) + private async parseSeriesFiles(torrent: IParsedTorrent, metadata: IMetadataResponse): Promise { + const fileCollection: ITorrentFileCollection = await this.getSeriesTorrentContent(torrent); + const parsedVideos: IFileAttributes[] = await Promise.resolve(fileCollection.videos) .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) .then(videos => this.parseSeriesVideos(torrent, videos)) .then(videos => this.decomposeEpisodes(torrent, videos, metadata)) @@ -119,7 +120,7 @@ class TorrentFileService { return {...torrent.fileCollection, videos: parsedVideos}; } - private async getMoviesTorrentContent(torrent: ParsedTorrent): Promise { + private async getMoviesTorrentContent(torrent: IParsedTorrent): Promise { const files = await torrentDownloadService.getTorrentFiles(torrent) .catch(error => { if (!this.isPackTorrent(torrent)) { @@ -135,11 +136,11 @@ class TorrentFileService { return files; } - private getDefaultFileEntries(torrent: ParsedTorrent): FileAttributes[] { + private getDefaultFileEntries(torrent: IParsedTorrent): IFileAttributes[] { return [{title: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; } - private async getSeriesTorrentContent(torrent: ParsedTorrent): Promise { + private async getSeriesTorrentContent(torrent: IParsedTorrent): Promise { return torrentDownloadService.getTorrentFiles(torrent) .catch(error => { if (!this.isPackTorrent(torrent)) { @@ -149,7 +150,7 @@ class TorrentFileService { }); } - private async mapSeriesEpisode(torrent: ParsedTorrent, file: FileAttributes, files: FileAttributes[]) : Promise { + private async mapSeriesEpisode(torrent: IParsedTorrent, file: IFileAttributes, files: IFileAttributes[]) : Promise { if (!file.episodes && !file.episodes) { if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { return Promise.resolve([{ @@ -179,7 +180,7 @@ class TorrentFileService { }))) } - private async mapSeriesMovie(torrent: ParsedTorrent, file: FileAttributes): Promise { + private async mapSeriesMovie(torrent: IParsedTorrent, file: IFileAttributes): Promise { const kitsuId= torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) .then(result => { if (result instanceof Error) { @@ -191,7 +192,7 @@ class TorrentFileService { const imdbId = !kitsuId ? await this.findMovieImdbId(file) : undefined; - const query: MetaDataQuery = { + const query: IMetaDataQuery = { id: kitsuId || imdbId, type: TorrentType.Movie }; @@ -230,7 +231,7 @@ class TorrentFileService { }]; } - private async decomposeEpisodes(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse = { episodeCount: [] }) { + private async decomposeEpisodes(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = { episodeCount: [] }) { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -275,7 +276,7 @@ class TorrentFileService { return files; } - private preprocessEpisodes(files: FileAttributes[]) { + private preprocessEpisodes(files: IFileAttributes[]) { // reverse special episode naming when they named with 0 episode, ie. S02E00 files .filter(file => Number.isInteger(file.season) && file.episode === 0) @@ -286,7 +287,7 @@ class TorrentFileService { }) } - private isConcatSeasonAndEpisodeFiles(files: FileAttributes[], sortedEpisodes: number[], metadata: MetadataResponse) { + private isConcatSeasonAndEpisodeFiles(files: IFileAttributes[], sortedEpisodes: number[], metadata: IMetadataResponse) { if (metadata.kitsuId !== undefined) { // anime does not use this naming scheme in 99% of cases; return false; @@ -313,11 +314,11 @@ class TorrentFileService { || concatAboveTotalEpisodeCount.length >= thresholdAbove; } - private isDateEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { + private isDateEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { return files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); } - private isAbsoluteEpisodeFiles(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse) { + private isAbsoluteEpisodeFiles(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) { const threshold = Math.ceil(files.length / 5); const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; const nonMovieEpisodes = files @@ -330,7 +331,7 @@ class TorrentFileService { || absoluteEpisodes.length >= threshold; } - private isNewEpisodeNotInMetadata(torrent: ParsedTorrent, video: FileAttributes, metadata: MetadataResponse) { + private isNewEpisodeNotInMetadata(torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse) { // new episode might not yet been indexed by cinemeta. // detect this if episode number is larger than the last episode or season is larger than the last one // only for non anime metas @@ -341,7 +342,7 @@ class TorrentFileService { && video.episodes.every(ep => ep > (metadata.episodeCount[video.season - 1] || 0)); } - private decomposeConcatSeasonAndEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { + private decomposeConcatSeasonAndEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { files .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) .filter(file => metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) @@ -353,7 +354,7 @@ class TorrentFileService { } - private decomposeAbsoluteEpisodeFiles(torrent: ParsedTorrent, videos: FileAttributes[], metadata: MetadataResponse) { + private decomposeAbsoluteEpisodeFiles(torrent: IParsedTorrent, videos: IFileAttributes[], metadata: IMetadataResponse) { if (metadata.episodeCount.length === 0) { videos .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) @@ -377,7 +378,7 @@ class TorrentFileService { }); } - private decomposeDateEpisodeFiles(files: FileAttributes[], metadata: MetadataResponse) { + private decomposeDateEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { if (!metadata || !metadata.videos || !metadata.videos.length) { return; } @@ -411,7 +412,7 @@ class TorrentFileService { } } - private assignKitsuOrImdbEpisodes(torrent: ParsedTorrent, files: FileAttributes[], metadata: MetadataResponse) { + private assignKitsuOrImdbEpisodes(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) { if (!metadata || !metadata.videos || !metadata.videos.length) { if (torrent.type === TorrentType.Anime) { // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping @@ -429,7 +430,7 @@ class TorrentFileService { return files; } - const seriesMapping: CommonVideoMetadata = metadata.videos + const seriesMapping: ICommonVideoMetadata = metadata.videos .reduce((map, video) => { const episodeMap = map[video.season] || {}; episodeMap[video.episode] = video; @@ -464,13 +465,13 @@ class TorrentFileService { file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); } else if (seriesMapping[file.season - 1]) { // sometimes a second season might be a continuation of the previous season - const seasonMapping = seriesMapping[file.season - 1] as CommonVideoMetadata; + const seasonMapping = seriesMapping[file.season - 1] as ICommonVideoMetadata; const episodes = Object.values(seasonMapping); const firstKitsuId = episodes.length && episodes[0]; const differentTitlesCount = new Set(episodes.map(ep => ep.id)).size const skippedCount = episodes.filter(ep => ep.id === firstKitsuId).length; const seasonEpisodes = files - .filter((otherFile: FileAttributes) => otherFile.season === file.season) + .filter((otherFile: IFileAttributes) => otherFile.season === file.season) .reduce((a, b) => a.concat(b.episodes), []); const isAbsoluteOrder = seasonEpisodes.every(ep => ep > skippedCount && ep <= episodes.length) const isNormalOrder = seasonEpisodes.every(ep => ep + skippedCount <= episodes.length) @@ -494,7 +495,7 @@ class TorrentFileService { return files; } - private needsCinemetaMetadataForAnime(files: FileAttributes[], metadata: MetadataResponse) { + private needsCinemetaMetadataForAnime(files: IFileAttributes[], metadata: IMetadataResponse) { if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { return false; } @@ -510,8 +511,8 @@ class TorrentFileService { .some(file => file.season < minSeason || file.season > maxSeason || file.episodes.every(ep => ep > total)); } - private async updateToCinemetaMetadata(metadata: MetadataResponse) { - const query: MetaDataQuery = { + private async updateToCinemetaMetadata(metadata: IMetadataResponse) { + const query: IMetaDataQuery = { id: metadata.imdbId, type: metadata.type }; @@ -536,7 +537,7 @@ class TorrentFileService { }) } - private findMovieImdbId(title: FileAttributes | string) { + private findMovieImdbId(title: IFileAttributes | string) { const parsedTitle = typeof title === 'string' ? parse(title) : title; logger.debug(`Finding movie imdbId for ${title}`); return this.imdb_limiter.schedule(async () => { @@ -553,7 +554,7 @@ class TorrentFileService { }); } - private async findMovieKitsuId(title: FileAttributes | string) { + private async findMovieKitsuId(title: IFileAttributes | string) { const parsedTitle = typeof title === 'string' ? parse(title) : title; const kitsuQuery = { title: parsedTitle.title, @@ -568,22 +569,22 @@ class TorrentFileService { } } - private isDiskTorrent(contents: ContentAttributes[]) { - return contents.some(content => extensionService.isDisk(content.path)); + private isDiskTorrent(contents: IContentAttributes[]) { + return contents.some(content => ExtensionHelpers.isDisk(content.path)); } - private isSingleMovie(videos: FileAttributes[]) { + private isSingleMovie(videos: IFileAttributes[]) { return videos.length === 1 || (videos.length === 2 && videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); } - private isFeaturette(video: FileAttributes) { + private isFeaturette(video: IFileAttributes) { return /featurettes?\/|extras-grym/i.test(video.path); } - private parseSeriesVideo(video: FileAttributes): FileAttributes { + private parseSeriesVideo(video: IFileAttributes): IFileAttributes { const videoInfo = parse(video.title); // the episode may be in a folder containing season number if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { @@ -629,7 +630,7 @@ class TorrentFileService { return { ...video, ...videoInfo }; } - private isMovieVideo(torrent: ParsedTorrent, video: FileAttributes, otherVideos: FileAttributes[], hasMovies: boolean): boolean { + private isMovieVideo(torrent: IParsedTorrent, video: IFileAttributes, otherVideos: IFileAttributes[], hasMovies: boolean): boolean { if (Number.isInteger(torrent.season) && Array.isArray(torrent.episodes)) { // not movie if video has season return false; @@ -653,7 +654,7 @@ class TorrentFileService { && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; } - private clearInfoFields(video: FileAttributes) { + private clearInfoFields(video: IFileAttributes) { video.imdbId = undefined; video.imdbSeason = undefined; video.imdbEpisode = undefined; diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index 9c59c39..f25fffd 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -2,14 +2,15 @@ import {TorrentType} from "../enums/torrent_types"; import {logger} from "./logging_service"; import {trackerService} from "./tracker_service"; import {torrentEntriesService} from "./torrent_entries_service"; -import {IngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; -import {ParsedTorrent} from "../interfaces/parsed_torrent"; +import {IIngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; -class TorrentProcessingService { - public async processTorrentRecord(torrent: IngestedTorrentAttributes): Promise { - const { category } = torrent; +class TorrentProcessingService implements ITorrentProcessingService { + public async processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise { + const {category} = torrent; const type = category === 'tv' ? TorrentType.Series : TorrentType.Movie; - const torrentInfo: ParsedTorrent = await this.parseTorrent(torrent, type); + const torrentInfo: IParsedTorrent = await this.parseTorrent(torrent, type); logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); @@ -25,7 +26,7 @@ class TorrentProcessingService { return trackers.join(','); } - private async parseTorrent(torrent: IngestedTorrentAttributes, category: string): Promise { + private async parseTorrent(torrent: IIngestedTorrentAttributes, category: string): Promise { const infoHash = torrent.info_hash?.trim().toLowerCase() return { title: torrent.name, @@ -41,7 +42,7 @@ class TorrentProcessingService { } } - private parseImdbId(torrent: IngestedTorrentAttributes): string | undefined { + private parseImdbId(torrent: IIngestedTorrentAttributes): string | undefined { if (torrent.imdb === undefined || torrent.imdb === null) { return undefined; } diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index e0c52a1..4ddabb3 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -1,28 +1,32 @@ -import { parse } from 'parse-torrent-title'; -import {TorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {FileAttributes} from "../../repository/interfaces/file_attributes"; +import {parse} from 'parse-torrent-title'; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {IFileAttributes} from "../../repository/interfaces/file_attributes"; +import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -class TorrentSubtitleService { - public assignSubtitles(fileCollection: TorrentFileCollection) : TorrentFileCollection { +class TorrentSubtitleService implements ITorrentSubtitleService { + public assignSubtitles(fileCollection: ITorrentFileCollection): ITorrentFileCollection { if (fileCollection.videos && fileCollection.videos.length && fileCollection.subtitles && fileCollection.subtitles.length) { if (fileCollection.videos.length === 1) { fileCollection.videos[0].subtitles = fileCollection.subtitles; - return { ...fileCollection, subtitles: [] }; + return {...fileCollection, subtitles: []}; } const parsedVideos = fileCollection.videos.map(video => this.parseVideo(video)); - const assignedSubs = fileCollection.subtitles.map(subtitle => ({ subtitle, videos: this.mostProbableSubtitleVideos(subtitle, parsedVideos) })); + const assignedSubs = fileCollection.subtitles.map(subtitle => ({ + subtitle, + videos: this.mostProbableSubtitleVideos(subtitle, parsedVideos) + })); const unassignedSubs = assignedSubs.filter(assignedSub => !assignedSub.videos).map(assignedSub => assignedSub.subtitle); assignedSubs .filter(assignedSub => assignedSub.videos) .forEach(assignedSub => assignedSub.videos.forEach(video => video.subtitles = (video.subtitles || []).concat(assignedSub.subtitle))); - return { ...fileCollection, subtitles: unassignedSubs }; + return {...fileCollection, subtitles: unassignedSubs}; } return fileCollection; } - private parseVideo(video: FileAttributes) { + private parseVideo(video: IFileAttributes) { const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); const folderName = video.title.replace(/\/?[^/]+$/, ''); return { diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index d17c7bb..a85e5de 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,13 +1,14 @@ -import axios, { AxiosResponse } from 'axios'; -import { cacheService } from "./cache_service"; -import { configurationService } from './configuration_service'; -import { logger } from "./logging_service"; +import axios, {AxiosResponse} from 'axios'; +import {cacheService} from "./cache_service"; +import {configurationService} from './configuration_service'; +import {logger} from "./logging_service"; +import {ITrackerService} from "../interfaces/tracker_service"; -class TrackerService { - public async getTrackers() : Promise { +class TrackerService implements ITrackerService { + public async getTrackers(): Promise { return cacheService.cacheTrackers(this.downloadTrackers); }; - + private async downloadTrackers(): Promise { const response: AxiosResponse = await axios.get(configurationService.trackerConfig.TRACKERS_URL); const trackersListText: string = response.data; diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index 51edac1..c3c4544 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -10,8 +10,8 @@ import {IngestedTorrent} from "./models/ingestedTorrent"; import {Subtitle} from "./models/subtitle"; import {Content} from "./models/content"; import {SkipTorrent} from "./models/skipTorrent"; -import {FileAttributes} from "./interfaces/file_attributes"; -import {TorrentAttributes} from "./interfaces/torrent_attributes"; +import {IFileAttributes} from "./interfaces/file_attributes"; +import {ITorrentAttributes} from "./interfaces/torrent_attributes"; import {IngestedPage} from "./models/ingestedPage"; import {logger} from "../lib/services/logging_service"; @@ -50,7 +50,7 @@ class DatabaseRepository { } } - public async getTorrent(torrent: TorrentAttributes): Promise { + public async getTorrent(torrent: ITorrentAttributes): Promise { const where = torrent.infoHash ? { infoHash: torrent.infoHash } : { provider: torrent.provider, torrentId: torrent.torrentId }; @@ -61,11 +61,11 @@ class DatabaseRepository { return this.getTorrentsBasedOnQuery({ title: { [Op.regexp]: `${titleQuery}` }, type }); } - public async getTorrentsBasedOnQuery(where: WhereOptions): Promise { + public async getTorrentsBasedOnQuery(where: WhereOptions): Promise { return await Torrent.findAll({ where }); } - public async getFilesBasedOnQuery(where: WhereOptions): Promise { + public async getFilesBasedOnQuery(where: WhereOptions): Promise { return await File.findAll({ where }); } @@ -118,7 +118,7 @@ class DatabaseRepository { await this.createSubtitles(torrent.infoHash, torrent.subtitles); } - public async setTorrentSeeders(torrent: TorrentAttributes, seeders: number): Promise<[number]> { + public async setTorrentSeeders(torrent: ITorrentAttributes, seeders: number): Promise<[number]> { const where = torrent.infoHash ? { infoHash: torrent.infoHash } : { provider: torrent.provider, torrentId: torrent.torrentId }; diff --git a/src/node/consumer/src/repository/interfaces/content_attributes.ts b/src/node/consumer/src/repository/interfaces/content_attributes.ts index c7d8e85..03d7944 100644 --- a/src/node/consumer/src/repository/interfaces/content_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/content_attributes.ts @@ -1,11 +1,11 @@ import {Optional} from "sequelize"; -export interface ContentAttributes { +export interface IContentAttributes { infoHash: string; fileIndex: number; path: string; size: number; } -export interface ContentCreationAttributes extends Optional { +export interface IContentCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/file_attributes.ts b/src/node/consumer/src/repository/interfaces/file_attributes.ts index 7ae8469..da75405 100644 --- a/src/node/consumer/src/repository/interfaces/file_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/file_attributes.ts @@ -1,8 +1,8 @@ import {Optional} from "sequelize"; -import {SubtitleAttributes} from "./subtitle_attributes"; -import {ParseTorrentTitleResult} from "../../lib/interfaces/parse_torrent_title_result"; +import {ISubtitleAttributes} from "./subtitle_attributes"; +import {IParseTorrentTitleResult} from "../../lib/interfaces/parse_torrent_title_result"; -export interface FileAttributes extends ParseTorrentTitleResult { +export interface IFileAttributes extends IParseTorrentTitleResult { id?: number; infoHash?: string; fileIndex?: number; @@ -13,10 +13,10 @@ export interface FileAttributes extends ParseTorrentTitleResult { imdbEpisode?: number; kitsuId?: number; kitsuEpisode?: number; - subtitles?: SubtitleAttributes[]; + subtitles?: ISubtitleAttributes[]; path?: string; isMovie?: boolean; } -export interface FileCreationAttributes extends Optional { +export interface IFileCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts index 21bf9a6..b8814f5 100644 --- a/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts @@ -1,6 +1,6 @@ -export interface IngestedPageAttributes { +export interface IIngestedPageAttributes { url: string; } -export interface IngestedPageCreationAttributes extends IngestedPageAttributes { +export interface IIngestedPageCreationAttributes extends IIngestedPageAttributes { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts index c29ba9e..53ab7ab 100644 --- a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts @@ -1,6 +1,6 @@ import {Optional} from "sequelize"; -export interface IngestedTorrentAttributes { +export interface IIngestedTorrentAttributes { name: string; source: string; category: string; @@ -13,5 +13,5 @@ export interface IngestedTorrentAttributes { createdAt?: Date; } -export interface IngestedTorrentCreationAttributes extends Optional { +export interface IIngestedTorrentCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/provider_attributes.ts b/src/node/consumer/src/repository/interfaces/provider_attributes.ts index c175caa..984ae2e 100644 --- a/src/node/consumer/src/repository/interfaces/provider_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/provider_attributes.ts @@ -1,10 +1,10 @@ import {Optional} from "sequelize"; -export interface ProviderAttributes { +export interface IProviderAttributes { name: string; lastScraped: Date; lastScrapedId: string; } -export interface ProviderCreationAttributes extends Optional { +export interface IProviderCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts index 9b843da..4d8c1da 100644 --- a/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts @@ -1,8 +1,8 @@ import {Optional} from "sequelize"; -export interface SkipTorrentAttributes { +export interface ISkipTorrentAttributes { infoHash: string; } -export interface SkipTorrentCreationAttributes extends Optional { +export interface ISkipTorrentCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts b/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts index 6e4a28b..ce0ecb9 100644 --- a/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts @@ -1,6 +1,6 @@ import {Optional} from "sequelize"; -export interface SubtitleAttributes { +export interface ISubtitleAttributes { infoHash: string; fileIndex: number; fileId?: number; @@ -8,5 +8,5 @@ export interface SubtitleAttributes { path: string; } -export interface SubtitleCreationAttributes extends Optional { +export interface ISubtitleCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts index 60e4bb7..3dfba91 100644 --- a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts +++ b/src/node/consumer/src/repository/interfaces/torrent_attributes.ts @@ -1,9 +1,9 @@ import {Optional} from "sequelize"; -import {ContentAttributes} from "./content_attributes"; -import {SubtitleAttributes} from "./subtitle_attributes"; -import {FileAttributes} from "./file_attributes"; +import {IContentAttributes} from "./content_attributes"; +import {ISubtitleAttributes} from "./subtitle_attributes"; +import {IFileAttributes} from "./file_attributes"; -export interface TorrentAttributes { +export interface ITorrentAttributes { infoHash: string; provider?: string; torrentId?: string; @@ -17,10 +17,10 @@ export interface TorrentAttributes { resolution?: string; reviewed?: boolean; opened?: boolean; - contents?: ContentAttributes[]; - files?: FileAttributes[]; - subtitles?: SubtitleAttributes[]; + contents?: IContentAttributes[]; + files?: IFileAttributes[]; + subtitles?: ISubtitleAttributes[]; } -export interface TorrentCreationAttributes extends Optional { +export interface ITorrentCreationAttributes extends Optional { } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/content.ts b/src/node/consumer/src/repository/models/content.ts index 7e70d7e..c17bca1 100644 --- a/src/node/consumer/src/repository/models/content.ts +++ b/src/node/consumer/src/repository/models/content.ts @@ -1,9 +1,9 @@ import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; -import {ContentAttributes, ContentCreationAttributes} from "../interfaces/content_attributes"; +import {IContentAttributes, IContentCreationAttributes} from "../interfaces/content_attributes"; import {Torrent} from "./torrent"; @Table({modelName: 'content', timestamps: false}) -export class Content extends Model { +export class Content extends Model { @Column({ type: DataType.STRING(64), primaryKey: true, allowNull: false, onDelete: 'CASCADE' }) @ForeignKey(() => Torrent) declare infoHash: string; diff --git a/src/node/consumer/src/repository/models/file.ts b/src/node/consumer/src/repository/models/file.ts index 2383a78..62a4ea2 100644 --- a/src/node/consumer/src/repository/models/file.ts +++ b/src/node/consumer/src/repository/models/file.ts @@ -1,8 +1,8 @@ import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; -import {FileAttributes, FileCreationAttributes} from "../interfaces/file_attributes"; +import {IFileAttributes, IFileCreationAttributes} from "../interfaces/file_attributes"; import {Torrent} from "./torrent"; import {Subtitle} from "./subtitle"; -import {SubtitleAttributes} from "../interfaces/subtitle_attributes"; +import {ISubtitleAttributes} from "../interfaces/subtitle_attributes"; const indexes = [ { @@ -23,7 +23,7 @@ const indexes = [ ]; @Table({modelName: 'file', timestamps: true, indexes: indexes }) -export class File extends Model { +export class File extends Model { @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) @ForeignKey(() => Torrent) declare infoHash: string; diff --git a/src/node/consumer/src/repository/models/ingestedPage.ts b/src/node/consumer/src/repository/models/ingestedPage.ts index 6504344..2dc64a3 100644 --- a/src/node/consumer/src/repository/models/ingestedPage.ts +++ b/src/node/consumer/src/repository/models/ingestedPage.ts @@ -1,5 +1,5 @@ import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; -import {IngestedPageAttributes, IngestedPageCreationAttributes} from "../interfaces/ingested_page_attributes"; +import {IIngestedPageAttributes, IIngestedPageCreationAttributes} from "../interfaces/ingested_page_attributes"; const indexes = [ { @@ -10,7 +10,7 @@ const indexes = [ ]; @Table({modelName: 'ingested_page', timestamps: true, indexes: indexes}) -export class IngestedPage extends Model { +export class IngestedPage extends Model { @Column({ type: DataType.STRING(512), allowNull: false }) declare url: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedTorrent.ts b/src/node/consumer/src/repository/models/ingestedTorrent.ts index 5a21a4a..a40571b 100644 --- a/src/node/consumer/src/repository/models/ingestedTorrent.ts +++ b/src/node/consumer/src/repository/models/ingestedTorrent.ts @@ -1,5 +1,5 @@ import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; -import {IngestedTorrentAttributes, IngestedTorrentCreationAttributes} from "../interfaces/ingested_torrent_attributes"; +import {IIngestedTorrentAttributes, IIngestedTorrentCreationAttributes} from "../interfaces/ingested_torrent_attributes"; const indexes = [ { @@ -10,7 +10,7 @@ const indexes = [ ]; @Table({modelName: 'ingested_torrent', timestamps: true, indexes: indexes}) -export class IngestedTorrent extends Model { +export class IngestedTorrent extends Model { @Column({ type: DataType.STRING(512) }) declare name: string; diff --git a/src/node/consumer/src/repository/models/provider.ts b/src/node/consumer/src/repository/models/provider.ts index 26a8bfc..97b5036 100644 --- a/src/node/consumer/src/repository/models/provider.ts +++ b/src/node/consumer/src/repository/models/provider.ts @@ -1,8 +1,8 @@ import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; -import {ProviderAttributes, ProviderCreationAttributes} from "../interfaces/provider_attributes"; +import {IProviderAttributes, IProviderCreationAttributes} from "../interfaces/provider_attributes"; @Table({modelName: 'provider', timestamps: false}) -export class Provider extends Model { +export class Provider extends Model { @Column({ type: DataType.STRING(32), primaryKey: true }) declare name: string; diff --git a/src/node/consumer/src/repository/models/skipTorrent.ts b/src/node/consumer/src/repository/models/skipTorrent.ts index 101ce68..7e1eb4a 100644 --- a/src/node/consumer/src/repository/models/skipTorrent.ts +++ b/src/node/consumer/src/repository/models/skipTorrent.ts @@ -1,9 +1,9 @@ import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; -import {SkipTorrentAttributes, SkipTorrentCreationAttributes} from "../interfaces/skip_torrent_attributes"; +import {ISkipTorrentAttributes, ISkipTorrentCreationAttributes} from "../interfaces/skip_torrent_attributes"; @Table({modelName: 'skip_torrent', timestamps: false}) -export class SkipTorrent extends Model { +export class SkipTorrent extends Model { @Column({ type: DataType.STRING(64), primaryKey: true }) declare infoHash: string; diff --git a/src/node/consumer/src/repository/models/subtitle.ts b/src/node/consumer/src/repository/models/subtitle.ts index 0a4157c..7a66baf 100644 --- a/src/node/consumer/src/repository/models/subtitle.ts +++ b/src/node/consumer/src/repository/models/subtitle.ts @@ -1,5 +1,5 @@ import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; -import {SubtitleAttributes, SubtitleCreationAttributes} from "../interfaces/subtitle_attributes"; +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "../interfaces/subtitle_attributes"; import {File} from "./file"; import {Torrent} from "./torrent"; @@ -17,7 +17,7 @@ const indexes = [ ]; @Table({modelName: 'subtitle', timestamps: false, indexes: indexes}) -export class Subtitle extends Model { +export class Subtitle extends Model { @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) declare infoHash: string; diff --git a/src/node/consumer/src/repository/models/torrent.ts b/src/node/consumer/src/repository/models/torrent.ts index b6b7a80..f345b55 100644 --- a/src/node/consumer/src/repository/models/torrent.ts +++ b/src/node/consumer/src/repository/models/torrent.ts @@ -1,12 +1,12 @@ import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; -import {TorrentAttributes, TorrentCreationAttributes} from "../interfaces/torrent_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "../interfaces/torrent_attributes"; import {Content} from "./content"; import {File} from "./file"; import {Subtitle} from "./subtitle"; @Table({modelName: 'torrent', timestamps: true}) -export class Torrent extends Model { +export class Torrent extends Model { @Column({type: DataType.STRING(64), primaryKey: true}) declare infoHash: string; From 5ebb9b4ae8a04a9ccda3b158e2c53338ef919420 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 11:12:10 +0000 Subject: [PATCH 25/55] ioc implemented --- src/node/consumer/esbuild.js | 2 +- src/node/consumer/package-lock.json | 6 + src/node/consumer/package.json | 3 +- src/node/consumer/src/index.ts | 9 - .../src/interfaces/process_torrents_job.ts | 3 + .../consumer/src/jobs/process_torrents_job.ts | 42 ++-- .../src/lib/interfaces/composition_root.ts | 3 + .../src/lib/models/composition_root.ts | 26 +++ .../src/lib/models/inversify_config.ts | 44 ++++ src/node/consumer/src/lib/models/ioc_types.ts | 18 ++ .../src/lib/services/cache_service.ts | 23 +- .../src/lib/services/logging_service.ts | 24 +-- .../src/lib/services/metadata_service.ts | 198 +++++++++-------- .../lib/services/torrent_download_service.ts | 62 +++--- .../lib/services/torrent_entries_service.ts | 123 ++++++----- .../src/lib/services/torrent_file_service.ts | 202 +++++++++--------- .../services/torrent_processing_service.ts | 46 ++-- .../lib/services/torrent_subtitle_service.ts | 22 +- .../src/lib/services/tracker_service.ts | 28 ++- src/node/consumer/src/main.ts | 8 + .../src/repository/database_repository.ts | 173 +++++++-------- .../interfaces/database_repository.ts | 62 ++++++ 22 files changed, 653 insertions(+), 474 deletions(-) delete mode 100644 src/node/consumer/src/index.ts create mode 100644 src/node/consumer/src/interfaces/process_torrents_job.ts create mode 100644 src/node/consumer/src/lib/interfaces/composition_root.ts create mode 100644 src/node/consumer/src/lib/models/composition_root.ts create mode 100644 src/node/consumer/src/lib/models/inversify_config.ts create mode 100644 src/node/consumer/src/lib/models/ioc_types.ts create mode 100644 src/node/consumer/src/main.ts create mode 100644 src/node/consumer/src/repository/interfaces/database_repository.ts diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js index 82f9e58..938948f 100644 --- a/src/node/consumer/esbuild.js +++ b/src/node/consumer/esbuild.js @@ -13,7 +13,7 @@ try { build({ bundle: true, entryPoints: [ - "./src/index.ts", + "./src/main.ts", ], external: [...(devDependencies && Object.keys(devDependencies))], keepNames: true, diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 444d7f2..eb2f591 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -15,6 +15,7 @@ "bottleneck": "^2.19.5", "cache-manager": "^5.4.0", "google-sr": "^3.2.1", + "inversify": "^6.0.2", "magnet-uri": "^6.2.0", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", @@ -2833,6 +2834,11 @@ "node": ">= 0.4" } }, + "node_modules/inversify": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", + "integrity": "sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA==" + }, "node_modules/ip": { "version": "1.1.8", "license": "MIT" diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 4b4fdb1..d6f6a7c 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "build": "node esbuild.js", - "dev": "tsx watch --ignore node_modules src/index.ts | pino-pretty", + "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", "start": "node dist/index.cjs", "lint": "npx eslint ./src --ext .ts,.js" }, @@ -16,6 +16,7 @@ "bottleneck": "^2.19.5", "cache-manager": "^5.4.0", "google-sr": "^3.2.1", + "inversify": "^6.0.2", "magnet-uri": "^6.2.0", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", diff --git a/src/node/consumer/src/index.ts b/src/node/consumer/src/index.ts deleted file mode 100644 index f022264..0000000 --- a/src/node/consumer/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { processTorrentsJob } from './jobs/process_torrents_job.js'; -import { repository } from "./repository/database_repository"; -import { trackerService } from "./lib/services/tracker_service"; - -(async () => { - await trackerService.getTrackers(); - await repository.connect(); - await processTorrentsJob.listenToQueue(); -})(); \ No newline at end of file diff --git a/src/node/consumer/src/interfaces/process_torrents_job.ts b/src/node/consumer/src/interfaces/process_torrents_job.ts new file mode 100644 index 0000000..1603f5d --- /dev/null +++ b/src/node/consumer/src/interfaces/process_torrents_job.ts @@ -0,0 +1,3 @@ +export interface IProcessTorrentsJob { + listenToQueue: () => Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/jobs/process_torrents_job.ts index 93a6f24..23bbfd3 100644 --- a/src/node/consumer/src/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/jobs/process_torrents_job.ts @@ -2,14 +2,26 @@ import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; import {configurationService} from '../lib/services/configuration_service'; -import {torrentProcessingService} from '../lib/services/torrent_processing_service'; -import {logger} from '../lib/services/logging_service'; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../lib/models/ioc_types"; +import {ITorrentProcessingService} from "../lib/interfaces/torrent_processing_service"; +import {ILoggingService} from "../lib/interfaces/logging_service"; +import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; -class ProcessTorrentsJob { +@injectable() +export class ProcessTorrentsJob implements IProcessTorrentsJob { private readonly assertQueueOptions: Options.AssertQueue = {durable: true}; private readonly consumeQueueOptions: Options.Consume = {noAck: false}; + private torrentProcessingService: ITorrentProcessingService; + private logger: ILoggingService; + + constructor(@inject(IocTypes.ITorrentProcessingService) torrentProcessingService: ITorrentProcessingService, + @inject(IocTypes.ILoggingService) logger: ILoggingService){ + this.torrentProcessingService = torrentProcessingService; + this.logger = logger; + } - public listenToQueue = async ()=> { + public listenToQueue = async () => { if (!configurationService.jobConfig.JOBS_ENABLED) { return; } @@ -19,12 +31,12 @@ class ProcessTorrentsJob { const channel: Channel = await connection.createChannel(); await this.assertAndConsumeQueue(channel); } catch (error) { - logger.error('Failed to connect and setup channel', error); + this.logger.error('Failed to connect and setup channel', error); } } private processMessage = (msg: ConsumeMessage) => { const ingestedTorrent: IIngestedTorrentAttributes = this.getMessageAsJson(msg); - return torrentProcessingService.processTorrentRecord(ingestedTorrent); + return this.torrentProcessingService.processTorrentRecord(ingestedTorrent); }; private getMessageAsJson = (msg: ConsumeMessage): IIngestedTorrentAttributes => { const content = msg?.content.toString('utf8') ?? "{}"; @@ -32,15 +44,15 @@ class ProcessTorrentsJob { const receivedTorrent: IIngestedRabbitTorrent = receivedObject.message; return {...receivedTorrent, info_hash: receivedTorrent.infoHash}; }; - private async assertAndConsumeQueue(channel: Channel) { - logger.info('Worker is running! Waiting for new torrents...'); + private assertAndConsumeQueue = async (channel: Channel) => { + this.logger.info('Worker is running! Waiting for new torrents...'); const ackMsg = async (msg: ConsumeMessage) => { try { await this.processMessage(msg); channel.ack(msg); } catch (error) { - logger.error('Failed processing torrent', error); + this.logger.error('Failed processing torrent', error); } } @@ -49,13 +61,7 @@ class ProcessTorrentsJob { await channel.prefetch(configurationService.jobConfig.JOB_CONCURRENCY); await channel.consume(configurationService.rabbitConfig.QUEUE_NAME, ackMsg, this.consumeQueueOptions); } catch (error) { - logger.error('Failed to setup channel', error); + this.logger.error('Failed to setup channel', error); } - } - - private test() { - - } -} - -export const processTorrentsJob = new ProcessTorrentsJob(); \ No newline at end of file + }; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/composition_root.ts b/src/node/consumer/src/lib/interfaces/composition_root.ts new file mode 100644 index 0000000..b584625 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/composition_root.ts @@ -0,0 +1,3 @@ +export interface ICompositionalRoot { + start(): Promise; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/composition_root.ts b/src/node/consumer/src/lib/models/composition_root.ts new file mode 100644 index 0000000..a6c47cb --- /dev/null +++ b/src/node/consumer/src/lib/models/composition_root.ts @@ -0,0 +1,26 @@ +import {inject, injectable} from "inversify"; +import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; +import {ITrackerService} from "../interfaces/tracker_service"; +import {IProcessTorrentsJob} from "../../interfaces/process_torrents_job"; +import {ICompositionalRoot} from "../interfaces/composition_root"; +import {IocTypes} from "./ioc_types"; + +@injectable() +export class CompositionalRoot implements ICompositionalRoot { + private trackerService: ITrackerService; + private databaseRepository: IDatabaseRepository; + private processTorrentsJob: IProcessTorrentsJob; + constructor(@inject(IocTypes.ITrackerService) trackerService: ITrackerService, + @inject(IocTypes.IDatabaseRepository) databaseRepository: IDatabaseRepository, + @inject(IocTypes.IProcessTorrentsJob) processTorrentsJob: IProcessTorrentsJob) { + this.trackerService = trackerService; + this.databaseRepository = databaseRepository; + this.processTorrentsJob = processTorrentsJob; + } + + start = async () => { + await this.trackerService.getTrackers(); + await this.databaseRepository.connect(); + await this.processTorrentsJob.listenToQueue(); + }; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/lib/models/inversify_config.ts new file mode 100644 index 0000000..898a2c7 --- /dev/null +++ b/src/node/consumer/src/lib/models/inversify_config.ts @@ -0,0 +1,44 @@ +import "reflect-metadata"; // required +import {Container} from "inversify"; +import { IocTypes } from "./ioc_types"; +import {ICacheService} from "../interfaces/cache_service"; +import {ILoggingService} from "../interfaces/logging_service"; +import {IMetadataService} from "../interfaces/metadata_service"; +import {ITorrentFileService} from "../interfaces/torrent_file_service"; +import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; +import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {ITrackerService} from "../interfaces/tracker_service"; +import {IProcessTorrentsJob} from "../../interfaces/process_torrents_job"; +import {ICompositionalRoot} from "../interfaces/composition_root"; +import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; +import {CompositionalRoot} from "./composition_root"; +import {CacheService} from "../services/cache_service"; +import {LoggingService} from "../services/logging_service"; +import {MetadataService} from "../services/metadata_service"; +import {TorrentDownloadService} from "../services/torrent_download_service"; +import {TorrentEntriesService} from "../services/torrent_entries_service"; +import {TorrentProcessingService} from "../services/torrent_processing_service"; +import {TorrentFileService} from "../services/torrent_file_service"; +import {TorrentSubtitleService} from "../services/torrent_subtitle_service"; +import {TrackerService} from "../services/tracker_service"; +import {DatabaseRepository} from "../../repository/database_repository"; +import {ProcessTorrentsJob} from "../../jobs/process_torrents_job"; + +const serviceContainer = new Container(); + +serviceContainer.bind(IocTypes.ICompositionalRoot).to(CompositionalRoot).inSingletonScope(); +serviceContainer.bind(IocTypes.ICacheService).to(CacheService).inSingletonScope(); +serviceContainer.bind(IocTypes.ITorrentFileService).to(TorrentFileService); +serviceContainer.bind(IocTypes.ITorrentProcessingService).to(TorrentProcessingService); +serviceContainer.bind(IocTypes.ITorrentSubtitleService).to(TorrentSubtitleService); +serviceContainer.bind(IocTypes.ITorrentEntriesService).to(TorrentEntriesService); +serviceContainer.bind(IocTypes.ITorrentDownloadService).to(TorrentDownloadService); +serviceContainer.bind(IocTypes.ILoggingService).to(LoggingService); +serviceContainer.bind(IocTypes.IMetadataService).to(MetadataService); +serviceContainer.bind(IocTypes.ITrackerService).to(TrackerService); +serviceContainer.bind(IocTypes.IDatabaseRepository).to(DatabaseRepository); +serviceContainer.bind(IocTypes.IProcessTorrentsJob).to(ProcessTorrentsJob); + +export { serviceContainer }; diff --git a/src/node/consumer/src/lib/models/ioc_types.ts b/src/node/consumer/src/lib/models/ioc_types.ts new file mode 100644 index 0000000..ebe437b --- /dev/null +++ b/src/node/consumer/src/lib/models/ioc_types.ts @@ -0,0 +1,18 @@ +export const IocTypes = { + // Composition root + ICompositionalRoot: Symbol.for("ICompositionalRoot"), + // Services + ICacheService: Symbol.for("ICacheService"), + ILoggingService: Symbol.for("ILoggingService"), + IMetadataService: Symbol.for("IMetadataService"), + ITorrentDownloadService: Symbol.for("ITorrentDownloadService"), + ITorrentEntriesService: Symbol.for("ITorrentEntriesService"), + ITorrentFileService: Symbol.for("ITorrentFileService"), + ITorrentProcessingService: Symbol.for("ITorrentProcessingService"), + ITorrentSubtitleService: Symbol.for("ITorrentSubtitleService"), + ITrackerService: Symbol.for("ITrackerService"), + // DAL + IDatabaseRepository: Symbol.for("IDatabaseRepository"), + // Jobs + IProcessTorrentsJob: Symbol.for("IProcessTorrentsJob"), +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 144000e..c89bd1d 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,10 +1,12 @@ import {Cache, createCache, memoryStore} from 'cache-manager'; import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' import {configurationService} from './configuration_service'; -import {logger} from './logging_service'; import {CacheType} from "../enums/cache_types"; import {ICacheOptions} from "../interfaces/cache_options"; import {ICacheService} from "../interfaces/cache_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {ILoggingService} from "../interfaces/logging_service"; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; @@ -18,10 +20,13 @@ const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days export type CacheMethod = () => any; -class CacheService implements ICacheService { - constructor() { +@injectable() +export class CacheService implements ICacheService { + private logger: ILoggingService; + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { + this.logger = logger; if (!configurationService.cacheConfig.NO_CACHE) { - logger.info('Cache is disabled'); + this.logger.info('Cache is disabled'); return; } @@ -64,7 +69,7 @@ class CacheService implements ICacheService { private initiateRemoteCache = (): Cache => { if (configurationService.cacheConfig.NO_CACHE) { - logger.debug('Cache is disabled'); + this.logger.debug('Cache is disabled'); return null; } @@ -93,13 +98,11 @@ class CacheService implements ICacheService { return method(); } - logger.debug(`Cache type: ${cacheType}`); - logger.debug(`Cache key: ${key}`); - logger.debug(`Cache options: ${JSON.stringify(options)}`); + this.logger.debug(`Cache type: ${cacheType}`); + this.logger.debug(`Cache key: ${key}`); + this.logger.debug(`Cache options: ${JSON.stringify(options)}`); return cache.wrap(key, method, options.ttl); } } -export const cacheService: CacheService = new CacheService(); - diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index 2d67911..ddc4dee 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -1,7 +1,9 @@ import {Logger, pino} from "pino"; import {ILoggingService} from "../interfaces/logging_service"; +import {injectable} from "inversify"; -class LoggingService implements ILoggingService { +@injectable() +export class LoggingService implements ILoggingService { private readonly logger: Logger; constructor() { @@ -10,21 +12,19 @@ class LoggingService implements ILoggingService { }); } - public info(message: string, ...args: any[]): void { + public info = (message: string, ...args: any[]): void => { this.logger.info(message, args); - } + }; - public error(message: string, ...args: any[]): void { + public error = (message: string, ...args: any[]): void => { this.logger.error(message, args); - } + }; - public debug(message: string, ...args: any[]): void { + public debug = (message: string, ...args: any[]): void => { this.logger.debug(message, args); - } + }; - public warn(message: string, ...args: any[]): void { + public warn = (message: string, ...args: any[]): void => { this.logger.warn(message, args); - } -} - -export const logger = new LoggingService(); \ No newline at end of file + }; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 3b52d4f..7e469da 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -1,7 +1,6 @@ import axios, {AxiosResponse} from 'axios'; import {ResultTypes, search} from 'google-sr'; import nameToImdb from 'name-to-imdb'; -import {cacheService} from './cache_service'; import {TorrentType} from '../enums/torrent_types'; import {IMetadataResponse} from "../interfaces/metadata_response"; import {ICinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; @@ -10,20 +9,29 @@ import {IKitsuJsonResponse} from "../interfaces/kitsu_metadata"; import {IMetaDataQuery} from "../interfaces/metadata_query"; import {IKitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; import {IMetadataService} from "../interfaces/metadata_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {ICacheService} from "../interfaces/cache_service"; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; const TIMEOUT = 20000; -class MetadataService implements IMetadataService { - public async getKitsuId(info: IMetaDataQuery): Promise { +@injectable() +export class MetadataService implements IMetadataService { + private cacheService: ICacheService; + constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService) { + this.cacheService = cacheService; + } + + public getKitsuId = async (info: IMetaDataQuery): Promise => { const title = this.escapeTitle(info.title.replace(/\s\|\s.*/, '')); const year = info.year ? ` ${info.year}` : ''; const season = info.season > 1 ? ` S${info.season}` : ''; const key = `${title}${year}${season}`; const query = encodeURIComponent(key); - return cacheService.cacheWrapKitsuId(key, + return this.cacheService.cacheWrapKitsuId(key, () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, {timeout: 60000}) .then((response) => { const body = response.data as IKitsuCatalogJsonResponse; @@ -33,9 +41,9 @@ class MetadataService implements IMetadataService { throw new Error('No search results'); } })); - } + }; - public async getImdbId(info: IMetaDataQuery): Promise { + public getImdbId = async (info: IMetaDataQuery): Promise => { const name = this.escapeTitle(info.title); const year = info.year || (info.date && info.date.slice(0, 4)); const key = `${name}_${year || 'NA'}_${info.type}`; @@ -44,7 +52,7 @@ class MetadataService implements IMetadataService { const googleQuery = year ? query : fallbackQuery; try { - const imdbId = await cacheService.cacheWrapImdbId(key, + const imdbId = await this.cacheService.cacheWrapImdbId(key, () => this.getIMDbIdFromNameToImdb(name, info) ); return imdbId && 'tt' + imdbId.replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); @@ -52,16 +60,16 @@ class MetadataService implements IMetadataService { const imdbIdFallback = await this.getIMDbIdFromGoogle(googleQuery); return imdbIdFallback && 'tt' + imdbIdFallback.toString().replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); } - } + }; - public getMetadata(query: IMetaDataQuery): Promise { + public getMetadata = (query: IMetaDataQuery): Promise => { if (!query.id) { return Promise.reject("no valid id provided"); } const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; const metaType = query.type === TorrentType.Movie ? TorrentType.Movie : TorrentType.Series; - return cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + return this.cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) .catch(() => this.requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) .catch(() => { // try different type in case there was a mismatch @@ -71,30 +79,28 @@ class MetadataService implements IMetadataService { .catch((error) => { throw new Error(`failed metadata query ${key} due: ${error.message}`); })); - } + }; - public async isEpisodeImdbId(imdbId: string | undefined): Promise { + public isEpisodeImdbId = async (imdbId: string | undefined): Promise => { if (!imdbId) { return false; } return axios.get(`https://www.imdb.com/title/${imdbId}/`, {timeout: 10000}) .then(response => !!(response.data && response.data.includes('video.episode'))) .catch(() => false); - } + }; - public escapeTitle(title: string): string { - return title.toLowerCase() - .normalize('NFKD') // normalize non-ASCII characters - .replace(/[\u0300-\u036F]/g, '') - .replace(/&/g, 'and') - .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces - .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars - .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering - .replace(/\s{2,}/, ' ') // replace multiple spaces - .trim(); - } + public escapeTitle = (title: string): string => title.toLowerCase() + .normalize('NFKD') // normalize non-ASCII characters + .replace(/[\u0300-\u036F]/g, '') + .replace(/&/g, 'and') + .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces + .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars + .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering + .replace(/\s{2,}/, ' ') // replace multiple spaces + .trim(); - private async requestMetadata(url: string): Promise { + private requestMetadata = async (url: string): Promise => { let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); let result: IMetadataResponse; const body = response.data; @@ -107,80 +113,74 @@ class MetadataService implements IMetadataService { } return result; - } + }; - private handleCinemetaResponse(body: ICinemetaJsonResponse): IMetadataResponse { - return { - imdbId: parseInt(body.meta.imdb_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos - ? body.meta.videos.map(video => ({ - name: video.name, - season: video.season, - episode: video.episode, - imdbSeason: video.season, - imdbEpisode: video.episode, - })) - : [], - episodeCount: body.meta.videos - ? this.getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }; - } + private handleCinemetaResponse = (body: ICinemetaJsonResponse): IMetadataResponse => ({ + imdbId: parseInt(body.meta.imdb_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.name, + season: video.season, + episode: video.episode, + imdbSeason: video.season, + imdbEpisode: video.episode, + })) + : [], + episodeCount: body.meta.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }); - private handleKitsuResponse(body: IKitsuJsonResponse): IMetadataResponse { - return { - kitsuId: parseInt(body.meta.kitsu_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos - ? body.meta.videos.map(video => ({ - name: video.title, - season: video.season, - episode: video.episode, - kitsuId: video.id, - kitsuEpisode: video.episode, - released: video.released, - })) - : [], - episodeCount: body.meta.videos - ? this.getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }; - } + private handleKitsuResponse = (body: IKitsuJsonResponse): IMetadataResponse => ({ + kitsuId: parseInt(body.meta.kitsu_id), + type: body.meta.type, + title: body.meta.name, + year: parseInt(body.meta.year), + country: body.meta.country, + genres: body.meta.genres, + status: body.meta.status, + videos: body.meta.videos + ? body.meta.videos.map(video => ({ + name: video.title, + season: video.season, + episode: video.episode, + kitsuId: video.id, + kitsuEpisode: video.episode, + released: video.released, + })) + : [], + episodeCount: body.meta.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }); - private getEpisodeCount(videos: ICommonVideoMetadata[]) { - return Object.values( - videos - .filter(entry => entry.season !== 0 && entry.episode !== 0) - .sort((a, b) => a.season - b.season) - .reduce((map, next) => { - map[next.season] = map[next.season] + 1 || 1; - return map; - }, {}) - ); - } + private getEpisodeCount = (videos: ICommonVideoMetadata[]) => Object.values( + videos + .filter(entry => entry.season !== 0 && entry.episode !== 0) + .sort((a, b) => a.season - b.season) + .reduce((map, next) => { + map[next.season] = map[next.season] + 1 || 1; + return map; + }, {}) + ); - private getIMDbIdFromNameToImdb(name: string, info: IMetaDataQuery): Promise { + private getIMDbIdFromNameToImdb = (name: string, info: IMetaDataQuery): Promise => { const year = info.year; const type = info.type; return new Promise((resolve, reject) => { @@ -192,9 +192,9 @@ class MetadataService implements IMetadataService { } }); }); - } + }; - private async getIMDbIdFromGoogle(query: string): Promise { + private getIMDbIdFromGoogle = async (query: string): Promise => { try { const searchResults = await search({query: query}); for (const result of searchResults) { @@ -211,8 +211,6 @@ class MetadataService implements IMetadataService { } catch (error) { throw new Error('Failed to find IMDb ID from Google search'); } - } + }; } -export const metadataService: MetadataService = new MetadataService(); - diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index dffcce2..28d46a7 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -9,6 +9,7 @@ import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attribut import {IContentAttributes} from "../../repository/interfaces/content_attributes"; import {parse} from "parse-torrent-title"; import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {injectable} from "inversify"; interface ITorrentFile { name: string; @@ -17,7 +18,8 @@ interface ITorrentFile { fileIndex: number; } -class TorrentDownloadService implements ITorrentDownloadService { +@injectable() +export class TorrentDownloadService implements ITorrentDownloadService { private engineOptions: TorrentStream.TorrentEngineOptions = { connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, uploads: 0, @@ -26,7 +28,7 @@ class TorrentDownloadService implements ITorrentDownloadService { tracker: true, }; - public async getTorrentFiles(torrent: IParsedTorrent, timeout: number = 30000): Promise { + public getTorrentFiles = async (torrent: IParsedTorrent, timeout: number = 30000): Promise => { const torrentFiles: ITorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); const videos = this.filterVideos(torrent, torrentFiles); @@ -38,9 +40,9 @@ class TorrentDownloadService implements ITorrentDownloadService { videos: videos, subtitles: subtitles, }; - } + }; - private async filesFromTorrentStream(torrent: IParsedTorrent, timeout: number): Promise { + private filesFromTorrentStream = async (torrent: IParsedTorrent, timeout: number): Promise => { if (!torrent.infoHash) { return Promise.reject(new Error("No infoHash...")); } @@ -72,9 +74,9 @@ class TorrentDownloadService implements ITorrentDownloadService { clearTimeout(timeoutId); }); }); - } + }; - private filterVideos(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IFileAttributes[] { + private filterVideos = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IFileAttributes[] => { if (torrentFiles.length === 1 && !Number.isInteger(torrentFiles[0].fileIndex)) { return [this.mapTorrentFileToFileAttributes(torrent, torrentFiles[0])]; } @@ -99,18 +101,14 @@ class TorrentDownloadService implements ITorrentDownloadService { .filter(video => !isRedundant(video)) .filter(video => !isWatermark(video)) .map(video => this.mapTorrentFileToFileAttributes(torrent, video)); - } + }; - private filterSubtitles(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): ISubtitleAttributes[] { - return torrentFiles.filter(file => ExtensionHelpers.isSubtitle(file.name || '')) - .map(file => this.mapTorrentFileToSubtitleAttributes(torrent, file)); - } + private filterSubtitles = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): ISubtitleAttributes[] => torrentFiles.filter(file => ExtensionHelpers.isSubtitle(file.name || '')) + .map(file => this.mapTorrentFileToSubtitleAttributes(torrent, file)); - private createContent(torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IContentAttributes[] { - return torrentFiles.map(file => this.mapTorrentFileToContentAttributes(torrent, file)); - } + private createContent = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IContentAttributes[] => torrentFiles.map(file => this.mapTorrentFileToContentAttributes(torrent, file)); - private mapTorrentFileToFileAttributes(torrent: IParsedTorrent, file: ITorrentFile): IFileAttributes { + private mapTorrentFileToFileAttributes = (torrent: IParsedTorrent, file: ITorrentFile): IFileAttributes => { const videoFile: IFileAttributes = { title: file.name, size: file.length, @@ -124,27 +122,21 @@ class TorrentDownloadService implements ITorrentDownloadService { }; return {...videoFile, ...parse(file.name)}; - } + }; - private mapTorrentFileToSubtitleAttributes(torrent: IParsedTorrent, file: ITorrentFile): ISubtitleAttributes { - return { - title: file.name, - infoHash: torrent.infoHash, - fileIndex: file.fileIndex, - fileId: file.fileIndex, - path: file.path, - }; - } + private mapTorrentFileToSubtitleAttributes = (torrent: IParsedTorrent, file: ITorrentFile): ISubtitleAttributes => ({ + title: file.name, + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + fileId: file.fileIndex, + path: file.path, + }); - private mapTorrentFileToContentAttributes(torrent: IParsedTorrent, file: ITorrentFile): IContentAttributes { - return { - infoHash: torrent.infoHash, - fileIndex: file.fileIndex, - path: file.path, - size: file.length, - }; - } + private mapTorrentFileToContentAttributes = (torrent: IParsedTorrent, file: ITorrentFile): IContentAttributes => ({ + infoHash: torrent.infoHash, + fileIndex: file.fileIndex, + path: file.path, + size: file.length, + }); } -export const torrentDownloadService = new TorrentDownloadService(); - diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 32d5360..d94f136 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -1,21 +1,42 @@ import {parse} from 'parse-torrent-title'; import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {repository} from '../../repository/database_repository'; import {TorrentType} from '../enums/torrent_types'; import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; import {Torrent} from "../../repository/models/torrent"; import {PromiseHelpers} from '../helpers/promises_helpers'; -import {logger} from './logging_service'; -import {metadataService} from './metadata_service'; -import {torrentFileService} from './torrent_file_service'; -import {torrentSubtitleService} from './torrent_subtitle_service'; import {ITorrentAttributes} from "../../repository/interfaces/torrent_attributes"; import {File} from "../../repository/models/file"; import {Subtitle} from "../../repository/models/subtitle"; import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {IMetadataService} from "../interfaces/metadata_service"; +import {ILoggingService} from "../interfaces/logging_service"; +import {ITorrentFileService} from "../interfaces/torrent_file_service"; +import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; +import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; -class TorrentEntriesService implements ITorrentEntriesService { - public async createTorrentEntry(torrent: IParsedTorrent, overwrite = false): Promise { +@injectable() +export class TorrentEntriesService implements ITorrentEntriesService { + private metadataService: IMetadataService; + private logger: ILoggingService; + private fileService: ITorrentFileService; + private subtitleService: ITorrentSubtitleService; + private repository: IDatabaseRepository; + + constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, + @inject(IocTypes.ILoggingService) logger: ILoggingService, + @inject(IocTypes.ITorrentFileService) fileService: ITorrentFileService, + @inject(IocTypes.ITorrentSubtitleService) torrentSubtitleService: ITorrentSubtitleService, + @inject(IocTypes.IDatabaseRepository) repository: IDatabaseRepository) { + this.metadataService = metadataService; + this.logger = logger; + this.fileService = fileService; + this.subtitleService = torrentSubtitleService; + this.repository = repository; + } + + public createTorrentEntry = async (torrent: IParsedTorrent, overwrite = false): Promise => { const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { @@ -24,7 +45,7 @@ class TorrentEntriesService implements ITorrentEntriesService { year: titleInfo.year, type: torrent.type }; - torrent.imdbId = await metadataService.getImdbId(imdbQuery) + torrent.imdbId = await this.metadataService.getImdbId(imdbQuery) .catch(() => undefined); } if (torrent.imdbId && torrent.imdbId.toString().length < 9) { @@ -41,25 +62,25 @@ class TorrentEntriesService implements ITorrentEntriesService { year: titleInfo.year, season: titleInfo.season, }; - torrent.kitsuId = await metadataService.getKitsuId(kitsuQuery) + torrent.kitsuId = await this.metadataService.getKitsuId(kitsuQuery) .catch(() => undefined); } - if (!torrent.imdbId && !torrent.kitsuId && !torrentFileService.isPackTorrent(torrent)) { - logger.warn(`imdbId or kitsuId not found: ${torrent.provider} ${torrent.title}`); + if (!torrent.imdbId && !torrent.kitsuId && !this.fileService.isPackTorrent(torrent)) { + this.logger.warn(`imdbId or kitsuId not found: ${torrent.provider} ${torrent.title}`); return; } - const fileCollection: ITorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) .then((torrentContents: ITorrentFileCollection) => overwrite ? this.overwriteExistingFiles(torrent, torrentContents) : torrentContents) - .then((torrentContents: ITorrentFileCollection) => torrentSubtitleService.assignSubtitles(torrentContents)) + .then((torrentContents: ITorrentFileCollection) =>this.subtitleService.assignSubtitles(torrentContents)) .catch(error => { - logger.warn(`Failed getting files for ${torrent.title}`, error.message); + this.logger.warn(`Failed getting files for ${torrent.title}`, error.message); return {}; }); if (!fileCollection.videos || !fileCollection.videos.length) { - logger.warn(`no video files found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); + this.logger.warn(`no video files found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); return; } @@ -69,31 +90,27 @@ class TorrentEntriesService implements ITorrentEntriesService { subtitles: fileCollection.subtitles }); - return repository.createTorrent(newTorrent) + return this.repository.createTorrent(newTorrent) .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { const newVideo = File.build(video); - return repository.createFile(newVideo) + return this.repository.createFile(newVideo) }))) - .then(() => logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); - } + .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); + }; - public async createSkipTorrentEntry(torrent: Torrent) { - return repository.createSkipTorrent(torrent); - } + public createSkipTorrentEntry = async (torrent: Torrent) => this.repository.createSkipTorrent(torrent); - public async getStoredTorrentEntry(torrent: Torrent) { - return repository.getSkipTorrent(torrent.infoHash) - .catch(() => repository.getTorrent(torrent)) - .catch(() => undefined); - } + public getStoredTorrentEntry = async (torrent: Torrent) => this.repository.getSkipTorrent(torrent.infoHash) + .catch(() => this.repository.getTorrent(torrent)) + .catch(() => undefined); - public async checkAndUpdateTorrent(torrent: IParsedTorrent): Promise { + public checkAndUpdateTorrent = async (torrent: IParsedTorrent): Promise => { const query: ITorrentAttributes = { infoHash: torrent.infoHash, provider: torrent.provider, } - const existingTorrent = await repository.getTorrent(query).catch(() => undefined); + const existingTorrent = await this.repository.getTorrent(query).catch(() => undefined); if (!existingTorrent) { return false; @@ -110,18 +127,18 @@ class TorrentEntriesService implements ITorrentEntriesService { if (!existingTorrent.languages && torrent.languages && existingTorrent.provider !== 'RARBG') { existingTorrent.languages = torrent.languages; await existingTorrent.save(); - logger.debug(`Updated [${existingTorrent.infoHash}] ${existingTorrent.title} language to ${torrent.languages}`); + this.logger.debug(`Updated [${existingTorrent.infoHash}] ${existingTorrent.title} language to ${torrent.languages}`); } return this.createTorrentContents(existingTorrent) .then(() => this.updateTorrentSeeders(existingTorrent)); - } + }; - public async createTorrentContents(torrent: Torrent) { + public createTorrentContents = async (torrent: Torrent) => { if (torrent.opened) { return; } - const storedVideos: File[] = await repository.getFiles(torrent.infoHash).catch(() => []); + const storedVideos: File[] = await this.repository.getFiles(torrent.infoHash).catch(() => []); if (!storedVideos || !storedVideos.length) { return; } @@ -129,12 +146,12 @@ class TorrentEntriesService implements ITorrentEntriesService { const imdbId: string | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); const kitsuId: number | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); - const fileCollection: ITorrentFileCollection = await torrentFileService.parseTorrentFiles(torrent) + const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos}) - .then(torrentContents => torrentSubtitleService.assignSubtitles(torrentContents)) + .then(torrentContents => this.subtitleService.assignSubtitles(torrentContents)) .then(torrentContents => this.assignMetaIds(torrentContents, imdbId, kitsuId)) .catch(error => { - logger.warn(`Failed getting contents for [${torrent.infoHash}] ${torrent.title}`, error.message); + this.logger.warn(`Failed getting contents for [${torrent.infoHash}] ${torrent.title}`, error.message); return {}; }); @@ -161,35 +178,35 @@ class TorrentEntriesService implements ITorrentEntriesService { subtitles: fileCollection.subtitles }); - return repository.createTorrent(newTorrent) + return this.repository.createTorrent(newTorrent) .then(() => { if (shouldDeleteOld) { - logger.debug(`Deleting old video for [${torrent.infoHash}] ${torrent.title}`) + this.logger.debug(`Deleting old video for [${torrent.infoHash}] ${torrent.title}`) return storedVideos[0].destroy(); } return Promise.resolve(); }) .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { const newVideo = File.build(video); - return repository.createFile(newVideo) + return this.repository.createFile(newVideo) }))) - .then(() => logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) - .catch(error => logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); - } + .then(() => this.logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) + .catch(error => this.logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); + }; - public async updateTorrentSeeders(torrent: ITorrentAttributes) { + public updateTorrentSeeders = async (torrent: ITorrentAttributes) => { if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { return torrent; } - return repository.setTorrentSeeders(torrent, torrent.seeders) + return this.repository.setTorrentSeeders(torrent, torrent.seeders) .catch(error => { - logger.warn('Failed updating seeders:', error); + this.logger.warn('Failed updating seeders:', error); return undefined; }); - } + }; - private assignMetaIds(fileCollection: ITorrentFileCollection, imdbId: string, kitsuId: number): ITorrentFileCollection { + private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string, kitsuId: number): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { video.imdbId = imdbId; @@ -198,12 +215,12 @@ class TorrentEntriesService implements ITorrentEntriesService { } return fileCollection; - } + }; - private async overwriteExistingFiles(torrent: IParsedTorrent, torrentContents: ITorrentFileCollection) { + private overwriteExistingFiles = async (torrent: IParsedTorrent, torrentContents: ITorrentFileCollection) => { const videos = torrentContents && torrentContents.videos; if (videos && videos.length) { - const existingFiles = await repository.getFiles(torrent.infoHash) + const existingFiles = await this.repository.getFiles(torrent.infoHash) .then((existing) => existing .reduce((map, next) => { const fileIndex = next.fileIndex !== undefined ? next.fileIndex : null; @@ -228,7 +245,5 @@ class TorrentEntriesService implements ITorrentEntriesService { return torrentContents; } return Promise.reject(`No video files found for: ${torrent.title}`); - } -} - -export const torrentEntriesService = new TorrentEntriesService(); \ No newline at end of file + }; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 1ad6bcd..877836f 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -5,9 +5,6 @@ import {PromiseHelpers} from '../helpers/promises_helpers'; import {TorrentType} from '../enums/torrent_types'; import {configurationService} from './configuration_service'; import {ExtensionHelpers} from '../helpers/extension_helpers'; -import {metadataService} from './metadata_service'; -import {torrentDownloadService} from "./torrent_download_service"; -import {logger} from "./logging_service"; import {IMetadataResponse} from "../interfaces/metadata_response"; import {IMetaDataQuery} from "../interfaces/metadata_query"; import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; @@ -16,23 +13,41 @@ import {IParsedTorrent} from "../interfaces/parsed_torrent"; import {IFileAttributes} from "../../repository/interfaces/file_attributes"; import {IContentAttributes} from "../../repository/interfaces/content_attributes"; import {ITorrentFileService} from "../interfaces/torrent_file_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {IMetadataService} from "../interfaces/metadata_service"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {ILoggingService} from "../interfaces/logging_service"; const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB -class TorrentFileService implements ITorrentFileService { +@injectable() +export class TorrentFileService implements ITorrentFileService { + private metadataService: IMetadataService; + private torrentDownloadService: ITorrentDownloadService; + private logger: ILoggingService; + + constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, + @inject(IocTypes.ITorrentDownloadService) torrentDownloadService: ITorrentDownloadService, + @inject(IocTypes.ILoggingService) logger: ILoggingService) { + this.metadataService = metadataService; + this.torrentDownloadService = torrentDownloadService; + this.logger = logger; + } + private readonly imdb_limiter: Bottleneck = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); - public async parseTorrentFiles(torrent: IParsedTorrent): Promise { + public parseTorrentFiles = async (torrent: IParsedTorrent): Promise => { const parsedTorrentName = parse(torrent.title); const query: IMetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, type: torrent.type || TorrentType.Movie, }; - const metadata = await metadataService.getMetadata(query) + const metadata = await this.metadataService.getMetadata(query) .then(meta => Object.assign({}, meta)) .catch(() => undefined); @@ -47,9 +62,9 @@ class TorrentFileService implements ITorrentFileService { } return this.parseSeriesFiles(torrent, metadata) - } + }; - public isPackTorrent(torrent: IParsedTorrent): boolean { + public isPackTorrent = (torrent: IParsedTorrent): boolean => { if (torrent.isPack) { return true; } @@ -64,17 +79,17 @@ class TorrentFileService implements ITorrentFileService { (parsedInfo.seasons && !parsedInfo.episodes); const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); return hasMultipleEpisodes && !hasSingleEpisode; - } + }; - private parseSeriesVideos(torrent: IParsedTorrent, videos: IFileAttributes[]): IFileAttributes[] { + private parseSeriesVideos = (torrent: IParsedTorrent, videos: IFileAttributes[]): IFileAttributes[] => { const parsedTorrentName = parse(torrent.title); const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); const parsedVideos = videos.map(video => this.parseSeriesVideo(video)); return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies) })); - } + }; - private async parseMovieFiles(torrent: IParsedTorrent, metadata: IMetadataResponse): Promise { + private parseMovieFiles = async (torrent: IParsedTorrent, metadata: IMetadataResponse): Promise => { const fileCollection: ITorrentFileCollection = await this.getMoviesTorrentContent(torrent); const filteredVideos = fileCollection.videos .filter(video => video.size > MIN_SIZE) @@ -102,9 +117,9 @@ class TorrentFileService implements ITorrentFileService { imdbId: video.imdbId, }))); return {...fileCollection, videos: parsedVideos}; - } + }; - private async parseSeriesFiles(torrent: IParsedTorrent, metadata: IMetadataResponse): Promise { + private parseSeriesFiles = async (torrent: IParsedTorrent, metadata: IMetadataResponse): Promise => { const fileCollection: ITorrentFileCollection = await this.getSeriesTorrentContent(torrent); const parsedVideos: IFileAttributes[] = await Promise.resolve(fileCollection.videos) .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) @@ -118,10 +133,10 @@ class TorrentFileService implements ITorrentFileService { .reduce((a, b) => a.concat(b), []) .map(video => this.isFeaturette(video) ? this.clearInfoFields(video) : video)); return {...torrent.fileCollection, videos: parsedVideos}; - } + }; - private async getMoviesTorrentContent(torrent: IParsedTorrent): Promise { - const files = await torrentDownloadService.getTorrentFiles(torrent) + private getMoviesTorrentContent = async (torrent: IParsedTorrent): Promise => { + const files = await this.torrentDownloadService.getTorrentFiles(torrent, configurationService.torrentConfig.TIMEOUT) .catch(error => { if (!this.isPackTorrent(torrent)) { const entries = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; @@ -134,23 +149,24 @@ class TorrentFileService implements ITorrentFileService { files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; } return files; - } - - private getDefaultFileEntries(torrent: IParsedTorrent): IFileAttributes[] { - return [{title: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; - } + }; - private async getSeriesTorrentContent(torrent: IParsedTorrent): Promise { - return torrentDownloadService.getTorrentFiles(torrent) - .catch(error => { - if (!this.isPackTorrent(torrent)) { - return { videos: this.getDefaultFileEntries(torrent), subtitles: [], contents: [] } - } - return Promise.reject(error); - }); - } + private getDefaultFileEntries = (torrent: IParsedTorrent): IFileAttributes[] => [{ + title: torrent.title, + path: torrent.title, + size: torrent.size, + fileIndex: null + }]; - private async mapSeriesEpisode(torrent: IParsedTorrent, file: IFileAttributes, files: IFileAttributes[]) : Promise { + private getSeriesTorrentContent = async (torrent: IParsedTorrent): Promise => this.torrentDownloadService.getTorrentFiles(torrent, configurationService.torrentConfig.TIMEOUT) + .catch(error => { + if (!this.isPackTorrent(torrent)) { + return {videos: this.getDefaultFileEntries(torrent), subtitles: [], contents: []} + } + return Promise.reject(error); + }); + + private mapSeriesEpisode = async (torrent: IParsedTorrent, file: IFileAttributes, files: IFileAttributes[]): Promise => { if (!file.episodes && !file.episodes) { if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { return Promise.resolve([{ @@ -178,13 +194,13 @@ class TorrentFileService implements ITorrentFileService { episodes: file.episodes, kitsuId: parseInt(file.kitsuId.toString() || torrent.kitsuId.toString()), }))) - } + }; - private async mapSeriesMovie(torrent: IParsedTorrent, file: IFileAttributes): Promise { + private mapSeriesMovie = async (torrent: IParsedTorrent, file: IFileAttributes): Promise => { const kitsuId= torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) .then(result => { if (result instanceof Error) { - logger.warn(`Failed to retrieve kitsuId due to error: ${result.message}`); + this.logger.warn(`Failed to retrieve kitsuId due to error: ${result.message}`); return undefined; } return result; @@ -197,9 +213,9 @@ class TorrentFileService implements ITorrentFileService { type: TorrentType.Movie }; - const metadataOrError = await metadataService.getMetadata(query); + const metadataOrError = await this.metadataService.getMetadata(query); if (metadataOrError instanceof Error) { - logger.warn(`Failed to retrieve metadata due to error: ${metadataOrError.message}`); + this.logger.warn(`Failed to retrieve metadata due to error: ${metadataOrError.message}`); // return default result or throw error, depending on your use case return [{ infoHash: torrent.infoHash, @@ -229,9 +245,9 @@ class TorrentFileService implements ITorrentFileService { imdbEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, kitsuEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, }]; - } + }; - private async decomposeEpisodes(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = { episodeCount: [] }) { + private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = { episodeCount: [] }) => { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -274,9 +290,9 @@ class TorrentFileService implements ITorrentFileService { // decomposeEpisodeTitleFiles(torrent, files, metadata); return files; - } + }; - private preprocessEpisodes(files: IFileAttributes[]) { + private preprocessEpisodes = (files: IFileAttributes[]) => { // reverse special episode naming when they named with 0 episode, ie. S02E00 files .filter(file => Number.isInteger(file.season) && file.episode === 0) @@ -285,9 +301,9 @@ class TorrentFileService implements ITorrentFileService { file.episodes = [file.season] file.season = 0; }) - } + }; - private isConcatSeasonAndEpisodeFiles(files: IFileAttributes[], sortedEpisodes: number[], metadata: IMetadataResponse) { + private isConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], sortedEpisodes: number[], metadata: IMetadataResponse) => { if (metadata.kitsuId !== undefined) { // anime does not use this naming scheme in 99% of cases; return false; @@ -312,13 +328,11 @@ class TorrentFileService implements ITorrentFileService { .filter(file => file.episodes.every(ep => ep > metadata.totalCount)); return sortedConcatEpisodes.length >= thresholdSorted && concatFileEpisodes.length >= threshold || concatAboveTotalEpisodeCount.length >= thresholdAbove; - } + }; - private isDateEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { - return files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); - } + private isDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); - private isAbsoluteEpisodeFiles(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) { + private isAbsoluteEpisodeFiles = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) => { const threshold = Math.ceil(files.length / 5); const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; const nonMovieEpisodes = files @@ -329,9 +343,9 @@ class TorrentFileService implements ITorrentFileService { return nonMovieEpisodes.every(file => !file.season) || (isAnime && nonMovieEpisodes.every(file => file.season > metadata.episodeCount.length)) || absoluteEpisodes.length >= threshold; - } + }; - private isNewEpisodeNotInMetadata(torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse) { + private isNewEpisodeNotInMetadata = (torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse) => { // new episode might not yet been indexed by cinemeta. // detect this if episode number is larger than the last episode or season is larger than the last one // only for non anime metas @@ -340,9 +354,9 @@ class TorrentFileService implements ITorrentFileService { && /continuing|current/i.test(metadata.status) && video.season >= metadata.episodeCount.length && video.episodes.every(ep => ep > (metadata.episodeCount[video.season - 1] || 0)); - } + }; - private decomposeConcatSeasonAndEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { + private decomposeConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => { files .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) .filter(file => metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) @@ -352,9 +366,9 @@ class TorrentFileService implements ITorrentFileService { file.episodes = file.episodes.map(ep => this.mod100(ep)) }); - } + }; - private decomposeAbsoluteEpisodeFiles(torrent: IParsedTorrent, videos: IFileAttributes[], metadata: IMetadataResponse) { + private decomposeAbsoluteEpisodeFiles = (torrent: IParsedTorrent, videos: IFileAttributes[], metadata: IMetadataResponse) => { if (metadata.episodeCount.length === 0) { videos .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) @@ -376,9 +390,9 @@ class TorrentFileService implements ITorrentFileService { file.episodes = file.episodes .map(ep => ep - metadata.episodeCount.slice(0, seasonIdx).reduce((a, b) => a + b, 0)) }); - } + }; - private decomposeDateEpisodeFiles(files: IFileAttributes[], metadata: IMetadataResponse) { + private decomposeDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => { if (!metadata || !metadata.videos || !metadata.videos.length) { return; } @@ -400,9 +414,9 @@ class TorrentFileService implements ITorrentFileService { file.episodes = [video.episode]; } }); - } + }; - private getTimeZoneOffset(country: string | undefined) { + private getTimeZoneOffset = (country: string | undefined) => { switch (country) { case 'United States': case 'USA': @@ -410,9 +424,9 @@ class TorrentFileService implements ITorrentFileService { default: return '00:00'; } - } + }; - private assignKitsuOrImdbEpisodes(torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) { + private assignKitsuOrImdbEpisodes = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) => { if (!metadata || !metadata.videos || !metadata.videos.length) { if (torrent.type === TorrentType.Anime) { // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping @@ -493,9 +507,9 @@ class TorrentFileService implements ITorrentFileService { }); } return files; - } + }; - private needsCinemetaMetadataForAnime(files: IFileAttributes[], metadata: IMetadataResponse) { + private needsCinemetaMetadataForAnime = (files: IFileAttributes[], metadata: IMetadataResponse) => { if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { return false; } @@ -509,19 +523,19 @@ class TorrentFileService implements ITorrentFileService { return differentSeasons > 1 || files .filter(file => !file.isMovie && file.episodes) .some(file => file.season < minSeason || file.season > maxSeason || file.episodes.every(ep => ep > total)); - } + }; - private async updateToCinemetaMetadata(metadata: IMetadataResponse) { + private updateToCinemetaMetadata = async (metadata: IMetadataResponse) => { const query: IMetaDataQuery = { id: metadata.imdbId, type: metadata.type }; - return await metadataService.getMetadata(query) + return await this.metadataService.getMetadata(query) .then((newMetadataOrError) => { if (newMetadataOrError instanceof Error) { // handle error - logger.warn(`Failed ${metadata.imdbId} metadata cinemeta update due: ${newMetadataOrError.message}`); + this.logger.warn(`Failed ${metadata.imdbId} metadata cinemeta update due: ${newMetadataOrError.message}`); return metadata; // or throw newMetadataOrError to propagate error up the call stack } // At this point TypeScript infers newMetadataOrError to be of type MetadataResponse @@ -535,11 +549,11 @@ class TorrentFileService implements ITorrentFileService { return metadata; } }) - } + }; - private findMovieImdbId(title: IFileAttributes | string) { + private findMovieImdbId = (title: IFileAttributes | string) => { const parsedTitle = typeof title === 'string' ? parse(title) : title; - logger.debug(`Finding movie imdbId for ${title}`); + this.logger.debug(`Finding movie imdbId for ${title}`); return this.imdb_limiter.schedule(async () => { const imdbQuery = { title: parsedTitle.title, @@ -547,14 +561,14 @@ class TorrentFileService implements ITorrentFileService { type: TorrentType.Movie }; try { - return await metadataService.getImdbId(imdbQuery); + return await this.metadataService.getImdbId(imdbQuery); } catch (e) { return undefined; } }); - } + }; - private async findMovieKitsuId(title: IFileAttributes | string) { + private findMovieKitsuId = async (title: IFileAttributes | string) => { const parsedTitle = typeof title === 'string' ? parse(title) : title; const kitsuQuery = { title: parsedTitle.title, @@ -563,28 +577,22 @@ class TorrentFileService implements ITorrentFileService { type: TorrentType.Movie }; try { - return await metadataService.getKitsuId(kitsuQuery); + return await this.metadataService.getKitsuId(kitsuQuery); } catch (e) { return undefined; } - } + }; - private isDiskTorrent(contents: IContentAttributes[]) { - return contents.some(content => ExtensionHelpers.isDisk(content.path)); - } + private isDiskTorrent = (contents: IContentAttributes[]) => contents.some(content => ExtensionHelpers.isDisk(content.path)); - private isSingleMovie(videos: IFileAttributes[]) { - return videos.length === 1 || - (videos.length === 2 && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); - } + private isSingleMovie = (videos: IFileAttributes[]) => videos.length === 1 || + (videos.length === 2 && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); - private isFeaturette(video: IFileAttributes) { - return /featurettes?\/|extras-grym/i.test(video.path); - } + private isFeaturette = (video: IFileAttributes) => /featurettes?\/|extras-grym/i.test(video.path); - private parseSeriesVideo(video: IFileAttributes): IFileAttributes { + private parseSeriesVideo = (video: IFileAttributes): IFileAttributes => { const videoInfo = parse(video.title); // the episode may be in a folder containing season number if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { @@ -628,9 +636,9 @@ class TorrentFileService implements ITorrentFileService { } return { ...video, ...videoInfo }; - } + }; - private isMovieVideo(torrent: IParsedTorrent, video: IFileAttributes, otherVideos: IFileAttributes[], hasMovies: boolean): boolean { + private isMovieVideo = (torrent: IParsedTorrent, video: IFileAttributes, otherVideos: IFileAttributes[], hasMovies: boolean): boolean => { if (Number.isInteger(torrent.season) && Array.isArray(torrent.episodes)) { // not movie if video has season return false; @@ -652,28 +660,22 @@ class TorrentFileService implements ITorrentFileService { return !!torrent.year && otherVideos.length > 3 && otherVideos.filter(other => other.title === video.title && other.year === video.year).length < 3; - } + }; - private clearInfoFields(video: IFileAttributes) { + private clearInfoFields = (video: IFileAttributes) => { video.imdbId = undefined; video.imdbSeason = undefined; video.imdbEpisode = undefined; video.kitsuId = undefined; video.kitsuEpisode = undefined; return video; - } + }; - private div100(episode: number) { - return (episode / 100 >> 0); // floor to nearest int - } + private div100 = (episode: number) => (episode / 100 >> 0); - private mod100(episode: number) { - return episode % 100; - } + private mod100 = (episode: number) => episode % 100; } -export const torrentFileService = new TorrentFileService(); - diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index f25fffd..516323d 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -1,32 +1,46 @@ import {TorrentType} from "../enums/torrent_types"; -import {logger} from "./logging_service"; -import {trackerService} from "./tracker_service"; -import {torrentEntriesService} from "./torrent_entries_service"; import {IIngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; import {IParsedTorrent} from "../interfaces/parsed_torrent"; import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {ILoggingService} from "../interfaces/logging_service"; +import {ITrackerService} from "../interfaces/tracker_service"; -class TorrentProcessingService implements ITorrentProcessingService { - public async processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise { +@injectable() +export class TorrentProcessingService implements ITorrentProcessingService { + private torrentEntriesService: ITorrentEntriesService; + private logger: ILoggingService; + private trackerService: ITrackerService; + constructor(@inject(IocTypes.ITorrentEntriesService) torrentEntriesService: ITorrentEntriesService, + @inject(IocTypes.ILoggingService) logger: ILoggingService, + @inject(IocTypes.ITrackerService) trackerService: ITrackerService){ + this.torrentEntriesService = torrentEntriesService; + this.logger = logger; + this.trackerService = trackerService; + } + + public processTorrentRecord = async (torrent: IIngestedTorrentAttributes): Promise => { const {category} = torrent; const type = category === 'tv' ? TorrentType.Series : TorrentType.Movie; const torrentInfo: IParsedTorrent = await this.parseTorrent(torrent, type); - logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); + this.logger.info(`Processing torrent ${torrentInfo.title} with infoHash ${torrentInfo.infoHash}`); - if (await torrentEntriesService.checkAndUpdateTorrent(torrentInfo)) { + if (await this.torrentEntriesService.checkAndUpdateTorrent(torrentInfo)) { return; } - return torrentEntriesService.createTorrentEntry(torrentInfo); - } + return this.torrentEntriesService.createTorrentEntry(torrentInfo, false); + }; - private async assignTorrentTrackers(): Promise { - const trackers = await trackerService.getTrackers(); + private assignTorrentTrackers = async (): Promise => { + const trackers = await this.trackerService.getTrackers(); return trackers.join(','); } - private async parseTorrent(torrent: IIngestedTorrentAttributes, category: string): Promise { + private parseTorrent = async (torrent: IIngestedTorrentAttributes, category: string): Promise => { const infoHash = torrent.info_hash?.trim().toLowerCase() return { title: torrent.name, @@ -40,16 +54,14 @@ class TorrentProcessingService implements ITorrentProcessingService { provider: torrent.source, trackers: await this.assignTorrentTrackers(), } - } + }; - private parseImdbId(torrent: IIngestedTorrentAttributes): string | undefined { + private parseImdbId = (torrent: IIngestedTorrentAttributes): string | undefined => { if (torrent.imdb === undefined || torrent.imdb === null) { return undefined; } return torrent.imdb; - } + }; } -export const torrentProcessingService = new TorrentProcessingService(); - diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 4ddabb3..83856ee 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -2,9 +2,11 @@ import {parse} from 'parse-torrent-title'; import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; import {IFileAttributes} from "../../repository/interfaces/file_attributes"; import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; +import {injectable} from "inversify"; -class TorrentSubtitleService implements ITorrentSubtitleService { - public assignSubtitles(fileCollection: ITorrentFileCollection): ITorrentFileCollection { +@injectable() +export class TorrentSubtitleService implements ITorrentSubtitleService { + public assignSubtitles = (fileCollection: ITorrentFileCollection): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length && fileCollection.subtitles && fileCollection.subtitles.length) { if (fileCollection.videos.length === 1) { fileCollection.videos[0].subtitles = fileCollection.subtitles; @@ -24,9 +26,9 @@ class TorrentSubtitleService implements ITorrentSubtitleService { return {...fileCollection, subtitles: unassignedSubs}; } return fileCollection; - } + }; - private parseVideo(video: IFileAttributes) { + private parseVideo = (video: IFileAttributes)=> { const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); const folderName = video.title.replace(/\/?[^/]+$/, ''); return { @@ -37,7 +39,7 @@ class TorrentSubtitleService implements ITorrentSubtitleService { }; } - private mostProbableSubtitleVideos(subtitle: any, parsedVideos: any[]) { + private mostProbableSubtitleVideos = (subtitle: any, parsedVideos: any[]) => { const subTitle = (subtitle.title || subtitle.path).split('/').pop().replace(/\.(\w{2,4})$/, ''); const parsedSub = this.parsePath(subtitle.title || subtitle.path); const byFileName = parsedVideos.filter(video => subTitle.includes(video.fileName)); @@ -66,17 +68,17 @@ class TorrentSubtitleService implements ITorrentSubtitleService { return undefined; } - private singleVideoFile(videos: any[]) { + private singleVideoFile = (videos: any[])=> { return new Set(videos.map(v => v.videoFile.fileIndex)).size === 1; } - private parsePath(path: string) { + private parsePath = (path: string) => { const pathParts = path.split('/').map(part => this.parseFilename(part)); const parsedWithEpisode = pathParts.find(parsed => parsed.season && parsed.episodes); return parsedWithEpisode || pathParts[pathParts.length - 1]; } - private parseFilename(filename: string) { + private parseFilename = (filename: string) => { const parsedInfo = parse(filename) const titleEpisode = parsedInfo.title.match(/(\d+)$/); if (!parsedInfo.episodes && titleEpisode) { @@ -85,10 +87,8 @@ class TorrentSubtitleService implements ITorrentSubtitleService { return parsedInfo; } - private arrayEquals(array1: any[], array2: any[]) { + private arrayEquals = (array1: any[], array2: any[]) => { if (!array1 || !array2) return array1 === array2; return array1.length === array2.length && array1.every((value, index) => value === array2[index]) } } - -export const torrentSubtitleService = new TorrentSubtitleService(); diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index a85e5de..b292314 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,15 +1,25 @@ import axios, {AxiosResponse} from 'axios'; -import {cacheService} from "./cache_service"; import {configurationService} from './configuration_service'; -import {logger} from "./logging_service"; import {ITrackerService} from "../interfaces/tracker_service"; +import {inject, injectable} from "inversify"; +import {IocTypes} from "../models/ioc_types"; +import {ICacheService} from "../interfaces/cache_service"; +import {ILoggingService} from "../interfaces/logging_service"; -class TrackerService implements ITrackerService { - public async getTrackers(): Promise { - return cacheService.cacheTrackers(this.downloadTrackers); - }; +@injectable() +export class TrackerService implements ITrackerService { + private cacheService: ICacheService; + private logger: ILoggingService; + + constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService, + @inject(IocTypes.ILoggingService) logger: ILoggingService) { + this.cacheService = cacheService; + this.logger = logger; + } - private async downloadTrackers(): Promise { + public getTrackers = async (): Promise => this.cacheService.cacheTrackers(this.downloadTrackers); + + private downloadTrackers = async(): Promise => { const response: AxiosResponse = await axios.get(configurationService.trackerConfig.TRACKERS_URL); const trackersListText: string = response.data; // Trackers are separated by a newline character @@ -23,11 +33,9 @@ class TrackerService implements ITrackerService { } - logger.info(`Trackers updated at ${Date.now()}: ${urlTrackers.length} trackers`); + this.logger.info(`Trackers updated at ${Date.now()}: ${urlTrackers.length} trackers`); return urlTrackers; }; } -export const trackerService = new TrackerService(); - diff --git a/src/node/consumer/src/main.ts b/src/node/consumer/src/main.ts new file mode 100644 index 0000000..a523bdf --- /dev/null +++ b/src/node/consumer/src/main.ts @@ -0,0 +1,8 @@ +import {serviceContainer} from "./lib/models/inversify_config"; +import {IocTypes} from "./lib/models/ioc_types"; +import {ICompositionalRoot} from "./lib/interfaces/composition_root"; + +(async () => { + const compositionalRoot = serviceContainer.get(IocTypes.ICompositionalRoot); + await compositionalRoot.start(); +})(); \ No newline at end of file diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index c3c4544..e5e93cd 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -13,9 +13,13 @@ import {SkipTorrent} from "./models/skipTorrent"; import {IFileAttributes} from "./interfaces/file_attributes"; import {ITorrentAttributes} from "./interfaces/torrent_attributes"; import {IngestedPage} from "./models/ingestedPage"; -import {logger} from "../lib/services/logging_service"; +import {ILoggingService} from "../lib/interfaces/logging_service"; +import {IocTypes} from "../lib/models/ioc_types"; +import {inject, injectable} from "inversify"; +import {IDatabaseRepository} from "./interfaces/database_repository"; -class DatabaseRepository { +@injectable() +export class DatabaseRepository implements IDatabaseRepository { private readonly database: Sequelize; private models = [ @@ -27,59 +31,56 @@ class DatabaseRepository { SkipTorrent, IngestedTorrent, IngestedPage]; + private logger: ILoggingService; - constructor() { + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { + this.logger = logger; this.database = this.createDatabase(); } - - public async connect() { + + public connect = async () => { try { await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); } catch { - logger.error('Failed syncing database'); + this.logger.error('Failed syncing database'); process.exit(1); } - } + }; - public async getProvider(provider: Provider) { + public getProvider = async (provider: Provider) => { try { - const [result] = await Provider.findOrCreate({ where: { name: { [Op.eq]: provider.name } }, defaults: provider }); + const [result] = await Provider.findOrCreate({where: {name: {[Op.eq]: provider.name}}, defaults: provider}); return result; } catch { return provider as Provider; } - } + }; - public async getTorrent(torrent: ITorrentAttributes): Promise { + public getTorrent = async (torrent: ITorrentAttributes): Promise => { const where = torrent.infoHash - ? { infoHash: torrent.infoHash } - : { provider: torrent.provider, torrentId: torrent.torrentId }; - return await Torrent.findOne({ where }); - } + ? {infoHash: torrent.infoHash} + : {provider: torrent.provider, torrentId: torrent.torrentId}; + return await Torrent.findOne({where}); + }; - public async getTorrentsBasedOnTitle(titleQuery: string, type: string): Promise { - return this.getTorrentsBasedOnQuery({ title: { [Op.regexp]: `${titleQuery}` }, type }); - } + public getTorrentsBasedOnTitle = async (titleQuery: string, type: string): Promise => this.getTorrentsBasedOnQuery({ + title: {[Op.regexp]: `${titleQuery}`}, + type + }); - public async getTorrentsBasedOnQuery(where: WhereOptions): Promise { - return await Torrent.findAll({ where }); - } + public getTorrentsBasedOnQuery = async (where: WhereOptions): Promise => await Torrent.findAll({where}); - public async getFilesBasedOnQuery(where: WhereOptions): Promise { - return await File.findAll({ where }); - } + public getFilesBasedOnQuery = async (where: WhereOptions): Promise => await File.findAll({where}); - public async getTorrentsWithoutSize(): Promise { - return await Torrent.findAll({ - where: literal( - 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), - order: [ - ['seeders', 'DESC'] - ] - }); - } + public getTorrentsWithoutSize = async (): Promise => await Torrent.findAll({ + where: literal( + 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), + order: [ + ['seeders', 'DESC'] + ] + }); - public async getUpdateSeedersTorrents(limit = 50): Promise { + public getUpdateSeedersTorrents = async (limit = 50): Promise => { const until = moment().subtract(7, 'days').format('YYYY-MM-DD'); return await Torrent.findAll({ where: literal(`torrent."updatedAt" < '${until}'`), @@ -89,9 +90,9 @@ class DatabaseRepository { ['updatedAt', 'ASC'] ] }); - } + }; - public async getUpdateSeedersNewTorrents(limit = 50): Promise { + public getUpdateSeedersNewTorrents = async (limit = 50): Promise => { const lastUpdate = moment().subtract(12, 'hours').format('YYYY-MM-DD'); const createdAfter = moment().subtract(4, 'days').format('YYYY-MM-DD'); return await Torrent.findAll({ @@ -102,38 +103,34 @@ class DatabaseRepository { ['updatedAt', 'ASC'] ] }); - } + }; - public async getNoContentsTorrents(): Promise { - return await Torrent.findAll({ - where: { opened: false, seeders: { [Op.gte]: 1 } }, - limit: 500, - order: literal('random()') - }); - } + public getNoContentsTorrents = async (): Promise => await Torrent.findAll({ + where: {opened: false, seeders: {[Op.gte]: 1}}, + limit: 500, + order: literal('random()') + }); - public async createTorrent(torrent: Torrent): Promise { + public createTorrent = async (torrent: Torrent): Promise => { await Torrent.upsert(torrent); await this.createContents(torrent.infoHash, torrent.contents); await this.createSubtitles(torrent.infoHash, torrent.subtitles); - } + }; - public async setTorrentSeeders(torrent: ITorrentAttributes, seeders: number): Promise<[number]> { + public setTorrentSeeders = async (torrent: ITorrentAttributes, seeders: number): Promise<[number]> => { const where = torrent.infoHash - ? { infoHash: torrent.infoHash } - : { provider: torrent.provider, torrentId: torrent.torrentId }; - + ? {infoHash: torrent.infoHash} + : {provider: torrent.provider, torrentId: torrent.torrentId}; + return await Torrent.update( - { seeders: seeders }, - { where: where } + {seeders: seeders}, + {where: where} ); - } + }; - public async deleteTorrent(infoHash: string): Promise { - return await Torrent.destroy({ where: { infoHash: infoHash } }); - } + public deleteTorrent = async (infoHash: string): Promise => await Torrent.destroy({where: {infoHash: infoHash}}); - public async createFile(file: File): Promise { + public createFile = async (file: File): Promise => { if (file.id) { if (file.dataValues) { await file.save(); @@ -148,30 +145,24 @@ class DatabaseRepository { return subtitle; }); } - await File.create(file, { include: [Subtitle], ignoreDuplicates: true }); + await File.create(file, {include: [Subtitle], ignoreDuplicates: true}); } - } + }; - public async getFiles(infoHash: string): Promise { - return File.findAll({ where: { infoHash: infoHash } }); - } + public getFiles = async (infoHash: string): Promise => File.findAll({where: {infoHash: infoHash}}); - public async getFilesBasedOnTitle(titleQuery: string): Promise { - return File.findAll({ where: { title: { [Op.regexp]: `${titleQuery}` } } }); - } + public getFilesBasedOnTitle = async (titleQuery: string): Promise => File.findAll({where: {title: {[Op.regexp]: `${titleQuery}`}}}); - public async deleteFile(id: number): Promise { - return File.destroy({ where: { id: id } }); - } + public deleteFile = async (id: number): Promise => File.destroy({where: {id: id}}); - public async createSubtitles(infoHash: string, subtitles: Subtitle[]): Promise[]> { + public createSubtitles = async (infoHash: string, subtitles: Subtitle[]): Promise[]> => { if (subtitles && subtitles.length) { - return Subtitle.bulkCreate(subtitles.map(subtitle => ({ infoHash, title: subtitle.path, ...subtitle }))); + return Subtitle.bulkCreate(subtitles.map(subtitle => ({infoHash, title: subtitle.path, ...subtitle}))); } return Promise.resolve(); - } + }; - public async upsertSubtitles(file: File, subtitles: Subtitle[]): Promise { + public upsertSubtitles = async (file: File, subtitles: Subtitle[]): Promise => { if (file.id && subtitles && subtitles.length) { await PromiseHelpers.sequence(subtitles .map(subtitle => { @@ -188,40 +179,32 @@ class DatabaseRepository { } })); } - } + }; - public async getSubtitles(infoHash: string): Promise { - return Subtitle.findAll({ where: { infoHash: infoHash } }); - } + public getSubtitles = async (infoHash: string): Promise => Subtitle.findAll({where: {infoHash: infoHash}}); - public async getUnassignedSubtitles(): Promise { - return Subtitle.findAll({ where: { fileId: null } }); - } + public getUnassignedSubtitles = async (): Promise => Subtitle.findAll({where: {fileId: null}}); - public async createContents(infoHash: string, contents: Content[]): Promise { + public createContents = async (infoHash: string, contents: Content[]): Promise => { if (contents && contents.length) { - await Content.bulkCreate(contents.map(content => ({ infoHash, ...content })), { ignoreDuplicates: true }); - await Torrent.update({ opened: true }, { where: { infoHash: infoHash }, silent: true }); + await Content.bulkCreate(contents.map(content => ({infoHash, ...content})), {ignoreDuplicates: true}); + await Torrent.update({opened: true}, {where: {infoHash: infoHash}, silent: true}); } - } + }; - public async getContents(infoHash: string): Promise { - return Content.findAll({ where: { infoHash: infoHash } }); - } + public getContents = async (infoHash: string): Promise => Content.findAll({where: {infoHash: infoHash}}); - public async getSkipTorrent(infoHash: string): Promise { + public getSkipTorrent = async (infoHash: string): Promise => { const result = await SkipTorrent.findByPk(infoHash); if (!result) { throw new Error(`torrent not found: ${infoHash}`); } return result.dataValues as SkipTorrent; - } + }; - public async createSkipTorrent(torrent: Torrent): Promise<[SkipTorrent, boolean]> { - return SkipTorrent.upsert({ infoHash: torrent.infoHash }); - } - - private createDatabase(): Sequelize { + public createSkipTorrent = async (torrent: Torrent): Promise<[SkipTorrent, boolean]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); + + private createDatabase = (): Sequelize => { const newDatabase = new Sequelize( configurationService.databaseConfig.POSTGRES_URI, { @@ -232,7 +215,5 @@ class DatabaseRepository { newDatabase.addModels(this.models); return newDatabase; - } + }; } - -export const repository = new DatabaseRepository(); diff --git a/src/node/consumer/src/repository/interfaces/database_repository.ts b/src/node/consumer/src/repository/interfaces/database_repository.ts new file mode 100644 index 0000000..0a3ce38 --- /dev/null +++ b/src/node/consumer/src/repository/interfaces/database_repository.ts @@ -0,0 +1,62 @@ +import {Provider} from "../models/provider"; +import {WhereOptions} from "sequelize"; +import {ITorrentAttributes} from "./torrent_attributes"; +import {Torrent} from "../models/torrent"; +import {IFileAttributes} from "./file_attributes"; +import {File} from "../models/file"; +import {Subtitle} from "../models/subtitle"; +import {Model} from "sequelize-typescript"; +import {Content} from "../models/content"; +import {SkipTorrent} from "../models/skipTorrent"; + +export interface IDatabaseRepository { + connect(): Promise; + + getProvider(provider: Provider): Promise; + + getTorrent(torrent: ITorrentAttributes): Promise; + + getTorrentsBasedOnTitle(titleQuery: string, type: string): Promise; + + getTorrentsBasedOnQuery(where: WhereOptions): Promise; + + getFilesBasedOnQuery(where: WhereOptions): Promise; + + getTorrentsWithoutSize(): Promise; + + getUpdateSeedersTorrents(limit): Promise; + + getUpdateSeedersNewTorrents(limit): Promise; + + getNoContentsTorrents(): Promise; + + createTorrent(torrent: Torrent): Promise; + + setTorrentSeeders(torrent: ITorrentAttributes, seeders: number): Promise<[number]>; + + deleteTorrent(infoHash: string): Promise; + + createFile(file: File): Promise; + + getFiles(infoHash: string): Promise; + + getFilesBasedOnTitle(titleQuery: string): Promise; + + deleteFile(id: number): Promise; + + createSubtitles(infoHash: string, subtitles: Subtitle[]): Promise[]>; + + upsertSubtitles(file: File, subtitles: Subtitle[]): Promise; + + getSubtitles(infoHash: string): Promise; + + getUnassignedSubtitles(): Promise; + + createContents(infoHash: string, contents: Content[]): Promise; + + getContents(infoHash: string): Promise; + + getSkipTorrent(infoHash: string): Promise; + + createSkipTorrent(torrent: Torrent): Promise<[SkipTorrent, boolean]>; +} \ No newline at end of file From 0f3e20eef3231d63706fb48a7ea557334c5732f6 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 11:22:32 +0000 Subject: [PATCH 26/55] trackers needs to be singleton, loggers should. be too --- .gitignore | 1 + src/node/consumer/package.json | 2 +- src/node/consumer/src/lib/models/inversify_config.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index cd4d1ba..6a0132e 100644 --- a/.gitignore +++ b/.gitignore @@ -404,3 +404,4 @@ FodyWeavers.xsd *.sln.iml dist/ +**/localdev.compose.yml \ No newline at end of file diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index d6f6a7c..192a1c5 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "node esbuild.js", "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", - "start": "node dist/index.cjs", + "start": "node dist/main.cjs", "lint": "npx eslint ./src --ext .ts,.js" }, "license": "MIT", diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/lib/models/inversify_config.ts index 898a2c7..6bbb2a2 100644 --- a/src/node/consumer/src/lib/models/inversify_config.ts +++ b/src/node/consumer/src/lib/models/inversify_config.ts @@ -30,14 +30,14 @@ const serviceContainer = new Container(); serviceContainer.bind(IocTypes.ICompositionalRoot).to(CompositionalRoot).inSingletonScope(); serviceContainer.bind(IocTypes.ICacheService).to(CacheService).inSingletonScope(); +serviceContainer.bind(IocTypes.ILoggingService).to(LoggingService).inSingletonScope(); +serviceContainer.bind(IocTypes.ITrackerService).to(TrackerService).inSingletonScope(); serviceContainer.bind(IocTypes.ITorrentFileService).to(TorrentFileService); serviceContainer.bind(IocTypes.ITorrentProcessingService).to(TorrentProcessingService); serviceContainer.bind(IocTypes.ITorrentSubtitleService).to(TorrentSubtitleService); serviceContainer.bind(IocTypes.ITorrentEntriesService).to(TorrentEntriesService); serviceContainer.bind(IocTypes.ITorrentDownloadService).to(TorrentDownloadService); -serviceContainer.bind(IocTypes.ILoggingService).to(LoggingService); serviceContainer.bind(IocTypes.IMetadataService).to(MetadataService); -serviceContainer.bind(IocTypes.ITrackerService).to(TrackerService); serviceContainer.bind(IocTypes.IDatabaseRepository).to(DatabaseRepository); serviceContainer.bind(IocTypes.IProcessTorrentsJob).to(ProcessTorrentsJob); From 6e2b776211a0fb70d6715d21c8fcd9b56ac827fc Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 11:37:59 +0000 Subject: [PATCH 27/55] doh - :P --- .../consumer/src/lib/services/cache_service.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index c89bd1d..dc140f9 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,4 +1,4 @@ -import {Cache, createCache, memoryStore} from 'cache-manager'; +import {Cache, createCache, MemoryCache, memoryStore, Store} from 'cache-manager'; import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' import {configurationService} from './configuration_service'; import {CacheType} from "../enums/cache_types"; @@ -23,9 +23,12 @@ export type CacheMethod = () => any; @injectable() export class CacheService implements ICacheService { private logger: ILoggingService; + private readonly memoryCache: MemoryCache; + private readonly remoteCache: Cache | MemoryCache; + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { this.logger = logger; - if (!configurationService.cacheConfig.NO_CACHE) { + if (configurationService.cacheConfig.NO_CACHE) { this.logger.info('Cache is disabled'); return; } @@ -49,7 +52,7 @@ export class CacheService implements ICacheService { private initiateMemoryCache = () => createCache(memoryStore(), { ttl: MEMORY_TTL - }) as Cache; + }); private initiateMongoCache = () => { const store = mongoDbStore({ @@ -76,7 +79,7 @@ export class CacheService implements ICacheService { return configurationService.cacheConfig.MONGO_URI ? this.initiateMongoCache() : this.initiateMemoryCache(); } - private getCacheType = (cacheType: CacheType): typeof this.memoryCache | null => { + private getCacheType = (cacheType: CacheType): MemoryCache | Cache => { switch (cacheType) { case CacheType.Memory: return this.memoryCache; @@ -87,9 +90,6 @@ export class CacheService implements ICacheService { } } - private readonly memoryCache: Cache; - private readonly remoteCache: Cache; - private cacheWrap = async ( cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { const cache = this.getCacheType(cacheType); From 7fe9b64f66ad09d2076bef3c867a3d2197e51d4c Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 14:03:57 +0000 Subject: [PATCH 28/55] replace torrent-stream (high vunerabilities) with webtorrent, gives us clean package audit --- src/node/consumer/.eslintrc | 9 +- src/node/consumer/esbuild.js | 14 +- src/node/consumer/package-lock.json | 2160 ++++++++++++----- src/node/consumer/package.json | 5 +- .../consumer/src/jobs/process_torrents_job.ts | 6 +- .../src/lib/helpers/boolean_helpers.ts | 2 +- .../src/lib/helpers/promises_helpers.ts | 10 +- .../src/lib/interfaces/cinemeta_metadata.ts | 7 + .../src/lib/interfaces/kitsu_metadata.ts | 4 + .../src/lib/interfaces/logging_service.ts | 3 + .../src/lib/interfaces/metadata_query.ts | 2 +- .../src/lib/models/composition_root.ts | 1 + .../models/configuration/torrent_config.ts | 1 + .../src/lib/models/inversify_config.ts | 6 +- .../src/lib/services/cache_service.ts | 4 +- .../src/lib/services/metadata_service.ts | 1 + .../lib/services/torrent_download_service.ts | 104 +- .../lib/services/torrent_entries_service.ts | 4 +- .../src/lib/services/torrent_file_service.ts | 35 +- .../services/torrent_processing_service.ts | 5 +- .../lib/services/torrent_subtitle_service.ts | 4 +- .../src/lib/services/tracker_service.ts | 4 +- .../src/repository/database_repository.ts | 22 +- .../consumer/src/repository/models/content.ts | 18 +- .../consumer/src/repository/models/file.ts | 47 +- .../src/repository/models/ingestedPage.ts | 4 +- .../src/repository/models/ingestedTorrent.ts | 36 +- .../src/repository/models/provider.ts | 14 +- .../src/repository/models/skipTorrent.ts | 6 +- .../src/repository/models/subtitle.ts | 25 +- .../consumer/src/repository/models/torrent.ts | 32 +- src/node/consumer/tsconfig.json | 9 +- 32 files changed, 1846 insertions(+), 758 deletions(-) diff --git a/src/node/consumer/.eslintrc b/src/node/consumer/.eslintrc index 85b3aad..e0c8130 100644 --- a/src/node/consumer/.eslintrc +++ b/src/node/consumer/.eslintrc @@ -64,7 +64,12 @@ }, "overrides": [ { - "files": ["*.ts", "*.mts", "*.cts", "*.tsx"], + "files": [ + "*.ts", + "*.mts", + "*.cts", + "*.tsx" + ], "rules": { "@typescript-eslint/explicit-function-return-type": "error", "@typescript-eslint/consistent-type-assertions": [ @@ -73,7 +78,7 @@ "assertionStyle": "as", "objectLiteralTypeAssertions": "never" } - ] + ] } } ] diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js index 938948f..17393df 100644 --- a/src/node/consumer/esbuild.js +++ b/src/node/consumer/esbuild.js @@ -1,14 +1,14 @@ -import { build } from "esbuild"; -import { readFileSync, rmSync } from "fs"; +import {build} from "esbuild"; +import {readFileSync, rmSync} from "fs"; -const { devDependencies } = JSON.parse(readFileSync("./package.json", "utf8")); +const {devDependencies} = JSON.parse(readFileSync("./package.json", "utf8")); const start = Date.now(); try { const outdir = "dist"; - rmSync(outdir, { recursive: true, force: true }); + rmSync(outdir, {recursive: true, force: true}); build({ bundle: true, @@ -27,8 +27,8 @@ try { plugins: [ { name: "populate-import-meta", - setup: ({ onLoad }) => { - onLoad({ filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`) }, args => { + setup: ({onLoad}) => { + onLoad({filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`)}, args => { const contents = readFileSync(args.path, "utf8"); const transformedContents = contents @@ -36,7 +36,7 @@ try { .replace(/import\.meta\.filename/g, "__filename") .replace(/import\.meta\.dirname/g, "__dirname"); - return { contents: transformedContents, loader: "default" }; + return {contents: transformedContents, loader: "default"}; }); }, } diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index eb2f591..88b7ff6 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@tirke/node-cache-manager-mongodb": "^1.6.0", + "@types/webtorrent": "^0.109.7", "amqplib": "^0.10.3", "axios": "^1.6.1", "bottleneck": "^2.19.5", @@ -26,8 +27,8 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", - "torrent-stream": "^1.2.1", - "user-agents": "^1.0.1444" + "user-agents": "^1.0.1444", + "webtorrent": "^2.1.35" }, "devDependencies": { "@types/amqplib": "^0.10.4", @@ -556,6 +557,87 @@ "node": ">= 8" } }, + "node_modules/@silentbot1/nat-api": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@silentbot1/nat-api/-/nat-api-0.4.7.tgz", + "integrity": "sha512-6aKXUf4AY6ETBdwjswQOekY6HGj3eZTAUhJx1oYicBqpMJcsphIydEQKp/Hooz6Y070MOI6tD/oT1MgS7bP3Vg==", + "dependencies": { + "chrome-dgram": "^3.0.6", + "cross-fetch-ponyfill": "^1.0.3", + "debug": "^4.3.4", + "default-gateway": "^6.0.3", + "unordered-array-remove": "^1.0.2", + "xml2js": "^0.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@thaunknown/idb-chunk-store": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@thaunknown/idb-chunk-store/-/idb-chunk-store-1.0.2.tgz", + "integrity": "sha512-UdKshbKdHDP+p0XPdv55QiU/scdB9TzvovGFSgXThf+7Yd3noLeYp6KpkYyc1jzUXvI3/8+TemPeASOimrOXvw==", + "dependencies": { + "idb": "^6.1.2", + "queue-microtask": "^1.2.3" + } + }, + "node_modules/@thaunknown/simple-peer": { + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/@thaunknown/simple-peer/-/simple-peer-9.12.1.tgz", + "integrity": "sha512-IS5BXvXx7cvBAzaxqotJf4s4rJCPk5JABLK6Gbnn7oAmWVcH4hYABabBBrvvJtv/xyUqR4v/H3LalnGRJJfEog==", + "dependencies": { + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "streamx": "^2.13.2", + "uint8-util": "^2.1.9" + } + }, + "node_modules/@thaunknown/simple-websocket": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@thaunknown/simple-websocket/-/simple-websocket-9.1.1.tgz", + "integrity": "sha512-vzQloFWRodRZqZhpxMpBljFtISesY8TihA8T5uKwCYdj2I1ImMhE/gAeTCPsCGOtxJfGKu3hw/is6MXauWLjOg==", + "dependencies": { + "debug": "^4.3.4", + "queue-microtask": "^1.2.3", + "streamx": "^2.13.2", + "uint8-util": "^2.1.9", + "ws": "^8.12.0" + } + }, + "node_modules/@thaunknown/simple-websocket/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@thaunknown/thirty-two": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@thaunknown/thirty-two/-/thirty-two-1.0.3.tgz", + "integrity": "sha512-bD6PvWbaf53JC04O7WnGDjqZBDgja/KT2Jd/6I2vJBIy+DLmQfQJZZ/G+16nAkVq1yGTIkO4rfc4RlH0DmEEqA==", + "dependencies": { + "uint8-util": "^2.1.9" + }, + "engines": { + "node": ">=0.2.6" + } + }, "node_modules/@tirke/node-cache-manager-mongodb": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz", @@ -579,6 +661,14 @@ "@types/node": "*" } }, + "node_modules/@types/bittorrent-protocol": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/bittorrent-protocol/-/bittorrent-protocol-3.1.6.tgz", + "integrity": "sha512-hqiRctJX9t9kknr6nn0q7UlcWHKvw2gSnPc/4jxt7Q/T0RP9txNv27Djue9ZjCNlAJ+irqAnCxtb+TcSpMyhtA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "license": "MIT", @@ -601,7 +691,6 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", "integrity": "sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -622,12 +711,38 @@ "version": "5.26.5", "license": "MIT" }, + "node_modules/@types/parse-torrent": { + "version": "5.8.7", + "resolved": "https://registry.npmjs.org/@types/parse-torrent/-/parse-torrent-5.8.7.tgz", + "integrity": "sha512-vZtYe450hO+KL7B5fejM8CHWg1LPZKeVXlolphPsWf6n4H0ZUlI6ICbqHoaFmH7JQmU2yRbGgyvqqizdFuGPFQ==", + "dependencies": { + "@types/magnet-uri": "*", + "@types/node": "*", + "@types/parse-torrent-file": "*" + } + }, + "node_modules/@types/parse-torrent-file": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/parse-torrent-file/-/parse-torrent-file-4.0.6.tgz", + "integrity": "sha512-SxqVth0Iv0WuEkqWS5MaY4S4Tlyi+QHkElQREvsUPw2xHcPgKyQ2dkJRRv5vAxmLzH+tnMdOj1Nws/wsenbzUw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/simple-peer": { + "version": "9.11.8", + "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.8.tgz", + "integrity": "sha512-rvqefdp2rvIA6wiomMgKWd2UZNPe6LM2EV5AuY3CPQJF+8TbdrL5TjYdMf0VAjGczzlkH4l1NjDkihwbj3Xodw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/stremio-addon-sdk": { "version": "1.6.11", "dev": true, @@ -651,6 +766,17 @@ "version": "7.0.3", "license": "MIT" }, + "node_modules/@types/webtorrent": { + "version": "0.109.7", + "resolved": "https://registry.npmjs.org/@types/webtorrent/-/webtorrent-0.109.7.tgz", + "integrity": "sha512-iDcZkXUMjWOtPpxAWXivs6rpYD++8w4vYJVqGJQKxZh1YxIXm5P3CyHGX735nJ6kFOFXLxD1O0ys/msI1nhRug==", + "dependencies": { + "@types/bittorrent-protocol": "*", + "@types/node": "*", + "@types/parse-torrent": "*", + "@types/simple-peer": "*" + } + }, "node_modules/@types/whatwg-url": { "version": "11.0.4", "license": "MIT", @@ -958,6 +1084,15 @@ "dev": true, "license": "ISC" }, + "node_modules/@webtorrent/http-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webtorrent/http-node/-/http-node-1.3.0.tgz", + "integrity": "sha512-GWZQKroPES4z91Ijx6zsOsb7+USOxjy66s8AoTWg0HiBBdfnbtf9aeh3Uav0MgYn4BL8Q7tVSUpd0gGpngKGEQ==", + "dependencies": { + "freelist": "^1.0.3", + "http-parser-js": "^0.4.3" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -988,10 +1123,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/addr-to-ip-port": { - "version": "1.5.4", - "license": "MIT" - }, "node_modules/ajv": { "version": "6.12.6", "dev": true, @@ -1190,10 +1321,23 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + }, "node_modules/balanced-match": { "version": "1.0.2", "license": "MIT" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1213,98 +1357,113 @@ } ] }, - "node_modules/bencode": { - "version": "0.7.0", - "license": "MIT" - }, "node_modules/bep53-range": { "version": "1.1.1", "license": "MIT" }, - "node_modules/bitfield": { - "version": "0.1.0", - "license": "-" - }, - "node_modules/bittorrent-dht": { - "version": "6.4.2", - "license": "MIT", - "dependencies": { - "bencode": "^0.7.0", - "buffer-equals": "^1.0.3", - "debug": "^2.2.0", - "inherits": "^2.0.1", - "k-bucket": "^0.6.0", - "k-rpc": "^3.6.0", - "lru": "^2.0.0" - } - }, - "node_modules/bittorrent-dht/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/bittorrent-dht/node_modules/debug/node_modules/ms": { + "node_modules/bittorrent-lsd": { "version": "2.0.0", - "license": "MIT" - }, - "node_modules/bittorrent-tracker": { - "version": "7.7.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bittorrent-lsd/-/bittorrent-lsd-2.0.0.tgz", + "integrity": "sha512-jV+SMTGNY1iGWjf5cPA2HMeA6axuMQRWwWELtsuZ1FmQmZwC74we92nwtDTfv1WMnLx+oqEjWRri42IHjZitSQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "bencode": "^0.8.0", - "bn.js": "^4.4.0", - "compact2string": "^1.2.0", - "debug": "^2.0.0", - "hat": "0.0.3", - "inherits": "^2.0.1", - "ip": "^1.0.1", - "minimist": "^1.1.1", - "once": "^1.3.0", - "random-iterate": "^1.0.1", - "run-parallel": "^1.1.2", - "run-series": "^1.0.2", - "simple-get": "^2.0.0", - "simple-peer": "^6.0.0", - "simple-websocket": "^4.0.0", - "string2compact": "^1.1.1", - "uniq": "^1.0.1", - "ws": "^1.0.0", - "xtend": "^4.0.0" + "chrome-dgram": "^3.0.6", + "debug": "^4.2.0" }, - "bin": { - "bittorrent-tracker": "bin/cmd.js" + "engines": { + "node": ">=12.20.0" } }, - "node_modules/bittorrent-tracker/node_modules/bencode": { - "version": "0.8.0", - "license": "MIT" + "node_modules/bittorrent-peerid": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/bittorrent-peerid/-/bittorrent-peerid-1.3.6.tgz", + "integrity": "sha512-VyLcUjVMEOdSpHaCG/7odvCdLbAB1y3l9A2V6WIje24uV7FkJPrQrH/RrlFmKxP89pFVDEnE+YlHaFujlFIZsg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/bittorrent-tracker/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", + "node_modules/bittorrent-protocol": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/bittorrent-protocol/-/bittorrent-protocol-4.1.11.tgz", + "integrity": "sha512-8ehCNnnRpxB6wrqDzYdLY6Bx0k1ZcXwHmxfVsU9xljolgfd4jhUq9gKcbnnUj4yR8I5/qHJ5fYVoGIfrmUlAAQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "ms": "2.0.0" + "bencode": "^4.0.0", + "bitfield": "^4.1.0", + "debug": "^4.3.4", + "rc4": "^0.1.5", + "streamx": "^2.15.1", + "throughput": "^1.0.1", + "uint8-util": "^2.2.2", + "unordered-array-remove": "^1.0.2" + }, + "engines": { + "node": ">=12.20.0" } }, - "node_modules/bittorrent-tracker/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/bittorrent-tracker/node_modules/once": { - "version": "1.4.0", - "license": "ISC", + "node_modules/bittorrent-protocol/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", "dependencies": { - "wrappy": "1" + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" } }, - "node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" + "node_modules/bittorrent-protocol/node_modules/bitfield": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", + "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } }, - "node_modules/bncode": { - "version": "0.5.3" + "node_modules/block-iterator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/block-iterator/-/block-iterator-1.1.1.tgz", + "integrity": "sha512-DrjdVWZemVO4iBf4tiOXjUrY5cNesjzy0t7sIiu2rdl8cOCHRxAgKjSJFc3vBZYYMMmshUAxajl8QQh/uxXTKQ==" }, "node_modules/boolbase": { "version": "1.0.0", @@ -1364,40 +1523,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/buffer-equal": { - "version": "0.0.1", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equals": { - "version": "1.0.4", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "license": "MIT" - }, "node_modules/buffer-more-ints": { "version": "1.0.0", "license": "MIT" @@ -1409,6 +1534,53 @@ "node": ">=4" } }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/cache-chunk-store": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/cache-chunk-store/-/cache-chunk-store-3.2.2.tgz", + "integrity": "sha512-2lJdWbgHFFxcSth9s2wpId3CR3v1YC63KjP4T9WhpW7LWlY7Hiiei3QwwqzkWqlJTfR8lSy9F5kRQECeyj+yQA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "lru": "^3.1.0", + "queue-microtask": "^1.2.3" + } + }, + "node_modules/cache-chunk-store/node_modules/lru": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz", + "integrity": "sha512-5OUtoiVIGU4VXBOshidmtOsvBIvcQR6FD/RzWSvaeHyxCGB+PCUCu+52lqMfdc0h/2CLvHhZS4TwUmMQrrMbBQ==", + "dependencies": { + "inherits": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/cache-manager": { "version": "5.4.0", "license": "MIT", @@ -1538,6 +1710,22 @@ "inherits": "^2.0.1" } }, + "node_modules/chunk-store-iterator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chunk-store-iterator/-/chunk-store-iterator-1.0.3.tgz", + "integrity": "sha512-JcSaB5h3wQstQKnaJi8sET40f0m+6Kh4mhKIr05lrWKi+EiQzn6XUoi6LipgRGMqXWNZZJaMz2tH4aeg4ptBDA==", + "dependencies": { + "block-iterator": "^1.1.1" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -1585,9 +1773,111 @@ "version": "1.0.3", "license": "MIT" }, + "node_modules/cpus": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cpus/-/cpus-1.0.3.tgz", + "integrity": "sha512-PXHBvGLuL69u55IkLa5e5838fLhIMHxmkV4ge42a8alGyn7BtawYgI0hQ849EedvtHIOLNNH3i6eQU1BiE9SUA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/create-torrent": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/create-torrent/-/create-torrent-6.0.16.tgz", + "integrity": "sha512-oO0M9KMPwEk825G7vLLUttgxBl/zwlsNdtPc9RnjFS6gQeq8sqJqlBmHcIA8sDwaYbu0mpIcARPokUgsRxjiaw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "block-iterator": "^1.1.1", + "fast-readable-async-iterator": "^2.0.0", + "is-file": "^1.0.0", + "join-async-iterator": "^1.1.1", + "junk": "^4.0.1", + "minimist": "^1.2.8", + "once": "^1.4.0", + "piece-length": "^2.0.1", + "queue-microtask": "^1.2.3", + "run-parallel": "^1.2.0", + "uint8-util": "^2.2.2" + }, + "bin": { + "create-torrent": "bin/cmd.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/create-torrent/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "dependencies": { + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/create-torrent/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/cross-fetch-ponyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cross-fetch-ponyfill/-/cross-fetch-ponyfill-1.0.3.tgz", + "integrity": "sha512-uOBkDhUAGAbx/FEzNKkOfx3w57H8xReBBXoZvUnOKTI0FW0Xvrj3GrYv2iZXUqlffC1LMGfQzhmBM/ke+6eTDA==", + "dependencies": { + "abort-controller": "^3.0.0", + "node-fetch": "^3.3.0" + } + }, + "node_modules/cross-fetch-ponyfill/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -1622,8 +1912,13 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cyclist": { - "version": "0.1.1" + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } }, "node_modules/dateformat": { "version": "4.6.3", @@ -1653,16 +1948,6 @@ "version": "2.1.2", "license": "MIT" }, - "node_modules/decompress-response": { - "version": "3.3.0", - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -1675,6 +1960,17 @@ "node": ">=16.0.0" } }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/define-data-property": { "version": "1.1.1", "dev": true, @@ -1789,13 +2085,6 @@ "version": "2.0.6", "license": "MIT" }, - "node_modules/end-of-stream": { - "version": "0.1.5", - "license": "MIT", - "dependencies": { - "once": "~1.3.0" - } - }, "node_modules/entities": { "version": "4.5.0", "license": "BSD-2-Clause", @@ -1806,6 +2095,11 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, "node_modules/es-abstract": { "version": "1.22.3", "dev": true, @@ -1933,6 +2227,11 @@ "@esbuild/win32-x64": "0.20.0" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, @@ -2208,6 +2507,28 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -2219,6 +2540,11 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -2257,6 +2583,11 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-readable-async-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-readable-async-iterator/-/fast-readable-async-iterator-2.0.0.tgz", + "integrity": "sha512-8Sld+DuyWRIftl86ZguJxR2oXCBccOiJxrY/Rj9/7ZBynW8pYMWzIcqxFL1da+25jaWJZVa+HHX/8SsA21JdTA==" + }, "node_modules/fast-redact": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", @@ -2279,9 +2610,27 @@ "reusify": "^1.0.4" } }, - "node_modules/fifo": { - "version": "0.1.4", - "license": "MIT" + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } }, "node_modules/file-entry-cache": { "version": "6.0.1", @@ -2294,6 +2643,17 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2353,12 +2713,6 @@ "dev": true, "license": "ISC" }, - "node_modules/flatten": { - "version": "0.0.1", - "engines": { - "node": "*" - } - }, "node_modules/follow-redirects": { "version": "1.15.5", "funding": [ @@ -2397,32 +2751,45 @@ "node": ">= 6" } }, - "node_modules/fs-chunk-store": { - "version": "1.7.0", - "license": "MIT", + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dependencies": { - "mkdirp": "^0.5.1", - "random-access-file": "^2.0.1", - "randombytes": "^2.0.3", - "rimraf": "^2.4.2", - "run-parallel": "^1.1.2", - "thunky": "^1.0.1" + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" } }, - "node_modules/fs-chunk-store/node_modules/mkdirp": { - "version": "0.5.6", - "license": "MIT", + "node_modules/freelist": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/freelist/-/freelist-1.0.3.tgz", + "integrity": "sha512-Ji7fEnMdZDGbS5oXElpRJsn9jPvBR8h/037D3bzreNmS8809cISq/2D9//JbA/TaZmkkN8cmecXwmQHmM+NHhg==" + }, + "node_modules/fs-native-extensions": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.2.5.tgz", + "integrity": "sha512-auDlsCu4bxLnspHJ+6bkAfCNjlVX6aIaHPI3fIexKrvLgjFedUChytCv7sxeuZfwmABdISI2A0/hDjZx7NWTKA==", + "hasInstallScript": true, + "optional": true, "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "napi-macros": "^2.0.0", + "node-gyp-build": "^4.2.3" } }, "node_modules/fs.realpath": { "version": "1.0.0", "license": "ISC" }, + "node_modules/fsa-chunk-store": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fsa-chunk-store/-/fsa-chunk-store-1.1.4.tgz", + "integrity": "sha512-Z4SJTYxZIta37RXJofM6HsKrgM9W+pQxiyQuw0bpvsfn1HGXcBWyXZWhsCfi7wbNb6GIlykXZ9Jxwc95IiPMzA==", + "dependencies": { + "filename-reserved-regex": "^3.0.0" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2488,6 +2855,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "dev": true, @@ -2517,6 +2906,7 @@ }, "node_modules/glob": { "version": "7.2.3", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -2546,6 +2936,7 @@ }, "node_modules/glob/node_modules/once": { "version": "1.4.0", + "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -2704,10 +3095,6 @@ "node": ">= 0.4" } }, - "node_modules/hat": { - "version": "0.0.3", - "license": "MIT/X11" - }, "node_modules/help-me": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", @@ -2731,6 +3118,30 @@ "entities": "^4.4.0" } }, + "node_modules/http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha512-u8u5ZaG0Tr/VvHlucK2ufMuOp4/5bvwgneXle+y228K5rMbJOlVjThONcaAw3ikAy8b2OO9RfEucdMHFz3UWMA==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hybrid-chunk-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/hybrid-chunk-store/-/hybrid-chunk-store-1.2.2.tgz", + "integrity": "sha512-oZtxLfVHWKVKPS8KoYpWgVohEKbq3s90s7a1FwG7+EZFC/8bqZrdX4axlH5tO/g2PnGpZTVxS2YnftyCpydKSw==", + "dependencies": { + "@thaunknown/idb-chunk-store": "^1.0.2", + "cache-chunk-store": "^3.2.2", + "fsa-chunk-store": "^1.1.4", + "memory-chunk-store": "^1.3.5" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "license": "MIT", @@ -2741,6 +3152,11 @@ "node": ">=0.10.0" } }, + "node_modules/idb": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", + "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2768,10 +3184,6 @@ "node": ">= 4" } }, - "node_modules/immediate-chunk-store": { - "version": "1.0.8", - "license": "MIT" - }, "node_modules/import-fresh": { "version": "3.3.0", "dev": true, @@ -2843,13 +3255,6 @@ "version": "1.1.8", "license": "MIT" }, - "node_modules/ip-set": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "ip": "^1.1.3" - } - }, "node_modules/ipaddr.js": { "version": "2.1.0", "license": "MIT", @@ -2942,6 +3347,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-file/-/is-file-1.0.0.tgz", + "integrity": "sha512-ZGMuc+xA8mRnrXtmtf2l/EkIW2zaD2LSBWlaOVEF6yH4RTndHob65V4SwWWdtGKVthQfXPVKsXqw4TDUjbVxVQ==" + }, "node_modules/is-glob": { "version": "4.0.3", "dev": true, @@ -3021,6 +3431,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "dev": true, @@ -3080,9 +3501,13 @@ }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, "license": "ISC" }, + "node_modules/join-async-iterator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/join-async-iterator/-/join-async-iterator-1.1.1.tgz", + "integrity": "sha512-ATse+nuNeKZ9K1y27LKdvPe/GCe9R/u9dw9vI248e+vILeRK3IcJP4JUPAlSmKRCDK0cKhEwfmiw4Skqx7UnGQ==" + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -3129,21 +3554,15 @@ "json5": "lib/cli.js" } }, - "node_modules/k-bucket": { - "version": "0.6.0", - "license": "MIT", - "dependencies": { - "buffer-equal": "0.0.1", - "inherits": "^2.0.1" - } - }, - "node_modules/k-rpc": { - "version": "3.7.0", - "license": "MIT", - "dependencies": { - "buffer-equals": "^1.0.3", - "k-bucket": "^2.0.0", - "k-rpc-socket": "^1.5.0" + "node_modules/junk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", + "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/k-rpc-socket": { @@ -3160,14 +3579,6 @@ "version": "2.0.3", "license": "MIT" }, - "node_modules/k-rpc/node_modules/k-bucket": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "buffer-equal": "0.0.1", - "randombytes": "^2.0.3" - } - }, "node_modules/keyv": { "version": "4.5.4", "dev": true, @@ -3176,6 +3587,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/last-one-wins": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/last-one-wins/-/last-one-wins-1.0.4.tgz", + "integrity": "sha512-t+KLJFkHPQk8lfN6WBOiGkiUXoub+gnb2XTYI2P3aiISL+94xgZ1vgz1SXN/N4hthuOoLXarXfBZPUruyjQtfA==" + }, "node_modules/levn": { "version": "0.4.1", "dev": true, @@ -3188,6 +3604,57 @@ "node": ">= 0.8.0" } }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/load-ip-set": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/load-ip-set/-/load-ip-set-3.0.1.tgz", + "integrity": "sha512-ZFZt1g4Exq01SFtKjffqau+L4Qibt+51utymHHiWo8Iu/W7LYSqE7fiZ/iAZ6dIqbmeU6ICSIK02IizSScBkLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "cross-fetch-ponyfill": "^1.0.1", + "ip-set": "^2.1.0", + "netmask": "^2.0.1", + "once": "^1.4.0", + "queue-microtask": "^1.2.3", + "split": "^1.0.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/load-ip-set/node_modules/ip-set": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-set/-/ip-set-2.1.0.tgz", + "integrity": "sha512-JdHz4tSMx1IeFj8yEcQU0i58qiSkOlmZXkZ8+HJ0ROV5KcgLRDO9F703oJ1GeZCvqggrcCbmagD/V7hghY62wA==", + "dependencies": { + "ip": "^1.1.5" + } + }, + "node_modules/load-ip-set/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -3215,16 +3682,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lru": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/lru-cache": { "version": "10.2.0", "license": "ISC", @@ -3232,6 +3689,32 @@ "node": "14 || >=16.14" } }, + "node_modules/lt_donthave": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lt_donthave/-/lt_donthave-2.0.0.tgz", + "integrity": "sha512-qrNtq9faD5ycTM8Of7OUqPHPMv0H8NONf+dTAxUsAr0bAgPnD56BBhhBlskJVNL4WO+Dl/qmqWHF9eQb7+2lNA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "debug": "^4.2.0", + "unordered-array-remove": "^1.0.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/magnet-uri": { "version": "6.2.0", "funding": [ @@ -3254,10 +3737,23 @@ "thirty-two": "^1.0.2" } }, + "node_modules/memory-chunk-store": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/memory-chunk-store/-/memory-chunk-store-1.3.5.tgz", + "integrity": "sha512-E1Xc1U4ifk/FkC2ZsWhCaW1xg9HbE/OBmQTLe2Tr9c27YPSLbW7kw1cnb3kQWD1rDtErFJHa7mB9EVrs7aTx9g==", + "dependencies": { + "queue-microtask": "^1.2.3" + } + }, "node_modules/memory-pager": { "version": "1.5.0", "license": "MIT" }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3280,6 +3776,17 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/mime-db": { "version": "1.52.0", "license": "MIT", @@ -3297,11 +3804,12 @@ "node": ">= 0.6" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "license": "MIT", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/minimatch": { @@ -3321,14 +3829,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp": { - "version": "0.3.5", - "license": "MIT" - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "license": "MIT" - }, "node_modules/moment": { "version": "2.30.1", "license": "MIT", @@ -3440,6 +3940,12 @@ "version": "2.2.1", "license": "MIT" }, + "node_modules/napi-macros": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", + "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", + "optional": true + }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -3470,6 +3976,32 @@ "version": "2.0.0", "license": "MIT" }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "license": "MIT", @@ -3504,6 +4036,28 @@ "version": "3.0.1", "license": "BSD-2-Clause" }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nth-check": { "version": "2.1.1", "license": "BSD-2-Clause", @@ -3605,6 +4159,20 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "dev": true, @@ -3621,12 +4189,6 @@ "node": ">= 0.8.0" } }, - "node_modules/options": { - "version": "0.0.6", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "dev": true, @@ -3670,28 +4232,6 @@ "node": ">=6" } }, - "node_modules/parse-torrent": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "magnet-uri": "^4.0.0", - "parse-torrent-file": "^2.0.0" - }, - "bin": { - "parse-torrent": "bin/cmd.js" - } - }, - "node_modules/parse-torrent-file": { - "version": "2.1.4", - "license": "MIT", - "dependencies": { - "bencode": "^0.7.0", - "simple-sha1": "^2.0.0" - }, - "bin": { - "parse-torrent-file": "bin/cmd.js" - } - }, "node_modules/parse-torrent-title": { "version": "1.3.0", "resolved": "git+ssh://git@github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", @@ -3704,21 +4244,6 @@ "node": ">=10" } }, - "node_modules/parse-torrent/node_modules/magnet-uri": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "flatten": "0.0.1", - "thirty-two": "^0.0.2", - "xtend": "^4.0.0" - } - }, - "node_modules/parse-torrent/node_modules/magnet-uri/node_modules/thirty-two": { - "version": "0.0.2", - "engines": { - "node": ">=0.2.6" - } - }, "node_modules/parse5": { "version": "7.1.2", "license": "MIT", @@ -3757,7 +4282,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3777,38 +4301,6 @@ "node": ">=8" } }, - "node_modules/peer-wire-protocol": { - "version": "0.7.1", - "dependencies": { - "bitfield": "^0.1.0", - "bncode": "^0.2.3", - "buffer-alloc": "^1.1.0", - "buffer-from": "^1.0.0", - "readable-stream": "^1.0.2", - "speedometer": "^0.1.2" - } - }, - "node_modules/peer-wire-protocol/node_modules/bncode": { - "version": "0.2.3" - }, - "node_modules/peer-wire-swarm": { - "version": "0.12.2", - "dependencies": { - "buffer-from": "^1.0.0", - "fifo": "^0.1.4", - "once": "^1.1.1", - "peer-wire-protocol": "^0.7.0", - "speedometer": "^0.1.2", - "utp": "0.0.7" - } - }, - "node_modules/peer-wire-swarm/node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/pg": { "version": "8.11.3", "license": "MIT", @@ -3906,6 +4398,11 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/piece-length": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/piece-length/-/piece-length-2.0.1.tgz", + "integrity": "sha512-dBILiDmm43y0JPISWEmVGKBETQjwJe6mSU9GND+P9KW0SJGUwoU/odyH1nbalOP9i8WSYuqf1lQnaj92Bhw+Ug==" + }, "node_modules/pino": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", @@ -4100,10 +4597,6 @@ "node": ">= 0.6.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "license": "MIT" - }, "node_modules/process-warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", @@ -4124,7 +4617,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -4134,7 +4626,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -4143,7 +4634,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -4187,23 +4677,6 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, - "node_modules/random-access-file": { - "version": "2.2.1", - "license": "MIT", - "dependencies": { - "mkdirp-classic": "^0.5.2", - "random-access-storage": "^1.1.1" - } - }, - "node_modules/random-access-storage": { - "version": "1.4.3", - "license": "MIT", - "dependencies": { - "events": "^3.3.0", - "inherits": "^2.0.3", - "queue-tick": "^1.0.0" - } - }, "node_modules/random-iterate": { "version": "1.0.1", "license": "MIT" @@ -4233,9 +4706,21 @@ ], "license": "MIT" }, - "node_modules/re-emitter": { - "version": "1.1.4", - "license": "MIT" + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc4": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/rc4/-/rc4-0.1.5.tgz", + "integrity": "sha512-xdDTNV90z5x5u25Oc871Xnvu7yAr4tV7Eluh0VSvrhUkry39q1k+zkz7xroqHbRq+8PiazySHJPArqifUvz9VA==", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/readable-stream": { "version": "1.1.14", @@ -4255,6 +4740,14 @@ "node": ">= 12.13.0" } }, + "node_modules/record-cache": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/record-cache/-/record-cache-1.2.0.tgz", + "integrity": "sha512-kyy3HWCez2WrotaL3O4fTn0rsIdfRKOdQQcEJ9KpvmKmbffKVvwsloX063EgRUlpJIXHiDQFhJcTbZequ2uTZw==", + "dependencies": { + "b4a": "^1.3.1" + } + }, "node_modules/reflect-metadata": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", @@ -4326,16 +4819,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "funding": [ @@ -4357,6 +4840,28 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/run-parallel-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", + "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/run-series": { "version": "1.1.9", "funding": [ @@ -4375,10 +4880,6 @@ ], "license": "MIT" }, - "node_modules/rusha": { - "version": "0.8.14", - "license": "MIT" - }, "node_modules/safe-array-concat": { "version": "1.1.0", "dev": true, @@ -4433,6 +4934,11 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, "node_modules/secure-json-parse": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", @@ -4604,7 +5110,6 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -4615,7 +5120,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4634,155 +5138,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "2.8.2", - "license": "MIT", - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/simple-peer": { - "version": "6.4.4", - "license": "MIT", - "dependencies": { - "debug": "^2.1.0", - "get-browser-rtc": "^1.0.0", - "inherits": "^2.0.1", - "randombytes": "^2.0.3", - "readable-stream": "^2.0.5" - } - }, - "node_modules/simple-peer/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/simple-peer/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/simple-peer/node_modules/readable-stream": { - "version": "2.3.8", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/simple-peer/node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/simple-peer/node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/simple-sha1": { - "version": "2.1.2", - "license": "MIT", - "dependencies": { - "rusha": "^0.8.1" - } - }, - "node_modules/simple-websocket": { - "version": "4.3.1", - "license": "MIT", - "dependencies": { - "debug": "^2.1.3", - "inherits": "^2.0.1", - "randombytes": "^2.0.3", - "readable-stream": "^2.0.5", - "ws": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "node_modules/simple-websocket/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/simple-websocket/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/simple-websocket/node_modules/readable-stream": { - "version": "2.3.8", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/simple-websocket/node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/simple-websocket/node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/simple-websocket/node_modules/ws": { - "version": "2.3.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.0.1", - "ultron": "~1.1.0" - } - }, - "node_modules/simple-websocket/node_modules/ws/node_modules/safe-buffer": { - "version": "5.0.1", - "license": "MIT" - }, - "node_modules/simple-websocket/node_modules/ws/node_modules/ultron": { - "version": "1.1.1", - "license": "MIT" + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/slash": { "version": "3.0.0", @@ -4793,6 +5152,33 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -4808,8 +5194,25 @@ "memory-pager": "^1.0.2" } }, - "node_modules/speedometer": { - "version": "0.1.4" + "node_modules/speed-limiter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/speed-limiter/-/speed-limiter-1.0.2.tgz", + "integrity": "sha512-Ax+TbUOho84bWUc3AKqWtkIvAIVws7d6QI4oJkgH4yQ5Yil+lR3vjd/7qd51dHKGzS5bFxg0++QwyNRN7s6rZA==", + "dependencies": { + "limiter": "^1.1.5", + "streamx": "^2.10.3" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } }, "node_modules/split2": { "version": "4.2.0", @@ -4818,6 +5221,15 @@ "node": ">= 10.x" } }, + "node_modules/streamx": { + "version": "2.15.7", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.7.tgz", + "integrity": "sha512-NPEKS5+yjyo597eafGbKW5ujh7Sm6lDLHZQd/lRSz6S0VarpADBJItqfB4PnwpS+472oob1GX5cCY9vzfJpHUA==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, "node_modules/string_decoder": { "version": "0.10.31", "license": "MIT" @@ -4864,14 +5276,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string2compact": { - "version": "1.3.2", - "license": "MIT", - "dependencies": { - "addr-to-ip-port": "^1.0.1", - "ipaddr.js": "^2.0.0" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "dev": true, @@ -4891,6 +5295,14 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "dev": true, @@ -4943,10 +5355,26 @@ "real-require": "^0.2.0" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/throughput": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throughput/-/throughput-1.0.1.tgz", + "integrity": "sha512-4Mvv5P4xyVz6RM07wS3tGyZ/kPAiKtLeqznq3hK4pxDiTUSyQ5xeFlBiWxflCWexvSnxo2aAfedzKajJqihz4Q==" + }, "node_modules/thunky": { "version": "1.1.0", "license": "MIT" }, + "node_modules/timeout-refresh": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-1.0.3.tgz", + "integrity": "sha512-Mz0CX4vBGM5lj8ttbIFt7o4ZMxk/9rgudJRh76EvB7xXZMur7T/cjRiH2w4Fmkq0zxf2QpM8IFvOSRn8FEu3gA==", + "optional": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4963,53 +5391,6 @@ "version": "1.0.1", "license": "MIT" }, - "node_modules/torrent-discovery": { - "version": "5.4.0", - "license": "MIT", - "dependencies": { - "bittorrent-dht": "^6.0.0", - "bittorrent-tracker": "^7.0.0", - "debug": "^2.0.0", - "inherits": "^2.0.1", - "re-emitter": "^1.0.0", - "run-parallel": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "node_modules/torrent-discovery/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/torrent-discovery/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/torrent-piece": { - "version": "1.1.2", - "license": "MIT" - }, - "node_modules/torrent-stream": { - "version": "1.2.1", - "dependencies": { - "bitfield": "^0.1.0", - "bncode": "^0.5.2", - "buffer-from": "^1.0.0", - "end-of-stream": "^0.1.4", - "fs-chunk-store": "^1.3.0", - "hat": "0.0.3", - "immediate-chunk-store": "^1.0.5", - "ip-set": "^1.0.0", - "mkdirp": "^0.3.5", - "parse-torrent": "^4.0.0", - "peer-wire-swarm": "^0.12.0", - "rimraf": "^2.2.5", - "torrent-discovery": "^5.2.0", - "torrent-piece": "^1.0.0" - } - }, "node_modules/ts-api-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", @@ -5558,9 +5939,13 @@ "node": ">=14.17" } }, - "node_modules/ultron": { - "version": "1.0.2", - "license": "MIT" + "node_modules/uint8-util": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/uint8-util/-/uint8-util-2.2.4.tgz", + "integrity": "sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -5580,9 +5965,16 @@ "version": "1.13.6", "license": "MIT" }, - "node_modules/uniq": { - "version": "1.0.1", - "license": "MIT" + "node_modules/unordered-array-remove": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz", + "integrity": "sha512-45YsfD6svkgaCBNyvD+dFHm4qFX9g3wRSIVgWVPtm2OCnphvPxzJoe20ATsiNpNJrmzHifnxm+BN5F7gFT/4gw==" + }, + "node_modules/unordered-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unordered-set/-/unordered-set-2.0.1.tgz", + "integrity": "sha512-eUmNTPzdx+q/WvOHW0bgGYLWvWHNT3PTKEQLg0MAQhc0AHASHVHoP/9YytYd4RBVariqno/mEUhVZN98CmD7bg==", + "optional": true }, "node_modules/uri-js": { "version": "4.4.1", @@ -5608,14 +6000,193 @@ "lodash.clonedeep": "^4.5.0" } }, + "node_modules/ut_metadata": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/ut_metadata/-/ut_metadata-4.0.3.tgz", + "integrity": "sha512-2tovup0VDYpT8t8+EhhhKBmbgIyiYyJQZ+Hf+/61+SvjuRS2MEeA5CiSARP4q+9/83Wu09OsGrUre/Zv6OI5NA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "bitfield": "^4.0.0", + "debug": "^4.2.0", + "uint8-util": "^2.1.3" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ut_metadata/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "dependencies": { + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ut_metadata/node_modules/bitfield": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", + "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/ut_pex": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ut_pex/-/ut_pex-4.0.4.tgz", + "integrity": "sha512-isVTbp2TKGoMOu+4Zh/i6ijpYr0VG83xjRPgCXaUjKzgXXndjCMWg32/9kZjubD+kxEXcmXMkoS8IttS9FZE8g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "compact2string": "^1.4.1", + "string2compact": "^2.0.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ut_pex/node_modules/addr-to-ip-port": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-2.0.0.tgz", + "integrity": "sha512-9bYbtjamtdLHZSqVIUXhilOryNPiL+x+Q5J/Unpg4VY3ZIkK3fT52UoErj1NdUeVm3J1t2iBEAur4Ywbl/bahw==", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ut_pex/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "dependencies": { + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ut_pex/node_modules/string2compact": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-2.0.1.tgz", + "integrity": "sha512-Bm/T8lHMTRXw+u83LE+OW7fXmC/wM+Mbccfdo533ajSBNxddDHlRrvxE49NdciGHgXkUQM5WYskJ7uTkbBUI0A==", + "dependencies": { + "addr-to-ip-port": "^2.0.0", + "ipaddr.js": "^2.0.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", - "license": "MIT" + "license": "MIT", + "optional": true }, - "node_modules/utp": { - "version": "0.0.7", + "node_modules/utp-native": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/utp-native/-/utp-native-2.5.3.tgz", + "integrity": "sha512-sWTrWYXPhhWJh+cS2baPzhaZc89zwlWCfwSthUjGhLkZztyPhcQllo+XVVCbNGi7dhyRlxkWxN4NKU6FbA9Y8w==", + "hasInstallScript": true, + "optional": true, "dependencies": { - "cyclist": "~0.1.0" + "napi-macros": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.0.2", + "timeout-refresh": "^1.0.0", + "unordered-set": "^2.0.1" + }, + "bin": { + "ucat": "ucat.js" + }, + "engines": { + "node": ">=8.12" + } + }, + "node_modules/utp-native/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/utp-native/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/utp-native/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" } }, "node_modules/uuid": { @@ -5632,9 +6203,460 @@ "node": ">= 0.10" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", + "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webtorrent": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/webtorrent/-/webtorrent-2.1.35.tgz", + "integrity": "sha512-JxAdPrX75zAtBumKxOM1691phN26qTx+RgxC20UUm91l/AQ5zAeGAZp1mtoAJoLQKeZPXguMV5RA4+IToLGdLA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "@silentbot1/nat-api": "^0.4.7", + "@thaunknown/simple-peer": "^9.12.1", + "@webtorrent/http-node": "^1.3.0", + "addr-to-ip-port": "^2.0.0", + "bitfield": "^4.1.0", + "bittorrent-dht": "^11.0.5", + "bittorrent-protocol": "^4.1.11", + "cache-chunk-store": "^3.2.2", + "chunk-store-iterator": "^1.0.3", + "cpus": "^1.0.3", + "create-torrent": "^6.0.16", + "cross-fetch-ponyfill": "^1.0.3", + "debug": "^4.3.4", + "escape-html": "^1.0.3", + "fs-chunk-store": "^4.1.0", + "hybrid-chunk-store": "^1.2.2", + "immediate-chunk-store": "^2.2.0", + "join-async-iterator": "^1.1.1", + "load-ip-set": "^3.0.1", + "lt_donthave": "^2.0.0", + "memory-chunk-store": "^1.3.5", + "mime": "^3.0.0", + "once": "^1.4.0", + "parse-torrent": "^11.0.16", + "pump": "^3.0.0", + "queue-microtask": "^1.2.3", + "random-iterate": "^1.0.1", + "range-parser": "^1.2.1", + "run-parallel": "^1.2.0", + "run-parallel-limit": "^1.1.0", + "speed-limiter": "^1.0.2", + "streamx": "^2.15.7", + "throughput": "^1.0.1", + "torrent-discovery": "^11.0.1", + "torrent-piece": "^3.0.0", + "uint8-util": "^2.2.4", + "unordered-array-remove": "^1.0.2", + "ut_metadata": "^4.0.3", + "ut_pex": "^4.0.4" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "utp-native": "^2.5.3" + } + }, + "node_modules/webtorrent/node_modules/addr-to-ip-port": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-2.0.0.tgz", + "integrity": "sha512-9bYbtjamtdLHZSqVIUXhilOryNPiL+x+Q5J/Unpg4VY3ZIkK3fT52UoErj1NdUeVm3J1t2iBEAur4Ywbl/bahw==", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/bencode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", + "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "dependencies": { + "uint8-util": "^2.2.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/bep53-range": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bep53-range/-/bep53-range-2.0.0.tgz", + "integrity": "sha512-sMm2sV5PRs0YOVk0LTKtjuIprVzxgTQUsrGX/7Yph2Rm4FO2Fqqtq7hNjsOB5xezM4v4+5rljCgK++UeQJZguA==", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/bitfield": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", + "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/webtorrent/node_modules/bittorrent-dht": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-11.0.5.tgz", + "integrity": "sha512-R09D6uNaziRqsc+B/j5QzkjceTak+wH9vcNLnkmt8A52EWF9lQwBP0vvCKgSA3AJOYYl+41n3osA2KYYn/z5uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "debug": "^4.3.4", + "k-bucket": "^5.1.0", + "k-rpc": "^5.1.0", + "last-one-wins": "^1.0.4", + "lru": "^3.1.0", + "randombytes": "^2.1.0", + "record-cache": "^1.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/bittorrent-tracker": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/bittorrent-tracker/-/bittorrent-tracker-11.0.1.tgz", + "integrity": "sha512-WDvixbEkLgnEeVk8iiF2/LwB2zsuxehir3wBFkHskB/LvYE4HQI+6RoWPHjwGqi9POPJdeOnSPFa8pZvB0Bd8A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "@thaunknown/simple-peer": "^9.12.1", + "@thaunknown/simple-websocket": "^9.1.0", + "bencode": "^4.0.0", + "bittorrent-peerid": "^1.3.3", + "chrome-dgram": "^3.0.6", + "clone": "^2.0.0", + "compact2string": "^1.4.1", + "cross-fetch-ponyfill": "^1.0.1", + "debug": "^4.1.1", + "ip": "^1.1.5", + "lru": "^3.1.0", + "minimist": "^1.2.5", + "once": "^1.4.0", + "queue-microtask": "^1.2.3", + "random-iterate": "^1.0.1", + "run-parallel": "^1.2.0", + "run-series": "^1.1.9", + "socks": "^2.0.0", + "string2compact": "^2.0.0", + "uint8-util": "^2.1.9", + "unordered-array-remove": "^1.0.2", + "ws": "^8.0.0" + }, + "bin": { + "bittorrent-tracker": "bin/cmd.js" + }, + "engines": { + "node": ">=12.20.0" + }, + "optionalDependencies": { + "bufferutil": "^4.0.3", + "utf-8-validate": "^5.0.5" + } + }, + "node_modules/webtorrent/node_modules/fs-chunk-store": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/fs-chunk-store/-/fs-chunk-store-4.1.0.tgz", + "integrity": "sha512-8apaYPaENIVUjVGqjo+Yg5/Hv7qL2fijWV+XGMCs3MR07o9DZZVMpF7dclxdjYotSjLdUGVPhqaJn+eAx6NLYQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "filename-reserved-regex": "^3.0.0", + "queue-microtask": "^1.2.2", + "random-access-file": "^4.0.0", + "randombytes": "^2.0.3", + "run-parallel": "^1.1.2", + "thunky": "^1.0.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/immediate-chunk-store": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/immediate-chunk-store/-/immediate-chunk-store-2.2.0.tgz", + "integrity": "sha512-1bHBna0hCa6arRXicu91IiL9RvvkbNYLVq+mzWdaLGZC3hXvX4doh8e1dLhMKez5siu63CYgO5NrGJbRX5lbPA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.3" + } + }, + "node_modules/webtorrent/node_modules/k-bucket": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-5.1.0.tgz", + "integrity": "sha512-Fac7iINEovXIWU20GPnOMLUbjctiS+cnmyjC4zAUgvs3XPf1vo9akfCHkigftSic/jiKqKl+KA3a/vFcJbHyCg==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/webtorrent/node_modules/k-rpc": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-5.1.0.tgz", + "integrity": "sha512-FGc+n70Hcjoa/X2JTwP+jMIOpBz+pkRffHnSl9yrYiwUxg3FIgD50+u1ePfJUOnRCnx6pbjmVk5aAeB1wIijuQ==", + "dependencies": { + "k-bucket": "^5.0.0", + "k-rpc-socket": "^1.7.2", + "randombytes": "^2.0.5" + } + }, + "node_modules/webtorrent/node_modules/lru": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz", + "integrity": "sha512-5OUtoiVIGU4VXBOshidmtOsvBIvcQR6FD/RzWSvaeHyxCGB+PCUCu+52lqMfdc0h/2CLvHhZS4TwUmMQrrMbBQ==", + "dependencies": { + "inherits": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/webtorrent/node_modules/magnet-uri": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-7.0.5.tgz", + "integrity": "sha512-Ke+dDiYHK1Rq/ZyGUAgk7NIkoypivxolTj/A0qr60ypP0FjeP+NTUNEhr965HsRan0zGxKEBK73+SsjRyJWkXg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "@thaunknown/thirty-two": "^1.0.3", + "bep53-range": "^2.0.0", + "uint8-util": "^2.1.9" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/webtorrent/node_modules/parse-torrent": { + "version": "11.0.16", + "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-11.0.16.tgz", + "integrity": "sha512-5GoOdmW0HpiB78aQpBz8/5V3V1LjBRDNiL7DOs33pKeCLOzFnfMrsRD6CYmaUBT5Vi/dXE0hfePsjDGJSMF48w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bencode": "^4.0.0", + "cross-fetch-ponyfill": "^1.0.3", + "get-stdin": "^9.0.0", + "magnet-uri": "^7.0.5", + "queue-microtask": "^1.2.3", + "uint8-util": "^2.2.4" + }, + "bin": { + "parse-torrent": "bin/cmd.js" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/random-access-file": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-4.0.6.tgz", + "integrity": "sha512-WLk07uxKsZQZWUDjoO5ZvJHMkrBbZ5GLrCWAXYLiiBbZ4Vf4+7VlJcUJyq3fMgp0lAwTqtbFKzIn5FwqgztnUQ==", + "dependencies": { + "random-access-storage": "^3.0.0" + }, + "optionalDependencies": { + "fs-native-extensions": "^1.1.0" + } + }, + "node_modules/webtorrent/node_modules/random-access-storage": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-3.0.1.tgz", + "integrity": "sha512-raFoHJ/orMyur04GKrA+5ThOwhX9wICdqMDLqTM7bHEXPz7zi5MxLsLUaybxGu3b4mJTt8zhCpZHgjlu0x4wpg==", + "dependencies": { + "events": "^3.3.0", + "queue-tick": "^1.0.0" + } + }, + "node_modules/webtorrent/node_modules/string2compact": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-2.0.1.tgz", + "integrity": "sha512-Bm/T8lHMTRXw+u83LE+OW7fXmC/wM+Mbccfdo533ajSBNxddDHlRrvxE49NdciGHgXkUQM5WYskJ7uTkbBUI0A==", + "dependencies": { + "addr-to-ip-port": "^2.0.0", + "ipaddr.js": "^2.0.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/torrent-discovery": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/torrent-discovery/-/torrent-discovery-11.0.1.tgz", + "integrity": "sha512-+QhOUWRxhR8Y6e5z5I0qil812q11Xz9Yaj1pfYwVkereTBQT1THBCeSHxWZEHuGjKLiIBueVzPP7+wiPtedXKg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bittorrent-dht": "^11.0.5", + "bittorrent-lsd": "^2.0.0", + "bittorrent-tracker": "^11.0.1", + "debug": "^4.3.4", + "run-parallel": "^1.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/torrent-piece": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/torrent-piece/-/torrent-piece-3.0.0.tgz", + "integrity": "sha512-j0tRX7qq22nIuVFF57Tg/wAvFq79F1eM9pcMxY+b0qCCe7yXJnIrqF+Q5YEJ94tNisDnJzcqDHNrPmD9X/yAIg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "uint8-util": "^2.1.9" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/webtorrent/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/which": { "version": "2.0.2", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -5690,12 +6712,24 @@ "version": "1.0.2", "license": "ISC" }, - "node_modules/ws": { - "version": "1.1.5", - "license": "MIT", + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", "dependencies": { - "options": ">=0.0.5", - "ultron": "1.0.x" + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" } }, "node_modules/xtend": { diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 192a1c5..3e515b1 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -27,15 +27,12 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", - "torrent-stream": "^1.2.1", - "user-agents": "^1.0.1444" + "webtorrent": "^2.1.35" }, "devDependencies": { "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", - "@types/stremio-addon-sdk": "^1.6.10", - "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/jobs/process_torrents_job.ts index 23bbfd3..4fed81f 100644 --- a/src/node/consumer/src/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/jobs/process_torrents_job.ts @@ -14,9 +14,9 @@ export class ProcessTorrentsJob implements IProcessTorrentsJob { private readonly consumeQueueOptions: Options.Consume = {noAck: false}; private torrentProcessingService: ITorrentProcessingService; private logger: ILoggingService; - + constructor(@inject(IocTypes.ITorrentProcessingService) torrentProcessingService: ITorrentProcessingService, - @inject(IocTypes.ILoggingService) logger: ILoggingService){ + @inject(IocTypes.ILoggingService) logger: ILoggingService) { this.torrentProcessingService = torrentProcessingService; this.logger = logger; } @@ -55,7 +55,7 @@ export class ProcessTorrentsJob implements IProcessTorrentsJob { this.logger.error('Failed processing torrent', error); } } - + try { await channel.assertQueue(configurationService.rabbitConfig.QUEUE_NAME, this.assertQueueOptions); await channel.prefetch(configurationService.jobConfig.JOB_CONCURRENCY); diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index cd66b22..79c68a0 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,5 +1,5 @@ export const BooleanHelpers = { - parseBool: function(value: string | number | undefined, defaultValue: boolean): boolean { + parseBool: function (value: string | number | undefined, defaultValue: boolean): boolean { switch (typeof value) { case 'string': return parseStringToBool(value, defaultValue); diff --git a/src/node/consumer/src/lib/helpers/promises_helpers.ts b/src/node/consumer/src/lib/helpers/promises_helpers.ts index 366ec24..dacefb7 100644 --- a/src/node/consumer/src/lib/helpers/promises_helpers.ts +++ b/src/node/consumer/src/lib/helpers/promises_helpers.ts @@ -1,11 +1,11 @@ export const PromiseHelpers = { - sequence: async function(promises: (() => Promise)[]) { + sequence: async function (promises: (() => Promise)[]) { return promises.reduce((promise, func) => promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); }, - first: async function(promises) { + first: async function (promises) { return Promise.all(promises.map(p => { return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); })).then( @@ -14,11 +14,11 @@ export const PromiseHelpers = { ); }, - delay: async function(duration: number) { + delay: async function (duration: number) { return new Promise(resolve => setTimeout(() => resolve(), duration)); }, - timeout: async function(timeoutMs: number, promise, message = 'Timed out') { + timeout: async function (timeoutMs: number, promise, message = 'Timed out') { return Promise.race([ promise, new Promise(function (resolve, reject) { @@ -29,7 +29,7 @@ export const PromiseHelpers = { ]); }, - mostCommonValue: function(array) { + mostCommonValue: function (array) { return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); } }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts index ad3fc1f..c2821f3 100644 --- a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -6,6 +6,7 @@ export interface ICinemetaJsonResponse { links?: ICinemetaLink[]; behaviorHints?: ICinemetaBehaviorHints; } + export interface ICinemetaMetaData { awards?: string; cast?: string[]; @@ -37,6 +38,7 @@ export interface ICinemetaMetaData { releaseInfo?: string; videos?: ICinemetaVideo[]; } + export interface ICinemetaPopularities { PXS_TEST?: number; PXS?: number; @@ -49,10 +51,12 @@ export interface ICinemetaPopularities { stremio?: number; stremio_lib?: number; } + export interface ICinemetaTrailer { source?: string; type?: string; } + export interface ICinemetaVideo extends ICommonVideoMetadata { name?: string; number?: number; @@ -63,15 +67,18 @@ export interface ICinemetaVideo extends ICommonVideoMetadata { thumbnail?: string; description?: string; } + export interface ICinemetaTrailerStream { title?: string; ytId?: string; } + export interface ICinemetaLink { name?: string; category?: string; url?: string; } + export interface ICinemetaBehaviorHints { defaultVideoId?: null; hasScheduledVideos?: boolean; diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts index ea3f5d5..9b4f4e6 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -4,6 +4,7 @@ export interface IKitsuJsonResponse { cacheMaxAge?: number; meta?: IKitsuMeta; } + export interface IKitsuMeta { aliases?: string[]; animeType?: string; @@ -29,16 +30,19 @@ export interface IKitsuMeta { videos?: IKitsuVideo[]; year?: string; } + export interface IKitsuVideo extends ICommonVideoMetadata { imdbEpisode?: number; imdbSeason?: number; imdb_id?: string; thumbnail?: string; } + export interface IKitsuTrailer { source?: string; type?: string; } + export interface IKitsuLink { name?: string; category?: string; diff --git a/src/node/consumer/src/lib/interfaces/logging_service.ts b/src/node/consumer/src/lib/interfaces/logging_service.ts index 44e7c49..06266ed 100644 --- a/src/node/consumer/src/lib/interfaces/logging_service.ts +++ b/src/node/consumer/src/lib/interfaces/logging_service.ts @@ -1,6 +1,9 @@ export interface ILoggingService { info(message: string, ...args: any[]): void; + error(message: string, ...args: any[]): void; + debug(message: string, ...args: any[]): void; + warn(message: string, ...args: any[]): void; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/metadata_query.ts b/src/node/consumer/src/lib/interfaces/metadata_query.ts index 3d6932a..8acca9c 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_query.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_query.ts @@ -1,4 +1,4 @@ -export interface IMetaDataQuery { +export interface IMetaDataQuery { title?: string type?: string year?: number | string diff --git a/src/node/consumer/src/lib/models/composition_root.ts b/src/node/consumer/src/lib/models/composition_root.ts index a6c47cb..e52e2f0 100644 --- a/src/node/consumer/src/lib/models/composition_root.ts +++ b/src/node/consumer/src/lib/models/composition_root.ts @@ -10,6 +10,7 @@ export class CompositionalRoot implements ICompositionalRoot { private trackerService: ITrackerService; private databaseRepository: IDatabaseRepository; private processTorrentsJob: IProcessTorrentsJob; + constructor(@inject(IocTypes.ITrackerService) trackerService: ITrackerService, @inject(IocTypes.IDatabaseRepository) databaseRepository: IDatabaseRepository, @inject(IocTypes.IProcessTorrentsJob) processTorrentsJob: IProcessTorrentsJob) { diff --git a/src/node/consumer/src/lib/models/configuration/torrent_config.ts b/src/node/consumer/src/lib/models/configuration/torrent_config.ts index 33ea6c6..543f277 100644 --- a/src/node/consumer/src/lib/models/configuration/torrent_config.ts +++ b/src/node/consumer/src/lib/models/configuration/torrent_config.ts @@ -1,4 +1,5 @@ export const torrentConfig = { MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10), + MAX_CONNECTIONS_OVERALL: parseInt(process.env.MAX_CONNECTIONS_OVERALL || "100", 10), TIMEOUT: parseInt(process.env.TORRENT_TIMEOUT || "30000", 10) }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/lib/models/inversify_config.ts index 6bbb2a2..17cd120 100644 --- a/src/node/consumer/src/lib/models/inversify_config.ts +++ b/src/node/consumer/src/lib/models/inversify_config.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; // required import {Container} from "inversify"; -import { IocTypes } from "./ioc_types"; +import {IocTypes} from "./ioc_types"; import {ICacheService} from "../interfaces/cache_service"; import {ILoggingService} from "../interfaces/logging_service"; import {IMetadataService} from "../interfaces/metadata_service"; @@ -32,13 +32,13 @@ serviceContainer.bind(IocTypes.ICompositionalRoot).to(Compos serviceContainer.bind(IocTypes.ICacheService).to(CacheService).inSingletonScope(); serviceContainer.bind(IocTypes.ILoggingService).to(LoggingService).inSingletonScope(); serviceContainer.bind(IocTypes.ITrackerService).to(TrackerService).inSingletonScope(); +serviceContainer.bind(IocTypes.ITorrentDownloadService).to(TorrentDownloadService).inSingletonScope(); serviceContainer.bind(IocTypes.ITorrentFileService).to(TorrentFileService); serviceContainer.bind(IocTypes.ITorrentProcessingService).to(TorrentProcessingService); serviceContainer.bind(IocTypes.ITorrentSubtitleService).to(TorrentSubtitleService); serviceContainer.bind(IocTypes.ITorrentEntriesService).to(TorrentEntriesService); -serviceContainer.bind(IocTypes.ITorrentDownloadService).to(TorrentDownloadService); serviceContainer.bind(IocTypes.IMetadataService).to(MetadataService); serviceContainer.bind(IocTypes.IDatabaseRepository).to(DatabaseRepository); serviceContainer.bind(IocTypes.IProcessTorrentsJob).to(ProcessTorrentsJob); -export { serviceContainer }; +export {serviceContainer}; diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index dc140f9..1afae05 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -25,7 +25,7 @@ export class CacheService implements ICacheService { private logger: ILoggingService; private readonly memoryCache: MemoryCache; private readonly remoteCache: Cache | MemoryCache; - + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { this.logger = logger; if (configurationService.cacheConfig.NO_CACHE) { @@ -59,7 +59,7 @@ export class CacheService implements ICacheService { collectionName: configurationService.cacheConfig.COLLECTION_NAME, ttl: GLOBAL_TTL, url: configurationService.cacheConfig.MONGO_URI, - mongoConfig:{ + mongoConfig: { socketTimeoutMS: 120000, appName: 'knightcrawler-consumer', } diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 7e469da..f684d8d 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -20,6 +20,7 @@ const TIMEOUT = 20000; @injectable() export class MetadataService implements IMetadataService { private cacheService: ICacheService; + constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService) { this.cacheService = cacheService; } diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 28d46a7..e265fba 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,5 +1,4 @@ import {encode} from 'magnet-uri'; -import torrentStream from 'torrent-stream'; import {configurationService} from './configuration_service'; import {ExtensionHelpers} from '../helpers/extension_helpers'; import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; @@ -9,7 +8,10 @@ import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attribut import {IContentAttributes} from "../../repository/interfaces/content_attributes"; import {parse} from "parse-torrent-title"; import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; -import {injectable} from "inversify"; +import {inject, injectable} from "inversify"; +import {ILoggingService} from "../interfaces/logging_service"; +import {IocTypes} from "../models/ioc_types"; +import WebTorrent from "webtorrent"; interface ITorrentFile { name: string; @@ -18,15 +20,28 @@ interface ITorrentFile { fileIndex: number; } +const clientOptions = { + maxConns: configurationService.torrentConfig.MAX_CONNECTIONS_OVERALL, +} + +const torrentOptions = { + skipVerify: true, + addUID: true, + destroyStoreOnDestroy: true, + private: true, + maxWebConns: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, +} + @injectable() export class TorrentDownloadService implements ITorrentDownloadService { - private engineOptions: TorrentStream.TorrentEngineOptions = { - connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, - uploads: 0, - verify: false, - dht: false, - tracker: true, - }; + private torrentClient: WebTorrent.Instance; + private logger: ILoggingService; + + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { + this.logger = logger; + this.torrentClient = new WebTorrent(clientOptions); + this.torrentClient.on('error', errors => this.logClientErrors(errors)); + } public getTorrentFiles = async (torrent: IParsedTorrent, timeout: number = 30000): Promise => { const torrentFiles: ITorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); @@ -48,29 +63,32 @@ export class TorrentDownloadService implements ITorrentDownloadService { } const magnet = encode({infoHash: torrent.infoHash, announce: torrent.trackers.split(',')}); - return new Promise((resolve, reject) => { - let engine: TorrentStream.TorrentEngine; + this.logger.debug(`Constructing torrent stream for ${torrent.title} with magnet ${magnet}`); + return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { - engine.destroy(() => { - }); + this.torrentClient.remove(magnet, {destroyStore: true}); reject(new Error('No available connections for torrent!')); }, timeout); - engine = torrentStream(magnet, this.engineOptions); + this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash}`); + + this.torrentClient.add(magnet, torrentOptions, (torrent) => { - engine.on("ready", () => { - const files: ITorrentFile[] = engine.files.map((file, fileId) => ({ - ...file, + this.logger.debug(`torrent with infoHash ${torrent.infoHash} added to client.`); + + const files: ITorrentFile[] = torrent.files.map((file, fileId) => ({ fileIndex: fileId, - size: file.length, - title: file.name + length: file.length, + name: file.name, + path: file.path, })); + this.logger.debug(`Found ${files.length} files in torrent ${torrent.infoHash}`); + resolve(files); - engine.destroy(() => { - }); + this.torrentClient.remove(magnet, {destroyStore: true}); clearTimeout(timeoutId); }); }); @@ -86,12 +104,12 @@ export class TorrentDownloadService implements ITorrentDownloadService { const minAnimeExtraRatio = 5; const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = (video: ITorrentFile) => video.path?.match(/sample|bonus|promo/i) && maxSize / parseInt(video.path.toString()) > minSampleRatio; - const isRedundant = (video: ITorrentFile) => maxSize / parseInt(video.path.toString()) > minRedundantRatio; - const isExtra = (video: ITorrentFile) => video.path?.match(/extras?\//i); - const isAnimeExtra = (video: ITorrentFile) => video.path?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + const isSample = (video: ITorrentFile) => video.path.toString()?.match(/sample|bonus|promo/i) && maxSize / video.length > minSampleRatio; + const isRedundant = (video: ITorrentFile) => maxSize / video.length > minRedundantRatio; + const isExtra = (video: ITorrentFile) => video.path.toString()?.match(/extras?\//i); + const isAnimeExtra = (video: ITorrentFile) => video.path.toString()?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; - const isWatermark = (video: ITorrentFile) => video.path?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + const isWatermark = (video: ITorrentFile) => video.path.toString()?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio return videos @@ -109,19 +127,23 @@ export class TorrentDownloadService implements ITorrentDownloadService { private createContent = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IContentAttributes[] => torrentFiles.map(file => this.mapTorrentFileToContentAttributes(torrent, file)); private mapTorrentFileToFileAttributes = (torrent: IParsedTorrent, file: ITorrentFile): IFileAttributes => { - const videoFile: IFileAttributes = { - title: file.name, - size: file.length, - fileIndex: file.fileIndex || 0, - infoHash: torrent.infoHash, - imdbId: torrent.imdbId.toString(), - imdbSeason: torrent.season || 0, - imdbEpisode: torrent.episode || 0, - kitsuId: parseInt(torrent.kitsuId.toString()) || 0, - kitsuEpisode: torrent.episode || 0 - }; - - return {...videoFile, ...parse(file.name)}; + try { + const videoFile: IFileAttributes = { + title: file.name, + size: file.length, + fileIndex: file.fileIndex || 0, + infoHash: torrent.infoHash, + imdbId: torrent.imdbId.toString(), + imdbSeason: torrent.season || 0, + imdbEpisode: torrent.episode || 0, + kitsuId: parseInt(torrent.kitsuId?.toString()) || 0, + kitsuEpisode: torrent.episode || 0 + }; + + return {...videoFile, ...parse(file.name)}; + } catch (error) { + throw new Error(`Error parsing file ${file.name} from torrent ${torrent.infoHash}: ${error}`); + } }; private mapTorrentFileToSubtitleAttributes = (torrent: IParsedTorrent, file: ITorrentFile): ISubtitleAttributes => ({ @@ -138,5 +160,9 @@ export class TorrentDownloadService implements ITorrentDownloadService { path: file.path, size: file.length, }); + + private logClientErrors(errors: Error | string) { + this.logger.error(`Error in torrent client: ${errors}`); + } } diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index d94f136..cc0548f 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -23,7 +23,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { private fileService: ITorrentFileService; private subtitleService: ITorrentSubtitleService; private repository: IDatabaseRepository; - + constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, @inject(IocTypes.ILoggingService) logger: ILoggingService, @inject(IocTypes.ITorrentFileService) fileService: ITorrentFileService, @@ -73,7 +73,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) .then((torrentContents: ITorrentFileCollection) => overwrite ? this.overwriteExistingFiles(torrent, torrentContents) : torrentContents) - .then((torrentContents: ITorrentFileCollection) =>this.subtitleService.assignSubtitles(torrentContents)) + .then((torrentContents: ITorrentFileCollection) => this.subtitleService.assignSubtitles(torrentContents)) .catch(error => { this.logger.warn(`Failed getting files for ${torrent.title}`, error.message); return {}; diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 877836f..7990cd8 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -27,7 +27,11 @@ export class TorrentFileService implements ITorrentFileService { private metadataService: IMetadataService; private torrentDownloadService: ITorrentDownloadService; private logger: ILoggingService; - + private readonly imdb_limiter: Bottleneck = new Bottleneck({ + maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, + minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS + }); + constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, @inject(IocTypes.ITorrentDownloadService) torrentDownloadService: ITorrentDownloadService, @inject(IocTypes.ILoggingService) logger: ILoggingService) { @@ -35,11 +39,6 @@ export class TorrentFileService implements ITorrentFileService { this.torrentDownloadService = torrentDownloadService; this.logger = logger; } - - private readonly imdb_limiter: Bottleneck = new Bottleneck({ - maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, - minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS - }); public parseTorrentFiles = async (torrent: IParsedTorrent): Promise => { const parsedTorrentName = parse(torrent.title); @@ -85,8 +84,8 @@ export class TorrentFileService implements ITorrentFileService { const parsedTorrentName = parse(torrent.title); const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); const parsedVideos = videos.map(video => this.parseSeriesVideo(video)); - - return parsedVideos.map(video => ({ ...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies) })); + + return parsedVideos.map(video => ({...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies)})); }; private parseMovieFiles = async (torrent: IParsedTorrent, metadata: IMetadataResponse): Promise => { @@ -100,8 +99,8 @@ export class TorrentFileService implements ITorrentFileService { fileIndex: video.fileIndex, title: video.path || torrent.title, size: video.size || torrent.size, - imdbId: torrent.imdbId.toString() || metadata && metadata.imdbId.toString(), - kitsuId: parseInt(torrent.kitsuId.toString() || metadata && metadata.kitsuId.toString()) + imdbId: torrent.imdbId?.toString() || metadata && metadata.imdbId?.toString(), + kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString()) })); return {...fileCollection, videos: parsedVideos}; } @@ -140,11 +139,11 @@ export class TorrentFileService implements ITorrentFileService { .catch(error => { if (!this.isPackTorrent(torrent)) { const entries = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; - return { videos: entries, contents:[], subtitles: [], files: entries} + return {videos: entries, contents: [], subtitles: [], files: entries} } return Promise.reject(error); }); - + if (files.contents && files.contents.length && !files.videos.length && this.isDiskTorrent(files.contents)) { files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; } @@ -197,22 +196,22 @@ export class TorrentFileService implements ITorrentFileService { }; private mapSeriesMovie = async (torrent: IParsedTorrent, file: IFileAttributes): Promise => { - const kitsuId= torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) + const kitsuId = torrent.type === TorrentType.Anime ? await this.findMovieKitsuId(file) .then(result => { if (result instanceof Error) { this.logger.warn(`Failed to retrieve kitsuId due to error: ${result.message}`); return undefined; } return result; - }): undefined; - + }) : undefined; + const imdbId = !kitsuId ? await this.findMovieImdbId(file) : undefined; const query: IMetaDataQuery = { id: kitsuId || imdbId, type: TorrentType.Movie }; - + const metadataOrError = await this.metadataService.getMetadata(query); if (metadataOrError instanceof Error) { this.logger.warn(`Failed to retrieve metadata due to error: ${metadataOrError.message}`); @@ -247,7 +246,7 @@ export class TorrentFileService implements ITorrentFileService { }]; }; - private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = { episodeCount: [] }) => { + private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = {episodeCount: []}) => { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -635,7 +634,7 @@ export class TorrentFileService implements ITorrentFileService { videoInfo.episode = videoInfo.episodes && videoInfo.episodes[0]; } - return { ...video, ...videoInfo }; + return {...video, ...videoInfo}; }; private isMovieVideo = (torrent: IParsedTorrent, video: IFileAttributes, otherVideos: IFileAttributes[], hasMovies: boolean): boolean => { diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index 516323d..c88d680 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -13,9 +13,10 @@ export class TorrentProcessingService implements ITorrentProcessingService { private torrentEntriesService: ITorrentEntriesService; private logger: ILoggingService; private trackerService: ITrackerService; + constructor(@inject(IocTypes.ITorrentEntriesService) torrentEntriesService: ITorrentEntriesService, @inject(IocTypes.ILoggingService) logger: ILoggingService, - @inject(IocTypes.ITrackerService) trackerService: ITrackerService){ + @inject(IocTypes.ITrackerService) trackerService: ITrackerService) { this.torrentEntriesService = torrentEntriesService; this.logger = logger; this.trackerService = trackerService; @@ -62,6 +63,6 @@ export class TorrentProcessingService implements ITorrentProcessingService { } return torrent.imdb; - }; + }; } diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 83856ee..97878f8 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -28,7 +28,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return fileCollection; }; - private parseVideo = (video: IFileAttributes)=> { + private parseVideo = (video: IFileAttributes) => { const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); const folderName = video.title.replace(/\/?[^/]+$/, ''); return { @@ -68,7 +68,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return undefined; } - private singleVideoFile = (videos: any[])=> { + private singleVideoFile = (videos: any[]) => { return new Set(videos.map(v => v.videoFile.fileIndex)).size === 1; } diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index b292314..5918e19 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -10,7 +10,7 @@ import {ILoggingService} from "../interfaces/logging_service"; export class TrackerService implements ITrackerService { private cacheService: ICacheService; private logger: ILoggingService; - + constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService, @inject(IocTypes.ILoggingService) logger: ILoggingService) { this.cacheService = cacheService; @@ -19,7 +19,7 @@ export class TrackerService implements ITrackerService { public getTrackers = async (): Promise => this.cacheService.cacheTrackers(this.downloadTrackers); - private downloadTrackers = async(): Promise => { + private downloadTrackers = async (): Promise => { const response: AxiosResponse = await axios.get(configurationService.trackerConfig.TRACKERS_URL); const trackersListText: string = response.data; // Trackers are separated by a newline character diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index e5e93cd..c3ed512 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -21,7 +21,7 @@ import {IDatabaseRepository} from "./interfaces/database_repository"; @injectable() export class DatabaseRepository implements IDatabaseRepository { private readonly database: Sequelize; - + private models = [ Torrent, Provider, @@ -32,7 +32,7 @@ export class DatabaseRepository implements IDatabaseRepository { IngestedTorrent, IngestedPage]; private logger: ILoggingService; - + constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { this.logger = logger; this.database = this.createDatabase(); @@ -41,7 +41,8 @@ export class DatabaseRepository implements IDatabaseRepository { public connect = async () => { try { await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); - } catch { + } catch (error) { + this.logger.debug('Failed to sync database', error); this.logger.error('Failed syncing database'); process.exit(1); } @@ -112,9 +113,14 @@ export class DatabaseRepository implements IDatabaseRepository { }); public createTorrent = async (torrent: Torrent): Promise => { - await Torrent.upsert(torrent); - await this.createContents(torrent.infoHash, torrent.contents); - await this.createSubtitles(torrent.infoHash, torrent.subtitles); + try { + await Torrent.upsert(torrent); + await this.createContents(torrent.infoHash, torrent.contents); + await this.createSubtitles(torrent.infoHash, torrent.subtitles); + } catch (error) { + this.logger.error(`Failed to create torrent: ${torrent.infoHash}`); + this.logger.debug(error); + } }; public setTorrentSeeders = async (torrent: ITorrentAttributes, seeders: number): Promise<[number]> => { @@ -211,9 +217,9 @@ export class DatabaseRepository implements IDatabaseRepository { logging: false } ); - + newDatabase.addModels(this.models); - + return newDatabase; }; } diff --git a/src/node/consumer/src/repository/models/content.ts b/src/node/consumer/src/repository/models/content.ts index c17bca1..6a697ee 100644 --- a/src/node/consumer/src/repository/models/content.ts +++ b/src/node/consumer/src/repository/models/content.ts @@ -1,22 +1,22 @@ -import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {BelongsTo, Column, DataType, ForeignKey, Model, Table} from 'sequelize-typescript'; import {IContentAttributes, IContentCreationAttributes} from "../interfaces/content_attributes"; import {Torrent} from "./torrent"; @Table({modelName: 'content', timestamps: false}) export class Content extends Model { - @Column({ type: DataType.STRING(64), primaryKey: true, allowNull: false, onDelete: 'CASCADE' }) + @Column({type: DataType.STRING(64), primaryKey: true, allowNull: false, onDelete: 'CASCADE'}) @ForeignKey(() => Torrent) declare infoHash: string; - - @Column({ type: DataType.INTEGER, primaryKey: true, allowNull: false }) + + @Column({type: DataType.INTEGER, primaryKey: true, allowNull: false}) declare fileIndex: number; - - @Column({ type: DataType.STRING(512), allowNull: false }) + + @Column({type: DataType.STRING(512), allowNull: false}) declare path: string; - - @Column({ type: DataType.BIGINT }) + + @Column({type: DataType.BIGINT}) declare size: number; - @BelongsTo(() => Torrent, { constraints: false, foreignKey: 'infoHash' }) + @BelongsTo(() => Torrent, {constraints: false, foreignKey: 'infoHash'}) torrent: Torrent; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/file.ts b/src/node/consumer/src/repository/models/file.ts index 62a4ea2..94a0b0a 100644 --- a/src/node/consumer/src/repository/models/file.ts +++ b/src/node/consumer/src/repository/models/file.ts @@ -1,8 +1,7 @@ -import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {BelongsTo, Column, DataType, ForeignKey, HasMany, Model, Table} from 'sequelize-typescript'; import {IFileAttributes, IFileCreationAttributes} from "../interfaces/file_attributes"; import {Torrent} from "./torrent"; import {Subtitle} from "./subtitle"; -import {ISubtitleAttributes} from "../interfaces/subtitle_attributes"; const indexes = [ { @@ -18,43 +17,43 @@ const indexes = [ 'kitsuEpisode' ] }, - { unique: false, fields: ['imdbId', 'imdbSeason', 'imdbEpisode'] }, - { unique: false, fields: ['kitsuId', 'kitsuEpisode'] } + {unique: false, fields: ['imdbId', 'imdbSeason', 'imdbEpisode']}, + {unique: false, fields: ['kitsuId', 'kitsuEpisode']} ]; -@Table({modelName: 'file', timestamps: true, indexes: indexes }) +@Table({modelName: 'file', timestamps: true, indexes: indexes}) export class File extends Model { - @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) + @Column({type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE'}) @ForeignKey(() => Torrent) declare infoHash: string; - - @Column({ type: DataType.INTEGER}) + + @Column({type: DataType.INTEGER}) declare fileIndex: number; - - @Column({ type: DataType.STRING(512), allowNull: false }) + + @Column({type: DataType.STRING(512), allowNull: false}) declare title: string; - - @Column({ type: DataType.BIGINT }) + + @Column({type: DataType.BIGINT}) declare size: number; - - @Column({ type: DataType.STRING(32) }) + + @Column({type: DataType.STRING(32)}) declare imdbId: string; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare imdbSeason: number; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare imdbEpisode: number; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare kitsuId: number; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare kitsuEpisode: number; - @HasMany(() => Subtitle, { constraints: false, foreignKey: 'fileId'}) + @HasMany(() => Subtitle, {constraints: false, foreignKey: 'fileId'}) declare subtitles?: Subtitle[]; - @BelongsTo(() => Torrent, { constraints: false, foreignKey: 'infoHash' }) + @BelongsTo(() => Torrent, {constraints: false, foreignKey: 'infoHash'}) torrent: Torrent; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedPage.ts b/src/node/consumer/src/repository/models/ingestedPage.ts index 2dc64a3..3c08b1b 100644 --- a/src/node/consumer/src/repository/models/ingestedPage.ts +++ b/src/node/consumer/src/repository/models/ingestedPage.ts @@ -1,4 +1,4 @@ -import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {Column, DataType, Model, Table} from 'sequelize-typescript'; import {IIngestedPageAttributes, IIngestedPageCreationAttributes} from "../interfaces/ingested_page_attributes"; const indexes = [ @@ -11,6 +11,6 @@ const indexes = [ @Table({modelName: 'ingested_page', timestamps: true, indexes: indexes}) export class IngestedPage extends Model { - @Column({ type: DataType.STRING(512), allowNull: false }) + @Column({type: DataType.STRING(512), allowNull: false}) declare url: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedTorrent.ts b/src/node/consumer/src/repository/models/ingestedTorrent.ts index a40571b..7f03914 100644 --- a/src/node/consumer/src/repository/models/ingestedTorrent.ts +++ b/src/node/consumer/src/repository/models/ingestedTorrent.ts @@ -1,4 +1,4 @@ -import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {Column, DataType, Model, Table} from 'sequelize-typescript'; import {IIngestedTorrentAttributes, IIngestedTorrentCreationAttributes} from "../interfaces/ingested_torrent_attributes"; const indexes = [ @@ -11,30 +11,30 @@ const indexes = [ @Table({modelName: 'ingested_torrent', timestamps: true, indexes: indexes}) export class IngestedTorrent extends Model { - @Column({ type: DataType.STRING(512) }) + @Column({type: DataType.STRING(512)}) declare name: string; - - @Column({ type: DataType.STRING(512) }) + + @Column({type: DataType.STRING(512)}) declare source: string; - - @Column({ type: DataType.STRING(32) }) + + @Column({type: DataType.STRING(32)}) declare category: string; - - @Column({ type: DataType.STRING(64) }) + + @Column({type: DataType.STRING(64)}) declare info_hash: string; - - @Column({ type: DataType.STRING(32) }) + + @Column({type: DataType.STRING(32)}) declare size: string; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare seeders: number; - - @Column({ type: DataType.INTEGER }) + + @Column({type: DataType.INTEGER}) declare leechers: number; - - @Column({ type: DataType.STRING(32) }) + + @Column({type: DataType.STRING(32)}) declare imdb: string; - - @Column({ type: DataType.BOOLEAN, defaultValue: false }) + + @Column({type: DataType.BOOLEAN, defaultValue: false}) declare processed: boolean; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/provider.ts b/src/node/consumer/src/repository/models/provider.ts index 97b5036..c3506ed 100644 --- a/src/node/consumer/src/repository/models/provider.ts +++ b/src/node/consumer/src/repository/models/provider.ts @@ -1,15 +1,15 @@ -import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {Column, DataType, Model, Table} from 'sequelize-typescript'; import {IProviderAttributes, IProviderCreationAttributes} from "../interfaces/provider_attributes"; @Table({modelName: 'provider', timestamps: false}) export class Provider extends Model { - - @Column({ type: DataType.STRING(32), primaryKey: true }) + + @Column({type: DataType.STRING(32), primaryKey: true}) declare name: string; - - @Column({ type: DataType.DATE }) + + @Column({type: DataType.DATE}) declare lastScraped: Date; - - @Column({ type: DataType.STRING(128) }) + + @Column({type: DataType.STRING(128)}) declare lastScrapedId: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/skipTorrent.ts b/src/node/consumer/src/repository/models/skipTorrent.ts index 7e1eb4a..6e34c79 100644 --- a/src/node/consumer/src/repository/models/skipTorrent.ts +++ b/src/node/consumer/src/repository/models/skipTorrent.ts @@ -1,10 +1,10 @@ -import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {Column, DataType, Model, Table} from 'sequelize-typescript'; import {ISkipTorrentAttributes, ISkipTorrentCreationAttributes} from "../interfaces/skip_torrent_attributes"; @Table({modelName: 'skip_torrent', timestamps: false}) export class SkipTorrent extends Model { - - @Column({ type: DataType.STRING(64), primaryKey: true }) + + @Column({type: DataType.STRING(64), primaryKey: true}) declare infoHash: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/subtitle.ts b/src/node/consumer/src/repository/models/subtitle.ts index 7a66baf..f8ffa1e 100644 --- a/src/node/consumer/src/repository/models/subtitle.ts +++ b/src/node/consumer/src/repository/models/subtitle.ts @@ -1,7 +1,6 @@ -import {Table, Column, Model, HasMany, DataType, BelongsTo, ForeignKey} from 'sequelize-typescript'; +import {BelongsTo, Column, DataType, ForeignKey, Model, Table} from 'sequelize-typescript'; import {ISubtitleAttributes, ISubtitleCreationAttributes} from "../interfaces/subtitle_attributes"; import {File} from "./file"; -import {Torrent} from "./torrent"; const indexes = [ { @@ -13,27 +12,27 @@ const indexes = [ 'fileId' ] }, - { unique: false, fields: ['fileId'] } + {unique: false, fields: ['fileId']} ]; @Table({modelName: 'subtitle', timestamps: false, indexes: indexes}) export class Subtitle extends Model { - - @Column({ type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE' }) + + @Column({type: DataType.STRING(64), allowNull: false, onDelete: 'CASCADE'}) declare infoHash: string; - - @Column({ type: DataType.INTEGER, allowNull: false }) + + @Column({type: DataType.INTEGER, allowNull: false}) declare fileIndex: number; - - @Column({ type: DataType.BIGINT, allowNull: true, onDelete: 'SET NULL' }) + + @Column({type: DataType.BIGINT, allowNull: true, onDelete: 'SET NULL'}) @ForeignKey(() => File) declare fileId?: number | null; - - @Column({ type: DataType.STRING(512), allowNull: false }) + + @Column({type: DataType.STRING(512), allowNull: false}) declare title: string; - @BelongsTo(() => File, { constraints: false, foreignKey: 'fileId' }) + @BelongsTo(() => File, {constraints: false, foreignKey: 'fileId'}) file: File; - + path: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/torrent.ts b/src/node/consumer/src/repository/models/torrent.ts index f345b55..c759d3a 100644 --- a/src/node/consumer/src/repository/models/torrent.ts +++ b/src/node/consumer/src/repository/models/torrent.ts @@ -1,4 +1,4 @@ -import { Table, Column, Model, HasMany, DataType } from 'sequelize-typescript'; +import {Column, DataType, HasMany, Model, Table} from 'sequelize-typescript'; import {ITorrentAttributes, ITorrentCreationAttributes} from "../interfaces/torrent_attributes"; import {Content} from "./content"; import {File} from "./file"; @@ -9,48 +9,48 @@ import {Subtitle} from "./subtitle"; export class Torrent extends Model { @Column({type: DataType.STRING(64), primaryKey: true}) declare infoHash: string; - + @Column({type: DataType.STRING(32), allowNull: false}) declare provider: string; - + @Column({type: DataType.STRING(512)}) declare torrentId: string; - + @Column({type: DataType.STRING(512), allowNull: false}) declare title: string; - + @Column({type: DataType.BIGINT}) declare size: number; - + @Column({type: DataType.STRING(16), allowNull: false}) declare type: string; - + @Column({type: DataType.DATE, allowNull: false}) declare uploadDate: Date; - + @Column({type: DataType.SMALLINT}) declare seeders: number; - + @Column({type: DataType.STRING(8000)}) declare trackers: string; - + @Column({type: DataType.STRING(4096)}) declare languages: string; - + @Column({type: DataType.STRING(16)}) declare resolution: string; - + @Column({type: DataType.BOOLEAN, allowNull: false, defaultValue: false}) declare reviewed: boolean; - + @Column({type: DataType.BOOLEAN, allowNull: false, defaultValue: false}) declare opened: boolean; - @HasMany(() => Content, { foreignKey: 'infoHash', constraints: false }) + @HasMany(() => Content, {foreignKey: 'infoHash', constraints: false}) contents?: Content[]; - @HasMany(() => File, { foreignKey: 'infoHash', constraints: false }) + @HasMany(() => File, {foreignKey: 'infoHash', constraints: false}) files?: File[]; - + subtitles?: Subtitle[]; } \ No newline at end of file diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index cd0f68d..435ebc2 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -8,8 +8,13 @@ "rootDir": "./src", "sourceMap": true, "target": "ES6", - "lib": ["es6"], - "types": ["node", "reflect-metadata"], + "lib": [ + "es6" + ], + "types": [ + "node", + "reflect-metadata" + ], "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, From 189fdd466ed8f0d9f658ec87f60d20380be60211 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 14:50:25 +0000 Subject: [PATCH 29/55] Few fixes with regards to sequelize usage from services --- .../src/lib/interfaces/metadata_service.ts | 2 +- .../src/lib/interfaces/parsed_torrent.ts | 2 +- .../lib/services/torrent_download_service.ts | 3 +- .../lib/services/torrent_entries_service.ts | 40 ++++++++++++---- .../src/lib/services/torrent_file_service.ts | 12 ++--- .../src/repository/database_repository.ts | 48 +++++++++++-------- .../interfaces/database_repository.ts | 16 ++++--- 7 files changed, 77 insertions(+), 46 deletions(-) diff --git a/src/node/consumer/src/lib/interfaces/metadata_service.ts b/src/node/consumer/src/lib/interfaces/metadata_service.ts index 71a1a2a..e7abec0 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_service.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_service.ts @@ -2,7 +2,7 @@ import {IMetaDataQuery} from "./metadata_query"; import {IMetadataResponse} from "./metadata_response"; export interface IMetadataService { - getKitsuId(info: IMetaDataQuery): Promise; + getKitsuId(info: IMetaDataQuery): Promise; getImdbId(info: IMetaDataQuery): Promise; diff --git a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts index 8e227ef..f61cfeb 100644 --- a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts +++ b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts @@ -6,7 +6,7 @@ export interface IParsedTorrent extends IParseTorrentTitleResult { size?: number; isPack?: boolean; imdbId?: string | number; - kitsuId?: string | number; + kitsuId?: number; trackers?: string; provider?: string | null; infoHash: string | null; diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index e265fba..6201940 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -132,12 +132,13 @@ export class TorrentDownloadService implements ITorrentDownloadService { title: file.name, size: file.length, fileIndex: file.fileIndex || 0, + path: file.path, infoHash: torrent.infoHash, imdbId: torrent.imdbId.toString(), imdbSeason: torrent.season || 0, imdbEpisode: torrent.episode || 0, kitsuId: parseInt(torrent.kitsuId?.toString()) || 0, - kitsuEpisode: torrent.episode || 0 + kitsuEpisode: torrent.episode || 0, }; return {...videoFile, ...parse(file.name)}; diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index cc0548f..93355b6 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -4,7 +4,7 @@ import {TorrentType} from '../enums/torrent_types'; import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; import {Torrent} from "../../repository/models/torrent"; import {PromiseHelpers} from '../helpers/promises_helpers'; -import {ITorrentAttributes} from "../../repository/interfaces/torrent_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "../../repository/interfaces/torrent_attributes"; import {File} from "../../repository/models/file"; import {Subtitle} from "../../repository/models/subtitle"; import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; @@ -15,6 +15,8 @@ import {ILoggingService} from "../interfaces/logging_service"; import {ITorrentFileService} from "../interfaces/torrent_file_service"; import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; +import {IIngestedTorrentCreationAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; +import {IFileCreationAttributes} from "../../repository/interfaces/file_attributes"; @injectable() export class TorrentEntriesService implements ITorrentEntriesService { @@ -62,8 +64,8 @@ export class TorrentEntriesService implements ITorrentEntriesService { year: titleInfo.year, season: titleInfo.season, }; - torrent.kitsuId = await this.metadataService.getKitsuId(kitsuQuery) - .catch(() => undefined); + + await this.assignKitsuId(kitsuQuery, torrent); } if (!torrent.imdbId && !torrent.kitsuId && !this.fileService.isPackTorrent(torrent)) { @@ -84,20 +86,38 @@ export class TorrentEntriesService implements ITorrentEntriesService { return; } - const newTorrent: Torrent = Torrent.build({ + const newTorrent: ITorrentCreationAttributes = ({ ...torrent, contents: fileCollection.contents, subtitles: fileCollection.subtitles }); - + return this.repository.createTorrent(newTorrent) .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { - const newVideo = File.build(video); + const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; + if (!newVideo.kitsuId) { + newVideo.kitsuId = 0; + } return this.repository.createFile(newVideo) }))) .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); }; + private assignKitsuId = async (kitsuQuery: { year: number | string; season: number; title: string }, torrent: IParsedTorrent) => { + await this.metadataService.getKitsuId(kitsuQuery) + .then((result: number | Error) => { + if (typeof result === 'number') { + torrent.kitsuId = result; + } else { + torrent.kitsuId = 0; + } + }) + .catch((error: Error) => { + this.logger.debug(`Failed getting kitsuId for ${torrent.title}`, error.message); + torrent.kitsuId = 0; + }); + }; + public createSkipTorrentEntry = async (torrent: Torrent) => this.repository.createSkipTorrent(torrent); public getStoredTorrentEntry = async (torrent: Torrent) => this.repository.getSkipTorrent(torrent.infoHash) @@ -144,7 +164,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { } const notOpenedVideo = storedVideos.length === 1 && !Number.isInteger(storedVideos[0].fileIndex); const imdbId: string | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.imdbId)); - const kitsuId: number | undefined = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId)); + const kitsuId: number = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId || 0)); const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos}) @@ -187,7 +207,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { return Promise.resolve(); }) .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { - const newVideo = File.build(video); + const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; return this.repository.createFile(newVideo) }))) .then(() => this.logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) @@ -209,8 +229,8 @@ export class TorrentEntriesService implements ITorrentEntriesService { private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string, kitsuId: number): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { - video.imdbId = imdbId; - video.kitsuId = kitsuId; + video.imdbId = imdbId || ''; + video.kitsuId = kitsuId || 0; }); } diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 7990cd8..d98f128 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -191,7 +191,7 @@ export class TorrentFileService implements ITorrentFileService { episode: file.episodes && file.episodes[index], kitsuEpisode: file.episodes && file.episodes[index], episodes: file.episodes, - kitsuId: parseInt(file.kitsuId.toString() || torrent.kitsuId.toString()), + kitsuId: parseInt(file.kitsuId.toString() || torrent.kitsuId.toString()) || 0, }))) }; @@ -222,7 +222,7 @@ export class TorrentFileService implements ITorrentFileService { title: file.path || file.title, size: file.size, imdbId: imdbId, - kitsuId: parseInt(kitsuId), + kitsuId: parseInt(kitsuId) || 0, episodes: undefined, imdbSeason: undefined, imdbEpisode: undefined, @@ -239,7 +239,7 @@ export class TorrentFileService implements ITorrentFileService { title: file.path || file.title, size: file.size, imdbId: metadata.imdbId.toString() || imdbId, - kitsuId: parseInt(metadata.kitsuId.toString() || kitsuId), + kitsuId: parseInt(metadata.kitsuId.toString() || kitsuId) || 0, imdbSeason: episodeVideo && metadata.imdbId ? episodeVideo.season : undefined, imdbEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, kitsuEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, @@ -474,7 +474,7 @@ export class TorrentFileService implements ITorrentFileService { if (seriesMapping[file.season]) { const seasonMapping = seriesMapping[file.season]; file.imdbId = metadata.imdbId.toString(); - file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId; + file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId || 0; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); } else if (seriesMapping[file.season - 1]) { // sometimes a second season might be a continuation of the previous season @@ -492,7 +492,7 @@ export class TorrentFileService implements ITorrentFileService { file.imdbId = metadata.imdbId.toString(); file.season = file.season - 1; file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; + file.kitsuId = seasonMapping[file.episodes[0]].kitsuId || 0; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); } } else if (Object.values(seriesMapping).length === 1 && seriesMapping[1]) { @@ -500,7 +500,7 @@ export class TorrentFileService implements ITorrentFileService { const seasonMapping = seriesMapping[1]; file.imdbId = metadata.imdbId.toString(); file.season = 1; - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId; + file.kitsuId = seasonMapping[file.episodes[0]].kitsuId || 0; file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); } }); diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/repository/database_repository.ts index c3ed512..2d1dfff 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/repository/database_repository.ts @@ -10,13 +10,15 @@ import {IngestedTorrent} from "./models/ingestedTorrent"; import {Subtitle} from "./models/subtitle"; import {Content} from "./models/content"; import {SkipTorrent} from "./models/skipTorrent"; -import {IFileAttributes} from "./interfaces/file_attributes"; -import {ITorrentAttributes} from "./interfaces/torrent_attributes"; +import {IFileAttributes, IFileCreationAttributes} from "./interfaces/file_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "./interfaces/torrent_attributes"; import {IngestedPage} from "./models/ingestedPage"; import {ILoggingService} from "../lib/interfaces/logging_service"; import {IocTypes} from "../lib/models/ioc_types"; import {inject, injectable} from "inversify"; import {IDatabaseRepository} from "./interfaces/database_repository"; +import {IContentCreationAttributes} from "./interfaces/content_attributes"; +import {ISubtitleCreationAttributes} from "./interfaces/subtitle_attributes"; @injectable() export class DatabaseRepository implements IDatabaseRepository { @@ -112,7 +114,7 @@ export class DatabaseRepository implements IDatabaseRepository { order: literal('random()') }); - public createTorrent = async (torrent: Torrent): Promise => { + public createTorrent = async (torrent: ITorrentCreationAttributes): Promise => { try { await Torrent.upsert(torrent); await this.createContents(torrent.infoHash, torrent.contents); @@ -136,22 +138,28 @@ export class DatabaseRepository implements IDatabaseRepository { public deleteTorrent = async (infoHash: string): Promise => await Torrent.destroy({where: {infoHash: infoHash}}); - public createFile = async (file: File): Promise => { - if (file.id) { - if (file.dataValues) { - await file.save(); + public createFile = async (file: IFileCreationAttributes): Promise => { + try { + const operatingFile = File.build(file); + if (operatingFile.id) { + if (operatingFile.dataValues) { + await operatingFile.save(); + } else { + await File.upsert(operatingFile); + } + await this.upsertSubtitles(operatingFile, operatingFile.subtitles); } else { - await File.upsert(file); + if (operatingFile.subtitles && operatingFile.subtitles.length) { + operatingFile.subtitles = operatingFile.subtitles.map(subtitle => { + subtitle.title = subtitle.path; + return subtitle; + }); + } + await File.create(file, {include: [Subtitle], ignoreDuplicates: true}); } - await this.upsertSubtitles(file, file.subtitles); - } else { - if (file.subtitles && file.subtitles.length) { - file.subtitles = file.subtitles.map(subtitle => { - subtitle.title = subtitle.path; - return subtitle; - }); - } - await File.create(file, {include: [Subtitle], ignoreDuplicates: true}); + } catch (error) { + this.logger.error(`Failed to create file: ${file.infoHash}`); + this.logger.debug(error); } }; @@ -161,7 +169,7 @@ export class DatabaseRepository implements IDatabaseRepository { public deleteFile = async (id: number): Promise => File.destroy({where: {id: id}}); - public createSubtitles = async (infoHash: string, subtitles: Subtitle[]): Promise[]> => { + public createSubtitles = async (infoHash: string, subtitles: ISubtitleCreationAttributes[]): Promise[]> => { if (subtitles && subtitles.length) { return Subtitle.bulkCreate(subtitles.map(subtitle => ({infoHash, title: subtitle.path, ...subtitle}))); } @@ -191,7 +199,7 @@ export class DatabaseRepository implements IDatabaseRepository { public getUnassignedSubtitles = async (): Promise => Subtitle.findAll({where: {fileId: null}}); - public createContents = async (infoHash: string, contents: Content[]): Promise => { + public createContents = async (infoHash: string, contents: IContentCreationAttributes[]): Promise => { if (contents && contents.length) { await Content.bulkCreate(contents.map(content => ({infoHash, ...content})), {ignoreDuplicates: true}); await Torrent.update({opened: true}, {where: {infoHash: infoHash}, silent: true}); @@ -208,7 +216,7 @@ export class DatabaseRepository implements IDatabaseRepository { return result.dataValues as SkipTorrent; }; - public createSkipTorrent = async (torrent: Torrent): Promise<[SkipTorrent, boolean]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); + public createSkipTorrent = async (torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); private createDatabase = (): Sequelize => { const newDatabase = new Sequelize( diff --git a/src/node/consumer/src/repository/interfaces/database_repository.ts b/src/node/consumer/src/repository/interfaces/database_repository.ts index 0a3ce38..a0d1d43 100644 --- a/src/node/consumer/src/repository/interfaces/database_repository.ts +++ b/src/node/consumer/src/repository/interfaces/database_repository.ts @@ -1,13 +1,15 @@ import {Provider} from "../models/provider"; import {WhereOptions} from "sequelize"; -import {ITorrentAttributes} from "./torrent_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "./torrent_attributes"; import {Torrent} from "../models/torrent"; -import {IFileAttributes} from "./file_attributes"; +import {IFileAttributes, IFileCreationAttributes} from "./file_attributes"; import {File} from "../models/file"; import {Subtitle} from "../models/subtitle"; import {Model} from "sequelize-typescript"; import {Content} from "../models/content"; import {SkipTorrent} from "../models/skipTorrent"; +import {ISubtitleCreationAttributes} from "./subtitle_attributes"; +import {IContentCreationAttributes} from "./content_attributes"; export interface IDatabaseRepository { connect(): Promise; @@ -30,13 +32,13 @@ export interface IDatabaseRepository { getNoContentsTorrents(): Promise; - createTorrent(torrent: Torrent): Promise; + createTorrent(torrent: ITorrentCreationAttributes): Promise; setTorrentSeeders(torrent: ITorrentAttributes, seeders: number): Promise<[number]>; deleteTorrent(infoHash: string): Promise; - createFile(file: File): Promise; + createFile(file: IFileCreationAttributes): Promise; getFiles(infoHash: string): Promise; @@ -44,7 +46,7 @@ export interface IDatabaseRepository { deleteFile(id: number): Promise; - createSubtitles(infoHash: string, subtitles: Subtitle[]): Promise[]>; + createSubtitles(infoHash: string, subtitles: ISubtitleCreationAttributes[]): Promise[]>; upsertSubtitles(file: File, subtitles: Subtitle[]): Promise; @@ -52,11 +54,11 @@ export interface IDatabaseRepository { getUnassignedSubtitles(): Promise; - createContents(infoHash: string, contents: Content[]): Promise; + createContents(infoHash: string, contents: IContentCreationAttributes[]): Promise; getContents(infoHash: string): Promise; getSkipTorrent(infoHash: string): Promise; - createSkipTorrent(torrent: Torrent): Promise<[SkipTorrent, boolean]>; + createSkipTorrent(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean]>; } \ No newline at end of file From 9aba1c13b13a2d137900754a7ea0d3c62e1bb807 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 19:58:29 +0000 Subject: [PATCH 30/55] And thats what happens when you do a crapload of work with *.ts in .eslintignore... :/ --- deployment/docker/.env.example | 4 +- src/node/consumer/.eslintignore | 2 +- src/node/consumer/.eslintrc | 30 +- src/node/consumer/.swcrc | 15 + src/node/consumer/Dockerfile | 7 +- src/node/consumer/esbuild.js | 54 - src/node/consumer/package-lock.json | 1391 ++++++++++++++++- src/node/consumer/package.json | 16 +- .../src/lib/helpers/extension_helpers.ts | 8 +- .../src/lib/helpers/promises_helpers.ts | 18 +- .../src/lib/interfaces/cache_service.ts | 4 +- .../src/lib/interfaces/logging_service.ts | 7 +- .../interfaces/parse_torrent_title_result.ts | 5 + .../src/lib/interfaces/parsed_torrent.ts | 4 +- .../interfaces/process_torrents_job.ts | 0 .../src/lib/interfaces/season_episode_map.ts | 7 + .../lib/interfaces/torrent_entries_service.ts | 14 +- .../lib/interfaces/torrent_file_collection.ts | 6 +- .../interfaces/torrent_processing_service.ts | 2 +- .../{ => lib}/jobs/process_torrents_job.ts | 35 +- .../src/lib/models/composition_root.ts | 8 +- .../lib/models/configuration/cache_config.ts | 2 +- .../models/configuration/database_config.ts | 2 +- .../models/configuration/torrent_config.ts | 2 +- .../src/lib/models/inversify_config.ts | 21 +- .../repository/database_repository.ts | 68 +- .../interfaces/content_attributes.ts | 0 .../interfaces/database_repository.ts | 24 +- .../repository/interfaces/file_attributes.ts | 4 +- .../interfaces/ingested_page_attributes.ts | 0 .../interfaces/ingested_torrent_attributes.ts | 0 .../interfaces/provider_attributes.ts | 0 .../interfaces/skip_torrent_attributes.ts | 0 .../interfaces/subtitle_attributes.ts | 2 +- .../interfaces/torrent_attributes.ts | 4 +- .../{ => lib}/repository/models/content.ts | 2 +- .../src/{ => lib}/repository/models/file.ts | 4 +- .../repository/models/ingestedPage.ts | 0 .../repository/models/ingestedTorrent.ts | 0 .../{ => lib}/repository/models/provider.ts | 0 .../repository/models/skipTorrent.ts | 0 .../{ => lib}/repository/models/subtitle.ts | 4 +- .../{ => lib}/repository/models/torrent.ts | 0 .../src/lib/services/cache_service.ts | 35 +- .../src/lib/services/configuration_service.ts | 6 +- .../src/lib/services/logging_service.ts | 6 +- .../src/lib/services/metadata_service.ts | 88 +- .../lib/services/torrent_download_service.ts | 98 +- .../lib/services/torrent_entries_service.ts | 119 +- .../src/lib/services/torrent_file_service.ts | 329 ++-- .../services/torrent_processing_service.ts | 12 +- .../lib/services/torrent_subtitle_service.ts | 51 +- .../src/lib/services/tracker_service.ts | 6 +- src/node/consumer/src/main.ts | 5 +- src/node/consumer/tsconfig.json | 32 +- 55 files changed, 1987 insertions(+), 576 deletions(-) create mode 100644 src/node/consumer/.swcrc delete mode 100644 src/node/consumer/esbuild.js rename src/node/consumer/src/{ => lib}/interfaces/process_torrents_job.ts (100%) create mode 100644 src/node/consumer/src/lib/interfaces/season_episode_map.ts rename src/node/consumer/src/{ => lib}/jobs/process_torrents_job.ts (72%) rename src/node/consumer/src/{ => lib}/repository/database_repository.ts (84%) rename src/node/consumer/src/{ => lib}/repository/interfaces/content_attributes.ts (100%) rename src/node/consumer/src/{ => lib}/repository/interfaces/database_repository.ts (81%) rename src/node/consumer/src/{ => lib}/repository/interfaces/file_attributes.ts (84%) rename src/node/consumer/src/{ => lib}/repository/interfaces/ingested_page_attributes.ts (100%) rename src/node/consumer/src/{ => lib}/repository/interfaces/ingested_torrent_attributes.ts (100%) rename src/node/consumer/src/{ => lib}/repository/interfaces/provider_attributes.ts (100%) rename src/node/consumer/src/{ => lib}/repository/interfaces/skip_torrent_attributes.ts (100%) rename src/node/consumer/src/{ => lib}/repository/interfaces/subtitle_attributes.ts (90%) rename src/node/consumer/src/{ => lib}/repository/interfaces/torrent_attributes.ts (96%) rename src/node/consumer/src/{ => lib}/repository/models/content.ts (97%) rename src/node/consumer/src/{ => lib}/repository/models/file.ts (98%) rename src/node/consumer/src/{ => lib}/repository/models/ingestedPage.ts (100%) rename src/node/consumer/src/{ => lib}/repository/models/ingestedTorrent.ts (100%) rename src/node/consumer/src/{ => lib}/repository/models/provider.ts (100%) rename src/node/consumer/src/{ => lib}/repository/models/skipTorrent.ts (100%) rename src/node/consumer/src/{ => lib}/repository/models/subtitle.ts (96%) rename src/node/consumer/src/{ => lib}/repository/models/torrent.ts (100%) diff --git a/deployment/docker/.env.example b/deployment/docker/.env.example index 32953d2..1d84fe9 100644 --- a/deployment/docker/.env.example +++ b/deployment/docker/.env.example @@ -23,7 +23,9 @@ RABBIT_URI=amqp://guest:guest@rabbitmq:5672/?heartbeat=30 QUEUE_NAME=ingested JOB_CONCURRENCY=5 JOBS_ENABLED=true -MAX_SINGLE_TORRENT_CONNECTIONS=10 +LOG_LEVEL=info # can be debug for extra verbosity (a lot more verbosity - useful for development) +MAX_CONNECTIONS_PER_TORRENT=10 +MAX_CONNECTIONS_OVERALL=100 TORRENT_TIMEOUT=30000 UDP_TRACKERS_ENABLED=true CONSUMER_REPLICAS=3 diff --git a/src/node/consumer/.eslintignore b/src/node/consumer/.eslintignore index b0a155e..7773828 100644 --- a/src/node/consumer/.eslintignore +++ b/src/node/consumer/.eslintignore @@ -1 +1 @@ -*.ts \ No newline at end of file +dist/ \ No newline at end of file diff --git a/src/node/consumer/.eslintrc b/src/node/consumer/.eslintrc index e0c8130..fbf723b 100644 --- a/src/node/consumer/.eslintrc +++ b/src/node/consumer/.eslintrc @@ -59,27 +59,13 @@ } ], "prefer-destructuring": "error", - "@typescript-eslint/consistent-type-assertions": "off", - "@typescript-eslint/explicit-function-return-type": "off" - }, - "overrides": [ - { - "files": [ - "*.ts", - "*.mts", - "*.cts", - "*.tsx" - ], - "rules": { - "@typescript-eslint/explicit-function-return-type": "error", - "@typescript-eslint/consistent-type-assertions": [ - "error", - { - "assertionStyle": "as", - "objectLiteralTypeAssertions": "never" - } - ] + "@typescript-eslint/explicit-function-return-type": "error", + "@typescript-eslint/consistent-type-assertions": [ + "error", + { + "assertionStyle": "as", + "objectLiteralTypeAssertions": "never" } - } - ] + ] + } } \ No newline at end of file diff --git a/src/node/consumer/.swcrc b/src/node/consumer/.swcrc new file mode 100644 index 0000000..eff14b3 --- /dev/null +++ b/src/node/consumer/.swcrc @@ -0,0 +1,15 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": false, + "decorators": true, + "dynamicImport": true + }, + "target": "es2020", + "baseUrl": "." + }, + "module": { + "type": "commonjs" + } +} \ No newline at end of file diff --git a/src/node/consumer/Dockerfile b/src/node/consumer/Dockerfile index c26b653..8914638 100644 --- a/src/node/consumer/Dockerfile +++ b/src/node/consumer/Dockerfile @@ -1,8 +1,11 @@ FROM node:lts-buster-slim as builder RUN apt-get update && \ - apt-get install -y git && \ - rm -rf /var/lib/apt/lists/* + apt-get upgrade -y && \ + apt-get install -y python3 make g++ && \ + rm -rf /var/lib/apt/lists/* + +RUN npm install -g npm@^8 && npm config set python /usr/bin/python3 WORKDIR /app diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js deleted file mode 100644 index 17393df..0000000 --- a/src/node/consumer/esbuild.js +++ /dev/null @@ -1,54 +0,0 @@ -import {build} from "esbuild"; -import {readFileSync, rmSync} from "fs"; - -const {devDependencies} = JSON.parse(readFileSync("./package.json", "utf8")); - -const start = Date.now(); - -try { - const outdir = "dist"; - - rmSync(outdir, {recursive: true, force: true}); - - build({ - bundle: true, - entryPoints: [ - "./src/main.ts", - ], - external: [...(devDependencies && Object.keys(devDependencies))], - keepNames: true, - minify: true, - outbase: "./src", - outdir, - outExtension: { - ".js": ".cjs", - }, - platform: "node", - plugins: [ - { - name: "populate-import-meta", - setup: ({onLoad}) => { - onLoad({filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`)}, args => { - const contents = readFileSync(args.path, "utf8"); - - const transformedContents = contents - .replace(/import\.meta/g, `{dirname:__dirname,filename:__filename}`) - .replace(/import\.meta\.filename/g, "__filename") - .replace(/import\.meta\.dirname/g, "__dirname"); - - return {contents: transformedContents, loader: "default"}; - }); - }, - } - ], - }).then(() => { - // biome-ignore lint/style/useTemplate: - // eslint-disable-next-line no-undef - console.log("⚡ " + "\x1b[32m" + `Done in ${Date.now() - start}ms`); - }); -} catch (e) { - // eslint-disable-next-line no-undef - console.log(e); - // eslint-disable-next-line no-undef - process.exit(1); -} \ No newline at end of file diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 88b7ff6..a7c3169 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "@tirke/node-cache-manager-mongodb": "^1.6.0", - "@types/webtorrent": "^0.109.7", "amqplib": "^0.10.3", "axios": "^1.6.1", "bottleneck": "^2.19.5", @@ -27,16 +26,17 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", - "user-agents": "^1.0.1444", + "utp-native": "^2.5.3", "webtorrent": "^2.1.35" }, "devDependencies": { + "@swc/cli": "^0.3.9", + "@swc/core": "^1.4.0", "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", - "@types/stremio-addon-sdk": "^1.6.10", - "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", + "@types/webtorrent": "^0.109.7", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "esbuild": "^0.20.0", @@ -518,6 +518,25 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@mole-inc/bin-wrapper": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz", + "integrity": "sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==", + "dev": true, + "dependencies": { + "bin-check": "^4.1.0", + "bin-version-check": "^5.0.0", + "content-disposition": "^0.5.4", + "ext-name": "^5.0.0", + "file-type": "^17.1.6", + "filenamify": "^5.0.2", + "got": "^11.8.5", + "os-filter-obj": "^2.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.4", "license": "MIT", @@ -573,6 +592,325 @@ "node": ">=10.0.0" } }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@swc/cli": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.3.9.tgz", + "integrity": "sha512-e5grxGEyNT0fYZEFmhSrRYL1kFAZAXlv+WjfQ35J6J9Hl0EtrMVymAEbGabetg2Q/2FX6HiRcjgc9LrdUCBk4A==", + "dev": true, + "dependencies": { + "@mole-inc/bin-wrapper": "^8.0.1", + "@swc/counter": "^0.1.3", + "commander": "^7.1.0", + "fast-glob": "^3.2.5", + "minimatch": "^9.0.3", + "piscina": "^4.3.0", + "semver": "^7.3.8", + "slash": "3.0.0", + "source-map": "^0.7.3" + }, + "bin": { + "spack": "bin/spack.js", + "swc": "bin/swc.js", + "swcx": "bin/swcx.js" + }, + "engines": { + "node": ">= 16.14.0" + }, + "peerDependencies": { + "@swc/core": "^1.2.66", + "chokidar": "^3.5.1" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@swc/cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@swc/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/cli/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@swc/cli/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.0.tgz", + "integrity": "sha512-wc5DMI5BJftnK0Fyx9SNJKkA0+BZSJQx8430yutWmsILkHMBD3Yd9GhlMaxasab9RhgKqZp7Ht30hUYO5ZDvQg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.4.0", + "@swc/core-darwin-x64": "1.4.0", + "@swc/core-linux-arm-gnueabihf": "1.4.0", + "@swc/core-linux-arm64-gnu": "1.4.0", + "@swc/core-linux-arm64-musl": "1.4.0", + "@swc/core-linux-x64-gnu": "1.4.0", + "@swc/core-linux-x64-musl": "1.4.0", + "@swc/core-win32-arm64-msvc": "1.4.0", + "@swc/core-win32-ia32-msvc": "1.4.0", + "@swc/core-win32-x64-msvc": "1.4.0" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.0.tgz", + "integrity": "sha512-UTJ/Vz+s7Pagef6HmufWt6Rs0aUu+EJF4Pzuwvr7JQQ5b1DZeAAUeUtkUTFx/PvCbM8Xfw4XdKBUZfrIKCfW8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.0.tgz", + "integrity": "sha512-f8v58u2GsGak8EtZFN9guXqE0Ep10Suny6xriaW2d8FGqESPyNrnBzli3aqkSeQk5gGqu2zJ7WiiKp3XoUOidA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.0.tgz", + "integrity": "sha512-q2KAkBzmPcTnRij/Y1fgHCKAGevUX/H4uUESrw1J5gmUg9Qip6onKV80lTumA1/aooGJ18LOsB31qdbwmZk9OA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.0.tgz", + "integrity": "sha512-SknGu96W0mzHtLHWm+62fk5+Omp9fMPFO7AWyGFmz2tr8EgRRXtTSrBUnWhAbgcalnhen48GsvtMdxf1KNputg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.0.tgz", + "integrity": "sha512-/k3TDvpBRMDNskHooNN1KqwUhcwkfBlIYxRTnJvsfT2C7My4pffR+4KXmt0IKynlTTbCdlU/4jgX4801FSuliw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.0.tgz", + "integrity": "sha512-GYsTMvNt5+WTVlwwQzOOWsPMw6P/F41u5PGHWmfev8Nd4QJ1h3rWPySKk4mV42IJwH9MgQCVSl3ygwNqwl6kFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.0.tgz", + "integrity": "sha512-jGVPdM/VwF7kK/uYRW5N6FwzKf/FnDjGIR3RPvQokjYJy7Auk+3Oj21C0Jev7sIT9RYnO/TrFEoEozKeD/z2Qw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.0.tgz", + "integrity": "sha512-biHYm1AronEKlt47O/H8sSOBM2BKXMmWT+ApvlxUw50m1RGNnVnE0bgY7tylFuuSiWyXsQPJbmUV708JqORXVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.0.tgz", + "integrity": "sha512-TL5L2tFQb19kJwv6+elToGBj74QXCn9j+hZfwQatvZEJRA5rDK16eH6oAE751dGUArhnWlW3Vj65hViPvTuycw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.0.tgz", + "integrity": "sha512-e2xVezU7XZ2Stzn4i7TOQe2Kn84oYdG0M3A7XI7oTdcpsKCcKwgiMoroiAhqCv+iN20KNqhnWwJiUiTj/qN5AA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@thaunknown/idb-chunk-store": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@thaunknown/idb-chunk-store/-/idb-chunk-store-1.0.2.tgz", @@ -652,6 +990,12 @@ "url": "https://github.com/sponsors/tirke" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true + }, "node_modules/@types/amqplib": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz", @@ -665,10 +1009,23 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/@types/bittorrent-protocol/-/bittorrent-protocol-3.1.6.tgz", "integrity": "sha512-hqiRctJX9t9kknr6nn0q7UlcWHKvw2gSnPc/4jxt7Q/T0RP9txNv27Djue9ZjCNlAJ+irqAnCxtb+TcSpMyhtA==", + "dev": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "license": "MIT", @@ -676,6 +1033,12 @@ "@types/ms": "*" } }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -687,10 +1050,20 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/magnet-uri": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", "integrity": "sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -715,6 +1088,7 @@ "version": "5.8.7", "resolved": "https://registry.npmjs.org/@types/parse-torrent/-/parse-torrent-5.8.7.tgz", "integrity": "sha512-vZtYe450hO+KL7B5fejM8CHWg1LPZKeVXlolphPsWf6n4H0ZUlI6ICbqHoaFmH7JQmU2yRbGgyvqqizdFuGPFQ==", + "dev": true, "dependencies": { "@types/magnet-uri": "*", "@types/node": "*", @@ -725,6 +1099,16 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/parse-torrent-file/-/parse-torrent-file-4.0.6.tgz", "integrity": "sha512-SxqVth0Iv0WuEkqWS5MaY4S4Tlyi+QHkElQREvsUPw2xHcPgKyQ2dkJRRv5vAxmLzH+tnMdOj1Nws/wsenbzUw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -739,19 +1123,6 @@ "version": "9.11.8", "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.8.tgz", "integrity": "sha512-rvqefdp2rvIA6wiomMgKWd2UZNPe6LM2EV5AuY3CPQJF+8TbdrL5TjYdMf0VAjGczzlkH4l1NjDkihwbj3Xodw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/stremio-addon-sdk": { - "version": "1.6.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/torrent-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/torrent-stream/-/torrent-stream-0.0.9.tgz", - "integrity": "sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -770,6 +1141,7 @@ "version": "0.109.7", "resolved": "https://registry.npmjs.org/@types/webtorrent/-/webtorrent-0.109.7.tgz", "integrity": "sha512-iDcZkXUMjWOtPpxAWXivs6rpYD++8w4vYJVqGJQKxZh1YxIXm5P3CyHGX735nJ6kFOFXLxD1O0ys/msI1nhRug==", + "dev": true, "dependencies": { "@types/bittorrent-protocol": "*", "@types/node": "*", @@ -1173,6 +1545,41 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/argparse": { "version": "2.0.1", "dev": true, @@ -1361,6 +1768,207 @@ "version": "1.1.1", "license": "MIT" }, + "node_modules/bin-check": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-4.1.0.tgz", + "integrity": "sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==", + "dev": true, + "dependencies": { + "execa": "^0.7.0", + "executable": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/bin-check/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-check/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/bin-check/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-check/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-check/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/bin-check/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, + "node_modules/bin-version": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-6.0.0.tgz", + "integrity": "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "find-versions": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bin-version-check": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.1.0.tgz", + "integrity": "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==", + "dev": true, + "dependencies": { + "bin-version": "^6.0.0", + "semver": "^7.5.3", + "semver-truncate": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bin-version-check/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/bin-version-check/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/bittorrent-lsd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bittorrent-lsd/-/bittorrent-lsd-2.0.0.tgz", @@ -1590,6 +2198,48 @@ "promise-coalesce": "^1.1.2" } }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/call-bind": { "version": "1.0.5", "dev": true, @@ -1660,6 +2310,46 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-dgram": { "version": "3.0.6", "funding": [ @@ -1726,6 +2416,18 @@ "node": ">=0.8" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -1758,6 +2460,15 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/compact2string": { "version": "1.4.1", "license": "BSD", @@ -1769,6 +2480,38 @@ "version": "0.0.1", "license": "MIT" }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/core-util-is": { "version": "1.0.3", "license": "MIT" @@ -1948,6 +2691,33 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -1971,6 +2741,15 @@ "node": ">= 10" } }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/define-data-property": { "version": "1.1.1", "dev": true, @@ -2529,6 +3308,43 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "dependencies": { + "mime-db": "^1.28.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "dependencies": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -2643,6 +3459,23 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-type": { + "version": "17.1.6", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", + "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", + "dev": true, + "dependencies": { + "readable-web-to-node-stream": "^3.0.2", + "strtok3": "^7.0.0-alpha.9", + "token-types": "^5.0.0-alpha.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/filename-reserved-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", @@ -2654,6 +3487,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/filenamify": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-5.1.1.tgz", + "integrity": "sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==", + "dev": true, + "dependencies": { + "filename-reserved-regex": "^3.0.0", + "strip-outer": "^2.0.0", + "trim-repeated": "^2.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2681,6 +3531,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "dev": true, + "dependencies": { + "semver-regex": "^4.0.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "dev": true, @@ -3016,6 +3881,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graphemer": { "version": "1.4.0", "dev": true, @@ -3118,11 +4008,30 @@ "entities": "^4.4.0" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, "node_modules/http-parser-js": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", "integrity": "sha512-u8u5ZaG0Tr/VvHlucK2ufMuOp4/5bvwgneXle+y228K5rMbJOlVjThONcaAw3ikAy8b2OO9RfEucdMHFz3UWMA==" }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3288,6 +4197,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "dev": true, @@ -3405,6 +4328,15 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.1.4", "dev": true, @@ -3682,6 +4614,15 @@ "dev": true, "license": "MIT" }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "10.2.0", "license": "ISC", @@ -3812,6 +4753,15 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "license": "ISC", @@ -3943,8 +4893,7 @@ "node_modules/napi-macros": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "optional": true + "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -3984,6 +4933,28 @@ "node": ">= 0.4.0" } }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -4040,13 +5011,35 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "optional": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -4189,6 +5182,36 @@ "node": ">= 0.8.0" } }, + "node_modules/os-filter-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz", + "integrity": "sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==", + "dev": true, + "dependencies": { + "arch": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "dev": true, @@ -4301,6 +5324,19 @@ "node": ">=8" } }, + "node_modules/peek-readable": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", + "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pg": { "version": "8.11.3", "license": "MIT", @@ -4403,6 +5439,15 @@ "resolved": "https://registry.npmjs.org/piece-length/-/piece-length-2.0.1.tgz", "integrity": "sha512-dBILiDmm43y0JPISWEmVGKBETQjwJe6mSU9GND+P9KW0SJGUwoU/odyH1nbalOP9i8WSYuqf1lQnaj92Bhw+Ug==" }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pino": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", @@ -4550,6 +5595,15 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, + "node_modules/piscina": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.3.1.tgz", + "integrity": "sha512-MBj0QYm3hJQ/C/wIXTN1OCYC8uQ4BBJ4LVele2P4ZwVQAH04vkk8E1SpDbuemLAL1dZorbuOob9rYqJeWCcCRg==", + "dev": true, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "license": "MIT", @@ -4613,6 +5667,12 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4677,6 +5737,18 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/random-iterate": { "version": "1.0.1", "license": "MIT" @@ -4732,6 +5804,79 @@ "string_decoder": "~0.10.x" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dev": true, + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readable-web-to-node-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -4789,6 +5934,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, "node_modules/resolve-from": { "version": "4.0.0", "dev": true, @@ -4806,6 +5957,18 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", "license": "MIT" @@ -4953,6 +6116,60 @@ "semver": "bin/semver.js" } }, + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-truncate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", + "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-truncate/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-truncate/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sequelize": { "version": "6.36.0", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", @@ -5187,6 +6404,39 @@ "atomic-sleep": "^1.0.0" } }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", + "dev": true, + "dependencies": { + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "license": "MIT", @@ -5295,6 +6545,15 @@ "node": ">=4" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -5314,6 +6573,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-2.0.0.tgz", + "integrity": "sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strtok3": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", + "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", + "dev": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -5372,8 +6660,7 @@ "node_modules/timeout-refresh": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-1.0.3.tgz", - "integrity": "sha512-Mz0CX4vBGM5lj8ttbIFt7o4ZMxk/9rgudJRh76EvB7xXZMur7T/cjRiH2w4Fmkq0zxf2QpM8IFvOSRn8FEu3gA==", - "optional": true + "integrity": "sha512-Mz0CX4vBGM5lj8ttbIFt7o4ZMxk/9rgudJRh76EvB7xXZMur7T/cjRiH2w4Fmkq0zxf2QpM8IFvOSRn8FEu3gA==" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -5387,10 +6674,51 @@ "node": ">=8.0" } }, + "node_modules/token-types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", + "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", + "dev": true, + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/toposort-class": { "version": "1.0.1", "license": "MIT" }, + "node_modules/trim-repeated": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-2.0.0.tgz", + "integrity": "sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-api-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", @@ -5973,8 +7301,7 @@ "node_modules/unordered-set": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unordered-set/-/unordered-set-2.0.1.tgz", - "integrity": "sha512-eUmNTPzdx+q/WvOHW0bgGYLWvWHNT3PTKEQLg0MAQhc0AHASHVHoP/9YytYd4RBVariqno/mEUhVZN98CmD7bg==", - "optional": true + "integrity": "sha512-eUmNTPzdx+q/WvOHW0bgGYLWvWHNT3PTKEQLg0MAQhc0AHASHVHoP/9YytYd4RBVariqno/mEUhVZN98CmD7bg==" }, "node_modules/uri-js": { "version": "4.4.1", @@ -5993,13 +7320,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/user-agents": { - "version": "1.1.104", - "license": "BSD-2-Clause", - "dependencies": { - "lodash.clonedeep": "^4.5.0" - } - }, "node_modules/ut_metadata": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/ut_metadata/-/ut_metadata-4.0.3.tgz", @@ -6123,15 +7443,13 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/utp-native": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/utp-native/-/utp-native-2.5.3.tgz", "integrity": "sha512-sWTrWYXPhhWJh+cS2baPzhaZc89zwlWCfwSthUjGhLkZztyPhcQllo+XVVCbNGi7dhyRlxkWxN4NKU6FbA9Y8w==", "hasInstallScript": true, - "optional": true, "dependencies": { "napi-macros": "^2.0.0", "node-gyp-build": "^4.2.0", @@ -6150,7 +7468,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6177,14 +7494,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true + ] }, "node_modules/utp-native/node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "optional": true, "dependencies": { "safe-buffer": "~5.2.0" } diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 3e515b1..1a04817 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -3,10 +3,14 @@ "version": "0.0.1", "type": "module", "scripts": { - "build": "node esbuild.js", - "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", - "start": "node dist/main.cjs", - "lint": "npx eslint ./src --ext .ts,.js" + "build": "swc src -d dist", + "watch-compile": "swc src -w --out-dir dist", + "watch-dev": "nodemon --watch \"dist/**/*\" -e js ./dist/main.js", + "dev": "concurrently \"npm run watch-compile\" \"npm run watch-dev\"", + "start": "node dist/main.js", + "clean": "rm -rf dist", + "lint": "eslint --ext .ts src", + "lint:fix": "eslint --ext .ts src --fix" }, "license": "MIT", "dependencies": { @@ -27,15 +31,19 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", + "utp-native": "^2.5.3", "webtorrent": "^2.1.35" }, "devDependencies": { + "@swc/cli": "^0.3.9", + "@swc/core": "^1.4.0", "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/validator": "^13.11.8", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", + "@types/webtorrent": "^0.109.7", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", diff --git a/src/node/consumer/src/lib/helpers/extension_helpers.ts b/src/node/consumer/src/lib/helpers/extension_helpers.ts index b74933b..f24b237 100644 --- a/src/node/consumer/src/lib/helpers/extension_helpers.ts +++ b/src/node/consumer/src/lib/helpers/extension_helpers.ts @@ -47,19 +47,19 @@ const DISK_EXTENSIONS = [ ]; export const ExtensionHelpers = { - isVideo(filename: string) { + isVideo(filename: string): boolean { return this.isExtension(filename, VIDEO_EXTENSIONS); }, - isSubtitle(filename: string) { + isSubtitle(filename: string): boolean { return this.isExtension(filename, SUBTITLE_EXTENSIONS); }, - isDisk(filename: string) { + isDisk(filename: string): boolean { return this.isExtension(filename, DISK_EXTENSIONS); }, - isExtension(filename: string, extensions: string[]) { + isExtension(filename: string, extensions: string[]): boolean { const extensionMatch = filename.match(/\.(\w{2,4})$/); return extensionMatch !== null && extensions.includes(extensionMatch[1].toLowerCase()); } diff --git a/src/node/consumer/src/lib/helpers/promises_helpers.ts b/src/node/consumer/src/lib/helpers/promises_helpers.ts index dacefb7..af38d2d 100644 --- a/src/node/consumer/src/lib/helpers/promises_helpers.ts +++ b/src/node/consumer/src/lib/helpers/promises_helpers.ts @@ -1,24 +1,25 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ export const PromiseHelpers = { - sequence: async function (promises: (() => Promise)[]) { + sequence: async function (promises: (() => Promise)[]): Promise { return promises.reduce((promise, func) => promise.then(result => func().then(res => result.concat(res))), Promise.resolve([])); }, - first: async function (promises) { - return Promise.all(promises.map(p => { - return p.then((val) => Promise.reject(val), (err) => Promise.resolve(err)); + first: async function (promises: any): Promise { + return Promise.all(promises.map((p: any) => { + return p.then((val: any) => Promise.reject(val), (err: any) => Promise.resolve(err)); })).then( (errors) => Promise.reject(errors), (val) => Promise.resolve(val) ); }, - delay: async function (duration: number) { + delay: async function (duration: number): Promise { return new Promise(resolve => setTimeout(() => resolve(), duration)); }, - timeout: async function (timeoutMs: number, promise, message = 'Timed out') { + timeout: async function (timeoutMs: number, promise: any, message = 'Timed out'): Promise { return Promise.race([ promise, new Promise(function (resolve, reject) { @@ -29,7 +30,8 @@ export const PromiseHelpers = { ]); }, - mostCommonValue: function (array) { + mostCommonValue: function (array: any[]): any { return array.sort((a, b) => array.filter(v => v === a).length - array.filter(v => v === b).length).pop(); } -}; \ No newline at end of file +}; +/* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/cache_service.ts b/src/node/consumer/src/lib/interfaces/cache_service.ts index 3a94858..9487547 100644 --- a/src/node/consumer/src/lib/interfaces/cache_service.ts +++ b/src/node/consumer/src/lib/interfaces/cache_service.ts @@ -1,8 +1,10 @@ import {CacheMethod} from "../services/cache_service"; +/* eslint-disable @typescript-eslint/no-explicit-any */ export interface ICacheService { cacheWrapImdbId: (key: string, method: CacheMethod) => Promise; cacheWrapKitsuId: (key: string, method: CacheMethod) => Promise; cacheWrapMetadata: (id: string, method: CacheMethod) => Promise; cacheTrackers: (method: CacheMethod) => Promise; -} \ No newline at end of file +} +/* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/logging_service.ts b/src/node/consumer/src/lib/interfaces/logging_service.ts index 06266ed..d980b22 100644 --- a/src/node/consumer/src/lib/interfaces/logging_service.ts +++ b/src/node/consumer/src/lib/interfaces/logging_service.ts @@ -1,9 +1,8 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ export interface ILoggingService { info(message: string, ...args: any[]): void; - error(message: string, ...args: any[]): void; - debug(message: string, ...args: any[]): void; - warn(message: string, ...args: any[]): void; -} \ No newline at end of file +} +/* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts index fcb9a61..71514b3 100644 --- a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts +++ b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts @@ -1,3 +1,5 @@ +import {IFileAttributes} from "../repository/interfaces/file_attributes"; + export interface IParseTorrentTitleResult { title?: string; date?: string; @@ -28,4 +30,7 @@ export interface IParseTorrentTitleResult { episode?: number; languages?: string; dubbed?: boolean; + videoFile?: IFileAttributes; + folderName?: string; + fileName?: string; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts index f61cfeb..26ec81d 100644 --- a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts +++ b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts @@ -1,5 +1,5 @@ -import {IParseTorrentTitleResult} from "./parse_torrent_title_result"; import {TorrentType} from "../enums/torrent_types"; +import {IParseTorrentTitleResult} from "./parse_torrent_title_result"; import {ITorrentFileCollection} from "./torrent_file_collection"; export interface IParsedTorrent extends IParseTorrentTitleResult { @@ -9,7 +9,7 @@ export interface IParsedTorrent extends IParseTorrentTitleResult { kitsuId?: number; trackers?: string; provider?: string | null; - infoHash: string | null; + infoHash: string; type: string | TorrentType; uploadDate?: Date; seeders?: number; diff --git a/src/node/consumer/src/interfaces/process_torrents_job.ts b/src/node/consumer/src/lib/interfaces/process_torrents_job.ts similarity index 100% rename from src/node/consumer/src/interfaces/process_torrents_job.ts rename to src/node/consumer/src/lib/interfaces/process_torrents_job.ts diff --git a/src/node/consumer/src/lib/interfaces/season_episode_map.ts b/src/node/consumer/src/lib/interfaces/season_episode_map.ts new file mode 100644 index 0000000..55bb2f7 --- /dev/null +++ b/src/node/consumer/src/lib/interfaces/season_episode_map.ts @@ -0,0 +1,7 @@ +import {ICommonVideoMetadata} from "./common_video_metadata"; + +export interface ISeasonEpisodeMap { + [season: number]: { + [episode: number]: ICommonVideoMetadata; + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts index 4d4696d..a92ba1c 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts @@ -1,18 +1,18 @@ +import {ITorrentAttributes} from "../repository/interfaces/torrent_attributes"; +import {SkipTorrent} from "../repository/models/skipTorrent"; +import {Torrent} from "../repository/models/torrent"; import {IParsedTorrent} from "./parsed_torrent"; -import {Torrent} from "../../repository/models/torrent"; -import {ITorrentAttributes} from "../../repository/interfaces/torrent_attributes"; -import {SkipTorrent} from "../../repository/models/skipTorrent"; export interface ITorrentEntriesService { - createTorrentEntry(torrent: IParsedTorrent, overwrite): Promise; + createTorrentEntry(torrent: IParsedTorrent, overwrite: boolean): Promise; - createSkipTorrentEntry(torrent: Torrent): Promise<[SkipTorrent, boolean]>; + createSkipTorrentEntry(torrent: Torrent): Promise<[SkipTorrent, boolean | null]>; - getStoredTorrentEntry(torrent: Torrent): Promise; + getStoredTorrentEntry(torrent: Torrent): Promise; checkAndUpdateTorrent(torrent: IParsedTorrent): Promise; createTorrentContents(torrent: Torrent): Promise; - updateTorrentSeeders(torrent: ITorrentAttributes): Promise<[number] | ITorrentAttributes>; + updateTorrentSeeders(torrent: ITorrentAttributes): Promise<[number] | undefined>; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts index 5b9f824..3306a44 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts @@ -1,6 +1,6 @@ -import {IContentAttributes} from "../../repository/interfaces/content_attributes"; -import {IFileAttributes} from "../../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; +import {IContentAttributes} from "../repository/interfaces/content_attributes"; +import {IFileAttributes} from "../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; export interface ITorrentFileCollection { contents?: IContentAttributes[]; diff --git a/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts index f4a1db7..e3aa901 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts @@ -1,4 +1,4 @@ -import {IIngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; +import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; export interface ITorrentProcessingService { processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise; diff --git a/src/node/consumer/src/jobs/process_torrents_job.ts b/src/node/consumer/src/lib/jobs/process_torrents_job.ts similarity index 72% rename from src/node/consumer/src/jobs/process_torrents_job.ts rename to src/node/consumer/src/lib/jobs/process_torrents_job.ts index 4fed81f..9ba5aef 100644 --- a/src/node/consumer/src/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/lib/jobs/process_torrents_job.ts @@ -1,12 +1,12 @@ import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' -import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "../lib/interfaces/ingested_rabbit_message"; -import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; -import {configurationService} from '../lib/services/configuration_service'; import {inject, injectable} from "inversify"; -import {IocTypes} from "../lib/models/ioc_types"; -import {ITorrentProcessingService} from "../lib/interfaces/torrent_processing_service"; -import {ILoggingService} from "../lib/interfaces/logging_service"; +import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "../interfaces/ingested_rabbit_message"; +import {ILoggingService} from "../interfaces/logging_service"; import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; +import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; +import {IocTypes} from "../models/ioc_types"; +import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; +import {configurationService} from '../services/configuration_service'; @injectable() export class ProcessTorrentsJob implements IProcessTorrentsJob { @@ -21,7 +21,7 @@ export class ProcessTorrentsJob implements IProcessTorrentsJob { this.logger = logger; } - public listenToQueue = async () => { + public listenToQueue = async (): Promise => { if (!configurationService.jobConfig.JOBS_ENABLED) { return; } @@ -34,26 +34,27 @@ export class ProcessTorrentsJob implements IProcessTorrentsJob { this.logger.error('Failed to connect and setup channel', error); } } - private processMessage = (msg: ConsumeMessage) => { + + private processMessage = (msg: ConsumeMessage | null): Promise => { const ingestedTorrent: IIngestedTorrentAttributes = this.getMessageAsJson(msg); return this.torrentProcessingService.processTorrentRecord(ingestedTorrent); }; - private getMessageAsJson = (msg: ConsumeMessage): IIngestedTorrentAttributes => { + + private getMessageAsJson = (msg: ConsumeMessage | null): IIngestedTorrentAttributes => { const content = msg?.content.toString('utf8') ?? "{}"; const receivedObject: IIngestedRabbitMessage = JSON.parse(content); const receivedTorrent: IIngestedRabbitTorrent = receivedObject.message; return {...receivedTorrent, info_hash: receivedTorrent.infoHash}; }; - private assertAndConsumeQueue = async (channel: Channel) => { + + private assertAndConsumeQueue = async (channel: Channel): Promise => { this.logger.info('Worker is running! Waiting for new torrents...'); - const ackMsg = async (msg: ConsumeMessage) => { - try { - await this.processMessage(msg); - channel.ack(msg); - } catch (error) { - this.logger.error('Failed processing torrent', error); - } + const ackMsg = async (msg: ConsumeMessage | null): Promise => { + await this.processMessage(msg) + .then(() => this.logger.info('Processed torrent')) + .then(() => msg && channel.ack(msg)) + .catch((error) => this.logger.error('Failed to process torrent', error)); } try { diff --git a/src/node/consumer/src/lib/models/composition_root.ts b/src/node/consumer/src/lib/models/composition_root.ts index e52e2f0..2b8dbf0 100644 --- a/src/node/consumer/src/lib/models/composition_root.ts +++ b/src/node/consumer/src/lib/models/composition_root.ts @@ -1,8 +1,8 @@ import {inject, injectable} from "inversify"; -import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; -import {ITrackerService} from "../interfaces/tracker_service"; -import {IProcessTorrentsJob} from "../../interfaces/process_torrents_job"; import {ICompositionalRoot} from "../interfaces/composition_root"; +import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; +import {ITrackerService} from "../interfaces/tracker_service"; +import {IDatabaseRepository} from "../repository/interfaces/database_repository"; import {IocTypes} from "./ioc_types"; @injectable() @@ -19,7 +19,7 @@ export class CompositionalRoot implements ICompositionalRoot { this.processTorrentsJob = processTorrentsJob; } - start = async () => { + start = async (): Promise => { await this.trackerService.getTrackers(); await this.databaseRepository.connect(); await this.processTorrentsJob.listenToQueue(); diff --git a/src/node/consumer/src/lib/models/configuration/cache_config.ts b/src/node/consumer/src/lib/models/configuration/cache_config.ts index 0e2c927..1cba364 100644 --- a/src/node/consumer/src/lib/models/configuration/cache_config.ts +++ b/src/node/consumer/src/lib/models/configuration/cache_config.ts @@ -9,7 +9,7 @@ export const cacheConfig = { NO_CACHE: BooleanHelpers.parseBool(process.env.NO_CACHE, false), COLLECTION_NAME: process.env.MONGODB_COLLECTION || 'knightcrawler_consumer_collection', - get MONGO_URI() { + get MONGO_URI(): string { return `mongodb://${this.MONGO_INITDB_ROOT_USERNAME}:${this.MONGO_INITDB_ROOT_PASSWORD}@${this.MONGODB_HOST}:${this.MONGODB_PORT}/${this.MONGODB_DB}?authSource=admin`; } }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts index 8e5dccd..bcefcd6 100644 --- a/src/node/consumer/src/lib/models/configuration/database_config.ts +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -8,7 +8,7 @@ export const databaseConfig = { POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD || 'postgres', AUTO_CREATE_AND_APPLY_MIGRATIONS: BooleanHelpers.parseBool(process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS, false), - get POSTGRES_URI() { + get POSTGRES_URI(): string { return `postgres://${this.POSTGRES_USER}:${this.POSTGRES_PASSWORD}@${this.POSTGRES_HOST}:${this.POSTGRES_PORT}/${this.POSTGRES_DB}`; } }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/configuration/torrent_config.ts b/src/node/consumer/src/lib/models/configuration/torrent_config.ts index 543f277..683a49a 100644 --- a/src/node/consumer/src/lib/models/configuration/torrent_config.ts +++ b/src/node/consumer/src/lib/models/configuration/torrent_config.ts @@ -1,5 +1,5 @@ export const torrentConfig = { - MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_SINGLE_TORRENT_CONNECTIONS || "20", 10), + MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_CONNECTIONS_PER_TORRENT || "20", 10), MAX_CONNECTIONS_OVERALL: parseInt(process.env.MAX_CONNECTIONS_OVERALL || "100", 10), TIMEOUT: parseInt(process.env.TORRENT_TIMEOUT || "30000", 10) }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/lib/models/inversify_config.ts index 17cd120..17da92b 100644 --- a/src/node/consumer/src/lib/models/inversify_config.ts +++ b/src/node/consumer/src/lib/models/inversify_config.ts @@ -1,30 +1,29 @@ -import "reflect-metadata"; // required import {Container} from "inversify"; -import {IocTypes} from "./ioc_types"; import {ICacheService} from "../interfaces/cache_service"; +import {ICompositionalRoot} from "../interfaces/composition_root"; import {ILoggingService} from "../interfaces/logging_service"; import {IMetadataService} from "../interfaces/metadata_service"; +import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; import {ITorrentFileService} from "../interfaces/torrent_file_service"; import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; import {ITrackerService} from "../interfaces/tracker_service"; -import {IProcessTorrentsJob} from "../../interfaces/process_torrents_job"; -import {ICompositionalRoot} from "../interfaces/composition_root"; -import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; -import {CompositionalRoot} from "./composition_root"; +import {ProcessTorrentsJob} from "../jobs/process_torrents_job"; +import {DatabaseRepository} from "../repository/database_repository"; +import {IDatabaseRepository} from "../repository/interfaces/database_repository"; import {CacheService} from "../services/cache_service"; import {LoggingService} from "../services/logging_service"; import {MetadataService} from "../services/metadata_service"; import {TorrentDownloadService} from "../services/torrent_download_service"; import {TorrentEntriesService} from "../services/torrent_entries_service"; -import {TorrentProcessingService} from "../services/torrent_processing_service"; import {TorrentFileService} from "../services/torrent_file_service"; +import {TorrentProcessingService} from "../services/torrent_processing_service"; import {TorrentSubtitleService} from "../services/torrent_subtitle_service"; import {TrackerService} from "../services/tracker_service"; -import {DatabaseRepository} from "../../repository/database_repository"; -import {ProcessTorrentsJob} from "../../jobs/process_torrents_job"; +import {CompositionalRoot} from "./composition_root"; +import {IocTypes} from "./ioc_types"; const serviceContainer = new Container(); diff --git a/src/node/consumer/src/repository/database_repository.ts b/src/node/consumer/src/lib/repository/database_repository.ts similarity index 84% rename from src/node/consumer/src/repository/database_repository.ts rename to src/node/consumer/src/lib/repository/database_repository.ts index 2d1dfff..c59f778 100644 --- a/src/node/consumer/src/repository/database_repository.ts +++ b/src/node/consumer/src/lib/repository/database_repository.ts @@ -1,24 +1,24 @@ +import {inject, injectable} from "inversify"; import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; import {Model, Sequelize} from 'sequelize-typescript'; -import {configurationService} from '../lib/services/configuration_service'; -import {PromiseHelpers} from '../lib/helpers/promises_helpers'; -import {Provider} from "./models/provider"; -import {File} from "./models/file"; -import {Torrent} from "./models/torrent"; -import {IngestedTorrent} from "./models/ingestedTorrent"; -import {Subtitle} from "./models/subtitle"; -import {Content} from "./models/content"; -import {SkipTorrent} from "./models/skipTorrent"; -import {IFileAttributes, IFileCreationAttributes} from "./interfaces/file_attributes"; -import {ITorrentAttributes, ITorrentCreationAttributes} from "./interfaces/torrent_attributes"; -import {IngestedPage} from "./models/ingestedPage"; -import {ILoggingService} from "../lib/interfaces/logging_service"; -import {IocTypes} from "../lib/models/ioc_types"; -import {inject, injectable} from "inversify"; -import {IDatabaseRepository} from "./interfaces/database_repository"; +import {PromiseHelpers} from '../helpers/promises_helpers'; +import {ILoggingService} from "../interfaces/logging_service"; +import {IocTypes} from "../models/ioc_types"; +import {configurationService} from '../services/configuration_service'; import {IContentCreationAttributes} from "./interfaces/content_attributes"; -import {ISubtitleCreationAttributes} from "./interfaces/subtitle_attributes"; +import {IDatabaseRepository} from "./interfaces/database_repository"; +import {IFileAttributes, IFileCreationAttributes} from "./interfaces/file_attributes"; +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "./interfaces/subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "./interfaces/torrent_attributes"; +import {Content} from "./models/content"; +import {File} from "./models/file"; +import {IngestedPage} from "./models/ingestedPage"; +import {IngestedTorrent} from "./models/ingestedTorrent"; +import {Provider} from "./models/provider"; +import {SkipTorrent} from "./models/skipTorrent"; +import {Subtitle} from "./models/subtitle"; +import {Torrent} from "./models/torrent"; @injectable() export class DatabaseRepository implements IDatabaseRepository { @@ -33,6 +33,7 @@ export class DatabaseRepository implements IDatabaseRepository { SkipTorrent, IngestedTorrent, IngestedPage]; + private logger: ILoggingService; constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { @@ -40,7 +41,7 @@ export class DatabaseRepository implements IDatabaseRepository { this.database = this.createDatabase(); } - public connect = async () => { + public connect = async (): Promise => { try { await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); } catch (error) { @@ -50,7 +51,7 @@ export class DatabaseRepository implements IDatabaseRepository { } }; - public getProvider = async (provider: Provider) => { + public getProvider = async (provider: Provider): Promise => { try { const [result] = await Provider.findOrCreate({where: {name: {[Op.eq]: provider.name}}, defaults: provider}); return result; @@ -121,7 +122,7 @@ export class DatabaseRepository implements IDatabaseRepository { await this.createSubtitles(torrent.infoHash, torrent.subtitles); } catch (error) { this.logger.error(`Failed to create torrent: ${torrent.infoHash}`); - this.logger.debug(error); + this.logger.debug("Error: ", error); } }; @@ -145,13 +146,13 @@ export class DatabaseRepository implements IDatabaseRepository { if (operatingFile.dataValues) { await operatingFile.save(); } else { - await File.upsert(operatingFile); + await File.upsert(file); } - await this.upsertSubtitles(operatingFile, operatingFile.subtitles); + await this.upsertSubtitles(operatingFile, file.subtitles); } else { if (operatingFile.subtitles && operatingFile.subtitles.length) { operatingFile.subtitles = operatingFile.subtitles.map(subtitle => { - subtitle.title = subtitle.path; + subtitle.title = subtitle.path || ''; return subtitle; }); } @@ -159,7 +160,7 @@ export class DatabaseRepository implements IDatabaseRepository { } } catch (error) { this.logger.error(`Failed to create file: ${file.infoHash}`); - this.logger.debug(error); + this.logger.debug("Error: ", error); } }; @@ -169,25 +170,26 @@ export class DatabaseRepository implements IDatabaseRepository { public deleteFile = async (id: number): Promise => File.destroy({where: {id: id}}); - public createSubtitles = async (infoHash: string, subtitles: ISubtitleCreationAttributes[]): Promise[]> => { + public createSubtitles = async (infoHash: string, subtitles: ISubtitleCreationAttributes[] | undefined): Promise[]> => { if (subtitles && subtitles.length) { - return Subtitle.bulkCreate(subtitles.map(subtitle => ({infoHash, title: subtitle.path, ...subtitle}))); + return Subtitle.bulkCreate(subtitles.map(subtitle => ({...subtitle, infoHash: infoHash, title: subtitle.path}))); } return Promise.resolve(); }; - public upsertSubtitles = async (file: File, subtitles: Subtitle[]): Promise => { + public upsertSubtitles = async (file: File, subtitles: ISubtitleCreationAttributes[] | undefined): Promise => { if (file.id && subtitles && subtitles.length) { await PromiseHelpers.sequence(subtitles .map(subtitle => { subtitle.fileId = file.id; subtitle.infoHash = subtitle.infoHash || file.infoHash; - subtitle.title = subtitle.title || subtitle.path; + subtitle.title = subtitle.title || subtitle.path || ''; return subtitle; }) .map(subtitle => async () => { - if (subtitle.dataValues) { - await subtitle.save(); + const operatingInstance = Subtitle.build(subtitle); + if (operatingInstance.dataValues) { + await operatingInstance.save(); } else { await Subtitle.create(subtitle); } @@ -199,9 +201,9 @@ export class DatabaseRepository implements IDatabaseRepository { public getUnassignedSubtitles = async (): Promise => Subtitle.findAll({where: {fileId: null}}); - public createContents = async (infoHash: string, contents: IContentCreationAttributes[]): Promise => { + public createContents = async (infoHash: string, contents: IContentCreationAttributes[] | undefined): Promise => { if (contents && contents.length) { - await Content.bulkCreate(contents.map(content => ({infoHash, ...content})), {ignoreDuplicates: true}); + await Content.bulkCreate(contents.map(content => ({...content, infoHash})), {ignoreDuplicates: true}); await Torrent.update({opened: true}, {where: {infoHash: infoHash}, silent: true}); } }; @@ -216,7 +218,7 @@ export class DatabaseRepository implements IDatabaseRepository { return result.dataValues as SkipTorrent; }; - public createSkipTorrent = async (torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); + public createSkipTorrent = async (torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); private createDatabase = (): Sequelize => { const newDatabase = new Sequelize( diff --git a/src/node/consumer/src/repository/interfaces/content_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/content_attributes.ts similarity index 100% rename from src/node/consumer/src/repository/interfaces/content_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/content_attributes.ts diff --git a/src/node/consumer/src/repository/interfaces/database_repository.ts b/src/node/consumer/src/lib/repository/interfaces/database_repository.ts similarity index 81% rename from src/node/consumer/src/repository/interfaces/database_repository.ts rename to src/node/consumer/src/lib/repository/interfaces/database_repository.ts index a0d1d43..9331853 100644 --- a/src/node/consumer/src/repository/interfaces/database_repository.ts +++ b/src/node/consumer/src/lib/repository/interfaces/database_repository.ts @@ -1,15 +1,15 @@ -import {Provider} from "../models/provider"; import {WhereOptions} from "sequelize"; -import {ITorrentAttributes, ITorrentCreationAttributes} from "./torrent_attributes"; -import {Torrent} from "../models/torrent"; -import {IFileAttributes, IFileCreationAttributes} from "./file_attributes"; -import {File} from "../models/file"; -import {Subtitle} from "../models/subtitle"; import {Model} from "sequelize-typescript"; import {Content} from "../models/content"; +import {File} from "../models/file"; +import {Provider} from "../models/provider"; import {SkipTorrent} from "../models/skipTorrent"; -import {ISubtitleCreationAttributes} from "./subtitle_attributes"; +import {Subtitle} from "../models/subtitle"; +import {Torrent} from "../models/torrent"; import {IContentCreationAttributes} from "./content_attributes"; +import {IFileAttributes, IFileCreationAttributes} from "./file_attributes"; +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "./subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "./torrent_attributes"; export interface IDatabaseRepository { connect(): Promise; @@ -26,9 +26,9 @@ export interface IDatabaseRepository { getTorrentsWithoutSize(): Promise; - getUpdateSeedersTorrents(limit): Promise; + getUpdateSeedersTorrents(limit: number): Promise; - getUpdateSeedersNewTorrents(limit): Promise; + getUpdateSeedersNewTorrents(limit: number): Promise; getNoContentsTorrents(): Promise; @@ -46,9 +46,9 @@ export interface IDatabaseRepository { deleteFile(id: number): Promise; - createSubtitles(infoHash: string, subtitles: ISubtitleCreationAttributes[]): Promise[]>; + createSubtitles(infoHash: string, subtitles: ISubtitleCreationAttributes[]): Promise[]>; - upsertSubtitles(file: File, subtitles: Subtitle[]): Promise; + upsertSubtitles(file: File, subtitles: ISubtitleCreationAttributes[] | undefined): Promise; getSubtitles(infoHash: string): Promise; @@ -60,5 +60,5 @@ export interface IDatabaseRepository { getSkipTorrent(infoHash: string): Promise; - createSkipTorrent(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean]>; + createSkipTorrent(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]>; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/interfaces/file_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts similarity index 84% rename from src/node/consumer/src/repository/interfaces/file_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/file_attributes.ts index da75405..25f025c 100644 --- a/src/node/consumer/src/repository/interfaces/file_attributes.ts +++ b/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts @@ -1,12 +1,12 @@ import {Optional} from "sequelize"; +import {IParseTorrentTitleResult} from "../../interfaces/parse_torrent_title_result"; import {ISubtitleAttributes} from "./subtitle_attributes"; -import {IParseTorrentTitleResult} from "../../lib/interfaces/parse_torrent_title_result"; export interface IFileAttributes extends IParseTorrentTitleResult { id?: number; infoHash?: string; fileIndex?: number; - title?: string; + title: string; size?: number; imdbId?: string; imdbSeason?: number; diff --git a/src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/ingested_page_attributes.ts similarity index 100% rename from src/node/consumer/src/repository/interfaces/ingested_page_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/ingested_page_attributes.ts diff --git a/src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/ingested_torrent_attributes.ts similarity index 100% rename from src/node/consumer/src/repository/interfaces/ingested_torrent_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/ingested_torrent_attributes.ts diff --git a/src/node/consumer/src/repository/interfaces/provider_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/provider_attributes.ts similarity index 100% rename from src/node/consumer/src/repository/interfaces/provider_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/provider_attributes.ts diff --git a/src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/skip_torrent_attributes.ts similarity index 100% rename from src/node/consumer/src/repository/interfaces/skip_torrent_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/skip_torrent_attributes.ts diff --git a/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/subtitle_attributes.ts similarity index 90% rename from src/node/consumer/src/repository/interfaces/subtitle_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/subtitle_attributes.ts index ce0ecb9..bef6538 100644 --- a/src/node/consumer/src/repository/interfaces/subtitle_attributes.ts +++ b/src/node/consumer/src/lib/repository/interfaces/subtitle_attributes.ts @@ -3,7 +3,7 @@ import {Optional} from "sequelize"; export interface ISubtitleAttributes { infoHash: string; fileIndex: number; - fileId?: number; + fileId?: number | null; title: string; path: string; } diff --git a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts similarity index 96% rename from src/node/consumer/src/repository/interfaces/torrent_attributes.ts rename to src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts index 3dfba91..64e4696 100644 --- a/src/node/consumer/src/repository/interfaces/torrent_attributes.ts +++ b/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts @@ -1,11 +1,11 @@ import {Optional} from "sequelize"; import {IContentAttributes} from "./content_attributes"; -import {ISubtitleAttributes} from "./subtitle_attributes"; import {IFileAttributes} from "./file_attributes"; +import {ISubtitleAttributes} from "./subtitle_attributes"; export interface ITorrentAttributes { infoHash: string; - provider?: string; + provider?: string | null; torrentId?: string; title?: string; size?: number; diff --git a/src/node/consumer/src/repository/models/content.ts b/src/node/consumer/src/lib/repository/models/content.ts similarity index 97% rename from src/node/consumer/src/repository/models/content.ts rename to src/node/consumer/src/lib/repository/models/content.ts index 6a697ee..0209273 100644 --- a/src/node/consumer/src/repository/models/content.ts +++ b/src/node/consumer/src/lib/repository/models/content.ts @@ -18,5 +18,5 @@ export class Content extends Model Torrent, {constraints: false, foreignKey: 'infoHash'}) - torrent: Torrent; + torrent?: Torrent; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/file.ts b/src/node/consumer/src/lib/repository/models/file.ts similarity index 98% rename from src/node/consumer/src/repository/models/file.ts rename to src/node/consumer/src/lib/repository/models/file.ts index 94a0b0a..a9785c8 100644 --- a/src/node/consumer/src/repository/models/file.ts +++ b/src/node/consumer/src/lib/repository/models/file.ts @@ -1,7 +1,7 @@ import {BelongsTo, Column, DataType, ForeignKey, HasMany, Model, Table} from 'sequelize-typescript'; import {IFileAttributes, IFileCreationAttributes} from "../interfaces/file_attributes"; -import {Torrent} from "./torrent"; import {Subtitle} from "./subtitle"; +import {Torrent} from "./torrent"; const indexes = [ { @@ -55,5 +55,5 @@ export class File extends Model { declare subtitles?: Subtitle[]; @BelongsTo(() => Torrent, {constraints: false, foreignKey: 'infoHash'}) - torrent: Torrent; + torrent?: Torrent; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/ingestedPage.ts b/src/node/consumer/src/lib/repository/models/ingestedPage.ts similarity index 100% rename from src/node/consumer/src/repository/models/ingestedPage.ts rename to src/node/consumer/src/lib/repository/models/ingestedPage.ts diff --git a/src/node/consumer/src/repository/models/ingestedTorrent.ts b/src/node/consumer/src/lib/repository/models/ingestedTorrent.ts similarity index 100% rename from src/node/consumer/src/repository/models/ingestedTorrent.ts rename to src/node/consumer/src/lib/repository/models/ingestedTorrent.ts diff --git a/src/node/consumer/src/repository/models/provider.ts b/src/node/consumer/src/lib/repository/models/provider.ts similarity index 100% rename from src/node/consumer/src/repository/models/provider.ts rename to src/node/consumer/src/lib/repository/models/provider.ts diff --git a/src/node/consumer/src/repository/models/skipTorrent.ts b/src/node/consumer/src/lib/repository/models/skipTorrent.ts similarity index 100% rename from src/node/consumer/src/repository/models/skipTorrent.ts rename to src/node/consumer/src/lib/repository/models/skipTorrent.ts diff --git a/src/node/consumer/src/repository/models/subtitle.ts b/src/node/consumer/src/lib/repository/models/subtitle.ts similarity index 96% rename from src/node/consumer/src/repository/models/subtitle.ts rename to src/node/consumer/src/lib/repository/models/subtitle.ts index f8ffa1e..06fb142 100644 --- a/src/node/consumer/src/repository/models/subtitle.ts +++ b/src/node/consumer/src/lib/repository/models/subtitle.ts @@ -32,7 +32,7 @@ export class Subtitle extends Model File, {constraints: false, foreignKey: 'fileId'}) - file: File; + file?: File; - path: string; + path?: string; } \ No newline at end of file diff --git a/src/node/consumer/src/repository/models/torrent.ts b/src/node/consumer/src/lib/repository/models/torrent.ts similarity index 100% rename from src/node/consumer/src/repository/models/torrent.ts rename to src/node/consumer/src/lib/repository/models/torrent.ts diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 1afae05..ab3b0a5 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,12 +1,12 @@ -import {Cache, createCache, MemoryCache, memoryStore, Store} from 'cache-manager'; import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' -import {configurationService} from './configuration_service'; +import {Cache, createCache, MemoryCache, memoryStore} from 'cache-manager'; +import {inject, injectable} from "inversify"; import {CacheType} from "../enums/cache_types"; import {ICacheOptions} from "../interfaces/cache_options"; import {ICacheService} from "../interfaces/cache_service"; -import {inject, injectable} from "inversify"; -import {IocTypes} from "../models/ioc_types"; import {ILoggingService} from "../interfaces/logging_service"; +import {IocTypes} from "../models/ioc_types"; +import {configurationService} from './configuration_service'; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; @@ -18,13 +18,14 @@ const GLOBAL_TTL: number = Number(process.env.METADATA_TTL) || 7 * 24 * 60 * 60; const MEMORY_TTL: number = Number(process.env.METADATA_TTL) || 2 * 60 * 60; // 2 hours const TRACKERS_TTL: number = 2 * 24 * 60 * 60; // 2 days +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ export type CacheMethod = () => any; @injectable() export class CacheService implements ICacheService { private logger: ILoggingService; - private readonly memoryCache: MemoryCache; - private readonly remoteCache: Cache | MemoryCache; + private readonly memoryCache: MemoryCache | undefined; + private readonly remoteCache: Cache | MemoryCache | undefined; constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { this.logger = logger; @@ -37,24 +38,24 @@ export class CacheService implements ICacheService { this.remoteCache = this.initiateRemoteCache(); } - public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => + public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); - public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => + public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); - public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => + public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, {ttl: MEMORY_TTL}); - public cacheTrackers = (method: CacheMethod): Promise => + public cacheTrackers = (method: CacheMethod): Promise => this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, {ttl: TRACKERS_TTL}); - private initiateMemoryCache = () => + private initiateMemoryCache = (): MemoryCache => createCache(memoryStore(), { ttl: MEMORY_TTL }); - private initiateMongoCache = () => { + private initiateMongoCache = (): Cache => { const store = mongoDbStore({ collectionName: configurationService.cacheConfig.COLLECTION_NAME, ttl: GLOBAL_TTL, @@ -70,28 +71,28 @@ export class CacheService implements ICacheService { }); } - private initiateRemoteCache = (): Cache => { + private initiateRemoteCache = (): Cache | undefined => { if (configurationService.cacheConfig.NO_CACHE) { this.logger.debug('Cache is disabled'); - return null; + return undefined; } return configurationService.cacheConfig.MONGO_URI ? this.initiateMongoCache() : this.initiateMemoryCache(); } - private getCacheType = (cacheType: CacheType): MemoryCache | Cache => { + private getCacheType = (cacheType: CacheType): MemoryCache | Cache | undefined => { switch (cacheType) { case CacheType.Memory: return this.memoryCache; case CacheType.MongoDb: return this.remoteCache; default: - return null; + return undefined; } } private cacheWrap = async ( - cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { + cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { const cache = this.getCacheType(cacheType); if (configurationService.cacheConfig.NO_CACHE || !cache) { diff --git a/src/node/consumer/src/lib/services/configuration_service.ts b/src/node/consumer/src/lib/services/configuration_service.ts index 32b56ca..8955dc9 100644 --- a/src/node/consumer/src/lib/services/configuration_service.ts +++ b/src/node/consumer/src/lib/services/configuration_service.ts @@ -1,10 +1,10 @@ -import {rabbitConfig} from "../models/configuration/rabbit_config"; -import {cacheConfig} from "../models/configuration/cache_config"; +import {cacheConfig} from "../models/configuration/cache_config"; import {databaseConfig} from "../models/configuration/database_config"; import {jobConfig} from "../models/configuration/job_config"; import {metadataConfig} from "../models/configuration/metadata_config"; -import {trackerConfig} from "../models/configuration/tracker_config"; +import {rabbitConfig} from "../models/configuration/rabbit_config"; import {torrentConfig} from "../models/configuration/torrent_config"; +import {trackerConfig} from "../models/configuration/tracker_config"; export const configurationService = { rabbitConfig: rabbitConfig, diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index ddc4dee..ee703ba 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -1,7 +1,8 @@ +import {injectable} from "inversify"; import {Logger, pino} from "pino"; import {ILoggingService} from "../interfaces/logging_service"; -import {injectable} from "inversify"; +/* eslint-disable @typescript-eslint/no-explicit-any */ @injectable() export class LoggingService implements ILoggingService { private readonly logger: Logger; @@ -27,4 +28,5 @@ export class LoggingService implements ILoggingService { public warn = (message: string, ...args: any[]): void => { this.logger.warn(message, args); }; -} \ No newline at end of file +} +/* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index f684d8d..1015fb1 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -1,17 +1,20 @@ + import axios, {AxiosResponse} from 'axios'; import {ResultTypes, search} from 'google-sr'; +import {inject, injectable} from "inversify"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error import nameToImdb from 'name-to-imdb'; import {TorrentType} from '../enums/torrent_types'; -import {IMetadataResponse} from "../interfaces/metadata_response"; +import {ICacheService} from "../interfaces/cache_service"; import {ICinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; +import {IKitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; import {IKitsuJsonResponse} from "../interfaces/kitsu_metadata"; import {IMetaDataQuery} from "../interfaces/metadata_query"; -import {IKitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; +import {IMetadataResponse} from "../interfaces/metadata_response"; import {IMetadataService} from "../interfaces/metadata_service"; -import {inject, injectable} from "inversify"; import {IocTypes} from "../models/ioc_types"; -import {ICacheService} from "../interfaces/cache_service"; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; @@ -25,10 +28,10 @@ export class MetadataService implements IMetadataService { this.cacheService = cacheService; } - public getKitsuId = async (info: IMetaDataQuery): Promise => { - const title = this.escapeTitle(info.title.replace(/\s\|\s.*/, '')); + public getKitsuId = async (info: IMetaDataQuery): Promise => { + const title = this.escapeTitle(info.title!.replace(/\s\|\s.*/, '')); const year = info.year ? ` ${info.year}` : ''; - const season = info.season > 1 ? ` S${info.season}` : ''; + const season = info.season || 0 > 1 ? ` S${info.season}` : ''; const key = `${title}${year}${season}`; const query = encodeURIComponent(key); @@ -45,7 +48,7 @@ export class MetadataService implements IMetadataService { }; public getImdbId = async (info: IMetaDataQuery): Promise => { - const name = this.escapeTitle(info.title); + const name = this.escapeTitle(info.title!); const year = info.year || (info.date && info.date.slice(0, 4)); const key = `${name}_${year || 'NA'}_${info.type}`; const query = `${name} ${year || ''} ${info.type} imdb`; @@ -102,7 +105,7 @@ export class MetadataService implements IMetadataService { .trim(); private requestMetadata = async (url: string): Promise => { - let response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); + const response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); let result: IMetadataResponse; const body = response.data; if ('kitsu_id' in body.meta) { @@ -117,14 +120,14 @@ export class MetadataService implements IMetadataService { }; private handleCinemetaResponse = (body: ICinemetaJsonResponse): IMetadataResponse => ({ - imdbId: parseInt(body.meta.imdb_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos + imdbId: parseInt(body.meta?.imdb_id || '0'), + type: body.meta?.type, + title: body.meta?.name, + year: parseInt(body.meta?.year || '0'), + country: body.meta?.country, + genres: body.meta?.genres, + status: body.meta?.status, + videos: body.meta?.videos ? body.meta.videos.map(video => ({ name: video.name, season: video.season, @@ -133,10 +136,10 @@ export class MetadataService implements IMetadataService { imdbEpisode: video.episode, })) : [], - episodeCount: body.meta.videos + episodeCount: body.meta?.videos ? this.getEpisodeCount(body.meta.videos) : [], - totalCount: body.meta.videos + totalCount: body.meta?.videos ? body.meta.videos.filter( entry => entry.season !== 0 && entry.episode !== 0 ).length @@ -144,15 +147,15 @@ export class MetadataService implements IMetadataService { }); private handleKitsuResponse = (body: IKitsuJsonResponse): IMetadataResponse => ({ - kitsuId: parseInt(body.meta.kitsu_id), - type: body.meta.type, - title: body.meta.name, - year: parseInt(body.meta.year), - country: body.meta.country, - genres: body.meta.genres, - status: body.meta.status, - videos: body.meta.videos - ? body.meta.videos.map(video => ({ + kitsuId: parseInt(body.meta?.kitsu_id || '0'), + type: body.meta?.type, + title: body.meta?.name, + year: parseInt(body.meta?.year || '0'), + country: body.meta?.country, + genres: body.meta?.genres, + status: body.meta?.status, + videos: body.meta?.videos + ? body.meta?.videos.map(video => ({ name: video.title, season: video.season, episode: video.episode, @@ -161,29 +164,32 @@ export class MetadataService implements IMetadataService { released: video.released, })) : [], - episodeCount: body.meta.videos + episodeCount: body.meta?.videos ? this.getEpisodeCount(body.meta.videos) : [], - totalCount: body.meta.videos + totalCount: body.meta?.videos ? body.meta.videos.filter( entry => entry.season !== 0 && entry.episode !== 0 ).length : 0, }); - private getEpisodeCount = (videos: ICommonVideoMetadata[]) => Object.values( - videos - .filter(entry => entry.season !== 0 && entry.episode !== 0) - .sort((a, b) => a.season - b.season) - .reduce((map, next) => { - map[next.season] = map[next.season] + 1 || 1; - return map; - }, {}) - ); + private getEpisodeCount = (videos: ICommonVideoMetadata[]): number[] => + Object.values( + videos + .filter(entry => entry.season !== null && entry.season !== 0 && entry.episode !== 0) + .sort((a, b) => (a.season || 0) - (b.season || 0)) + .reduce((map: Record, next) => { + if(next.season || next.season === 0) { + map[next.season] = (map[next.season] || 0) + 1; + } + return map; + }, {}) + ); private getIMDbIdFromNameToImdb = (name: string, info: IMetaDataQuery): Promise => { - const year = info.year; - const type = info.type; + const {year} = info; + const {type} = info; return new Promise((resolve, reject) => { nameToImdb({name, year, type}, function (err: Error, res: string) { if (res) { diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 6201940..03a1719 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,17 +1,17 @@ -import {encode} from 'magnet-uri'; -import {configurationService} from './configuration_service'; -import {ExtensionHelpers} from '../helpers/extension_helpers'; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {IFileAttributes} from "../../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../../repository/interfaces/subtitle_attributes"; -import {IContentAttributes} from "../../repository/interfaces/content_attributes"; -import {parse} from "parse-torrent-title"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; import {inject, injectable} from "inversify"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IocTypes} from "../models/ioc_types"; +import {encode} from 'magnet-uri'; +import {parse} from "parse-torrent-title"; import WebTorrent from "webtorrent"; +import {ExtensionHelpers} from '../helpers/extension_helpers'; +import {ILoggingService} from "../interfaces/logging_service"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {IocTypes} from "../models/ioc_types"; +import {IContentAttributes} from "../repository/interfaces/content_attributes"; +import {IFileAttributes} from "../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; +import {configurationService} from './configuration_service'; interface ITorrentFile { name: string; @@ -20,13 +20,13 @@ interface ITorrentFile { fileIndex: number; } -const clientOptions = { +const clientOptions : WebTorrent.Options = { maxConns: configurationService.torrentConfig.MAX_CONNECTIONS_OVERALL, + utp: false, } -const torrentOptions = { +const torrentOptions: WebTorrent.TorrentOptions = { skipVerify: true, - addUID: true, destroyStoreOnDestroy: true, private: true, maxWebConns: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, @@ -61,23 +61,20 @@ export class TorrentDownloadService implements ITorrentDownloadService { if (!torrent.infoHash) { return Promise.reject(new Error("No infoHash...")); } - const magnet = encode({infoHash: torrent.infoHash, announce: torrent.trackers.split(',')}); - - this.logger.debug(`Constructing torrent stream for ${torrent.title} with magnet ${magnet}`); + const magnet = encode({infoHash: torrent.infoHash, announce: torrent.trackers!.split(',')}); return new Promise((resolve, reject) => { + this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash} to webtorrent client...`); + + const currentTorrent = this.torrentClient.add(magnet, torrentOptions); + const timeoutId = setTimeout(() => { - this.torrentClient.remove(magnet, {destroyStore: true}); + this.removeTorrent(currentTorrent, torrent); reject(new Error('No available connections for torrent!')); }, timeout); - - this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash}`); - this.torrentClient.add(magnet, torrentOptions, (torrent) => { - - this.logger.debug(`torrent with infoHash ${torrent.infoHash} added to client.`); - - const files: ITorrentFile[] = torrent.files.map((file, fileId) => ({ + currentTorrent.on('ready', () => { + const files: ITorrentFile[] = currentTorrent.files.map((file, fileId) => ({ fileIndex: fileId, length: file.length, name: file.name, @@ -87,13 +84,22 @@ export class TorrentDownloadService implements ITorrentDownloadService { this.logger.debug(`Found ${files.length} files in torrent ${torrent.infoHash}`); resolve(files); - - this.torrentClient.remove(magnet, {destroyStore: true}); clearTimeout(timeoutId); + this.removeTorrent(currentTorrent, torrent); }); }); }; + private removeTorrent = (currentTorrent: WebTorrent.Torrent, torrent: IParsedTorrent): void => { + try { + this.torrentClient.remove(currentTorrent, {destroyStore: true}, () => { + this.logger.debug(`Removed torrent ${torrent.infoHash} from webtorrent client...`); + }); + } catch (error) { + this.logClientErrors(error); + } + }; + private filterVideos = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IFileAttributes[] => { if (torrentFiles.length === 1 && !Number.isInteger(torrentFiles[0].fileIndex)) { return [this.mapTorrentFileToFileAttributes(torrent, torrentFiles[0])]; @@ -104,13 +110,25 @@ export class TorrentDownloadService implements ITorrentDownloadService { const minAnimeExtraRatio = 5; const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; - const isSample = (video: ITorrentFile) => video.path.toString()?.match(/sample|bonus|promo/i) && maxSize / video.length > minSampleRatio; - const isRedundant = (video: ITorrentFile) => maxSize / video.length > minRedundantRatio; - const isExtra = (video: ITorrentFile) => video.path.toString()?.match(/extras?\//i); - const isAnimeExtra = (video: ITorrentFile) => video.path.toString()?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) - && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio; - const isWatermark = (video: ITorrentFile) => video.path.toString()?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) - && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio + const isSample = (video: ITorrentFile): boolean => video.path?.toString()?.match(/sample|bonus|promo/i) && maxSize / video.length > minSampleRatio || false; + const isRedundant = (video: ITorrentFile):boolean => maxSize / video.length > minRedundantRatio; + const isExtra = (video: ITorrentFile): boolean => /extras?\//i.test(video.path?.toString() || ""); + const isAnimeExtra = (video: ITorrentFile): boolean => { + if (!video.path || !video.length) { + return false; + } + + return video.path.toString()?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) + && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio || false; + }; + const isWatermark = (video: ITorrentFile): boolean => { + if (!video.path || !video.length) { + return false; + } + + return video.path.toString()?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) + && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio || false; + } return videos .filter(video => !isSample(video)) @@ -133,11 +151,11 @@ export class TorrentDownloadService implements ITorrentDownloadService { size: file.length, fileIndex: file.fileIndex || 0, path: file.path, - infoHash: torrent.infoHash, - imdbId: torrent.imdbId.toString(), + infoHash: torrent.infoHash?.toString(), + imdbId: torrent.imdbId?.toString() || '', imdbSeason: torrent.season || 0, imdbEpisode: torrent.episode || 0, - kitsuId: parseInt(torrent.kitsuId?.toString()) || 0, + kitsuId: parseInt(torrent.kitsuId?.toString() || '0') || 0, kitsuEpisode: torrent.episode || 0, }; @@ -162,8 +180,8 @@ export class TorrentDownloadService implements ITorrentDownloadService { size: file.length, }); - private logClientErrors(errors: Error | string) { - this.logger.error(`Error in torrent client: ${errors}`); + private logClientErrors(errors: Error | string | unknown): void { + this.logger.error(`Error in webtorrent client: ${errors}`); } } diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 93355b6..141bf7c 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -1,22 +1,24 @@ -import {parse} from 'parse-torrent-title'; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {TorrentType} from '../enums/torrent_types'; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {Torrent} from "../../repository/models/torrent"; -import {PromiseHelpers} from '../helpers/promises_helpers'; -import {ITorrentAttributes, ITorrentCreationAttributes} from "../../repository/interfaces/torrent_attributes"; -import {File} from "../../repository/models/file"; -import {Subtitle} from "../../repository/models/subtitle"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; import {inject, injectable} from "inversify"; -import {IocTypes} from "../models/ioc_types"; -import {IMetadataService} from "../interfaces/metadata_service"; +import {parse} from 'parse-torrent-title'; +import {TorrentType} from '../enums/torrent_types'; +import {PromiseHelpers} from '../helpers/promises_helpers'; import {ILoggingService} from "../interfaces/logging_service"; +import {IMetaDataQuery} from "../interfaces/metadata_query"; +import {IMetadataService} from "../interfaces/metadata_service"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; import {ITorrentFileService} from "../interfaces/torrent_file_service"; import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {IDatabaseRepository} from "../../repository/interfaces/database_repository"; -import {IIngestedTorrentCreationAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; -import {IFileCreationAttributes} from "../../repository/interfaces/file_attributes"; +import {IocTypes} from "../models/ioc_types"; +import {IDatabaseRepository} from "../repository/interfaces/database_repository"; +import {IFileCreationAttributes} from "../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "../repository/interfaces/torrent_attributes"; +import {File} from "../repository/models/file"; +import {SkipTorrent} from "../repository/models/skipTorrent"; +import {Subtitle} from "../repository/models/subtitle"; +import {Torrent} from "../repository/models/torrent"; @injectable() export class TorrentEntriesService implements ITorrentEntriesService { @@ -39,6 +41,11 @@ export class TorrentEntriesService implements ITorrentEntriesService { } public createTorrentEntry = async (torrent: IParsedTorrent, overwrite = false): Promise => { + if (!torrent.title) { + this.logger.warn(`No title found for ${torrent.provider} [${torrent.infoHash}]`); + return; + } + const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { @@ -93,7 +100,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { }); return this.repository.createTorrent(newTorrent) - .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { + .then(() => PromiseHelpers.sequence(fileCollection.videos!.map(video => () => { const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; if (!newVideo.kitsuId) { newVideo.kitsuId = 0; @@ -103,7 +110,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); }; - private assignKitsuId = async (kitsuQuery: { year: number | string; season: number; title: string }, torrent: IParsedTorrent) => { + private assignKitsuId = async (kitsuQuery: IMetaDataQuery, torrent: IParsedTorrent): Promise => { await this.metadataService.getKitsuId(kitsuQuery) .then((result: number | Error) => { if (typeof result === 'number') { @@ -118,10 +125,10 @@ export class TorrentEntriesService implements ITorrentEntriesService { }); }; - public createSkipTorrentEntry = async (torrent: Torrent) => this.repository.createSkipTorrent(torrent); + public createSkipTorrentEntry: (torrent: Torrent) => Promise<[SkipTorrent, boolean | null]> = async (torrent: Torrent)=> this.repository.createSkipTorrent(torrent.dataValues); - public getStoredTorrentEntry = async (torrent: Torrent) => this.repository.getSkipTorrent(torrent.infoHash) - .catch(() => this.repository.getTorrent(torrent)) + public getStoredTorrentEntry = async (torrent: Torrent): Promise => this.repository.getSkipTorrent(torrent.infoHash) + .catch(() => this.repository.getTorrent(torrent.dataValues)) .catch(() => undefined); public checkAndUpdateTorrent = async (torrent: IParsedTorrent): Promise => { @@ -141,7 +148,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { } if (existingTorrent.provider === 'KickassTorrents' && torrent.provider) { existingTorrent.provider = torrent.provider; - existingTorrent.torrentId = torrent.torrentId; + existingTorrent.torrentId = torrent.torrentId!; } if (!existingTorrent.languages && torrent.languages && existingTorrent.provider !== 'RARBG') { @@ -149,11 +156,14 @@ export class TorrentEntriesService implements ITorrentEntriesService { await existingTorrent.save(); this.logger.debug(`Updated [${existingTorrent.infoHash}] ${existingTorrent.title} language to ${torrent.languages}`); } + return this.createTorrentContents(existingTorrent) - .then(() => this.updateTorrentSeeders(existingTorrent)); + .then(() => this.updateTorrentSeeders(existingTorrent.dataValues)) + .then(() => Promise.resolve(true)) + .catch(() => Promise.reject(false)); }; - public createTorrentContents = async (torrent: Torrent) => { + public createTorrentContents = async (torrent: Torrent): Promise => { if (torrent.opened) { return; } @@ -167,7 +177,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { const kitsuId: number = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId || 0)); const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) - .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos}) + .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos.map(video => video.dataValues)}) .then(torrentContents => this.subtitleService.assignSubtitles(torrentContents)) .then(torrentContents => this.assignMetaIds(torrentContents, imdbId, kitsuId)) .catch(error => { @@ -181,22 +191,24 @@ export class TorrentEntriesService implements ITorrentEntriesService { return; } - if (notOpenedVideo && fileCollection.videos.length === 1) { + if (notOpenedVideo && fileCollection.videos?.length === 1) { // if both have a single video and stored one was not opened, update stored one to true metadata and use that - storedVideos[0].fileIndex = fileCollection.videos[0].fileIndex; + storedVideos[0].fileIndex = fileCollection?.videos[0]?.fileIndex || 0; storedVideos[0].title = fileCollection.videos[0].title; - storedVideos[0].size = fileCollection.videos[0].size; - storedVideos[0].subtitles = fileCollection.videos[0].subtitles.map(subtitle => Subtitle.build(subtitle)); - fileCollection.videos[0] = storedVideos[0]; + storedVideos[0].size = fileCollection.videos[0].size || 0; + const subtitles: ISubtitleAttributes[] = fileCollection.videos[0]?.subtitles || []; + storedVideos[0].subtitles = subtitles.map(subtitle => Subtitle.build(subtitle)); + fileCollection.videos[0] = {...storedVideos[0], subtitles: subtitles}; } // no videos available or more than one new videos were in the torrent - const shouldDeleteOld = notOpenedVideo && fileCollection.videos.every(video => !video.id); + const shouldDeleteOld = notOpenedVideo && fileCollection.videos?.every(video => !video.id) || false; - const newTorrent: Torrent = Torrent.build({ + const newTorrent: ITorrentCreationAttributes = { ...torrent, + files: fileCollection.videos, contents: fileCollection.contents, subtitles: fileCollection.subtitles - }); + }; return this.repository.createTorrent(newTorrent) .then(() => { @@ -206,7 +218,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { } return Promise.resolve(); }) - .then(() => PromiseHelpers.sequence(fileCollection.videos.map(video => () => { + .then(() => PromiseHelpers.sequence(fileCollection.videos!.map(video => (): Promise => { const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; return this.repository.createFile(newVideo) }))) @@ -214,19 +226,25 @@ export class TorrentEntriesService implements ITorrentEntriesService { .catch(error => this.logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); }; - public updateTorrentSeeders = async (torrent: ITorrentAttributes) => { + public updateTorrentSeeders = async (torrent: ITorrentAttributes): Promise<[number]> => { if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { - return torrent; + return [0]; } - + + if (torrent.seeders === undefined) { + this.logger.warn(`Seeders not found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); + return [0]; + } + + return this.repository.setTorrentSeeders(torrent, torrent.seeders) .catch(error => { this.logger.warn('Failed updating seeders:', error); - return undefined; + return [0]; }); }; - private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string, kitsuId: number): ITorrentFileCollection => { + private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string | undefined, kitsuId: number): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { video.imdbId = imdbId || ''; @@ -237,26 +255,31 @@ export class TorrentEntriesService implements ITorrentEntriesService { return fileCollection; }; - private overwriteExistingFiles = async (torrent: IParsedTorrent, torrentContents: ITorrentFileCollection) => { + private overwriteExistingFiles = async (torrent: IParsedTorrent, torrentContents: ITorrentFileCollection): Promise => { const videos = torrentContents && torrentContents.videos; if (videos && videos.length) { const existingFiles = await this.repository.getFiles(torrent.infoHash) - .then((existing) => existing - .reduce((map, next) => { - const fileIndex = next.fileIndex !== undefined ? next.fileIndex : null; + .then((existing) => existing.reduce<{ [key: number]: File[] }>((map, next) => { + const fileIndex = next.fileIndex !== undefined ? next.fileIndex : null; + if (fileIndex !== null) { map[fileIndex] = (map[fileIndex] || []).concat(next); - return map; - }, {})) + } + return map; + }, {})) .catch(() => undefined); if (existingFiles && Object.keys(existingFiles).length) { const overwrittenVideos = videos .map(file => { - const mapping = videos.length === 1 && Object.keys(existingFiles).length === 1 - ? Object.values(existingFiles)[0] - : existingFiles[file.fileIndex !== undefined ? file.fileIndex : null]; + const index = file.fileIndex !== undefined ? file.fileIndex : null; + let mapping; + if (index !== null) { + mapping = videos.length === 1 && Object.keys(existingFiles).length === 1 + ? Object.values(existingFiles)[0] + : existingFiles[index]; + } if (mapping) { const originalFile = mapping.shift(); - return {id: originalFile.id, ...file}; + return {id: originalFile!.id, ...file}; } return file; }); diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index d98f128..59a3360 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -1,23 +1,24 @@ import Bottleneck from 'bottleneck'; +import {inject, injectable} from "inversify"; import moment from 'moment'; import {parse} from 'parse-torrent-title'; -import {PromiseHelpers} from '../helpers/promises_helpers'; import {TorrentType} from '../enums/torrent_types'; -import {configurationService} from './configuration_service'; import {ExtensionHelpers} from '../helpers/extension_helpers'; -import {IMetadataResponse} from "../interfaces/metadata_response"; -import {IMetaDataQuery} from "../interfaces/metadata_query"; +import {PromiseHelpers} from '../helpers/promises_helpers'; import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {IFileAttributes} from "../../repository/interfaces/file_attributes"; -import {IContentAttributes} from "../../repository/interfaces/content_attributes"; -import {ITorrentFileService} from "../interfaces/torrent_file_service"; -import {inject, injectable} from "inversify"; -import {IocTypes} from "../models/ioc_types"; -import {IMetadataService} from "../interfaces/metadata_service"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; import {ILoggingService} from "../interfaces/logging_service"; +import {IMetaDataQuery} from "../interfaces/metadata_query"; +import {IMetadataResponse} from "../interfaces/metadata_response"; +import {IMetadataService} from "../interfaces/metadata_service"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {ISeasonEpisodeMap} from "../interfaces/season_episode_map"; +import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; +import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; +import {ITorrentFileService} from "../interfaces/torrent_file_service"; +import {IocTypes} from "../models/ioc_types"; +import {IContentAttributes} from "../repository/interfaces/content_attributes"; +import {IFileAttributes} from "../repository/interfaces/file_attributes"; +import {configurationService} from './configuration_service'; const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB @@ -41,6 +42,10 @@ export class TorrentFileService implements ITorrentFileService { } public parseTorrentFiles = async (torrent: IParsedTorrent): Promise => { + if (!torrent.title) { + return Promise.reject(new Error('Torrent title is missing')); + } + const parsedTorrentName = parse(torrent.title); const query: IMetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, @@ -49,6 +54,12 @@ export class TorrentFileService implements ITorrentFileService { const metadata = await this.metadataService.getMetadata(query) .then(meta => Object.assign({}, meta)) .catch(() => undefined); + + if (metadata === undefined || metadata instanceof Error) { + this.logger.warn(`Failed to retrieve metadata for torrent ${torrent.title}`); + this.logger.debug(`Metadata Error: ${torrent.title}`, metadata); + return Promise.reject(new Error('Failed to retrieve metadata')); + } if (torrent.type !== TorrentType.Anime && metadata && metadata.type && metadata.type !== torrent.type) { // it's actually a movie/series @@ -56,7 +67,7 @@ export class TorrentFileService implements ITorrentFileService { } if (torrent.type === TorrentType.Movie && (!parsedTorrentName.seasons || - parsedTorrentName.season === 5 && [1, 5].includes(parsedTorrentName.episode))) { + parsedTorrentName.season === 5 && [1, 5].includes(parsedTorrentName.episode || 0))) { return this.parseMovieFiles(torrent, metadata); } @@ -67,22 +78,27 @@ export class TorrentFileService implements ITorrentFileService { if (torrent.isPack) { return true; } + if (!torrent.title) { + return false; + } const parsedInfo = parse(torrent.title); if (torrent.type === TorrentType.Movie) { return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); } - const hasMultipleEpisodes = parsedInfo.complete || - torrent.size > MULTIPLE_FILES_SIZE || + + const hasMultipleEpisodes = Boolean(parsedInfo.complete || torrent.size || 0 > MULTIPLE_FILES_SIZE || (parsedInfo.seasons && parsedInfo.seasons.length > 1) || (parsedInfo.episodes && parsedInfo.episodes.length > 1) || - (parsedInfo.seasons && !parsedInfo.episodes); - const hasSingleEpisode = Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date); + (parsedInfo.seasons && !parsedInfo.episodes)); + + const hasSingleEpisode: boolean = Boolean(Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date)); + return hasMultipleEpisodes && !hasSingleEpisode; }; private parseSeriesVideos = (torrent: IParsedTorrent, videos: IFileAttributes[]): IFileAttributes[] => { - const parsedTorrentName = parse(torrent.title); - const hasMovies = parsedTorrentName.complete || !!torrent.title.match(/movies?(?:\W|$)/i); + const parsedTorrentName = parse(torrent.title!); + const hasMovies = parsedTorrentName.complete || !!torrent.title!.match(/movies?(?:\W|$)/i); const parsedVideos = videos.map(video => this.parseSeriesVideo(video)); return parsedVideos.map(video => ({...video, isMovie: this.isMovieVideo(torrent, video, parsedVideos, hasMovies)})); @@ -90,28 +106,32 @@ export class TorrentFileService implements ITorrentFileService { private parseMovieFiles = async (torrent: IParsedTorrent, metadata: IMetadataResponse): Promise => { const fileCollection: ITorrentFileCollection = await this.getMoviesTorrentContent(torrent); + if (fileCollection.videos === undefined || fileCollection.videos.length === 0) { + return {...fileCollection, videos: this.getDefaultFileEntries(torrent)}; + } + const filteredVideos = fileCollection.videos - .filter(video => video.size > MIN_SIZE) + .filter(video => video.size! > MIN_SIZE) .filter(video => !this.isFeaturette(video)); if (this.isSingleMovie(filteredVideos)) { const parsedVideos = filteredVideos.map(video => ({ infoHash: torrent.infoHash, fileIndex: video.fileIndex, - title: video.path || torrent.title, + title: video.path || video.title || video.fileName || '', size: video.size || torrent.size, imdbId: torrent.imdbId?.toString() || metadata && metadata.imdbId?.toString(), - kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString()) + kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString() || '0') })); return {...fileCollection, videos: parsedVideos}; } const parsedVideos = await PromiseHelpers.sequence(filteredVideos.map(video => () => this.isFeaturette(video) ? Promise.resolve(video) - : this.findMovieImdbId(video.title).then(imdbId => ({...video, imdbId})))) - .then(videos => videos.map(video => ({ + : this.findMovieImdbId(video.title).then(imdbId => ({...video, imdbId: imdbId?.toString() || ''})))) + .then(videos => videos.map((video: IFileAttributes) => ({ infoHash: torrent.infoHash, fileIndex: video.fileIndex, - title: video.path || video.name, + title: video.path || video.title, size: video.size, imdbId: video.imdbId, }))); @@ -120,8 +140,12 @@ export class TorrentFileService implements ITorrentFileService { private parseSeriesFiles = async (torrent: IParsedTorrent, metadata: IMetadataResponse): Promise => { const fileCollection: ITorrentFileCollection = await this.getSeriesTorrentContent(torrent); + if (fileCollection.videos === undefined || fileCollection.videos.length === 0) { + return {...fileCollection, videos: this.getDefaultFileEntries(torrent)}; + } + const parsedVideos: IFileAttributes[] = await Promise.resolve(fileCollection.videos) - .then(videos => videos.filter(video => videos.length === 1 || video.size > MIN_SIZE)) + .then(videos => videos.filter(video => videos?.length === 1 || video.size! > MIN_SIZE)) .then(videos => this.parseSeriesVideos(torrent, videos)) .then(videos => this.decomposeEpisodes(torrent, videos, metadata)) .then(videos => this.assignKitsuOrImdbEpisodes(torrent, videos, metadata)) @@ -138,23 +162,24 @@ export class TorrentFileService implements ITorrentFileService { const files = await this.torrentDownloadService.getTorrentFiles(torrent, configurationService.torrentConfig.TIMEOUT) .catch(error => { if (!this.isPackTorrent(torrent)) { - const entries = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; + const entries = this.getDefaultFileEntries(torrent); return {videos: entries, contents: [], subtitles: [], files: entries} } return Promise.reject(error); }); - if (files.contents && files.contents.length && !files.videos.length && this.isDiskTorrent(files.contents)) { - files.videos = [{name: torrent.title, path: torrent.title, size: torrent.size, fileIndex: null}]; + if (files.contents && files.contents.length && !files.videos?.length && this.isDiskTorrent(files.contents)) { + files.videos = this.getDefaultFileEntries(torrent); } + return files; }; private getDefaultFileEntries = (torrent: IParsedTorrent): IFileAttributes[] => [{ - title: torrent.title, + title: torrent.title!, path: torrent.title, size: torrent.size, - fileIndex: null + fileIndex: 0, }]; private getSeriesTorrentContent = async (torrent: IParsedTorrent): Promise => this.torrentDownloadService.getTorrentFiles(torrent, configurationService.torrentConfig.TIMEOUT) @@ -167,13 +192,13 @@ export class TorrentFileService implements ITorrentFileService { private mapSeriesEpisode = async (torrent: IParsedTorrent, file: IFileAttributes, files: IFileAttributes[]): Promise => { if (!file.episodes && !file.episodes) { - if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title).seasons) { + if (files.length === 1 || files.some(f => f.episodes || f.episodes) || parse(torrent.title!).seasons) { return Promise.resolve([{ infoHash: torrent.infoHash, fileIndex: file.fileIndex, title: file.path || file.title, size: file.size, - imdbId: torrent.imdbId.toString() || file.imdbId.toString(), + imdbId: torrent?.imdbId?.toString() || file?.imdbId?.toString() || '', }]); } return Promise.resolve([]); @@ -184,14 +209,14 @@ export class TorrentFileService implements ITorrentFileService { fileIndex: file.fileIndex, title: file.path || file.title, size: file.size, - imdbId: file.imdbId.toString() || torrent.imdbId.toString(), + imdbId: file?.imdbId?.toString() || torrent?.imdbId?.toString() || '', imdbSeason: file.season, season: file.season, imdbEpisode: file.episodes && file.episodes[index], episode: file.episodes && file.episodes[index], kitsuEpisode: file.episodes && file.episodes[index], episodes: file.episodes, - kitsuId: parseInt(file.kitsuId.toString() || torrent.kitsuId.toString()) || 0, + kitsuId: parseInt(file.kitsuId?.toString() || torrent.kitsuId?.toString() || '0') || 0, }))) }; @@ -222,7 +247,7 @@ export class TorrentFileService implements ITorrentFileService { title: file.path || file.title, size: file.size, imdbId: imdbId, - kitsuId: parseInt(kitsuId) || 0, + kitsuId: parseInt(kitsuId?.toString() || '0') || 0, episodes: undefined, imdbSeason: undefined, imdbEpisode: undefined, @@ -232,21 +257,21 @@ export class TorrentFileService implements ITorrentFileService { // at this point, TypeScript infers that metadataOrError is actually MetadataResponse const metadata = metadataOrError; const hasEpisode = metadata.videos && metadata.videos.length && (file.episode || metadata.videos.length === 1); - const episodeVideo = hasEpisode && metadata.videos[(file.episode || 1) - 1]; + const episodeVideo = hasEpisode && metadata.videos && metadata.videos[(file.episode || 1) - 1]; return [{ infoHash: torrent.infoHash, fileIndex: file.fileIndex, title: file.path || file.title, size: file.size, - imdbId: metadata.imdbId.toString() || imdbId, - kitsuId: parseInt(metadata.kitsuId.toString() || kitsuId) || 0, + imdbId: metadata.imdbId?.toString() || imdbId || '', + kitsuId: parseInt(metadata.kitsuId?.toString() || kitsuId?.toString() || '0') || 0, imdbSeason: episodeVideo && metadata.imdbId ? episodeVideo.season : undefined, - imdbEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, - kitsuEpisode: episodeVideo && metadata.imdbId | metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, + imdbEpisode: episodeVideo && metadata.imdbId || episodeVideo && metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, + kitsuEpisode: episodeVideo && metadata.imdbId || episodeVideo && metadata.kitsuId ? episodeVideo.episode || episodeVideo.episode : undefined, }]; }; - private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = {episodeCount: []}) => { + private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = {episodeCount: []}):Promise => { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -291,18 +316,18 @@ export class TorrentFileService implements ITorrentFileService { return files; }; - private preprocessEpisodes = (files: IFileAttributes[]) => { + private preprocessEpisodes = (files: IFileAttributes[]): void => { // reverse special episode naming when they named with 0 episode, ie. S02E00 files .filter(file => Number.isInteger(file.season) && file.episode === 0) .forEach(file => { file.episode = file.season - file.episodes = [file.season] + file.episodes = [file.season || 0]; file.season = 0; }) }; - private isConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], sortedEpisodes: number[], metadata: IMetadataResponse) => { + private isConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], sortedEpisodes: number[], metadata: IMetadataResponse): boolean => { if (metadata.kitsuId !== undefined) { // anime does not use this naming scheme in 99% of cases; return false; @@ -317,58 +342,59 @@ export class TorrentFileService implements ITorrentFileService { const threshold = Math.max(Math.ceil(files.length * 0.8), 5); const sortedConcatEpisodes = sortedEpisodes .filter(ep => ep > 100) - .filter(ep => metadata.episodeCount[this.div100(ep) - 1] < ep) - .filter(ep => metadata.episodeCount[this.div100(ep) - 1] >= this.mod100(ep)); + .filter(ep => metadata.episodeCount && metadata.episodeCount[this.div100(ep) - 1] < ep) + .filter(ep => metadata.episodeCount && metadata.episodeCount[this.div100(ep) - 1] >= this.mod100(ep)); const concatFileEpisodes = files .filter(file => !file.isMovie && file.episodes) - .filter(file => !file.season || file.episodes.every(ep => this.div100(ep) === file.season)); + .filter(file => !file.season || file.episodes?.every(ep => this.div100(ep) === file.season)); const concatAboveTotalEpisodeCount = files .filter(file => !file.isMovie && file.episodes && file.episodes.every(ep => ep > 100)) - .filter(file => file.episodes.every(ep => ep > metadata.totalCount)); + .filter(file => file.episodes?.every(ep => ep > metadata.totalCount!)); return sortedConcatEpisodes.length >= thresholdSorted && concatFileEpisodes.length >= threshold || concatAboveTotalEpisodeCount.length >= thresholdAbove; }; - private isDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => files.every(file => (!file.season || !metadata.episodeCount[file.season - 1]) && file.date); + private isDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse): boolean => files.every(file => (!file.season || metadata.episodeCount && !metadata.episodeCount[file.season - 1]) && file.date); - private isAbsoluteEpisodeFiles = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) => { + private isAbsoluteEpisodeFiles = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse): boolean => { const threshold = Math.ceil(files.length / 5); const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; - const nonMovieEpisodes = files - .filter(file => !file.isMovie && file.episodes); + const nonMovieEpisodes = files.filter(file => !file.isMovie && file.episodes); const absoluteEpisodes = files .filter(file => file.season && file.episodes) - .filter(file => file.episodes.every(ep => metadata.episodeCount[file.season - 1] < ep)) + .filter(file => file.episodes?.every(ep => + metadata.episodeCount && file.season && metadata.episodeCount[file.season - 1] < ep)); return nonMovieEpisodes.every(file => !file.season) - || (isAnime && nonMovieEpisodes.every(file => file.season > metadata.episodeCount.length)) + || (isAnime && nonMovieEpisodes.every(file => + metadata.episodeCount && file.season && file.season > metadata.episodeCount.length)) || absoluteEpisodes.length >= threshold; }; - private isNewEpisodeNotInMetadata = (torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse) => { - // new episode might not yet been indexed by cinemeta. - // detect this if episode number is larger than the last episode or season is larger than the last one - // only for non anime metas + private isNewEpisodeNotInMetadata = (torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse): boolean => { const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; - return !isAnime && !video.isMovie && video.episodes && video.season !== 1 - && /continuing|current/i.test(metadata.status) - && video.season >= metadata.episodeCount.length - && video.episodes.every(ep => ep > (metadata.episodeCount[video.season - 1] || 0)); + return !!( !isAnime && !video.isMovie && video.episodes && video.season !== 1 + && metadata.status && /continuing|current/i.test(metadata.status) + && metadata.episodeCount && video.season && video.season >= metadata.episodeCount.length + && video.episodes.every(ep => metadata.episodeCount && video.season && ep > (metadata.episodeCount[video.season - 1] || 0))); }; - private decomposeConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => { + private decomposeConcatSeasonAndEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse): void => { files .filter(file => file.episodes && file.season !== 0 && file.episodes.every(ep => ep > 100)) - .filter(file => metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) - .filter(file => file.season && file.episodes.every(ep => this.div100(ep) === file.season) || !file.season) + .filter(file => file.episodes && metadata?.episodeCount && + ((file.season || this.div100(file.episodes[0])) - 1) >= 0 && + metadata.episodeCount[(file.season || this.div100(file.episodes[0])) - 1] < 100) + .filter(file => (file.season && file.episodes && file.episodes.every(ep => this.div100(ep) === file.season)) || !file.season) .forEach(file => { - file.season = this.div100(file.episodes[0]); - file.episodes = file.episodes.map(ep => this.mod100(ep)) + if (file.episodes) { + file.season = this.div100(file.episodes[0]); + file.episodes = file.episodes.map(ep => this.mod100(ep)); + } }); - }; - private decomposeAbsoluteEpisodeFiles = (torrent: IParsedTorrent, videos: IFileAttributes[], metadata: IMetadataResponse) => { - if (metadata.episodeCount.length === 0) { + private decomposeAbsoluteEpisodeFiles = (torrent: IParsedTorrent, videos: IFileAttributes[], metadata: IMetadataResponse): void => { + if (metadata.episodeCount?.length === 0) { videos .filter(file => !Number.isInteger(file.season) && file.episodes && !file.isMovie) .forEach(file => { @@ -376,29 +402,38 @@ export class TorrentFileService implements ITorrentFileService { }); return; } + if (!metadata.episodeCount) return; + videos .filter(file => file.episodes && !file.isMovie && file.season !== 0) .filter(file => !this.isNewEpisodeNotInMetadata(torrent, file, metadata)) - .filter(file => !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]) + .filter(file => { + if (!file.episodes || !metadata.episodeCount) return false; + return !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]; + }) .forEach(file => { - const seasonIdx = ([...metadata.episodeCount.keys()] - .find((i) => metadata.episodeCount.slice(0, i + 1).reduce((a, b) => a + b) >= file.episodes[0]) - + 1 || metadata.episodeCount.length) - 1; + if(!file.episodes || !metadata.episodeCount) return; + + let seasonIdx = metadata.episodeCount + .map((_, i) => i) + .find(i => metadata.episodeCount && file.episodes && metadata.episodeCount.slice(0, i + 1).reduce((a, b) => a + b) >= file.episodes[0]); + + seasonIdx = (seasonIdx || 1 || metadata.episodeCount.length) - 1; file.season = seasonIdx + 1; file.episodes = file.episodes - .map(ep => ep - metadata.episodeCount.slice(0, seasonIdx).reduce((a, b) => a + b, 0)) + .map(ep => ep - (metadata.episodeCount?.slice(0, seasonIdx).reduce((a, b) => a + b, 0) || 0)); }); }; - private decomposeDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse) => { + private decomposeDateEpisodeFiles = (files: IFileAttributes[], metadata: IMetadataResponse): void => { if (!metadata || !metadata.videos || !metadata.videos.length) { return; } const timeZoneOffset = this.getTimeZoneOffset(metadata.country); - const offsetVideos = metadata.videos - .reduce((map, video) => { + const offsetVideos: { [key: string]: ICommonVideoMetadata } = metadata.videos + .reduce((map: { [key: string]: ICommonVideoMetadata }, video: ICommonVideoMetadata) => { const releaseDate = moment(video.released).utcOffset(timeZoneOffset).format('YYYY-MM-DD'); map[releaseDate] = video; return map; @@ -407,15 +442,15 @@ export class TorrentFileService implements ITorrentFileService { files .filter(file => file.date) .forEach(file => { - const video = offsetVideos[file.date]; + const video = offsetVideos[file.date!]; if (video) { file.season = video.season; - file.episodes = [video.episode]; + file.episodes = [video.episode || 0]; } }); }; - private getTimeZoneOffset = (country: string | undefined) => { + private getTimeZoneOffset = (country: string | undefined): string => { switch (country) { case 'United States': case 'USA': @@ -425,7 +460,7 @@ export class TorrentFileService implements ITorrentFileService { } }; - private assignKitsuOrImdbEpisodes = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse) => { + private assignKitsuOrImdbEpisodes = (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse): IFileAttributes[] => { if (!metadata || !metadata.videos || !metadata.videos.length) { if (torrent.type === TorrentType.Anime) { // assign episodes as kitsu episodes for anime when no metadata available for imdb mapping @@ -437,31 +472,35 @@ export class TorrentFileService implements ITorrentFileService { }) if (metadata.type === TorrentType.Movie && files.every(file => !file.imdbId)) { // sometimes a movie has episode naming, thus not recognized as a movie and imdbId not assigned - files.forEach(file => file.imdbId = metadata.imdbId.toString()); + files.forEach(file => file.imdbId = metadata.imdbId?.toString()); } } return files; } - const seriesMapping: ICommonVideoMetadata = metadata.videos - .reduce((map, video) => { - const episodeMap = map[video.season] || {}; - episodeMap[video.episode] = video; - map[video.season] = episodeMap; + const seriesMapping = metadata.videos + .filter(video => video.season !== undefined && Number.isInteger(video.season) && video.episode !== undefined && Number.isInteger(video.episode)) + .reduce((map, video) => { + if (video.season !== undefined && video.episode !== undefined) { + const episodeMap = map[video.season] || {}; + episodeMap[video.episode] = video; + map[video.season] = episodeMap; + } return map; }, {}); + if (metadata.videos.some(video => Number.isInteger(video.season)) || !metadata.imdbId) { - files.filter((file => Number.isInteger(file.season) && file.episodes)) + files.filter(file => file && Number.isInteger(file.season) && file.episodes) .map(file => { - const seasonMapping = seriesMapping[file.season]; - const episodeMapping = seasonMapping && seasonMapping[file.episodes[0]]; + const seasonMapping = file && file.season && seriesMapping[file.season] || null; + const episodeMapping = seasonMapping && file && file.episodes && file.episodes[0] && seasonMapping[file.episodes[0]] || null; + if (episodeMapping && Number.isInteger(episodeMapping.season)) { - file.imdbId = metadata.imdbId.toString(); + file.imdbId = metadata.imdbId?.toString(); file.season = episodeMapping.season; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].episode); + file.episodes = file.episodes && file.episodes.map(ep => (seasonMapping && seasonMapping[ep]) ? Number(seasonMapping[ep].episode) : 0); } else { - // no imdb mapping available for episode file.season = undefined; file.episodes = undefined; } @@ -471,11 +510,16 @@ export class TorrentFileService implements ITorrentFileService { files .filter(file => Number.isInteger(file.season) && file.episodes) .forEach(file => { + if (!file.season || !file.episodes) { + return; + } if (seriesMapping[file.season]) { + const seasonMapping = seriesMapping[file.season]; - file.imdbId = metadata.imdbId.toString(); - file.kitsuId = seasonMapping[file.episodes[0]] && seasonMapping[file.episodes[0]].kitsuId || 0; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + file.imdbId = metadata.imdbId?.toString(); + file.kitsuId = seasonMapping[file.episodes[0]] && parseInt(seasonMapping[file.episodes[0]].id || '0') || 0; + file.episodes = file.episodes.map(ep => seasonMapping[ep]?.episode) + .filter((ep): ep is number => ep !== undefined); } else if (seriesMapping[file.season - 1]) { // sometimes a second season might be a continuation of the previous season const seasonMapping = seriesMapping[file.season - 1] as ICommonVideoMetadata; @@ -483,48 +527,65 @@ export class TorrentFileService implements ITorrentFileService { const firstKitsuId = episodes.length && episodes[0]; const differentTitlesCount = new Set(episodes.map(ep => ep.id)).size const skippedCount = episodes.filter(ep => ep.id === firstKitsuId).length; + const emptyArray: number[] = []; const seasonEpisodes = files - .filter((otherFile: IFileAttributes) => otherFile.season === file.season) - .reduce((a, b) => a.concat(b.episodes), []); + .filter((otherFile: IFileAttributes) => otherFile.season === file.season && otherFile.episodes) + .reduce((a, b) => a.concat(b.episodes || []), emptyArray); const isAbsoluteOrder = seasonEpisodes.every(ep => ep > skippedCount && ep <= episodes.length) const isNormalOrder = seasonEpisodes.every(ep => ep + skippedCount <= episodes.length) if (differentTitlesCount >= 1 && (isAbsoluteOrder || isNormalOrder)) { - file.imdbId = metadata.imdbId.toString(); + const {season} = file; + const [episode] = file.episodes; + file.imdbId = metadata.imdbId?.toString(); file.season = file.season - 1; file.episodes = file.episodes.map(ep => isAbsoluteOrder ? ep : ep + skippedCount); - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId || 0; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + const currentEpisode = seriesMapping[season][episode]; + file.kitsuId = currentEpisode ? parseInt(currentEpisode.id || '0') : 0; + if (typeof season === 'number' && Array.isArray(file.episodes)) { + file.episodes = file.episodes.map(ep => + seriesMapping[season] + && seriesMapping[season][ep] + && seriesMapping[season][ep].episode + || ep); + } } } else if (Object.values(seriesMapping).length === 1 && seriesMapping[1]) { // sometimes series might be named with sequel season but it's not a season on imdb and a new title + // eslint-disable-next-line prefer-destructuring const seasonMapping = seriesMapping[1]; - file.imdbId = metadata.imdbId.toString(); + file.imdbId = metadata.imdbId?.toString(); file.season = 1; - file.kitsuId = seasonMapping[file.episodes[0]].kitsuId || 0; - file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].kitsuEpisode); + file.kitsuId = parseInt(seasonMapping[file.episodes[0]].id || '0') || 0; + file.episodes = file.episodes.map(ep => seasonMapping[ep] && seasonMapping[ep].episode) + .filter((ep): ep is number => ep !== undefined); } }); } return files; }; - private needsCinemetaMetadataForAnime = (files: IFileAttributes[], metadata: IMetadataResponse) => { + private needsCinemetaMetadataForAnime = (files: IFileAttributes[], metadata: IMetadataResponse): boolean => { if (!metadata || !metadata.imdbId || !metadata.videos || !metadata.videos.length) { return false; } - const minSeason = Math.min(...metadata.videos.map(video => video.season)) || Number.MAX_VALUE; - const maxSeason = Math.max(...metadata.videos.map(video => video.season)) || Number.MAX_VALUE; - const differentSeasons = new Set(metadata.videos + const seasons = metadata.videos .map(video => video.season) - .filter(season => Number.isInteger(season))).size; + .filter((season): season is number => season !== null && season !== undefined); + + // Using || 0 instead of || Number.MAX_VALUE to match previous logic + const minSeason = Math.min(...seasons) || 0; + const maxSeason = Math.max(...seasons) || 0; + const differentSeasons = new Set(seasons.filter(season => Number.isInteger(season))).size; + const total = metadata.totalCount || Number.MAX_VALUE; + return differentSeasons > 1 || files .filter(file => !file.isMovie && file.episodes) - .some(file => file.season < minSeason || file.season > maxSeason || file.episodes.every(ep => ep > total)); + .some(file => file.season || 0 < minSeason || file.season || 0 > maxSeason || file.episodes?.every(ep => ep > total)); }; - private updateToCinemetaMetadata = async (metadata: IMetadataResponse) => { + private updateToCinemetaMetadata = async (metadata: IMetadataResponse): Promise => { const query: IMetaDataQuery = { id: metadata.imdbId, type: metadata.type @@ -538,7 +599,7 @@ export class TorrentFileService implements ITorrentFileService { return metadata; // or throw newMetadataOrError to propagate error up the call stack } // At this point TypeScript infers newMetadataOrError to be of type MetadataResponse - let newMetadata = newMetadataOrError; + const newMetadata = newMetadataOrError; if (!newMetadata.videos || !newMetadata.videos.length) { return metadata; } else { @@ -550,7 +611,7 @@ export class TorrentFileService implements ITorrentFileService { }) }; - private findMovieImdbId = (title: IFileAttributes | string) => { + private findMovieImdbId = (title: IFileAttributes | string):Promise => { const parsedTitle = typeof title === 'string' ? parse(title) : title; this.logger.debug(`Finding movie imdbId for ${title}`); return this.imdb_limiter.schedule(async () => { @@ -567,7 +628,7 @@ export class TorrentFileService implements ITorrentFileService { }); }; - private findMovieKitsuId = async (title: IFileAttributes | string) => { + private findMovieKitsuId = async (title: IFileAttributes | string):Promise => { const parsedTitle = typeof title === 'string' ? parse(title) : title; const kitsuQuery = { title: parsedTitle.title, @@ -582,20 +643,20 @@ export class TorrentFileService implements ITorrentFileService { } }; - private isDiskTorrent = (contents: IContentAttributes[]) => contents.some(content => ExtensionHelpers.isDisk(content.path)); + private isDiskTorrent = (contents: IContentAttributes[]): boolean => contents.some(content => ExtensionHelpers.isDisk(content.path)); - private isSingleMovie = (videos: IFileAttributes[]) => videos.length === 1 || + private isSingleMovie = (videos: IFileAttributes[]): boolean => videos.length === 1 || (videos.length === 2 && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path)) && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path))); + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path!)) && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path!))) !== undefined; - private isFeaturette = (video: IFileAttributes) => /featurettes?\/|extras-grym/i.test(video.path); + private isFeaturette = (video: IFileAttributes):boolean => /featurettes?\/|extras-grym/i.test(video.path!); private parseSeriesVideo = (video: IFileAttributes): IFileAttributes => { const videoInfo = parse(video.title); // the episode may be in a folder containing season number - if (!Number.isInteger(videoInfo.season) && video.path.includes('/')) { - const folders = video.path.split('/'); + if (!Number.isInteger(videoInfo.season) && video.path?.includes('/')) { + const folders = video.path?.split('/'); const pathInfo = parse(folders[folders.length - 2]); videoInfo.season = pathInfo.season; } @@ -604,12 +665,12 @@ export class TorrentFileService implements ITorrentFileService { } if (!Number.isInteger(videoInfo.season) && videoInfo.seasons && videoInfo.seasons.length > 1) { // in case single file was interpreted as having multiple seasons - videoInfo.season = videoInfo.seasons[0]; + [videoInfo.season] = videoInfo.seasons; } - if (!Number.isInteger(videoInfo.season) && video.path.includes('/') && video.seasons + if (!Number.isInteger(videoInfo.season) && video.path?.includes('/') && video.seasons && video.seasons.length > 1) { // russian season are usually named with 'series name-2` i.e. Улицы разбитых фонарей-6/22. Одиночный выстрел.mkv - const folderPathSeasonMatch = video.path.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); + const folderPathSeasonMatch = video.path?.match(/[\u0400-\u04ff]-(\d{1,2})(?=.*\/)/); videoInfo.season = folderPathSeasonMatch && parseInt(folderPathSeasonMatch[1], 10) || undefined; } // sometimes video file does not have correct date format as in torrent title @@ -619,18 +680,18 @@ export class TorrentFileService implements ITorrentFileService { // limit number of episodes in case of incorrect parsing if (videoInfo.episodes && videoInfo.episodes.length > 20) { videoInfo.episodes = [videoInfo.episodes[0]]; - videoInfo.episode = videoInfo.episodes[0]; + [videoInfo.episode] = videoInfo.episodes; } // force episode to any found number if it was not parsed if (!videoInfo.episodes && !videoInfo.date) { const epMatcher = videoInfo.title.match( /(? other.title === video.title && other.year === video.year).length < 3; }; - private clearInfoFields = (video: IFileAttributes) => { + private clearInfoFields = (video: IFileAttributes): IFileAttributes => { video.imdbId = undefined; video.imdbSeason = undefined; video.imdbEpisode = undefined; @@ -670,9 +731,9 @@ export class TorrentFileService implements ITorrentFileService { return video; }; - private div100 = (episode: number) => (episode / 100 >> 0); + private div100 = (episode: number): number => (episode / 100 >> 0); - private mod100 = (episode: number) => episode % 100; + private mod100 = (episode: number): number => episode % 100; } diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index c88d680..dd19b78 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -1,12 +1,12 @@ -import {TorrentType} from "../enums/torrent_types"; -import {IIngestedTorrentAttributes} from "../../repository/interfaces/ingested_torrent_attributes"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; import {inject, injectable} from "inversify"; -import {IocTypes} from "../models/ioc_types"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {TorrentType} from "../enums/torrent_types"; import {ILoggingService} from "../interfaces/logging_service"; +import {IParsedTorrent} from "../interfaces/parsed_torrent"; +import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; +import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; import {ITrackerService} from "../interfaces/tracker_service"; +import {IocTypes} from "../models/ioc_types"; +import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; @injectable() export class TorrentProcessingService implements ITorrentProcessingService { diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 97878f8..ec227dc 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -1,8 +1,9 @@ +import {injectable} from "inversify"; import {parse} from 'parse-torrent-title'; import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {IFileAttributes} from "../../repository/interfaces/file_attributes"; import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {injectable} from "inversify"; +import {IFileAttributes} from "../repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; @injectable() export class TorrentSubtitleService implements ITorrentSubtitleService { @@ -28,57 +29,57 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return fileCollection; }; - private parseVideo = (video: IFileAttributes) => { - const fileName = video.title.split('/').pop().replace(/\.(\w{2,4})$/, ''); - const folderName = video.title.replace(/\/?[^/]+$/, ''); + private parseVideo = (video: IFileAttributes): IFileAttributes => { + const fileName = video.title?.split('/')?.pop()?.replace(/\.(\w{2,4})$/, '') || ''; + const folderName = video.title?.replace(/\/?[^/]+$/, '') || ''; return { videoFile: video, fileName: fileName, folderName: folderName, - ...this.parseFilename(video.title) + ...this.parseFilename(video.title.toString() || '') }; } - private mostProbableSubtitleVideos = (subtitle: any, parsedVideos: any[]) => { - const subTitle = (subtitle.title || subtitle.path).split('/').pop().replace(/\.(\w{2,4})$/, ''); + private mostProbableSubtitleVideos = (subtitle: ISubtitleAttributes, parsedVideos: IFileAttributes[]) : IFileAttributes[] => { + const subTitle = (subtitle.title || subtitle.path)?.split('/')?.pop()?.replace(/\.(\w{2,4})$/, '') || ''; const parsedSub = this.parsePath(subtitle.title || subtitle.path); - const byFileName = parsedVideos.filter(video => subTitle.includes(video.fileName)); + const byFileName = parsedVideos.filter(video => subTitle.includes(video.title!)); if (byFileName.length === 1) { - return byFileName.map(v => v.videoFile); + return byFileName.map(v => v); } const byTitleSeasonEpisode = parsedVideos.filter(video => video.title === parsedSub.title - && this.arrayEquals(video.seasons, parsedSub.seasons) - && this.arrayEquals(video.episodes, parsedSub.episodes)); + && this.arrayEquals(video.seasons || [], parsedSub.seasons || []) + && this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); if (this.singleVideoFile(byTitleSeasonEpisode)) { - return byTitleSeasonEpisode.map(v => v.videoFile); + return byTitleSeasonEpisode.map(v => v); } - const bySeasonEpisode = parsedVideos.filter(video => this.arrayEquals(video.seasons, parsedSub.seasons) - && this.arrayEquals(video.episodes, parsedSub.episodes)); + const bySeasonEpisode = parsedVideos.filter(video => this.arrayEquals(video.seasons || [], parsedSub.seasons || []) + && this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); if (this.singleVideoFile(bySeasonEpisode)) { - return bySeasonEpisode.map(v => v.videoFile); + return bySeasonEpisode.map(v => v); } const byTitle = parsedVideos.filter(video => video.title && video.title === parsedSub.title); if (this.singleVideoFile(byTitle)) { - return byTitle.map(v => v.videoFile); + return byTitle.map(v => v); } - const byEpisode = parsedVideos.filter(video => this.arrayEquals(video.episodes, parsedSub.episodes)); + const byEpisode = parsedVideos.filter(video => this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); if (this.singleVideoFile(byEpisode)) { - return byEpisode.map(v => v.videoFile); + return byEpisode.map(v => v); } - return undefined; + return []; } - private singleVideoFile = (videos: any[]) => { - return new Set(videos.map(v => v.videoFile.fileIndex)).size === 1; + private singleVideoFile = (videos: IFileAttributes[]): boolean => { + return new Set(videos.map(v => v.fileIndex)).size === 1; } - private parsePath = (path: string) => { + private parsePath = (path: string): IFileAttributes => { const pathParts = path.split('/').map(part => this.parseFilename(part)); const parsedWithEpisode = pathParts.find(parsed => parsed.season && parsed.episodes); return parsedWithEpisode || pathParts[pathParts.length - 1]; } - private parseFilename = (filename: string) => { + private parseFilename = (filename: string) : IFileAttributes => { const parsedInfo = parse(filename) const titleEpisode = parsedInfo.title.match(/(\d+)$/); if (!parsedInfo.episodes && titleEpisode) { @@ -87,7 +88,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return parsedInfo; } - private arrayEquals = (array1: any[], array2: any[]) => { + private arrayEquals = (array1: T[], array2: T[]): boolean => { if (!array1 || !array2) return array1 === array2; return array1.length === array2.length && array1.every((value, index) => value === array2[index]) } diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index 5918e19..ad324aa 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,10 +1,10 @@ import axios, {AxiosResponse} from 'axios'; -import {configurationService} from './configuration_service'; -import {ITrackerService} from "../interfaces/tracker_service"; import {inject, injectable} from "inversify"; -import {IocTypes} from "../models/ioc_types"; import {ICacheService} from "../interfaces/cache_service"; import {ILoggingService} from "../interfaces/logging_service"; +import {ITrackerService} from "../interfaces/tracker_service"; +import {IocTypes} from "../models/ioc_types"; +import {configurationService} from './configuration_service'; @injectable() export class TrackerService implements ITrackerService { diff --git a/src/node/consumer/src/main.ts b/src/node/consumer/src/main.ts index a523bdf..9efc598 100644 --- a/src/node/consumer/src/main.ts +++ b/src/node/consumer/src/main.ts @@ -1,8 +1,9 @@ +import "reflect-metadata"; // required +import {ICompositionalRoot} from "./lib/interfaces/composition_root"; import {serviceContainer} from "./lib/models/inversify_config"; import {IocTypes} from "./lib/models/ioc_types"; -import {ICompositionalRoot} from "./lib/interfaces/composition_root"; -(async () => { +(async (): Promise => { const compositionalRoot = serviceContainer.get(IocTypes.ICompositionalRoot); await compositionalRoot.start(); })(); \ No newline at end of file diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index 435ebc2..cf2dbcd 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -1,23 +1,29 @@ { "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "pretty": true, + "target": "es2020", + "module": "es2020", + "allowJs": true, "removeComments": true, - "rootDir": "./src", + "resolveJsonModule": true, + "typeRoots": [ + "./node_modules/@types" + ], "sourceMap": true, - "target": "ES6", + "outDir": "dist", + "strict": true, "lib": [ - "es6" - ], - "types": [ - "node", - "reflect-metadata" + "es2020" ], + "baseUrl": ".", + "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true - } + "moduleResolution": "Node", + "skipLibCheck": true, + }, + "include": [ + "src/**/*" + ], + "exclude": ["node_modules"], } \ No newline at end of file From 028bb122e17474089eaeb5b5eb462413cdcb313c Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 20:59:37 +0000 Subject: [PATCH 31/55] back to esbuild- imports changed --- src/node/consumer/.swcrc | 15 - src/node/consumer/esbuild.js | 54 + src/node/consumer/package-lock.json | 1662 ++++++++++++++++- src/node/consumer/package.json | 21 +- .../src/lib/interfaces/cache_service.ts | 2 +- .../src/lib/interfaces/cinemeta_metadata.ts | 2 +- .../lib/interfaces/kitsu_catalog_metadata.ts | 2 +- .../src/lib/interfaces/kitsu_metadata.ts | 2 +- .../src/lib/interfaces/metadata_response.ts | 2 +- .../src/lib/interfaces/metadata_service.ts | 4 +- .../interfaces/parse_torrent_title_result.ts | 2 +- .../src/lib/interfaces/parsed_torrent.ts | 6 +- .../src/lib/interfaces/season_episode_map.ts | 2 +- .../interfaces/torrent_download_service.ts | 4 +- .../lib/interfaces/torrent_entries_service.ts | 8 +- .../lib/interfaces/torrent_file_collection.ts | 6 +- .../lib/interfaces/torrent_file_service.ts | 4 +- .../interfaces/torrent_processing_service.ts | 2 +- .../interfaces/torrent_subtitle_service.ts | 2 +- .../src/lib/jobs/process_torrents_job.ts | 16 +- .../src/lib/models/composition_root.ts | 10 +- .../lib/models/configuration/cache_config.ts | 2 +- .../models/configuration/database_config.ts | 2 +- .../lib/models/configuration/job_config.ts | 2 +- .../models/configuration/tracker_config.ts | 2 +- .../src/lib/models/inversify_config.ts | 50 +- .../src/lib/repository/database_repository.ts | 34 +- .../interfaces/database_repository.ts | 20 +- .../repository/interfaces/file_attributes.ts | 4 +- .../interfaces/torrent_attributes.ts | 6 +- .../src/lib/repository/models/content.ts | 4 +- .../src/lib/repository/models/file.ts | 6 +- .../src/lib/repository/models/ingestedPage.ts | 2 +- .../lib/repository/models/ingestedTorrent.ts | 2 +- .../src/lib/repository/models/provider.ts | 2 +- .../src/lib/repository/models/skipTorrent.ts | 2 +- .../src/lib/repository/models/subtitle.ts | 4 +- .../src/lib/repository/models/torrent.ts | 8 +- .../src/lib/services/cache_service.ts | 12 +- .../src/lib/services/configuration_service.ts | 14 +- .../src/lib/services/logging_service.ts | 2 +- .../src/lib/services/metadata_service.ts | 23 +- .../lib/services/torrent_download_service.ts | 20 +- .../lib/services/torrent_entries_service.ts | 38 +- .../src/lib/services/torrent_file_service.ts | 34 +- .../services/torrent_processing_service.ts | 16 +- .../lib/services/torrent_subtitle_service.ts | 8 +- .../src/lib/services/tracker_service.ts | 10 +- src/node/consumer/src/main.ts | 6 +- src/node/consumer/tsconfig.json | 53 +- 50 files changed, 1935 insertions(+), 281 deletions(-) delete mode 100644 src/node/consumer/.swcrc create mode 100644 src/node/consumer/esbuild.js diff --git a/src/node/consumer/.swcrc b/src/node/consumer/.swcrc deleted file mode 100644 index eff14b3..0000000 --- a/src/node/consumer/.swcrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "jsc": { - "parser": { - "syntax": "typescript", - "tsx": false, - "decorators": true, - "dynamicImport": true - }, - "target": "es2020", - "baseUrl": "." - }, - "module": { - "type": "commonjs" - } -} \ No newline at end of file diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.js new file mode 100644 index 0000000..17393df --- /dev/null +++ b/src/node/consumer/esbuild.js @@ -0,0 +1,54 @@ +import {build} from "esbuild"; +import {readFileSync, rmSync} from "fs"; + +const {devDependencies} = JSON.parse(readFileSync("./package.json", "utf8")); + +const start = Date.now(); + +try { + const outdir = "dist"; + + rmSync(outdir, {recursive: true, force: true}); + + build({ + bundle: true, + entryPoints: [ + "./src/main.ts", + ], + external: [...(devDependencies && Object.keys(devDependencies))], + keepNames: true, + minify: true, + outbase: "./src", + outdir, + outExtension: { + ".js": ".cjs", + }, + platform: "node", + plugins: [ + { + name: "populate-import-meta", + setup: ({onLoad}) => { + onLoad({filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`)}, args => { + const contents = readFileSync(args.path, "utf8"); + + const transformedContents = contents + .replace(/import\.meta/g, `{dirname:__dirname,filename:__filename}`) + .replace(/import\.meta\.filename/g, "__filename") + .replace(/import\.meta\.dirname/g, "__dirname"); + + return {contents: transformedContents, loader: "default"}; + }); + }, + } + ], + }).then(() => { + // biome-ignore lint/style/useTemplate: + // eslint-disable-next-line no-undef + console.log("⚡ " + "\x1b[32m" + `Done in ${Date.now() - start}ms`); + }); +} catch (e) { + // eslint-disable-next-line no-undef + console.log(e); + // eslint-disable-next-line no-undef + process.exit(1); +} \ No newline at end of file diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index a7c3169..c5ada6b 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -39,11 +39,18 @@ "@types/webtorrent": "^0.109.7", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", + "node-gyp": "^10.0.1", + "nodemon": "^3.0.3", "pino-pretty": "^10.3.1", + "ts-node": "^10.9.2", + "tsc-alias": "^1.8.8", + "tsconfig-paths": "^4.2.0", "tsx": "^4.7.0", "typescript": "^5.3.3" } @@ -68,6 +75,30 @@ "node": ">=0.8" } }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz", @@ -518,6 +549,127 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@mole-inc/bin-wrapper": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz", @@ -576,6 +728,71 @@ "node": ">= 8" } }, + "node_modules/@npmcli/agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", + "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@silentbot1/nat-api": { "version": "0.4.7", "resolved": "https://registry.npmjs.org/@silentbot1/nat-api/-/nat-api-0.4.7.tgz", @@ -996,6 +1213,30 @@ "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", "dev": true }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, "node_modules/@types/amqplib": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz", @@ -1047,8 +1288,9 @@ }, "node_modules/@types/json5": { "version": "0.0.29", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, "node_modules/@types/keyv": { "version": "3.1.4", @@ -1465,6 +1707,12 @@ "http-parser-js": "^0.4.3" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1495,6 +1743,40 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "dev": true, @@ -1550,8 +1832,6 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1580,6 +1860,12 @@ } ] }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "dev": true, @@ -1963,8 +2249,6 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -2155,6 +2439,75 @@ "node": ">=6.14.2" } }, + "node_modules/cacache": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", + "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/cache-chunk-store": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/cache-chunk-store/-/cache-chunk-store-3.2.2.tgz", @@ -2315,8 +2668,6 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2341,8 +2692,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -2350,6 +2699,15 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-dgram": { "version": "3.0.6", "funding": [ @@ -2408,6 +2766,29 @@ "block-iterator": "^1.1.1" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -2480,6 +2861,48 @@ "version": "0.0.1", "license": "MIT" }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2535,6 +2958,12 @@ } ] }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/create-torrent": { "version": "6.0.16", "resolved": "https://registry.npmjs.org/create-torrent/-/create-torrent-6.0.16.tgz", @@ -2593,6 +3022,24 @@ "wrappy": "1" } }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-fetch-ponyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cross-fetch-ponyfill/-/cross-fetch-ponyfill-1.0.3.tgz", @@ -2663,6 +3110,22 @@ "node": ">= 12" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -2790,6 +3253,15 @@ "version": "1.3.0", "license": "MIT" }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2864,6 +3336,39 @@ "version": "2.0.6", "license": "MIT" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/entities": { "version": "4.5.0", "license": "BSD-2-Clause", @@ -2874,6 +3379,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/err-code": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", @@ -3006,6 +3520,15 @@ "@esbuild/win32-x64": "0.20.0" } }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3191,6 +3714,30 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "dev": true, @@ -3320,6 +3867,12 @@ "node": ">=4" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, "node_modules/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -3604,6 +4157,34 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "license": "MIT", @@ -3632,6 +4213,18 @@ "resolved": "https://registry.npmjs.org/freelist/-/freelist-1.0.3.tgz", "integrity": "sha512-Ji7fEnMdZDGbS5oXElpRJsn9jPvBR8h/037D3bzreNmS8809cISq/2D9//JbA/TaZmkkN8cmecXwmQHmM+NHhg==" }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/fs-native-extensions": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.2.5.tgz", @@ -3706,6 +4299,15 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "dev": true, @@ -3906,6 +4508,12 @@ "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/graphemer": { "version": "1.4.0", "dev": true, @@ -4019,6 +4627,19 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", "integrity": "sha512-u8u5ZaG0Tr/VvHlucK2ufMuOp4/5bvwgneXle+y228K5rMbJOlVjThONcaAw3ikAy8b2OO9RfEucdMHFz3UWMA==" }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -4032,6 +4653,19 @@ "node": ">=10.19.0" } }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4093,6 +4727,12 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "dev": true, @@ -4116,6 +4756,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inflection": { "version": "1.13.4", "engines": [ @@ -4202,8 +4851,6 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4275,6 +4922,15 @@ "resolved": "https://registry.npmjs.org/is-file/-/is-file-1.0.0.tgz", "integrity": "sha512-ZGMuc+xA8mRnrXtmtf2l/EkIW2zaD2LSBWlaOVEF6yH4RTndHob65V4SwWWdtGKVthQfXPVKsXqw4TDUjbVxVQ==" }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "dev": true, @@ -4286,6 +4942,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, "node_modules/is-negative-zero": { "version": "2.0.2", "dev": true, @@ -4435,6 +5097,24 @@ "version": "2.0.0", "license": "ISC" }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/join-async-iterator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/join-async-iterator/-/join-async-iterator-1.1.1.tgz", @@ -4476,14 +5156,15 @@ "license": "MIT" }, "node_modules/json5": { - "version": "1.0.2", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/junk": { @@ -4678,6 +5359,34 @@ "thirty-two": "^1.0.2" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "dev": true, + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/memory-chunk-store": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/memory-chunk-store/-/memory-chunk-store-1.3.5.tgz", @@ -4779,6 +5488,153 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/moment": { "version": "2.30.1", "license": "MIT", @@ -4876,6 +5732,19 @@ "node": ">=12" } }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, "node_modules/name-to-imdb": { "version": "3.0.4", "license": "MIT", @@ -4925,6 +5794,15 @@ "version": "2.0.0", "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -5007,6 +5885,30 @@ "version": "3.0.1", "license": "BSD-2-Clause" }, + "node_modules/node-gyp": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/node-gyp-build": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", @@ -5017,13 +5919,223 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/nodemon": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", + "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "optional": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5240,6 +6352,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "license": "MIT" @@ -5315,6 +6442,22 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5604,6 +6747,18 @@ "nice-napi": "^1.0.2" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "license": "MIT", @@ -5643,6 +6798,15 @@ "node": ">= 0.8.0" } }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5663,6 +6827,25 @@ "node": ">=16" } }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-retry/node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, "node_modules/proxy-from-env": { "version": "1.1.0", "license": "MIT" @@ -5673,6 +6856,12 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -5710,6 +6899,15 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "funding": [ @@ -5868,8 +7066,6 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "optional": true, - "peer": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -5898,6 +7094,12 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "dev": true, @@ -5914,6 +7116,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requires-port": { "version": "1.0.0", "license": "MIT" @@ -5969,6 +7180,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", "license": "MIT" @@ -6043,6 +7263,15 @@ ], "license": "MIT" }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-array-concat": { "version": "1.1.0", "dev": true, @@ -6342,6 +7571,15 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.0.4", "dev": true, @@ -6360,6 +7598,45 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6391,6 +7668,20 @@ "npm": ">= 3.0.0" } }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/socks/node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", @@ -6444,6 +7735,12 @@ "memory-pager": "^1.0.2" } }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, "node_modules/speed-limiter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/speed-limiter/-/speed-limiter-1.0.2.tgz", @@ -6471,6 +7768,18 @@ "node": ">= 10.x" } }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/streamx": { "version": "2.15.7", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.7.tgz", @@ -6484,6 +7793,35 @@ "version": "0.10.31", "license": "MIT" }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.8", "dev": true, @@ -6537,6 +7875,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "dev": true, @@ -6624,6 +7975,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -6695,6 +8096,27 @@ "version": "1.0.1", "license": "MIT" }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trim-repeated": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-2.0.0.tgz", @@ -6731,15 +8153,87 @@ "typescript": ">=4.2.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, - "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsc-alias": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.8.tgz", + "integrity": "sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/tslib": { @@ -7289,10 +8783,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/underscore": { "version": "1.13.6", "license": "MIT" }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/unordered-array-remove": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz", @@ -7511,6 +9035,12 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/validator": { "version": "13.11.0", "license": "MIT", @@ -8023,6 +9553,41 @@ "@types/node": "*" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "license": "ISC" @@ -8054,10 +9619,55 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "license": "ISC" }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 1a04817..bd5bdf9 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -3,14 +3,12 @@ "version": "0.0.1", "type": "module", "scripts": { - "build": "swc src -d dist", - "watch-compile": "swc src -w --out-dir dist", - "watch-dev": "nodemon --watch \"dist/**/*\" -e js ./dist/main.js", - "dev": "concurrently \"npm run watch-compile\" \"npm run watch-dev\"", - "start": "node dist/main.js", "clean": "rm -rf dist", - "lint": "eslint --ext .ts src", - "lint:fix": "eslint --ext .ts src --fix" + "build": "node esbuild.js", + "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", + "start": "node dist/main.cjs", + "lint": "npx eslint ./src --ext .ts,.js", + "lint-fix": "npm run lint -- --fix" }, "license": "MIT", "dependencies": { @@ -35,21 +33,24 @@ "webtorrent": "^2.1.35" }, "devDependencies": { - "@swc/cli": "^0.3.9", - "@swc/core": "^1.4.0", + "node-gyp": "^10.0.1", + "nodemon": "^3.0.3", "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/validator": "^13.11.8", + "@types/webtorrent": "^0.109.7", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "@types/webtorrent": "^0.109.7", + "concurrently": "^8.2.2", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", "pino-pretty": "^10.3.1", "tsx": "^4.7.0", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", "typescript": "^5.3.3" } } diff --git a/src/node/consumer/src/lib/interfaces/cache_service.ts b/src/node/consumer/src/lib/interfaces/cache_service.ts index 9487547..40d56c6 100644 --- a/src/node/consumer/src/lib/interfaces/cache_service.ts +++ b/src/node/consumer/src/lib/interfaces/cache_service.ts @@ -1,4 +1,4 @@ -import {CacheMethod} from "../services/cache_service"; +import {CacheMethod} from "@services/cache_service"; /* eslint-disable @typescript-eslint/no-explicit-any */ export interface ICacheService { diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts index c2821f3..c19ebf4 100644 --- a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -1,4 +1,4 @@ -import {ICommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; export interface ICinemetaJsonResponse { meta?: ICinemetaMetaData; diff --git a/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts index a29f798..277b44c 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_catalog_metadata.ts @@ -1,4 +1,4 @@ -import {IKitsuLink, IKitsuTrailer} from "./kitsu_metadata"; +import {IKitsuLink, IKitsuTrailer} from "@interfaces/kitsu_metadata"; export interface IKitsuCatalogJsonResponse { metas: IKitsuCatalogMetaData[]; diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts index 9b4f4e6..56229b5 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -1,4 +1,4 @@ -import {ICommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; export interface IKitsuJsonResponse { cacheMaxAge?: number; diff --git a/src/node/consumer/src/lib/interfaces/metadata_response.ts b/src/node/consumer/src/lib/interfaces/metadata_response.ts index c3d481f..8bccc5e 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_response.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_response.ts @@ -1,4 +1,4 @@ -import {ICommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; export interface IMetadataResponse { kitsuId?: number; diff --git a/src/node/consumer/src/lib/interfaces/metadata_service.ts b/src/node/consumer/src/lib/interfaces/metadata_service.ts index e7abec0..d9c583d 100644 --- a/src/node/consumer/src/lib/interfaces/metadata_service.ts +++ b/src/node/consumer/src/lib/interfaces/metadata_service.ts @@ -1,5 +1,5 @@ -import {IMetaDataQuery} from "./metadata_query"; -import {IMetadataResponse} from "./metadata_response"; +import {IMetaDataQuery} from "@interfaces/metadata_query"; +import {IMetadataResponse} from "@interfaces/metadata_response"; export interface IMetadataService { getKitsuId(info: IMetaDataQuery): Promise; diff --git a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts index 71514b3..24429fc 100644 --- a/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts +++ b/src/node/consumer/src/lib/interfaces/parse_torrent_title_result.ts @@ -1,4 +1,4 @@ -import {IFileAttributes} from "../repository/interfaces/file_attributes"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; export interface IParseTorrentTitleResult { title?: string; diff --git a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts index 26ec81d..cf30030 100644 --- a/src/node/consumer/src/lib/interfaces/parsed_torrent.ts +++ b/src/node/consumer/src/lib/interfaces/parsed_torrent.ts @@ -1,6 +1,6 @@ -import {TorrentType} from "../enums/torrent_types"; -import {IParseTorrentTitleResult} from "./parse_torrent_title_result"; -import {ITorrentFileCollection} from "./torrent_file_collection"; +import {TorrentType} from "@enums/torrent_types"; +import {IParseTorrentTitleResult} from "@interfaces/parse_torrent_title_result"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; export interface IParsedTorrent extends IParseTorrentTitleResult { size?: number; diff --git a/src/node/consumer/src/lib/interfaces/season_episode_map.ts b/src/node/consumer/src/lib/interfaces/season_episode_map.ts index 55bb2f7..5fae99b 100644 --- a/src/node/consumer/src/lib/interfaces/season_episode_map.ts +++ b/src/node/consumer/src/lib/interfaces/season_episode_map.ts @@ -1,4 +1,4 @@ -import {ICommonVideoMetadata} from "./common_video_metadata"; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; export interface ISeasonEpisodeMap { [season: number]: { diff --git a/src/node/consumer/src/lib/interfaces/torrent_download_service.ts b/src/node/consumer/src/lib/interfaces/torrent_download_service.ts index 980b354..5d7789c 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_download_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_download_service.ts @@ -1,5 +1,5 @@ -import {IParsedTorrent} from "./parsed_torrent"; -import {ITorrentFileCollection} from "./torrent_file_collection"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; export interface ITorrentDownloadService { getTorrentFiles(torrent: IParsedTorrent, timeout: number): Promise; diff --git a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts index a92ba1c..f05268a 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts @@ -1,7 +1,7 @@ -import {ITorrentAttributes} from "../repository/interfaces/torrent_attributes"; -import {SkipTorrent} from "../repository/models/skipTorrent"; -import {Torrent} from "../repository/models/torrent"; -import {IParsedTorrent} from "./parsed_torrent"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentAttributes} from "@repository/interfaces/torrent_attributes"; +import {SkipTorrent} from "@repository/models/skipTorrent"; +import {Torrent} from "@repository/models/torrent"; export interface ITorrentEntriesService { createTorrentEntry(torrent: IParsedTorrent, overwrite: boolean): Promise; diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts index 3306a44..043c01a 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_file_collection.ts @@ -1,6 +1,6 @@ -import {IContentAttributes} from "../repository/interfaces/content_attributes"; -import {IFileAttributes} from "../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; +import {IContentAttributes} from "@repository/interfaces/content_attributes"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; export interface ITorrentFileCollection { contents?: IContentAttributes[]; diff --git a/src/node/consumer/src/lib/interfaces/torrent_file_service.ts b/src/node/consumer/src/lib/interfaces/torrent_file_service.ts index f34218c..bedea14 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_file_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_file_service.ts @@ -1,5 +1,5 @@ -import {IParsedTorrent} from "./parsed_torrent"; -import {ITorrentFileCollection} from "./torrent_file_collection"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; export interface ITorrentFileService { parseTorrentFiles(torrent: IParsedTorrent): Promise; diff --git a/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts index e3aa901..abdbd5f 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_processing_service.ts @@ -1,4 +1,4 @@ -import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; +import {IIngestedTorrentAttributes} from "@repository/interfaces/ingested_torrent_attributes"; export interface ITorrentProcessingService { processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise; diff --git a/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts b/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts index 66648b5..1869c0b 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_subtitle_service.ts @@ -1,4 +1,4 @@ -import {ITorrentFileCollection} from "./torrent_file_collection"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; export interface ITorrentSubtitleService { assignSubtitles(fileCollection: ITorrentFileCollection): ITorrentFileCollection; diff --git a/src/node/consumer/src/lib/jobs/process_torrents_job.ts b/src/node/consumer/src/lib/jobs/process_torrents_job.ts index 9ba5aef..6af4966 100644 --- a/src/node/consumer/src/lib/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/lib/jobs/process_torrents_job.ts @@ -1,12 +1,12 @@ -import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' +import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "@interfaces/ingested_rabbit_message"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; +import {ITorrentProcessingService} from "@interfaces/torrent_processing_service"; +import {IocTypes} from "@models/ioc_types"; +import {IIngestedTorrentAttributes} from "@repository/interfaces/ingested_torrent_attributes"; +import {configurationService} from '@services/configuration_service'; +import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' import {inject, injectable} from "inversify"; -import {IIngestedRabbitMessage, IIngestedRabbitTorrent} from "../interfaces/ingested_rabbit_message"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; -import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; -import {IocTypes} from "../models/ioc_types"; -import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; -import {configurationService} from '../services/configuration_service'; @injectable() export class ProcessTorrentsJob implements IProcessTorrentsJob { diff --git a/src/node/consumer/src/lib/models/composition_root.ts b/src/node/consumer/src/lib/models/composition_root.ts index 2b8dbf0..7270cd4 100644 --- a/src/node/consumer/src/lib/models/composition_root.ts +++ b/src/node/consumer/src/lib/models/composition_root.ts @@ -1,9 +1,9 @@ +import {ICompositionalRoot} from "@interfaces/composition_root"; +import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; +import {ITrackerService} from "@interfaces/tracker_service"; +import {IocTypes} from "@models/ioc_types"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; import {inject, injectable} from "inversify"; -import {ICompositionalRoot} from "../interfaces/composition_root"; -import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; -import {ITrackerService} from "../interfaces/tracker_service"; -import {IDatabaseRepository} from "../repository/interfaces/database_repository"; -import {IocTypes} from "./ioc_types"; @injectable() export class CompositionalRoot implements ICompositionalRoot { diff --git a/src/node/consumer/src/lib/models/configuration/cache_config.ts b/src/node/consumer/src/lib/models/configuration/cache_config.ts index 1cba364..21f283f 100644 --- a/src/node/consumer/src/lib/models/configuration/cache_config.ts +++ b/src/node/consumer/src/lib/models/configuration/cache_config.ts @@ -1,4 +1,4 @@ -import {BooleanHelpers} from "../../helpers/boolean_helpers"; +import {BooleanHelpers} from "@helpers/boolean_helpers"; export const cacheConfig = { MONGODB_HOST: process.env.MONGODB_HOST || 'mongodb', diff --git a/src/node/consumer/src/lib/models/configuration/database_config.ts b/src/node/consumer/src/lib/models/configuration/database_config.ts index bcefcd6..4c07d73 100644 --- a/src/node/consumer/src/lib/models/configuration/database_config.ts +++ b/src/node/consumer/src/lib/models/configuration/database_config.ts @@ -1,4 +1,4 @@ -import {BooleanHelpers} from "../../helpers/boolean_helpers"; +import {BooleanHelpers} from "@helpers/boolean_helpers"; export const databaseConfig = { POSTGRES_HOST: process.env.POSTGRES_HOST || 'postgres', diff --git a/src/node/consumer/src/lib/models/configuration/job_config.ts b/src/node/consumer/src/lib/models/configuration/job_config.ts index 57cb6ad..70f8476 100644 --- a/src/node/consumer/src/lib/models/configuration/job_config.ts +++ b/src/node/consumer/src/lib/models/configuration/job_config.ts @@ -1,4 +1,4 @@ -import {BooleanHelpers} from "../../helpers/boolean_helpers"; +import {BooleanHelpers} from "@helpers/boolean_helpers"; export const jobConfig = { JOB_CONCURRENCY: parseInt(process.env.JOB_CONCURRENCY || "1", 10), diff --git a/src/node/consumer/src/lib/models/configuration/tracker_config.ts b/src/node/consumer/src/lib/models/configuration/tracker_config.ts index 8b31fff..f748b93 100644 --- a/src/node/consumer/src/lib/models/configuration/tracker_config.ts +++ b/src/node/consumer/src/lib/models/configuration/tracker_config.ts @@ -1,4 +1,4 @@ -import {BooleanHelpers} from "../../helpers/boolean_helpers"; +import {BooleanHelpers} from "@helpers/boolean_helpers"; export const trackerConfig = { TRACKERS_URL: process.env.TRACKERS_URL || 'https://ngosang.github.io/trackerslist/trackers_all.txt', diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/lib/models/inversify_config.ts index 17da92b..2dcbc8c 100644 --- a/src/node/consumer/src/lib/models/inversify_config.ts +++ b/src/node/consumer/src/lib/models/inversify_config.ts @@ -1,29 +1,29 @@ +import {ICacheService} from "@interfaces/cache_service"; +import {ICompositionalRoot} from "@interfaces/composition_root"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; +import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; +import {ITorrentEntriesService} from "@interfaces/torrent_entries_service"; +import {ITorrentFileService} from "@interfaces/torrent_file_service"; +import {ITorrentProcessingService} from "@interfaces/torrent_processing_service"; +import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; +import {ITrackerService} from "@interfaces/tracker_service"; +import {ProcessTorrentsJob} from "@jobs/process_torrents_job"; +import {CompositionalRoot} from "@models/composition_root"; +import {IocTypes} from "@models/ioc_types"; +import {DatabaseRepository} from "@repository/database_repository"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {CacheService} from "@services/cache_service"; +import {LoggingService} from "@services/logging_service"; +import {MetadataService} from "@services/metadata_service"; +import {TorrentDownloadService} from "@services/torrent_download_service"; +import {TorrentEntriesService} from "@services/torrent_entries_service"; +import {TorrentFileService} from "@services/torrent_file_service"; +import {TorrentProcessingService} from "@services/torrent_processing_service"; +import {TorrentSubtitleService} from "@services/torrent_subtitle_service"; +import {TrackerService} from "@services/tracker_service"; import {Container} from "inversify"; -import {ICacheService} from "../interfaces/cache_service"; -import {ICompositionalRoot} from "../interfaces/composition_root"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IMetadataService} from "../interfaces/metadata_service"; -import {IProcessTorrentsJob} from "../interfaces/process_torrents_job"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; -import {ITorrentFileService} from "../interfaces/torrent_file_service"; -import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; -import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {ITrackerService} from "../interfaces/tracker_service"; -import {ProcessTorrentsJob} from "../jobs/process_torrents_job"; -import {DatabaseRepository} from "../repository/database_repository"; -import {IDatabaseRepository} from "../repository/interfaces/database_repository"; -import {CacheService} from "../services/cache_service"; -import {LoggingService} from "../services/logging_service"; -import {MetadataService} from "../services/metadata_service"; -import {TorrentDownloadService} from "../services/torrent_download_service"; -import {TorrentEntriesService} from "../services/torrent_entries_service"; -import {TorrentFileService} from "../services/torrent_file_service"; -import {TorrentProcessingService} from "../services/torrent_processing_service"; -import {TorrentSubtitleService} from "../services/torrent_subtitle_service"; -import {TrackerService} from "../services/tracker_service"; -import {CompositionalRoot} from "./composition_root"; -import {IocTypes} from "./ioc_types"; const serviceContainer = new Container(); diff --git a/src/node/consumer/src/lib/repository/database_repository.ts b/src/node/consumer/src/lib/repository/database_repository.ts index c59f778..0a1a657 100644 --- a/src/node/consumer/src/lib/repository/database_repository.ts +++ b/src/node/consumer/src/lib/repository/database_repository.ts @@ -1,24 +1,24 @@ +import {PromiseHelpers} from '@helpers/promises_helpers'; +import {ILoggingService} from "@interfaces/logging_service"; +import {IocTypes} from "@models/ioc_types"; +import {IContentCreationAttributes} from "@repository/interfaces/content_attributes"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {IFileAttributes, IFileCreationAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "@repository/interfaces/subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; +import {Content} from "@repository/models/content"; +import {File} from "@repository/models/file"; +import {IngestedPage} from "@repository/models/ingestedPage"; +import {IngestedTorrent} from "@repository/models/ingestedTorrent"; +import {Provider} from "@repository/models/provider"; +import {SkipTorrent} from "@repository/models/skipTorrent"; +import {Subtitle} from "@repository/models/subtitle"; +import {Torrent} from "@repository/models/torrent"; +import {configurationService} from '@services/configuration_service'; import {inject, injectable} from "inversify"; import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; import {Model, Sequelize} from 'sequelize-typescript'; -import {PromiseHelpers} from '../helpers/promises_helpers'; -import {ILoggingService} from "../interfaces/logging_service"; -import {IocTypes} from "../models/ioc_types"; -import {configurationService} from '../services/configuration_service'; -import {IContentCreationAttributes} from "./interfaces/content_attributes"; -import {IDatabaseRepository} from "./interfaces/database_repository"; -import {IFileAttributes, IFileCreationAttributes} from "./interfaces/file_attributes"; -import {ISubtitleAttributes, ISubtitleCreationAttributes} from "./interfaces/subtitle_attributes"; -import {ITorrentAttributes, ITorrentCreationAttributes} from "./interfaces/torrent_attributes"; -import {Content} from "./models/content"; -import {File} from "./models/file"; -import {IngestedPage} from "./models/ingestedPage"; -import {IngestedTorrent} from "./models/ingestedTorrent"; -import {Provider} from "./models/provider"; -import {SkipTorrent} from "./models/skipTorrent"; -import {Subtitle} from "./models/subtitle"; -import {Torrent} from "./models/torrent"; @injectable() export class DatabaseRepository implements IDatabaseRepository { diff --git a/src/node/consumer/src/lib/repository/interfaces/database_repository.ts b/src/node/consumer/src/lib/repository/interfaces/database_repository.ts index 9331853..9b54278 100644 --- a/src/node/consumer/src/lib/repository/interfaces/database_repository.ts +++ b/src/node/consumer/src/lib/repository/interfaces/database_repository.ts @@ -1,15 +1,15 @@ +import {IContentCreationAttributes} from "@repository/interfaces/content_attributes"; +import {IFileAttributes, IFileCreationAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "@repository/interfaces/subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; +import {Content} from "@repository/models/content"; +import {File} from "@repository/models/file"; +import {Provider} from "@repository/models/provider"; +import {SkipTorrent} from "@repository/models/skipTorrent"; +import {Subtitle} from "@repository/models/subtitle"; +import {Torrent} from "@repository/models/torrent"; import {WhereOptions} from "sequelize"; import {Model} from "sequelize-typescript"; -import {Content} from "../models/content"; -import {File} from "../models/file"; -import {Provider} from "../models/provider"; -import {SkipTorrent} from "../models/skipTorrent"; -import {Subtitle} from "../models/subtitle"; -import {Torrent} from "../models/torrent"; -import {IContentCreationAttributes} from "./content_attributes"; -import {IFileAttributes, IFileCreationAttributes} from "./file_attributes"; -import {ISubtitleAttributes, ISubtitleCreationAttributes} from "./subtitle_attributes"; -import {ITorrentAttributes, ITorrentCreationAttributes} from "./torrent_attributes"; export interface IDatabaseRepository { connect(): Promise; diff --git a/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts index 25f025c..b899f56 100644 --- a/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts +++ b/src/node/consumer/src/lib/repository/interfaces/file_attributes.ts @@ -1,6 +1,6 @@ +import {IParseTorrentTitleResult} from "@interfaces/parse_torrent_title_result"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; import {Optional} from "sequelize"; -import {IParseTorrentTitleResult} from "../../interfaces/parse_torrent_title_result"; -import {ISubtitleAttributes} from "./subtitle_attributes"; export interface IFileAttributes extends IParseTorrentTitleResult { id?: number; diff --git a/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts b/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts index 64e4696..c34fa4c 100644 --- a/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts +++ b/src/node/consumer/src/lib/repository/interfaces/torrent_attributes.ts @@ -1,7 +1,7 @@ +import {IContentAttributes} from "@repository/interfaces/content_attributes"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; import {Optional} from "sequelize"; -import {IContentAttributes} from "./content_attributes"; -import {IFileAttributes} from "./file_attributes"; -import {ISubtitleAttributes} from "./subtitle_attributes"; export interface ITorrentAttributes { infoHash: string; diff --git a/src/node/consumer/src/lib/repository/models/content.ts b/src/node/consumer/src/lib/repository/models/content.ts index 0209273..db7c7cc 100644 --- a/src/node/consumer/src/lib/repository/models/content.ts +++ b/src/node/consumer/src/lib/repository/models/content.ts @@ -1,6 +1,6 @@ +import {IContentAttributes, IContentCreationAttributes} from "@repository/interfaces/content_attributes"; +import {Torrent} from "@repository/models/torrent"; import {BelongsTo, Column, DataType, ForeignKey, Model, Table} from 'sequelize-typescript'; -import {IContentAttributes, IContentCreationAttributes} from "../interfaces/content_attributes"; -import {Torrent} from "./torrent"; @Table({modelName: 'content', timestamps: false}) export class Content extends Model { diff --git a/src/node/consumer/src/lib/repository/models/file.ts b/src/node/consumer/src/lib/repository/models/file.ts index a9785c8..378311b 100644 --- a/src/node/consumer/src/lib/repository/models/file.ts +++ b/src/node/consumer/src/lib/repository/models/file.ts @@ -1,7 +1,7 @@ +import {IFileAttributes, IFileCreationAttributes} from "@repository/interfaces/file_attributes"; +import {Subtitle} from "@repository/models/subtitle"; +import {Torrent} from "@repository/models/torrent"; import {BelongsTo, Column, DataType, ForeignKey, HasMany, Model, Table} from 'sequelize-typescript'; -import {IFileAttributes, IFileCreationAttributes} from "../interfaces/file_attributes"; -import {Subtitle} from "./subtitle"; -import {Torrent} from "./torrent"; const indexes = [ { diff --git a/src/node/consumer/src/lib/repository/models/ingestedPage.ts b/src/node/consumer/src/lib/repository/models/ingestedPage.ts index 3c08b1b..0e91bb5 100644 --- a/src/node/consumer/src/lib/repository/models/ingestedPage.ts +++ b/src/node/consumer/src/lib/repository/models/ingestedPage.ts @@ -1,5 +1,5 @@ +import {IIngestedPageAttributes, IIngestedPageCreationAttributes} from "@repository/interfaces/ingested_page_attributes"; import {Column, DataType, Model, Table} from 'sequelize-typescript'; -import {IIngestedPageAttributes, IIngestedPageCreationAttributes} from "../interfaces/ingested_page_attributes"; const indexes = [ { diff --git a/src/node/consumer/src/lib/repository/models/ingestedTorrent.ts b/src/node/consumer/src/lib/repository/models/ingestedTorrent.ts index 7f03914..437eeca 100644 --- a/src/node/consumer/src/lib/repository/models/ingestedTorrent.ts +++ b/src/node/consumer/src/lib/repository/models/ingestedTorrent.ts @@ -1,5 +1,5 @@ +import {IIngestedTorrentAttributes, IIngestedTorrentCreationAttributes} from "@repository/interfaces/ingested_torrent_attributes"; import {Column, DataType, Model, Table} from 'sequelize-typescript'; -import {IIngestedTorrentAttributes, IIngestedTorrentCreationAttributes} from "../interfaces/ingested_torrent_attributes"; const indexes = [ { diff --git a/src/node/consumer/src/lib/repository/models/provider.ts b/src/node/consumer/src/lib/repository/models/provider.ts index c3506ed..fef9c18 100644 --- a/src/node/consumer/src/lib/repository/models/provider.ts +++ b/src/node/consumer/src/lib/repository/models/provider.ts @@ -1,5 +1,5 @@ +import {IProviderAttributes, IProviderCreationAttributes} from "@repository/interfaces/provider_attributes"; import {Column, DataType, Model, Table} from 'sequelize-typescript'; -import {IProviderAttributes, IProviderCreationAttributes} from "../interfaces/provider_attributes"; @Table({modelName: 'provider', timestamps: false}) export class Provider extends Model { diff --git a/src/node/consumer/src/lib/repository/models/skipTorrent.ts b/src/node/consumer/src/lib/repository/models/skipTorrent.ts index 6e34c79..b280004 100644 --- a/src/node/consumer/src/lib/repository/models/skipTorrent.ts +++ b/src/node/consumer/src/lib/repository/models/skipTorrent.ts @@ -1,5 +1,5 @@ +import {ISkipTorrentAttributes, ISkipTorrentCreationAttributes} from "@repository/interfaces/skip_torrent_attributes"; import {Column, DataType, Model, Table} from 'sequelize-typescript'; -import {ISkipTorrentAttributes, ISkipTorrentCreationAttributes} from "../interfaces/skip_torrent_attributes"; @Table({modelName: 'skip_torrent', timestamps: false}) diff --git a/src/node/consumer/src/lib/repository/models/subtitle.ts b/src/node/consumer/src/lib/repository/models/subtitle.ts index 06fb142..3742caf 100644 --- a/src/node/consumer/src/lib/repository/models/subtitle.ts +++ b/src/node/consumer/src/lib/repository/models/subtitle.ts @@ -1,6 +1,6 @@ +import {ISubtitleAttributes, ISubtitleCreationAttributes} from "@repository/interfaces/subtitle_attributes"; +import {File} from "@repository/models/file"; import {BelongsTo, Column, DataType, ForeignKey, Model, Table} from 'sequelize-typescript'; -import {ISubtitleAttributes, ISubtitleCreationAttributes} from "../interfaces/subtitle_attributes"; -import {File} from "./file"; const indexes = [ { diff --git a/src/node/consumer/src/lib/repository/models/torrent.ts b/src/node/consumer/src/lib/repository/models/torrent.ts index c759d3a..4539e69 100644 --- a/src/node/consumer/src/lib/repository/models/torrent.ts +++ b/src/node/consumer/src/lib/repository/models/torrent.ts @@ -1,8 +1,8 @@ +import {ITorrentAttributes, ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; +import {Content} from "@repository/models/content"; +import {File} from "@repository/models/file"; +import {Subtitle} from "@repository/models/subtitle"; import {Column, DataType, HasMany, Model, Table} from 'sequelize-typescript'; -import {ITorrentAttributes, ITorrentCreationAttributes} from "../interfaces/torrent_attributes"; -import {Content} from "./content"; -import {File} from "./file"; -import {Subtitle} from "./subtitle"; @Table({modelName: 'torrent', timestamps: true}) diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index ab3b0a5..761784a 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -1,12 +1,12 @@ +import {CacheType} from "@enums/cache_types"; +import {ICacheOptions} from "@interfaces/cache_options"; +import {ICacheService} from "@interfaces/cache_service"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IocTypes} from "@models/ioc_types"; +import {configurationService} from '@services/configuration_service'; import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' import {Cache, createCache, MemoryCache, memoryStore} from 'cache-manager'; import {inject, injectable} from "inversify"; -import {CacheType} from "../enums/cache_types"; -import {ICacheOptions} from "../interfaces/cache_options"; -import {ICacheService} from "../interfaces/cache_service"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IocTypes} from "../models/ioc_types"; -import {configurationService} from './configuration_service'; const GLOBAL_KEY_PREFIX = 'knightcrawler-consumer'; const IMDB_ID_PREFIX = `${GLOBAL_KEY_PREFIX}|imdb_id`; diff --git a/src/node/consumer/src/lib/services/configuration_service.ts b/src/node/consumer/src/lib/services/configuration_service.ts index 8955dc9..7545d56 100644 --- a/src/node/consumer/src/lib/services/configuration_service.ts +++ b/src/node/consumer/src/lib/services/configuration_service.ts @@ -1,10 +1,10 @@ -import {cacheConfig} from "../models/configuration/cache_config"; -import {databaseConfig} from "../models/configuration/database_config"; -import {jobConfig} from "../models/configuration/job_config"; -import {metadataConfig} from "../models/configuration/metadata_config"; -import {rabbitConfig} from "../models/configuration/rabbit_config"; -import {torrentConfig} from "../models/configuration/torrent_config"; -import {trackerConfig} from "../models/configuration/tracker_config"; +import {cacheConfig} from "@models/configuration/cache_config"; +import {databaseConfig} from "@models/configuration/database_config"; +import {jobConfig} from "@models/configuration/job_config"; +import {metadataConfig} from "@models/configuration/metadata_config"; +import {rabbitConfig} from "@models/configuration/rabbit_config"; +import {torrentConfig} from "@models/configuration/torrent_config"; +import {trackerConfig} from "@models/configuration/tracker_config"; export const configurationService = { rabbitConfig: rabbitConfig, diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index ee703ba..5b2837d 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -1,6 +1,6 @@ +import {ILoggingService} from "@interfaces/logging_service"; import {injectable} from "inversify"; import {Logger, pino} from "pino"; -import {ILoggingService} from "../interfaces/logging_service"; /* eslint-disable @typescript-eslint/no-explicit-any */ @injectable() diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 1015fb1..3aed419 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -1,20 +1,17 @@ - +import {TorrentType} from '@enums/torrent_types'; +import {ICacheService} from "@interfaces/cache_service"; +import {ICinemetaJsonResponse} from "@interfaces/cinemeta_metadata"; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; +import {IKitsuCatalogJsonResponse} from "@interfaces/kitsu_catalog_metadata"; +import {IKitsuJsonResponse} from "@interfaces/kitsu_metadata"; +import {IMetaDataQuery} from "@interfaces/metadata_query"; +import {IMetadataResponse} from "@interfaces/metadata_response"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IocTypes} from "@models/ioc_types"; import axios, {AxiosResponse} from 'axios'; import {ResultTypes, search} from 'google-sr'; import {inject, injectable} from "inversify"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-expect-error import nameToImdb from 'name-to-imdb'; -import {TorrentType} from '../enums/torrent_types'; -import {ICacheService} from "../interfaces/cache_service"; -import {ICinemetaJsonResponse} from "../interfaces/cinemeta_metadata"; -import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; -import {IKitsuCatalogJsonResponse} from "../interfaces/kitsu_catalog_metadata"; -import {IKitsuJsonResponse} from "../interfaces/kitsu_metadata"; -import {IMetaDataQuery} from "../interfaces/metadata_query"; -import {IMetadataResponse} from "../interfaces/metadata_response"; -import {IMetadataService} from "../interfaces/metadata_service"; -import {IocTypes} from "../models/ioc_types"; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 03a1719..146502d 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -1,17 +1,17 @@ +import {ExtensionHelpers} from '@helpers/extension_helpers'; +import {ILoggingService} from "@interfaces/logging_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {IocTypes} from "@models/ioc_types"; +import {IContentAttributes} from "@repository/interfaces/content_attributes"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; +import {configurationService} from '@services/configuration_service'; import {inject, injectable} from "inversify"; import {encode} from 'magnet-uri'; import {parse} from "parse-torrent-title"; import WebTorrent from "webtorrent"; -import {ExtensionHelpers} from '../helpers/extension_helpers'; -import {ILoggingService} from "../interfaces/logging_service"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {IocTypes} from "../models/ioc_types"; -import {IContentAttributes} from "../repository/interfaces/content_attributes"; -import {IFileAttributes} from "../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; -import {configurationService} from './configuration_service'; interface ITorrentFile { name: string; diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 141bf7c..769510e 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -1,24 +1,24 @@ +import {TorrentType} from '@enums/torrent_types'; +import {PromiseHelpers} from '@helpers/promises_helpers'; +import {ILoggingService} from "@interfaces/logging_service"; +import {IMetaDataQuery} from "@interfaces/metadata_query"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentEntriesService} from "@interfaces/torrent_entries_service"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {ITorrentFileService} from "@interfaces/torrent_file_service"; +import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; +import {IocTypes} from "@models/ioc_types"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {IFileCreationAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; +import {File} from "@repository/models/file"; +import {SkipTorrent} from "@repository/models/skipTorrent"; +import {Subtitle} from "@repository/models/subtitle"; +import {Torrent} from "@repository/models/torrent"; import {inject, injectable} from "inversify"; import {parse} from 'parse-torrent-title'; -import {TorrentType} from '../enums/torrent_types'; -import {PromiseHelpers} from '../helpers/promises_helpers'; -import {ILoggingService} from "../interfaces/logging_service"; -import {IMetaDataQuery} from "../interfaces/metadata_query"; -import {IMetadataService} from "../interfaces/metadata_service"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ITorrentFileService} from "../interfaces/torrent_file_service"; -import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {IocTypes} from "../models/ioc_types"; -import {IDatabaseRepository} from "../repository/interfaces/database_repository"; -import {IFileCreationAttributes} from "../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; -import {ITorrentAttributes, ITorrentCreationAttributes} from "../repository/interfaces/torrent_attributes"; -import {File} from "../repository/models/file"; -import {SkipTorrent} from "../repository/models/skipTorrent"; -import {Subtitle} from "../repository/models/subtitle"; -import {Torrent} from "../repository/models/torrent"; @injectable() export class TorrentEntriesService implements ITorrentEntriesService { diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 59a3360..364d853 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -1,24 +1,24 @@ +import {TorrentType} from '@enums/torrent_types'; +import {ExtensionHelpers} from '@helpers/extension_helpers'; +import {PromiseHelpers} from '@helpers/promises_helpers'; +import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IMetaDataQuery} from "@interfaces/metadata_query"; +import {IMetadataResponse} from "@interfaces/metadata_response"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ISeasonEpisodeMap} from "@interfaces/season_episode_map"; +import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {ITorrentFileService} from "@interfaces/torrent_file_service"; +import {IocTypes} from "@models/ioc_types"; +import {IContentAttributes} from "@repository/interfaces/content_attributes"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {configurationService} from '@services/configuration_service'; import Bottleneck from 'bottleneck'; import {inject, injectable} from "inversify"; import moment from 'moment'; import {parse} from 'parse-torrent-title'; -import {TorrentType} from '../enums/torrent_types'; -import {ExtensionHelpers} from '../helpers/extension_helpers'; -import {PromiseHelpers} from '../helpers/promises_helpers'; -import {ICommonVideoMetadata} from "../interfaces/common_video_metadata"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IMetaDataQuery} from "../interfaces/metadata_query"; -import {IMetadataResponse} from "../interfaces/metadata_response"; -import {IMetadataService} from "../interfaces/metadata_service"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {ISeasonEpisodeMap} from "../interfaces/season_episode_map"; -import {ITorrentDownloadService} from "../interfaces/torrent_download_service"; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ITorrentFileService} from "../interfaces/torrent_file_service"; -import {IocTypes} from "../models/ioc_types"; -import {IContentAttributes} from "../repository/interfaces/content_attributes"; -import {IFileAttributes} from "../repository/interfaces/file_attributes"; -import {configurationService} from './configuration_service'; const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index dd19b78..e62990c 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -1,12 +1,12 @@ +import {TorrentType} from "@enums/torrent_types"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentEntriesService} from "@interfaces/torrent_entries_service"; +import {ITorrentProcessingService} from "@interfaces/torrent_processing_service"; +import {ITrackerService} from "@interfaces/tracker_service"; +import {IocTypes} from "@models/ioc_types"; +import {IIngestedTorrentAttributes} from "@repository/interfaces/ingested_torrent_attributes"; import {inject, injectable} from "inversify"; -import {TorrentType} from "../enums/torrent_types"; -import {ILoggingService} from "../interfaces/logging_service"; -import {IParsedTorrent} from "../interfaces/parsed_torrent"; -import {ITorrentEntriesService} from "../interfaces/torrent_entries_service"; -import {ITorrentProcessingService} from "../interfaces/torrent_processing_service"; -import {ITrackerService} from "../interfaces/tracker_service"; -import {IocTypes} from "../models/ioc_types"; -import {IIngestedTorrentAttributes} from "../repository/interfaces/ingested_torrent_attributes"; @injectable() export class TorrentProcessingService implements ITorrentProcessingService { diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index ec227dc..776bbbd 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -1,9 +1,9 @@ +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; import {injectable} from "inversify"; import {parse} from 'parse-torrent-title'; -import {ITorrentFileCollection} from "../interfaces/torrent_file_collection"; -import {ITorrentSubtitleService} from "../interfaces/torrent_subtitle_service"; -import {IFileAttributes} from "../repository/interfaces/file_attributes"; -import {ISubtitleAttributes} from "../repository/interfaces/subtitle_attributes"; @injectable() export class TorrentSubtitleService implements ITorrentSubtitleService { diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index ad324aa..11f2ad1 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,10 +1,10 @@ +import {ICacheService} from "@interfaces/cache_service"; +import {ILoggingService} from "@interfaces/logging_service"; +import {ITrackerService} from "@interfaces/tracker_service"; +import {IocTypes} from "@models/ioc_types"; +import {configurationService} from '@services/configuration_service'; import axios, {AxiosResponse} from 'axios'; import {inject, injectable} from "inversify"; -import {ICacheService} from "../interfaces/cache_service"; -import {ILoggingService} from "../interfaces/logging_service"; -import {ITrackerService} from "../interfaces/tracker_service"; -import {IocTypes} from "../models/ioc_types"; -import {configurationService} from './configuration_service'; @injectable() export class TrackerService implements ITrackerService { diff --git a/src/node/consumer/src/main.ts b/src/node/consumer/src/main.ts index 9efc598..22466a7 100644 --- a/src/node/consumer/src/main.ts +++ b/src/node/consumer/src/main.ts @@ -1,7 +1,7 @@ import "reflect-metadata"; // required -import {ICompositionalRoot} from "./lib/interfaces/composition_root"; -import {serviceContainer} from "./lib/models/inversify_config"; -import {IocTypes} from "./lib/models/ioc_types"; +import {ICompositionalRoot} from "@interfaces/composition_root"; +import {serviceContainer} from "@models/inversify_config"; +import {IocTypes} from "@models/ioc_types"; (async (): Promise => { const compositionalRoot = serviceContainer.get(IocTypes.ICompositionalRoot); diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index cf2dbcd..fadbe95 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -1,29 +1,36 @@ { + "compileOnSave": false, "compilerOptions": { - "target": "es2020", - "module": "es2020", - "allowJs": true, - "removeComments": true, - "resolveJsonModule": true, - "typeRoots": [ - "./node_modules/@types" - ], - "sourceMap": true, - "outDir": "dist", - "strict": true, - "lib": [ - "es2020" - ], - "baseUrl": ".", - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, + "target": "ESNext", + "lib": ["ESNext"], + "typeRoots": ["node_modules/@types"], + "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "moduleResolution": "Node", - "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "module": "ESNext", + "pretty": true, + "sourceMap": true, + "declaration": true, + "outDir": "dist", + "allowJs": false, + "noEmit": false, + "esModuleInterop": true, + "resolveJsonModule": true, + "importHelpers": true, + "baseUrl": "src", + "paths": { + "@/*": ["*"], + "@enums/*": ["lib/enums/*"], + "@repository/*": ["lib/repository/*"], + "@interfaces/*": ["lib/interfaces/*"], + "@models/*": ["lib/models/*"], + "@services/*": ["lib/services/*"], + "@helpers/*": ["lib/helpers/*"], + "@jobs/*": ["lib/jobs/*"] + } }, - "include": [ - "src/**/*" - ], - "exclude": ["node_modules"], + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] } \ No newline at end of file From 6919622c3034051e257261bf58274740b556941d Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Wed, 7 Feb 2024 21:42:31 +0000 Subject: [PATCH 32/55] meta data seems a bit iffy right now Also gone back to torrent-stream WebTorrent seemed to be throwing the occasional engine crash --- src/node/consumer/package-lock.json | 3282 ++++------------- src/node/consumer/package.json | 11 +- .../src/lib/interfaces/cinemeta_metadata.ts | 1 - .../lib/interfaces/common_video_metadata.ts | 1 + .../src/lib/interfaces/kitsu_metadata.ts | 1 - .../models/configuration/torrent_config.ts | 1 - .../src/lib/services/metadata_service.ts | 29 +- .../lib/services/torrent_download_service.ts | 59 +- .../src/lib/services/torrent_file_service.ts | 2 - 9 files changed, 666 insertions(+), 2721 deletions(-) diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index c5ada6b..820c26c 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -26,21 +26,17 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", - "utp-native": "^2.5.3", - "webtorrent": "^2.1.35" + "torrent-stream": "^1.2.1" }, "devDependencies": { - "@swc/cli": "^0.3.9", - "@swc/core": "^1.4.0", "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", + "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", - "@types/webtorrent": "^0.109.7", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "concurrently": "^8.2.2", - "cross-env": "^7.0.3", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", @@ -49,7 +45,6 @@ "nodemon": "^3.0.3", "pino-pretty": "^10.3.1", "ts-node": "^10.9.2", - "tsc-alias": "^1.8.8", "tsconfig-paths": "^4.2.0", "tsx": "^4.7.0", "typescript": "^5.3.3" @@ -670,25 +665,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@mole-inc/bin-wrapper": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz", - "integrity": "sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==", - "dev": true, - "dependencies": { - "bin-check": "^4.1.0", - "bin-version-check": "^5.0.0", - "content-disposition": "^0.5.4", - "ext-name": "^5.0.0", - "file-type": "^17.1.6", - "filenamify": "^5.0.2", - "got": "^11.8.5", - "os-filter-obj": "^2.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.4", "license": "MIT", @@ -793,125 +769,14 @@ "node": ">=14" } }, - "node_modules/@silentbot1/nat-api": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@silentbot1/nat-api/-/nat-api-0.4.7.tgz", - "integrity": "sha512-6aKXUf4AY6ETBdwjswQOekY6HGj3eZTAUhJx1oYicBqpMJcsphIydEQKp/Hooz6Y070MOI6tD/oT1MgS7bP3Vg==", - "dependencies": { - "chrome-dgram": "^3.0.6", - "cross-fetch-ponyfill": "^1.0.3", - "debug": "^4.3.4", - "default-gateway": "^6.0.3", - "unordered-array-remove": "^1.0.2", - "xml2js": "^0.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@swc/cli": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.3.9.tgz", - "integrity": "sha512-e5grxGEyNT0fYZEFmhSrRYL1kFAZAXlv+WjfQ35J6J9Hl0EtrMVymAEbGabetg2Q/2FX6HiRcjgc9LrdUCBk4A==", - "dev": true, - "dependencies": { - "@mole-inc/bin-wrapper": "^8.0.1", - "@swc/counter": "^0.1.3", - "commander": "^7.1.0", - "fast-glob": "^3.2.5", - "minimatch": "^9.0.3", - "piscina": "^4.3.0", - "semver": "^7.3.8", - "slash": "3.0.0", - "source-map": "^0.7.3" - }, - "bin": { - "spack": "bin/spack.js", - "swc": "bin/swc.js", - "swcx": "bin/swcx.js" - }, - "engines": { - "node": ">= 16.14.0" - }, - "peerDependencies": { - "@swc/core": "^1.2.66", - "chokidar": "^3.5.1" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@swc/cli/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@swc/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/cli/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@swc/cli/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.0.tgz", "integrity": "sha512-wc5DMI5BJftnK0Fyx9SNJKkA0+BZSJQx8430yutWmsILkHMBD3Yd9GhlMaxasab9RhgKqZp7Ht30hUYO5ZDvQg==", "dev": true, "hasInstallScript": true, + "optional": true, + "peer": true, "dependencies": { "@swc/counter": "^0.1.1", "@swc/types": "^0.1.5" @@ -956,6 +821,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=10" } @@ -972,6 +838,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=10" } @@ -988,6 +855,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=10" } @@ -1004,6 +872,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=10" } @@ -1020,6 +889,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=10" } @@ -1036,6 +906,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=10" } @@ -1052,6 +923,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=10" } @@ -1068,6 +940,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=10" } @@ -1084,6 +957,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=10" } @@ -1100,6 +974,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=10" } @@ -1108,90 +983,17 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/@swc/types": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@thaunknown/idb-chunk-store": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@thaunknown/idb-chunk-store/-/idb-chunk-store-1.0.2.tgz", - "integrity": "sha512-UdKshbKdHDP+p0XPdv55QiU/scdB9TzvovGFSgXThf+7Yd3noLeYp6KpkYyc1jzUXvI3/8+TemPeASOimrOXvw==", - "dependencies": { - "idb": "^6.1.2", - "queue-microtask": "^1.2.3" - } - }, - "node_modules/@thaunknown/simple-peer": { - "version": "9.12.1", - "resolved": "https://registry.npmjs.org/@thaunknown/simple-peer/-/simple-peer-9.12.1.tgz", - "integrity": "sha512-IS5BXvXx7cvBAzaxqotJf4s4rJCPk5JABLK6Gbnn7oAmWVcH4hYABabBBrvvJtv/xyUqR4v/H3LalnGRJJfEog==", - "dependencies": { - "debug": "^4.3.2", - "err-code": "^3.0.1", - "get-browser-rtc": "^1.1.0", - "queue-microtask": "^1.2.3", - "streamx": "^2.13.2", - "uint8-util": "^2.1.9" - } - }, - "node_modules/@thaunknown/simple-websocket": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@thaunknown/simple-websocket/-/simple-websocket-9.1.1.tgz", - "integrity": "sha512-vzQloFWRodRZqZhpxMpBljFtISesY8TihA8T5uKwCYdj2I1ImMhE/gAeTCPsCGOtxJfGKu3hw/is6MXauWLjOg==", - "dependencies": { - "debug": "^4.3.4", - "queue-microtask": "^1.2.3", - "streamx": "^2.13.2", - "uint8-util": "^2.1.9", - "ws": "^8.12.0" - } - }, - "node_modules/@thaunknown/simple-websocket/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@thaunknown/thirty-two": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@thaunknown/thirty-two/-/thirty-two-1.0.3.tgz", - "integrity": "sha512-bD6PvWbaf53JC04O7WnGDjqZBDgja/KT2Jd/6I2vJBIy+DLmQfQJZZ/G+16nAkVq1yGTIkO4rfc4RlH0DmEEqA==", - "dependencies": { - "uint8-util": "^2.1.9" - }, - "engines": { - "node": ">=0.2.6" - } + "optional": true, + "peer": true }, "node_modules/@tirke/node-cache-manager-mongodb": { "version": "1.6.0", @@ -1207,12 +1009,6 @@ "url": "https://github.com/sponsors/tirke" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1246,27 +1042,6 @@ "@types/node": "*" } }, - "node_modules/@types/bittorrent-protocol": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/bittorrent-protocol/-/bittorrent-protocol-3.1.6.tgz", - "integrity": "sha512-hqiRctJX9t9kknr6nn0q7UlcWHKvw2gSnPc/4jxt7Q/T0RP9txNv27Djue9ZjCNlAJ+irqAnCxtb+TcSpMyhtA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, "node_modules/@types/debug": { "version": "4.1.12", "license": "MIT", @@ -1274,12 +1049,6 @@ "@types/ms": "*" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1292,15 +1061,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/magnet-uri": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", @@ -1326,45 +1086,16 @@ "version": "5.26.5", "license": "MIT" }, - "node_modules/@types/parse-torrent": { - "version": "5.8.7", - "resolved": "https://registry.npmjs.org/@types/parse-torrent/-/parse-torrent-5.8.7.tgz", - "integrity": "sha512-vZtYe450hO+KL7B5fejM8CHWg1LPZKeVXlolphPsWf6n4H0ZUlI6ICbqHoaFmH7JQmU2yRbGgyvqqizdFuGPFQ==", - "dev": true, - "dependencies": { - "@types/magnet-uri": "*", - "@types/node": "*", - "@types/parse-torrent-file": "*" - } - }, - "node_modules/@types/parse-torrent-file": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/parse-torrent-file/-/parse-torrent-file-4.0.6.tgz", - "integrity": "sha512-SxqVth0Iv0WuEkqWS5MaY4S4Tlyi+QHkElQREvsUPw2xHcPgKyQ2dkJRRv5vAxmLzH+tnMdOj1Nws/wsenbzUw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, - "node_modules/@types/simple-peer": { - "version": "9.11.8", - "resolved": "https://registry.npmjs.org/@types/simple-peer/-/simple-peer-9.11.8.tgz", - "integrity": "sha512-rvqefdp2rvIA6wiomMgKWd2UZNPe6LM2EV5AuY3CPQJF+8TbdrL5TjYdMf0VAjGczzlkH4l1NjDkihwbj3Xodw==", + "node_modules/@types/torrent-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/torrent-stream/-/torrent-stream-0.0.9.tgz", + "integrity": "sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -1379,18 +1110,6 @@ "version": "7.0.3", "license": "MIT" }, - "node_modules/@types/webtorrent": { - "version": "0.109.7", - "resolved": "https://registry.npmjs.org/@types/webtorrent/-/webtorrent-0.109.7.tgz", - "integrity": "sha512-iDcZkXUMjWOtPpxAWXivs6rpYD++8w4vYJVqGJQKxZh1YxIXm5P3CyHGX735nJ6kFOFXLxD1O0ys/msI1nhRug==", - "dev": true, - "dependencies": { - "@types/bittorrent-protocol": "*", - "@types/node": "*", - "@types/parse-torrent": "*", - "@types/simple-peer": "*" - } - }, "node_modules/@types/whatwg-url": { "version": "11.0.4", "license": "MIT", @@ -1698,15 +1417,6 @@ "dev": true, "license": "ISC" }, - "node_modules/@webtorrent/http-node": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@webtorrent/http-node/-/http-node-1.3.0.tgz", - "integrity": "sha512-GWZQKroPES4z91Ijx6zsOsb7+USOxjy66s8AoTWg0HiBBdfnbtf9aeh3Uav0MgYn4BL8Q7tVSUpd0gGpngKGEQ==", - "dependencies": { - "freelist": "^1.0.3", - "http-parser-js": "^0.4.3" - } - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1752,6 +1462,11 @@ "node": ">=0.4.0" } }, + "node_modules/addr-to-ip-port": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz", + "integrity": "sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg==" + }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -1840,26 +1555,6 @@ "node": ">= 8" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2014,23 +1709,10 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" - }, "node_modules/balanced-match": { "version": "1.0.2", "license": "MIT" }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2050,200 +1732,15 @@ } ] }, + "node_modules/bencode": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.7.0.tgz", + "integrity": "sha512-MG5AM/hkQIZoz/layZ1JK3xBTfqkLcJ3dJ7u2lx+6vZT1JWyK3OgEFGx1WFzWt6grGH6OSGQvRcCnhWKLp4f1Q==" + }, "node_modules/bep53-range": { "version": "1.1.1", "license": "MIT" }, - "node_modules/bin-check": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-4.1.0.tgz", - "integrity": "sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==", - "dev": true, - "dependencies": { - "execa": "^0.7.0", - "executable": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-check/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/bin-check/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", - "dev": true, - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-check/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-check/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bin-check/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/bin-check/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-check/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/bin-check/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bin-check/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bin-check/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/bin-check/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/bin-version": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-6.0.0.tgz", - "integrity": "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "find-versions": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bin-version-check": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.1.0.tgz", - "integrity": "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==", - "dev": true, - "dependencies": { - "bin-version": "^6.0.0", - "semver": "^7.5.3", - "semver-truncate": "^3.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bin-version-check/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/bin-version-check/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2253,109 +1750,84 @@ "node": ">=8" } }, - "node_modules/bittorrent-lsd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bittorrent-lsd/-/bittorrent-lsd-2.0.0.tgz", - "integrity": "sha512-jV+SMTGNY1iGWjf5cPA2HMeA6axuMQRWwWELtsuZ1FmQmZwC74we92nwtDTfv1WMnLx+oqEjWRri42IHjZitSQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/bitfield": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-0.1.0.tgz", + "integrity": "sha512-M15ypXCxXd81FSOWL2ejHpB1TDKmz7Y55/VuqfExJi72sHW0JzE5dfV+hrSZafZtWRg/tdMsdte5dgwrlOM7nA==" + }, + "node_modules/bittorrent-dht": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-6.4.2.tgz", + "integrity": "sha512-DeBunF1nL/ckThYyU3AVtHFR195zNV06Ob6bKNXA1y6X56GSKMfkNCABB45YcbZevGMW1dytFlm59D/fws5lTg==", "dependencies": { - "chrome-dgram": "^3.0.6", - "debug": "^4.2.0" - }, - "engines": { - "node": ">=12.20.0" + "bencode": "^0.7.0", + "buffer-equals": "^1.0.3", + "debug": "^2.2.0", + "inherits": "^2.0.1", + "k-bucket": "^0.6.0", + "k-rpc": "^3.6.0", + "lru": "^2.0.0" } }, - "node_modules/bittorrent-peerid": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/bittorrent-peerid/-/bittorrent-peerid-1.3.6.tgz", - "integrity": "sha512-VyLcUjVMEOdSpHaCG/7odvCdLbAB1y3l9A2V6WIje24uV7FkJPrQrH/RrlFmKxP89pFVDEnE+YlHaFujlFIZsg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bittorrent-protocol": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/bittorrent-protocol/-/bittorrent-protocol-4.1.11.tgz", - "integrity": "sha512-8ehCNnnRpxB6wrqDzYdLY6Bx0k1ZcXwHmxfVsU9xljolgfd4jhUq9gKcbnnUj4yR8I5/qHJ5fYVoGIfrmUlAAQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/bittorrent-dht/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "bencode": "^4.0.0", - "bitfield": "^4.1.0", - "debug": "^4.3.4", - "rc4": "^0.1.5", - "streamx": "^2.15.1", - "throughput": "^1.0.1", - "uint8-util": "^2.2.2", - "unordered-array-remove": "^1.0.2" - }, - "engines": { - "node": ">=12.20.0" + "ms": "2.0.0" } }, - "node_modules/bittorrent-protocol/node_modules/bencode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", - "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", + "node_modules/bittorrent-tracker": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/bittorrent-tracker/-/bittorrent-tracker-7.7.0.tgz", + "integrity": "sha512-YFgPTVRhUMncZr8tM3ige7gnViMGhKoGF23qaiISRG8xtYebTGHrMSMXsTXo6O1KbtdEI+4jzvGY1K/wdT9GUA==", "dependencies": { - "uint8-util": "^2.2.2" + "bencode": "^0.8.0", + "bn.js": "^4.4.0", + "compact2string": "^1.2.0", + "debug": "^2.0.0", + "hat": "0.0.3", + "inherits": "^2.0.1", + "ip": "^1.0.1", + "minimist": "^1.1.1", + "once": "^1.3.0", + "random-iterate": "^1.0.1", + "run-parallel": "^1.1.2", + "run-series": "^1.0.2", + "simple-get": "^2.0.0", + "simple-peer": "^6.0.0", + "simple-websocket": "^4.0.0", + "string2compact": "^1.1.1", + "uniq": "^1.0.1", + "ws": "^1.0.0", + "xtend": "^4.0.0" }, - "engines": { - "node": ">=12.20.0" + "bin": { + "bittorrent-tracker": "bin/cmd.js" } }, - "node_modules/bittorrent-protocol/node_modules/bitfield": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", - "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node_modules/bittorrent-tracker/node_modules/bencode": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.8.0.tgz", + "integrity": "sha512-MWs3FqaWOGg5l+quIT9JTx7+SlcMbfPqqpWy+GOYi5rjZkX8i03tkNhAQn3pD2GAKENPpP3ScUR97ZUMffhHZA==" + }, + "node_modules/bittorrent-tracker/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/block-iterator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/block-iterator/-/block-iterator-1.1.1.tgz", - "integrity": "sha512-DrjdVWZemVO4iBf4tiOXjUrY5cNesjzy0t7sIiu2rdl8cOCHRxAgKjSJFc3vBZYYMMmshUAxajl8QQh/uxXTKQ==" + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/bncode": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.5.3.tgz", + "integrity": "sha512-0P5VuWobU5Gwbeio8n9Jsdv0tE1IikrV9n4f7RsnXHNtxmdd/oeIO6QyoSEUAEyo5P6i3XMfBppi82WqNsT4JA==" }, "node_modules/boolbase": { "version": "1.0.0", @@ -2415,6 +1887,46 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-equals": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", + "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/buffer-more-ints": { "version": "1.0.0", "license": "MIT" @@ -2426,19 +1938,6 @@ "node": ">=4" } }, - "node_modules/bufferutil": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", - "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/cacache": { "version": "18.0.2", "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", @@ -2508,40 +2007,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cache-chunk-store": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/cache-chunk-store/-/cache-chunk-store-3.2.2.tgz", - "integrity": "sha512-2lJdWbgHFFxcSth9s2wpId3CR3v1YC63KjP4T9WhpW7LWlY7Hiiei3QwwqzkWqlJTfR8lSy9F5kRQECeyj+yQA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "lru": "^3.1.0", - "queue-microtask": "^1.2.3" - } - }, - "node_modules/cache-chunk-store/node_modules/lru": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz", - "integrity": "sha512-5OUtoiVIGU4VXBOshidmtOsvBIvcQR6FD/RzWSvaeHyxCGB+PCUCu+52lqMfdc0h/2CLvHhZS4TwUmMQrrMbBQ==", - "dependencies": { - "inherits": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/cache-manager": { "version": "5.4.0", "license": "MIT", @@ -2551,48 +2016,6 @@ "promise-coalesce": "^1.1.2" } }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.5", "dev": true, @@ -2758,14 +2181,6 @@ "inherits": "^2.0.1" } }, - "node_modules/chunk-store-iterator": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chunk-store-iterator/-/chunk-store-iterator-1.0.3.tgz", - "integrity": "sha512-JcSaB5h3wQstQKnaJi8sET40f0m+6Kh4mhKIr05lrWKi+EiQzn6XUoi6LipgRGMqXWNZZJaMz2tH4aeg4ptBDA==", - "dependencies": { - "block-iterator": "^1.1.1" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2789,26 +2204,6 @@ "node": ">=12" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -2841,15 +2236,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/compact2string": { "version": "1.4.1", "license": "BSD", @@ -2903,171 +2289,19 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/core-util-is": { "version": "1.0.3", "license": "MIT" }, - "node_modules/cpus": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cpus/-/cpus-1.0.3.tgz", - "integrity": "sha512-PXHBvGLuL69u55IkLa5e5838fLhIMHxmkV4ge42a8alGyn7BtawYgI0hQ849EedvtHIOLNNH3i6eQU1BiE9SUA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/create-torrent": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/create-torrent/-/create-torrent-6.0.16.tgz", - "integrity": "sha512-oO0M9KMPwEk825G7vLLUttgxBl/zwlsNdtPc9RnjFS6gQeq8sqJqlBmHcIA8sDwaYbu0mpIcARPokUgsRxjiaw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bencode": "^4.0.0", - "block-iterator": "^1.1.1", - "fast-readable-async-iterator": "^2.0.0", - "is-file": "^1.0.0", - "join-async-iterator": "^1.1.1", - "junk": "^4.0.1", - "minimist": "^1.2.8", - "once": "^1.4.0", - "piece-length": "^2.0.1", - "queue-microtask": "^1.2.3", - "run-parallel": "^1.2.0", - "uint8-util": "^2.2.2" - }, - "bin": { - "create-torrent": "bin/cmd.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/create-torrent/node_modules/bencode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", - "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", - "dependencies": { - "uint8-util": "^2.2.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/create-torrent/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-fetch-ponyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cross-fetch-ponyfill/-/cross-fetch-ponyfill-1.0.3.tgz", - "integrity": "sha512-uOBkDhUAGAbx/FEzNKkOfx3w57H8xReBBXoZvUnOKTI0FW0Xvrj3GrYv2iZXUqlffC1LMGfQzhmBM/ke+6eTDA==", - "dependencies": { - "abort-controller": "^3.0.0", - "node-fetch": "^3.3.0" - } - }, - "node_modules/cross-fetch-ponyfill/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3102,13 +2336,10 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } + "node_modules/cyclist": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.1.1.tgz", + "integrity": "sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw==" }, "node_modules/date-fns": { "version": "2.30.0", @@ -3154,33 +2385,6 @@ "version": "2.1.2", "license": "MIT" }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -3193,26 +2397,6 @@ "node": ">=16.0.0" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/define-data-property": { "version": "1.1.1", "dev": true, @@ -3369,6 +2553,14 @@ "node": ">=0.10.0" } }, + "node_modules/end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw==", + "dependencies": { + "once": "~1.3.0" + } + }, "node_modules/entities": { "version": "4.5.0", "license": "BSD-2-Clause", @@ -3388,11 +2580,6 @@ "node": ">=6" } }, - "node_modules/err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" - }, "node_modules/es-abstract": { "version": "1.22.3", "dev": true, @@ -3529,11 +2716,6 @@ "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, @@ -3833,71 +3015,12 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, - "dependencies": { - "mime-db": "^1.28.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, - "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -3909,11 +3032,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -3952,11 +3070,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-readable-async-iterator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-readable-async-iterator/-/fast-readable-async-iterator-2.0.0.tgz", - "integrity": "sha512-8Sld+DuyWRIftl86ZguJxR2oXCBccOiJxrY/Rj9/7ZBynW8pYMWzIcqxFL1da+25jaWJZVa+HHX/8SsA21JdTA==" - }, "node_modules/fast-redact": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", @@ -3979,27 +3092,10 @@ "reusify": "^1.0.4" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } + "node_modules/fifo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/fifo/-/fifo-0.1.4.tgz", + "integrity": "sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g==" }, "node_modules/file-entry-cache": { "version": "6.0.1", @@ -4012,51 +3108,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-type": { - "version": "17.1.6", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", - "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", - "dev": true, - "dependencies": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0-alpha.9", - "token-types": "^5.0.0-alpha.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/filename-reserved-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", - "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/filenamify": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-5.1.1.tgz", - "integrity": "sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==", - "dev": true, - "dependencies": { - "filename-reserved-regex": "^3.0.0", - "strip-outer": "^2.0.0", - "trim-repeated": "^2.0.0" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -4084,21 +3135,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-versions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", - "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", - "dev": true, - "dependencies": { - "semver-regex": "^4.0.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "dev": true, @@ -4131,6 +3167,15 @@ "dev": true, "license": "ISC" }, + "node_modules/flatten": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-0.0.1.tgz", + "integrity": "sha512-pzNZh42/A2HmcRIpddSP0T+zBofd119o5rNB2u1YHv36CM2C/ietI2ZsjWZ2LSL7J0BNVkFn1a9Ad+cmO2lDQg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "engines": { + "node": "*" + } + }, "node_modules/follow-redirects": { "version": "1.15.5", "funding": [ @@ -4197,21 +3242,29 @@ "node": ">= 6" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "node_modules/fs-chunk-store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/fs-chunk-store/-/fs-chunk-store-1.7.0.tgz", + "integrity": "sha512-KhjJmZAs2eqfhCb6PdPx4RcZtheGTz86tpTC5JTvqBn/xda+Nb+0C7dCyjOSN7T76H6a56LvH0SVXQMchLXDRw==", "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" + "mkdirp": "^0.5.1", + "random-access-file": "^2.0.1", + "randombytes": "^2.0.3", + "rimraf": "^2.4.2", + "run-parallel": "^1.1.2", + "thunky": "^1.0.1" } }, - "node_modules/freelist": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/freelist/-/freelist-1.0.3.tgz", - "integrity": "sha512-Ji7fEnMdZDGbS5oXElpRJsn9jPvBR8h/037D3bzreNmS8809cISq/2D9//JbA/TaZmkkN8cmecXwmQHmM+NHhg==" + "node_modules/fs-chunk-store/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } }, "node_modules/fs-minipass": { "version": "3.0.3", @@ -4225,29 +3278,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/fs-native-extensions": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-native-extensions/-/fs-native-extensions-1.2.5.tgz", - "integrity": "sha512-auDlsCu4bxLnspHJ+6bkAfCNjlVX6aIaHPI3fIexKrvLgjFedUChytCv7sxeuZfwmABdISI2A0/hDjZx7NWTKA==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "napi-macros": "^2.0.0", - "node-gyp-build": "^4.2.3" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "license": "ISC" }, - "node_modules/fsa-chunk-store": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fsa-chunk-store/-/fsa-chunk-store-1.1.4.tgz", - "integrity": "sha512-Z4SJTYxZIta37RXJofM6HsKrgM9W+pQxiyQuw0bpvsfn1HGXcBWyXZWhsCfi7wbNb6GIlykXZ9Jxwc95IiPMzA==", - "dependencies": { - "filename-reserved-regex": "^3.0.0" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4322,28 +3356,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "dev": true, @@ -4373,7 +3385,6 @@ }, "node_modules/glob": { "version": "7.2.3", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -4403,7 +3414,6 @@ }, "node_modules/glob/node_modules/once": { "version": "1.4.0", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -4483,31 +3493,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4593,6 +3578,14 @@ "node": ">= 0.4" } }, + "node_modules/hat": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz", + "integrity": "sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==", + "engines": { + "node": "*" + } + }, "node_modules/help-me": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", @@ -4622,11 +3615,6 @@ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, - "node_modules/http-parser-js": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", - "integrity": "sha512-u8u5ZaG0Tr/VvHlucK2ufMuOp4/5bvwgneXle+y228K5rMbJOlVjThONcaAw3ikAy8b2OO9RfEucdMHFz3UWMA==" - }, "node_modules/http-proxy-agent": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", @@ -4640,19 +3628,6 @@ "node": ">= 14" } }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", @@ -4666,25 +3641,6 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/hybrid-chunk-store": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/hybrid-chunk-store/-/hybrid-chunk-store-1.2.2.tgz", - "integrity": "sha512-oZtxLfVHWKVKPS8KoYpWgVohEKbq3s90s7a1FwG7+EZFC/8bqZrdX4axlH5tO/g2PnGpZTVxS2YnftyCpydKSw==", - "dependencies": { - "@thaunknown/idb-chunk-store": "^1.0.2", - "cache-chunk-store": "^3.2.2", - "fsa-chunk-store": "^1.1.4", - "memory-chunk-store": "^1.3.5" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "license": "MIT", @@ -4695,11 +3651,6 @@ "node": ">=0.10.0" } }, - "node_modules/idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -4733,6 +3684,11 @@ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, + "node_modules/immediate-chunk-store": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/immediate-chunk-store/-/immediate-chunk-store-1.0.8.tgz", + "integrity": "sha512-0tQyTytUaIUskpv5j5L5ZeQuEjYDl9QIekwDUisdqpAM81OZjBaEIriW7hoiRLaLNxj1fXE8e1yx5JaCGrrE7A==" + }, "node_modules/import-fresh": { "version": "3.3.0", "dev": true, @@ -4813,6 +3769,14 @@ "version": "1.1.8", "license": "MIT" }, + "node_modules/ip-set": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ip-set/-/ip-set-1.0.2.tgz", + "integrity": "sha512-Mb6kv78bTi4RNAIIWL8Bbre7hXOR2pNUi3j8FaQkLaitf/ZWxkq3/iIwXNYk2ACO3IMfdVdQrOkUtwZblO7uBA==", + "dependencies": { + "ip": "^1.1.3" + } + }, "node_modules/ipaddr.js": { "version": "2.1.0", "license": "MIT", @@ -4917,11 +3881,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file/-/is-file-1.0.0.tgz", - "integrity": "sha512-ZGMuc+xA8mRnrXtmtf2l/EkIW2zaD2LSBWlaOVEF6yH4RTndHob65V4SwWWdtGKVthQfXPVKsXqw4TDUjbVxVQ==" - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -4990,15 +3949,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-regex": { "version": "1.1.4", "dev": true, @@ -5025,17 +3975,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-string": { "version": "1.0.7", "dev": true, @@ -5095,6 +4034,7 @@ }, "node_modules/isexe": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/jackspeak": { @@ -5115,11 +4055,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/join-async-iterator": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/join-async-iterator/-/join-async-iterator-1.1.1.tgz", - "integrity": "sha512-ATse+nuNeKZ9K1y27LKdvPe/GCe9R/u9dw9vI248e+vILeRK3IcJP4JUPAlSmKRCDK0cKhEwfmiw4Skqx7UnGQ==" - }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -5167,15 +4102,23 @@ "node": ">=6" } }, - "node_modules/junk": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", - "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/k-bucket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-0.6.0.tgz", + "integrity": "sha512-1zJpqkrLYgolqdO1TE1/FWf+mHfhJKLC2Wpi4JaMFZKi4b6tFEn9/d+JqscBIJw5auWFewp16CSAEetFGEC4NQ==", + "dependencies": { + "buffer-equal": "0.0.1", + "inherits": "^2.0.1" + } + }, + "node_modules/k-rpc": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-3.7.0.tgz", + "integrity": "sha512-XFL8PatIToQ/qhSSAq9FSK73wk4fX4DcHqjnkvSCrWC59PV02Oj1KeYa3KnREAXgA1DlCSzcKjk7M8usnT/dUw==", + "dependencies": { + "buffer-equals": "^1.0.3", + "k-bucket": "^2.0.0", + "k-rpc-socket": "^1.5.0" } }, "node_modules/k-rpc-socket": { @@ -5192,6 +4135,15 @@ "version": "2.0.3", "license": "MIT" }, + "node_modules/k-rpc/node_modules/k-bucket": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-2.0.1.tgz", + "integrity": "sha512-Xuye90xBBDJJbvNSuy3z/Yl8ceVX02/sopqGUEwJkMgRw+//TQXx0/Hbgp60GsoVfZcCBllQXXp6AWe2INu8pw==", + "dependencies": { + "buffer-equal": "0.0.1", + "randombytes": "^2.0.3" + } + }, "node_modules/keyv": { "version": "4.5.4", "dev": true, @@ -5200,11 +4152,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/last-one-wins": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/last-one-wins/-/last-one-wins-1.0.4.tgz", - "integrity": "sha512-t+KLJFkHPQk8lfN6WBOiGkiUXoub+gnb2XTYI2P3aiISL+94xgZ1vgz1SXN/N4hthuOoLXarXfBZPUruyjQtfA==" - }, "node_modules/levn": { "version": "0.4.1", "dev": true, @@ -5217,57 +4164,6 @@ "node": ">= 0.8.0" } }, - "node_modules/limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" - }, - "node_modules/load-ip-set": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/load-ip-set/-/load-ip-set-3.0.1.tgz", - "integrity": "sha512-ZFZt1g4Exq01SFtKjffqau+L4Qibt+51utymHHiWo8Iu/W7LYSqE7fiZ/iAZ6dIqbmeU6ICSIK02IizSScBkLQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "cross-fetch-ponyfill": "^1.0.1", - "ip-set": "^2.1.0", - "netmask": "^2.0.1", - "once": "^1.4.0", - "queue-microtask": "^1.2.3", - "split": "^1.0.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/load-ip-set/node_modules/ip-set": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-set/-/ip-set-2.1.0.tgz", - "integrity": "sha512-JdHz4tSMx1IeFj8yEcQU0i58qiSkOlmZXkZ8+HJ0ROV5KcgLRDO9F703oJ1GeZCvqggrcCbmagD/V7hghY62wA==", - "dependencies": { - "ip": "^1.1.5" - } - }, - "node_modules/load-ip-set/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -5295,13 +4191,15 @@ "dev": true, "license": "MIT" }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, + "node_modules/lru": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lru/-/lru-2.0.1.tgz", + "integrity": "sha512-JGRd3IHM64MPsGVw1Mqbz2Y2HDIePqi/MLfPtdrkHQwvvJnSrS9b6gM3KS9PFR5xJnufXJczHHZSmGqfuII1ew==", + "dependencies": { + "inherits": "^2.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.4.0" } }, "node_modules/lru-cache": { @@ -5311,32 +4209,6 @@ "node": "14 || >=16.14" } }, - "node_modules/lt_donthave": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lt_donthave/-/lt_donthave-2.0.0.tgz", - "integrity": "sha512-qrNtq9faD5ycTM8Of7OUqPHPMv0H8NONf+dTAxUsAr0bAgPnD56BBhhBlskJVNL4WO+Dl/qmqWHF9eQb7+2lNA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "debug": "^4.2.0", - "unordered-array-remove": "^1.0.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/magnet-uri": { "version": "6.2.0", "funding": [ @@ -5387,23 +4259,10 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/memory-chunk-store": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/memory-chunk-store/-/memory-chunk-store-1.3.5.tgz", - "integrity": "sha512-E1Xc1U4ifk/FkC2ZsWhCaW1xg9HbE/OBmQTLe2Tr9c27YPSLbW7kw1cnb3kQWD1rDtErFJHa7mB9EVrs7aTx9g==", - "dependencies": { - "queue-microtask": "^1.2.3" - } - }, "node_modules/memory-pager": { "version": "1.5.0", "license": "MIT" }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5426,17 +4285,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/mime-db": { "version": "1.52.0", "license": "MIT", @@ -5454,19 +4302,10 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -5635,6 +4474,11 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/moment": { "version": "2.30.1", "license": "MIT", @@ -5732,18 +4576,10 @@ "node": ">=12" } }, - "node_modules/mylas": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", - "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/raouldeheer" - } + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/name-to-imdb": { "version": "3.0.4", @@ -5759,11 +4595,6 @@ "version": "2.2.1", "license": "MIT" }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==" - }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -5790,10 +4621,6 @@ "ms": "2.0.0" } }, - "node_modules/needle/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -5803,54 +4630,6 @@ "node": ">= 0.6" } }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "!win32" - ], - "dependencies": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "license": "MIT", @@ -5909,16 +4688,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/node-gyp/node_modules/abbrev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", @@ -6140,29 +4909,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nth-check": { "version": "2.1.1", "license": "BSD-2-Clause", @@ -6264,20 +5010,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.3", "dev": true, @@ -6294,34 +5026,12 @@ "node": ">= 0.8.0" } }, - "node_modules/os-filter-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz", - "integrity": "sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==", - "dev": true, - "dependencies": { - "arch": "^2.1.0" - }, + "node_modules/options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==", "engines": { - "node": ">=4" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=0.4.0" } }, "node_modules/p-limit": { @@ -6382,6 +5092,31 @@ "node": ">=6" } }, + "node_modules/parse-torrent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-4.1.0.tgz", + "integrity": "sha512-FeoGe8bOYmSzxO31kYy44A03FjuULCMOIMom8KyuGvO8/lLVPJyo2nr9CwH/iYmNHm74hk7h70o59DOfk9Rq+A==", + "dependencies": { + "magnet-uri": "^4.0.0", + "parse-torrent-file": "^2.0.0" + }, + "bin": { + "parse-torrent": "bin/cmd.js" + } + }, + "node_modules/parse-torrent-file": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz", + "integrity": "sha512-u2MgLOjZPDDer1oRg1c+H/+54iIQYY5TKgQ5G8KrGLT1Dcwdo7Lj+QfQR123+u8J0AMSFGbQUvsBlSB7uIJcCA==", + "deprecated": "Use the parse-torrent package instead", + "dependencies": { + "bencode": "^0.7.0", + "simple-sha1": "^2.0.0" + }, + "bin": { + "parse-torrent-file": "bin/cmd.js" + } + }, "node_modules/parse-torrent-title": { "version": "1.3.0", "resolved": "git+ssh://git@github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", @@ -6394,6 +5129,24 @@ "node": ">=10" } }, + "node_modules/parse-torrent/node_modules/magnet-uri": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-4.2.3.tgz", + "integrity": "sha512-aHhR49CRBOq3BX6jQOBdGMXhNT2+9LIH3CCIwHlR+aFE8nWMfBD1aNYxfm2u2LsCOwvfPeyCsdIg9KXSwdsOLQ==", + "dependencies": { + "flatten": "0.0.1", + "thirty-two": "^0.0.2", + "xtend": "^4.0.0" + } + }, + "node_modules/parse-torrent/node_modules/thirty-two": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-0.0.2.tgz", + "integrity": "sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA==", + "engines": { + "node": ">=0.2.6" + } + }, "node_modules/parse5": { "version": "7.1.2", "license": "MIT", @@ -6432,6 +5185,7 @@ }, "node_modules/path-key": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6467,17 +5221,35 @@ "node": ">=8" } }, - "node_modules/peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node_modules/peer-wire-protocol": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/peer-wire-protocol/-/peer-wire-protocol-0.7.1.tgz", + "integrity": "sha512-V9oTa/ZcfNNz9fAST28Gg0fXbPeFPk3SBImsYO8GDDG5D0E195vxXmjZ+SPrzr4BJyMQmdDmwUfTf9MZ62z4mw==", + "dependencies": { + "bitfield": "^0.1.0", + "bncode": "^0.2.3", + "buffer-alloc": "^1.1.0", + "buffer-from": "^1.0.0", + "readable-stream": "^1.0.2", + "speedometer": "^0.1.2" + } + }, + "node_modules/peer-wire-protocol/node_modules/bncode": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.2.3.tgz", + "integrity": "sha512-IXGfySD68R/J2X/it8GZqAM+Vb3ByZvAlUi0Gysq4ZACq6hXGQ3YshKo0QS/f3S9wOWKjJnEjP6x3ELxqBnAOA==" + }, + "node_modules/peer-wire-swarm": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/peer-wire-swarm/-/peer-wire-swarm-0.12.2.tgz", + "integrity": "sha512-sIWZ1nTL9l6mI9J18kW1AeByBwagvNzGJlMmQA9pM+otKQtTIwnigK8SR0nEFrNZYqZelI6RQ6g4udvtQ2TI1g==", + "dependencies": { + "buffer-from": "^1.0.0", + "fifo": "^0.1.4", + "once": "^1.1.1", + "peer-wire-protocol": "^0.7.0", + "speedometer": "^0.1.2", + "utp": "0.0.7" } }, "node_modules/pg": { @@ -6577,20 +5349,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/piece-length": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/piece-length/-/piece-length-2.0.1.tgz", - "integrity": "sha512-dBILiDmm43y0JPISWEmVGKBETQjwJe6mSU9GND+P9KW0SJGUwoU/odyH1nbalOP9i8WSYuqf1lQnaj92Bhw+Ug==" - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pino": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", @@ -6738,27 +5496,6 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, - "node_modules/piscina": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.3.1.tgz", - "integrity": "sha512-MBj0QYm3hJQ/C/wIXTN1OCYC8uQ4BBJ4LVele2P4ZwVQAH04vkk8E1SpDbuemLAL1dZorbuOob9rYqJeWCcCRg==", - "dev": true, - "optionalDependencies": { - "nice-napi": "^1.0.2" - } - }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/postgres-array": { "version": "2.0.0", "license": "MIT", @@ -6815,6 +5552,11 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/process-warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", @@ -6850,12 +5592,6 @@ "version": "1.1.0", "license": "MIT" }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -6866,6 +5602,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -6875,6 +5612,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -6883,6 +5621,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -6899,15 +5638,6 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "funding": [ @@ -6935,16 +5665,23 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/random-access-file": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-2.2.1.tgz", + "integrity": "sha512-RGU0xmDqdOyEiynob1KYSeh8+9c9Td1MJ74GT1viMEYAn8SJ9oBtWCXLsYZukCF46yududHOdM449uRYbzBrZQ==", + "dependencies": { + "mkdirp-classic": "^0.5.2", + "random-access-storage": "^1.1.1" + } + }, + "node_modules/random-access-storage": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-1.4.3.tgz", + "integrity": "sha512-D5e2iIC5dNENWyBxsjhEnNOMCwZZ64TARK6dyMN+3g4OTC4MJxyjh9hKLjTGoNhDOPrgjI+YlFEHFnrp/cSnzQ==", + "dependencies": { + "events": "^3.3.0", + "inherits": "^2.0.3", + "queue-tick": "^1.0.0" } }, "node_modules/random-iterate": { @@ -6976,21 +5713,10 @@ ], "license": "MIT" }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/rc4": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/rc4/-/rc4-0.1.5.tgz", - "integrity": "sha512-xdDTNV90z5x5u25Oc871Xnvu7yAr4tV7Eluh0VSvrhUkry39q1k+zkz7xroqHbRq+8PiazySHJPArqifUvz9VA==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/re-emitter": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.4.tgz", + "integrity": "sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA==" }, "node_modules/readable-stream": { "version": "1.1.14", @@ -7002,65 +5728,6 @@ "string_decoder": "~0.10.x" } }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readable-web-to-node-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -7081,14 +5748,6 @@ "node": ">= 12.13.0" } }, - "node_modules/record-cache": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/record-cache/-/record-cache-1.2.0.tgz", - "integrity": "sha512-kyy3HWCez2WrotaL3O4fTn0rsIdfRKOdQQcEJ9KpvmKmbffKVvwsloX063EgRUlpJIXHiDQFhJcTbZequ2uTZw==", - "dependencies": { - "b4a": "^1.3.1" - } - }, "node_modules/reflect-metadata": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", @@ -7145,12 +5804,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, "node_modules/resolve-from": { "version": "4.0.0", "dev": true, @@ -7168,18 +5821,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -7202,6 +5843,17 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "funding": [ @@ -7223,28 +5875,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/run-series": { "version": "1.1.9", "funding": [ @@ -7263,6 +5893,11 @@ ], "license": "MIT" }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" + }, "node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -7326,11 +5961,6 @@ "version": "2.1.2", "license": "MIT" }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" - }, "node_modules/secure-json-parse": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", @@ -7345,60 +5975,6 @@ "semver": "bin/semver.js" } }, - "node_modules/semver-regex": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", - "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semver-truncate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", - "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semver-truncate/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-truncate/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/sequelize": { "version": "6.36.0", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", @@ -7556,6 +6132,7 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -7566,6 +6143,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7593,10 +6171,100 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-peer": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-6.4.4.tgz", + "integrity": "sha512-sY35UHankz0ba02Dd8YzdyXhEeTAnW6ZUyDfKOSwUht1GLp9VuMT4jQUXF/wG7C9vpwvitV7Ig7a6IkY/qizwg==", + "dependencies": { + "debug": "^2.1.0", + "get-browser-rtc": "^1.0.0", + "inherits": "^2.0.1", + "randombytes": "^2.0.3", + "readable-stream": "^2.0.5" + } + }, + "node_modules/simple-peer/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/simple-peer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/simple-peer/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/simple-sha1": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/simple-sha1/-/simple-sha1-2.1.2.tgz", + "integrity": "sha512-TQl9rm4rdKAVmhO++sXAb8TNN0D6JAD5iyI1mqEPNpxUzTRrtm4aOG1pDf/5W/qCFihiaoK6uuL9rvQz1x1VKw==", + "dependencies": { + "rusha": "^0.8.1" + } }, "node_modules/simple-update-notifier": { "version": "2.0.0", @@ -7637,6 +6305,73 @@ "node": ">=10" } }, + "node_modules/simple-websocket": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-4.3.1.tgz", + "integrity": "sha512-knEO6ub2Pw00c7ueOV6snKE1hr7jIdY068+239v0I8DVKofyd7IQmYHXrM9pZL1zuI0H7sd+Y5kedndBi5GXIA==", + "dependencies": { + "debug": "^2.1.3", + "inherits": "^2.0.1", + "randombytes": "^2.0.3", + "readable-stream": "^2.0.5", + "ws": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/simple-websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/simple-websocket/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/simple-websocket/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/simple-websocket/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/simple-websocket/node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "node_modules/simple-websocket/node_modules/ws": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha512-61a+9LgtYZxTq1hAonhX8Xwpo2riK4IOR/BIVxioFbCfc3QFKmpE4x9dLExfLHKtUfVZigYa36tThVhO57erEw==", + "dependencies": { + "safe-buffer": "~5.0.1", + "ultron": "~1.1.0" + } + }, + "node_modules/simple-websocket/node_modules/ws/node_modules/safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha512-cr7dZWLwOeaFBLTIuZeYdkfO7UzGIKhjYENJFAxUOMKWGaWDm2nJM2rzxNRm5Owu0DH3ApwNo6kx5idXZfb/Iw==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7650,6 +6385,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -7659,6 +6395,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -7685,7 +6422,8 @@ "node_modules/socks/node_modules/ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true }, "node_modules/sonic-boom": { "version": "3.8.0", @@ -7695,39 +6433,6 @@ "atomic-sleep": "^1.0.0" } }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", - "dev": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", - "dev": true, - "dependencies": { - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/sparse-bitfield": { "version": "3.0.3", "license": "MIT", @@ -7741,25 +6446,10 @@ "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, - "node_modules/speed-limiter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/speed-limiter/-/speed-limiter-1.0.2.tgz", - "integrity": "sha512-Ax+TbUOho84bWUc3AKqWtkIvAIVws7d6QI4oJkgH4yQ5Yil+lR3vjd/7qd51dHKGzS5bFxg0++QwyNRN7s6rZA==", - "dependencies": { - "limiter": "^1.1.5", - "streamx": "^2.10.3" - } - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } + "node_modules/speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q==" }, "node_modules/split2": { "version": "4.2.0", @@ -7780,15 +6470,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/streamx": { - "version": "2.15.7", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.7.tgz", - "integrity": "sha512-NPEKS5+yjyo597eafGbKW5ujh7Sm6lDLHZQd/lRSz6S0VarpADBJItqfB4PnwpS+472oob1GX5cCY9vzfJpHUA==", - "dependencies": { - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" - } - }, "node_modules/string_decoder": { "version": "0.10.31", "license": "MIT" @@ -7864,6 +6545,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string2compact": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-1.3.2.tgz", + "integrity": "sha512-3XUxUgwhj7Eqh2djae35QHZZT4mN3fsO7kagZhSGmhhlrQagVvWSFuuFIWnpxFS0CdTB2PlQcaL16RDi14I8uw==", + "dependencies": { + "addr-to-ip-port": "^1.0.1", + "ipaddr.js": "^2.0.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "dev": true, @@ -7896,23 +6586,6 @@ "node": ">=4" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "dev": true, @@ -7924,35 +6597,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-outer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-2.0.0.tgz", - "integrity": "sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -8044,25 +6688,10 @@ "real-require": "^0.2.0" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/throughput": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throughput/-/throughput-1.0.1.tgz", - "integrity": "sha512-4Mvv5P4xyVz6RM07wS3tGyZ/kPAiKtLeqznq3hK4pxDiTUSyQ5xeFlBiWxflCWexvSnxo2aAfedzKajJqihz4Q==" - }, "node_modules/thunky": { "version": "1.1.0", "license": "MIT" }, - "node_modules/timeout-refresh": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-1.0.3.tgz", - "integrity": "sha512-Mz0CX4vBGM5lj8ttbIFt7o4ZMxk/9rgudJRh76EvB7xXZMur7T/cjRiH2w4Fmkq0zxf2QpM8IFvOSRn8FEu3gA==" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8075,27 +6704,64 @@ "node": ">=8.0" } }, - "node_modules/token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/toposort-class": { "version": "1.0.1", "license": "MIT" }, + "node_modules/torrent-discovery": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/torrent-discovery/-/torrent-discovery-5.4.0.tgz", + "integrity": "sha512-bPTDIA7XEjRlw6vQyt7kM/h1mg1INBsibjbujISITonx4POENZgxfyCSEXZpDhbAkluSPH4HKRKs4/YTmNLC6w==", + "dependencies": { + "bittorrent-dht": "^6.0.0", + "bittorrent-tracker": "^7.0.0", + "debug": "^2.0.0", + "inherits": "^2.0.1", + "re-emitter": "^1.0.0", + "run-parallel": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "node_modules/torrent-discovery/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/torrent-piece": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/torrent-piece/-/torrent-piece-1.1.2.tgz", + "integrity": "sha512-ElXPyXKKG73o+uziHJ8qlYE9EuyDVxnK2zWL+pW/2bma7RsLpSwFFIJAb8Qui7/tel2hsHQW1z3zBnfQNREpWA==" + }, + "node_modules/torrent-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/torrent-stream/-/torrent-stream-1.2.1.tgz", + "integrity": "sha512-F+3tYmXnpO2gyhZQ7o8yakELJH3FtKISI/FU0iWvchOWFUXiFnjbEBoumSzfcK1P71Qxzx2az4lVK4Dkq4KSew==", + "dependencies": { + "bitfield": "^0.1.0", + "bncode": "^0.5.2", + "buffer-from": "^1.0.0", + "end-of-stream": "^0.1.4", + "fs-chunk-store": "^1.3.0", + "hat": "0.0.3", + "immediate-chunk-store": "^1.0.5", + "ip-set": "^1.0.0", + "mkdirp": "^0.3.5", + "parse-torrent": "^4.0.0", + "peer-wire-swarm": "^0.12.0", + "rimraf": "^2.2.5", + "torrent-discovery": "^5.2.0", + "torrent-piece": "^1.0.0" + } + }, + "node_modules/torrent-stream/node_modules/mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)" + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -8117,30 +6783,6 @@ "tree-kill": "cli.js" } }, - "node_modules/trim-repeated": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-2.0.0.tgz", - "integrity": "sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/trim-repeated/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-api-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", @@ -8196,32 +6838,6 @@ } } }, - "node_modules/tsc-alias": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.8.tgz", - "integrity": "sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" - }, - "bin": { - "tsc-alias": "dist/bin/index.js" - } - }, - "node_modules/tsc-alias/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -8761,13 +7377,10 @@ "node": ">=14.17" } }, - "node_modules/uint8-util": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/uint8-util/-/uint8-util-2.2.4.tgz", - "integrity": "sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA==", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } + "node_modules/ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow==" }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -8793,6 +7406,11 @@ "version": "1.13.6", "license": "MIT" }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" + }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -8817,16 +7435,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/unordered-array-remove": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz", - "integrity": "sha512-45YsfD6svkgaCBNyvD+dFHm4qFX9g3wRSIVgWVPtm2OCnphvPxzJoe20ATsiNpNJrmzHifnxm+BN5F7gFT/4gw==" - }, - "node_modules/unordered-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unordered-set/-/unordered-set-2.0.1.tgz", - "integrity": "sha512-eUmNTPzdx+q/WvOHW0bgGYLWvWHNT3PTKEQLg0MAQhc0AHASHVHoP/9YytYd4RBVariqno/mEUhVZN98CmD7bg==" - }, "node_modules/uri-js": { "version": "4.4.1", "dev": true, @@ -8844,188 +7452,16 @@ "requires-port": "^1.0.0" } }, - "node_modules/ut_metadata": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/ut_metadata/-/ut_metadata-4.0.3.tgz", - "integrity": "sha512-2tovup0VDYpT8t8+EhhhKBmbgIyiYyJQZ+Hf+/61+SvjuRS2MEeA5CiSARP4q+9/83Wu09OsGrUre/Zv6OI5NA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bencode": "^4.0.0", - "bitfield": "^4.0.0", - "debug": "^4.2.0", - "uint8-util": "^2.1.3" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/ut_metadata/node_modules/bencode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", - "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", - "dependencies": { - "uint8-util": "^2.2.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/ut_metadata/node_modules/bitfield": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", - "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/ut_pex": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/ut_pex/-/ut_pex-4.0.4.tgz", - "integrity": "sha512-isVTbp2TKGoMOu+4Zh/i6ijpYr0VG83xjRPgCXaUjKzgXXndjCMWg32/9kZjubD+kxEXcmXMkoS8IttS9FZE8g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bencode": "^4.0.0", - "compact2string": "^1.4.1", - "string2compact": "^2.0.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/ut_pex/node_modules/addr-to-ip-port": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-2.0.0.tgz", - "integrity": "sha512-9bYbtjamtdLHZSqVIUXhilOryNPiL+x+Q5J/Unpg4VY3ZIkK3fT52UoErj1NdUeVm3J1t2iBEAur4Ywbl/bahw==", - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/ut_pex/node_modules/bencode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", - "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", - "dependencies": { - "uint8-util": "^2.2.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/ut_pex/node_modules/string2compact": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-2.0.1.tgz", - "integrity": "sha512-Bm/T8lHMTRXw+u83LE+OW7fXmC/wM+Mbccfdo533ajSBNxddDHlRrvxE49NdciGHgXkUQM5WYskJ7uTkbBUI0A==", - "dependencies": { - "addr-to-ip-port": "^2.0.0", - "ipaddr.js": "^2.0.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "license": "MIT" }, - "node_modules/utp-native": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/utp-native/-/utp-native-2.5.3.tgz", - "integrity": "sha512-sWTrWYXPhhWJh+cS2baPzhaZc89zwlWCfwSthUjGhLkZztyPhcQllo+XVVCbNGi7dhyRlxkWxN4NKU6FbA9Y8w==", - "hasInstallScript": true, + "node_modules/utp": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/utp/-/utp-0.0.7.tgz", + "integrity": "sha512-2ZLjisH0HQkpqZTg2m7TK0Yn7TETTg7DxM0EpCKIIIV2ky9w9nSxW5a7gzdk4nH2h+pomrrGw0uywrUJfsm2eA==", "dependencies": { - "napi-macros": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.0.2", - "timeout-refresh": "^1.0.0", - "unordered-set": "^2.0.1" - }, - "bin": { - "ucat": "ucat.js" - }, - "engines": { - "node": ">=8.12" - } - }, - "node_modules/utp-native/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/utp-native/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/utp-native/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" + "cyclist": "~0.1.0" } }, "node_modules/uuid": { @@ -9048,460 +7484,9 @@ "node": ">= 0.10" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/webtorrent": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/webtorrent/-/webtorrent-2.1.35.tgz", - "integrity": "sha512-JxAdPrX75zAtBumKxOM1691phN26qTx+RgxC20UUm91l/AQ5zAeGAZp1mtoAJoLQKeZPXguMV5RA4+IToLGdLA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "@silentbot1/nat-api": "^0.4.7", - "@thaunknown/simple-peer": "^9.12.1", - "@webtorrent/http-node": "^1.3.0", - "addr-to-ip-port": "^2.0.0", - "bitfield": "^4.1.0", - "bittorrent-dht": "^11.0.5", - "bittorrent-protocol": "^4.1.11", - "cache-chunk-store": "^3.2.2", - "chunk-store-iterator": "^1.0.3", - "cpus": "^1.0.3", - "create-torrent": "^6.0.16", - "cross-fetch-ponyfill": "^1.0.3", - "debug": "^4.3.4", - "escape-html": "^1.0.3", - "fs-chunk-store": "^4.1.0", - "hybrid-chunk-store": "^1.2.2", - "immediate-chunk-store": "^2.2.0", - "join-async-iterator": "^1.1.1", - "load-ip-set": "^3.0.1", - "lt_donthave": "^2.0.0", - "memory-chunk-store": "^1.3.5", - "mime": "^3.0.0", - "once": "^1.4.0", - "parse-torrent": "^11.0.16", - "pump": "^3.0.0", - "queue-microtask": "^1.2.3", - "random-iterate": "^1.0.1", - "range-parser": "^1.2.1", - "run-parallel": "^1.2.0", - "run-parallel-limit": "^1.1.0", - "speed-limiter": "^1.0.2", - "streamx": "^2.15.7", - "throughput": "^1.0.1", - "torrent-discovery": "^11.0.1", - "torrent-piece": "^3.0.0", - "uint8-util": "^2.2.4", - "unordered-array-remove": "^1.0.2", - "ut_metadata": "^4.0.3", - "ut_pex": "^4.0.4" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "utp-native": "^2.5.3" - } - }, - "node_modules/webtorrent/node_modules/addr-to-ip-port": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-2.0.0.tgz", - "integrity": "sha512-9bYbtjamtdLHZSqVIUXhilOryNPiL+x+Q5J/Unpg4VY3ZIkK3fT52UoErj1NdUeVm3J1t2iBEAur4Ywbl/bahw==", - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/bencode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-4.0.0.tgz", - "integrity": "sha512-AERXw18df0pF3ziGOCyUjqKZBVNH8HV3lBxnx5w0qtgMIk4a1wb9BkcCQbkp9Zstfrn/dzRwl7MmUHHocX3sRQ==", - "dependencies": { - "uint8-util": "^2.2.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/bep53-range": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bep53-range/-/bep53-range-2.0.0.tgz", - "integrity": "sha512-sMm2sV5PRs0YOVk0LTKtjuIprVzxgTQUsrGX/7Yph2Rm4FO2Fqqtq7hNjsOB5xezM4v4+5rljCgK++UeQJZguA==", - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/bitfield": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-4.2.0.tgz", - "integrity": "sha512-kUTatQb/mBd8uhvdLrUkouGDBUQiJaIOvPlptUwOWp6MFqih4d1MiVf0m3ATxfZSzu+LjW/awFeABltYa62uIA==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/webtorrent/node_modules/bittorrent-dht": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-11.0.5.tgz", - "integrity": "sha512-R09D6uNaziRqsc+B/j5QzkjceTak+wH9vcNLnkmt8A52EWF9lQwBP0vvCKgSA3AJOYYl+41n3osA2KYYn/z5uQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bencode": "^4.0.0", - "debug": "^4.3.4", - "k-bucket": "^5.1.0", - "k-rpc": "^5.1.0", - "last-one-wins": "^1.0.4", - "lru": "^3.1.0", - "randombytes": "^2.1.0", - "record-cache": "^1.2.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/bittorrent-tracker": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/bittorrent-tracker/-/bittorrent-tracker-11.0.1.tgz", - "integrity": "sha512-WDvixbEkLgnEeVk8iiF2/LwB2zsuxehir3wBFkHskB/LvYE4HQI+6RoWPHjwGqi9POPJdeOnSPFa8pZvB0Bd8A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "@thaunknown/simple-peer": "^9.12.1", - "@thaunknown/simple-websocket": "^9.1.0", - "bencode": "^4.0.0", - "bittorrent-peerid": "^1.3.3", - "chrome-dgram": "^3.0.6", - "clone": "^2.0.0", - "compact2string": "^1.4.1", - "cross-fetch-ponyfill": "^1.0.1", - "debug": "^4.1.1", - "ip": "^1.1.5", - "lru": "^3.1.0", - "minimist": "^1.2.5", - "once": "^1.4.0", - "queue-microtask": "^1.2.3", - "random-iterate": "^1.0.1", - "run-parallel": "^1.2.0", - "run-series": "^1.1.9", - "socks": "^2.0.0", - "string2compact": "^2.0.0", - "uint8-util": "^2.1.9", - "unordered-array-remove": "^1.0.2", - "ws": "^8.0.0" - }, - "bin": { - "bittorrent-tracker": "bin/cmd.js" - }, - "engines": { - "node": ">=12.20.0" - }, - "optionalDependencies": { - "bufferutil": "^4.0.3", - "utf-8-validate": "^5.0.5" - } - }, - "node_modules/webtorrent/node_modules/fs-chunk-store": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/fs-chunk-store/-/fs-chunk-store-4.1.0.tgz", - "integrity": "sha512-8apaYPaENIVUjVGqjo+Yg5/Hv7qL2fijWV+XGMCs3MR07o9DZZVMpF7dclxdjYotSjLdUGVPhqaJn+eAx6NLYQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "filename-reserved-regex": "^3.0.0", - "queue-microtask": "^1.2.2", - "random-access-file": "^4.0.0", - "randombytes": "^2.0.3", - "run-parallel": "^1.1.2", - "thunky": "^1.0.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/immediate-chunk-store": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/immediate-chunk-store/-/immediate-chunk-store-2.2.0.tgz", - "integrity": "sha512-1bHBna0hCa6arRXicu91IiL9RvvkbNYLVq+mzWdaLGZC3hXvX4doh8e1dLhMKez5siu63CYgO5NrGJbRX5lbPA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.3" - } - }, - "node_modules/webtorrent/node_modules/k-bucket": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-5.1.0.tgz", - "integrity": "sha512-Fac7iINEovXIWU20GPnOMLUbjctiS+cnmyjC4zAUgvs3XPf1vo9akfCHkigftSic/jiKqKl+KA3a/vFcJbHyCg==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/webtorrent/node_modules/k-rpc": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-5.1.0.tgz", - "integrity": "sha512-FGc+n70Hcjoa/X2JTwP+jMIOpBz+pkRffHnSl9yrYiwUxg3FIgD50+u1ePfJUOnRCnx6pbjmVk5aAeB1wIijuQ==", - "dependencies": { - "k-bucket": "^5.0.0", - "k-rpc-socket": "^1.7.2", - "randombytes": "^2.0.5" - } - }, - "node_modules/webtorrent/node_modules/lru": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lru/-/lru-3.1.0.tgz", - "integrity": "sha512-5OUtoiVIGU4VXBOshidmtOsvBIvcQR6FD/RzWSvaeHyxCGB+PCUCu+52lqMfdc0h/2CLvHhZS4TwUmMQrrMbBQ==", - "dependencies": { - "inherits": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/webtorrent/node_modules/magnet-uri": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-7.0.5.tgz", - "integrity": "sha512-Ke+dDiYHK1Rq/ZyGUAgk7NIkoypivxolTj/A0qr60ypP0FjeP+NTUNEhr965HsRan0zGxKEBK73+SsjRyJWkXg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "@thaunknown/thirty-two": "^1.0.3", - "bep53-range": "^2.0.0", - "uint8-util": "^2.1.9" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/webtorrent/node_modules/parse-torrent": { - "version": "11.0.16", - "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-11.0.16.tgz", - "integrity": "sha512-5GoOdmW0HpiB78aQpBz8/5V3V1LjBRDNiL7DOs33pKeCLOzFnfMrsRD6CYmaUBT5Vi/dXE0hfePsjDGJSMF48w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bencode": "^4.0.0", - "cross-fetch-ponyfill": "^1.0.3", - "get-stdin": "^9.0.0", - "magnet-uri": "^7.0.5", - "queue-microtask": "^1.2.3", - "uint8-util": "^2.2.4" - }, - "bin": { - "parse-torrent": "bin/cmd.js" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/random-access-file": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-4.0.6.tgz", - "integrity": "sha512-WLk07uxKsZQZWUDjoO5ZvJHMkrBbZ5GLrCWAXYLiiBbZ4Vf4+7VlJcUJyq3fMgp0lAwTqtbFKzIn5FwqgztnUQ==", - "dependencies": { - "random-access-storage": "^3.0.0" - }, - "optionalDependencies": { - "fs-native-extensions": "^1.1.0" - } - }, - "node_modules/webtorrent/node_modules/random-access-storage": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-3.0.1.tgz", - "integrity": "sha512-raFoHJ/orMyur04GKrA+5ThOwhX9wICdqMDLqTM7bHEXPz7zi5MxLsLUaybxGu3b4mJTt8zhCpZHgjlu0x4wpg==", - "dependencies": { - "events": "^3.3.0", - "queue-tick": "^1.0.0" - } - }, - "node_modules/webtorrent/node_modules/string2compact": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-2.0.1.tgz", - "integrity": "sha512-Bm/T8lHMTRXw+u83LE+OW7fXmC/wM+Mbccfdo533ajSBNxddDHlRrvxE49NdciGHgXkUQM5WYskJ7uTkbBUI0A==", - "dependencies": { - "addr-to-ip-port": "^2.0.0", - "ipaddr.js": "^2.0.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/torrent-discovery": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/torrent-discovery/-/torrent-discovery-11.0.1.tgz", - "integrity": "sha512-+QhOUWRxhR8Y6e5z5I0qil812q11Xz9Yaj1pfYwVkereTBQT1THBCeSHxWZEHuGjKLiIBueVzPP7+wiPtedXKg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "bittorrent-dht": "^11.0.5", - "bittorrent-lsd": "^2.0.0", - "bittorrent-tracker": "^11.0.1", - "debug": "^4.3.4", - "run-parallel": "^1.2.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/torrent-piece": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/torrent-piece/-/torrent-piece-3.0.0.tgz", - "integrity": "sha512-j0tRX7qq22nIuVFF57Tg/wAvFq79F1eM9pcMxY+b0qCCe7yXJnIrqF+Q5YEJ94tNisDnJzcqDHNrPmD9X/yAIg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "uint8-util": "^2.1.9" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/webtorrent/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/which": { "version": "2.0.2", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -9592,24 +7577,13 @@ "version": "1.0.2", "license": "ISC" }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "node_modules/ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" + "options": ">=0.0.5", + "ultron": "1.0.x" } }, "node_modules/xtend": { diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index bd5bdf9..cbfad95 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -29,17 +29,14 @@ "reflect-metadata": "^0.2.1", "sequelize": "^6.36.0", "sequelize-typescript": "^2.1.6", - "utp-native": "^2.5.3", - "webtorrent": "^2.1.35" + "torrent-stream": "^1.2.1" }, "devDependencies": { - "node-gyp": "^10.0.1", - "nodemon": "^3.0.3", "@types/amqplib": "^0.10.4", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", + "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", - "@types/webtorrent": "^0.109.7", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "concurrently": "^8.2.2", @@ -47,10 +44,12 @@ "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", + "node-gyp": "^10.0.1", + "nodemon": "^3.0.3", "pino-pretty": "^10.3.1", - "tsx": "^4.7.0", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", + "tsx": "^4.7.0", "typescript": "^5.3.3" } } diff --git a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts index c19ebf4..cb3a427 100644 --- a/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/cinemeta_metadata.ts @@ -16,7 +16,6 @@ export interface ICinemetaMetaData { dvdRelease?: null; genre?: string[]; imdbRating?: string; - imdb_id?: string; name?: string; popularity?: number; poster?: string; diff --git a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts index 1a0faf7..6b7546c 100644 --- a/src/node/consumer/src/lib/interfaces/common_video_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/common_video_metadata.ts @@ -5,4 +5,5 @@ export interface ICommonVideoMetadata { title?: string; name?: string; id?: string; + imdb_id?: string; } \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts index 56229b5..2c29416 100644 --- a/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts +++ b/src/node/consumer/src/lib/interfaces/kitsu_metadata.ts @@ -34,7 +34,6 @@ export interface IKitsuMeta { export interface IKitsuVideo extends ICommonVideoMetadata { imdbEpisode?: number; imdbSeason?: number; - imdb_id?: string; thumbnail?: string; } diff --git a/src/node/consumer/src/lib/models/configuration/torrent_config.ts b/src/node/consumer/src/lib/models/configuration/torrent_config.ts index 683a49a..d40d0ed 100644 --- a/src/node/consumer/src/lib/models/configuration/torrent_config.ts +++ b/src/node/consumer/src/lib/models/configuration/torrent_config.ts @@ -1,5 +1,4 @@ export const torrentConfig = { MAX_CONNECTIONS_PER_TORRENT: parseInt(process.env.MAX_CONNECTIONS_PER_TORRENT || "20", 10), - MAX_CONNECTIONS_OVERALL: parseInt(process.env.MAX_CONNECTIONS_OVERALL || "100", 10), TIMEOUT: parseInt(process.env.TORRENT_TIMEOUT || "30000", 10) }; \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 3aed419..b669339 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -8,7 +8,7 @@ import {IMetaDataQuery} from "@interfaces/metadata_query"; import {IMetadataResponse} from "@interfaces/metadata_response"; import {IMetadataService} from "@interfaces/metadata_service"; import {IocTypes} from "@models/ioc_types"; -import axios, {AxiosResponse} from 'axios'; +import axios from 'axios'; import {ResultTypes, search} from 'google-sr'; import {inject, injectable} from "inversify"; import nameToImdb from 'name-to-imdb'; @@ -70,12 +70,12 @@ export class MetadataService implements IMetadataService { const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; const metaType = query.type === TorrentType.Movie ? TorrentType.Movie : TorrentType.Series; - return this.cacheService.cacheWrapMetadata(key.toString(), () => this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) - .catch(() => this.requestMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) + return this.cacheService.cacheWrapMetadata(key.toString(), () => this.requestKitsuMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + .catch(() => this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) .catch(() => { // try different type in case there was a mismatch const otherType = metaType === TorrentType.Movie ? TorrentType.Series : TorrentType.Movie; - return this.requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) + return this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) }) .catch((error) => { throw new Error(`failed metadata query ${key} due: ${error.message}`); @@ -101,23 +101,20 @@ export class MetadataService implements IMetadataService { .replace(/\s{2,}/, ' ') // replace multiple spaces .trim(); - private requestMetadata = async (url: string): Promise => { - const response: AxiosResponse = await axios.get(url, {timeout: TIMEOUT}); - let result: IMetadataResponse; + private requestKitsuMetadata = async (url: string): Promise => { + const response = await axios.get(url, {timeout: TIMEOUT}); const body = response.data; - if ('kitsu_id' in body.meta) { - result = this.handleKitsuResponse(body as IKitsuJsonResponse); - } else if ('imdb_id' in body.meta) { - result = this.handleCinemetaResponse(body as ICinemetaJsonResponse); - } else { - throw new Error('No valid metadata'); - } + return this.handleKitsuResponse(body as IKitsuJsonResponse); + }; - return result; + private requestCinemetaMetadata = async (url: string): Promise => { + const response = await axios.get(url, {timeout: TIMEOUT}); + const body = response.data; + return this.handleCinemetaResponse(body as ICinemetaJsonResponse); }; private handleCinemetaResponse = (body: ICinemetaJsonResponse): IMetadataResponse => ({ - imdbId: parseInt(body.meta?.imdb_id || '0'), + imdbId: parseInt(body.meta?.id || '0'), type: body.meta?.type, title: body.meta?.name, year: parseInt(body.meta?.year || '0'), diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 146502d..3729fae 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -11,7 +11,10 @@ import {configurationService} from '@services/configuration_service'; import {inject, injectable} from "inversify"; import {encode} from 'magnet-uri'; import {parse} from "parse-torrent-title"; -import WebTorrent from "webtorrent"; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as torrentStream from "torrent-stream"; +import TorrentEngine = TorrentStream.TorrentEngine; +import TorrentEngineOptions = TorrentStream.TorrentEngineOptions; interface ITorrentFile { name: string; @@ -20,27 +23,19 @@ interface ITorrentFile { fileIndex: number; } -const clientOptions : WebTorrent.Options = { - maxConns: configurationService.torrentConfig.MAX_CONNECTIONS_OVERALL, - utp: false, -} - -const torrentOptions: WebTorrent.TorrentOptions = { - skipVerify: true, - destroyStoreOnDestroy: true, - private: true, - maxWebConns: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, -} - @injectable() export class TorrentDownloadService implements ITorrentDownloadService { - private torrentClient: WebTorrent.Instance; private logger: ILoggingService; + private engineOptions: TorrentEngineOptions = { + connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, + uploads: 0, + verify: false, + dht: false, + tracker: true, + }; constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { this.logger = logger; - this.torrentClient = new WebTorrent(clientOptions); - this.torrentClient.on('error', errors => this.logClientErrors(errors)); } public getTorrentFiles = async (torrent: IParsedTorrent, timeout: number = 30000): Promise => { @@ -64,42 +59,30 @@ export class TorrentDownloadService implements ITorrentDownloadService { const magnet = encode({infoHash: torrent.infoHash, announce: torrent.trackers!.split(',')}); return new Promise((resolve, reject) => { - this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash} to webtorrent client...`); - - const currentTorrent = this.torrentClient.add(magnet, torrentOptions); + this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash} to torrent engine...`); const timeoutId = setTimeout(() => { - this.removeTorrent(currentTorrent, torrent); + engine.destroy(() => {}); reject(new Error('No available connections for torrent!')); }, timeout); - - currentTorrent.on('ready', () => { - const files: ITorrentFile[] = currentTorrent.files.map((file, fileId) => ({ + + const engine: TorrentEngine = torrentStream.default(magnet, this.engineOptions); + + engine.on("ready", () => { + const files: ITorrentFile[] = engine.files.map((file, fileId) => ({ fileIndex: fileId, length: file.length, name: file.name, path: file.path, })); - this.logger.debug(`Found ${files.length} files in torrent ${torrent.infoHash}`); - resolve(files); clearTimeout(timeoutId); - this.removeTorrent(currentTorrent, torrent); + engine.destroy(() => {}); }); }); }; - private removeTorrent = (currentTorrent: WebTorrent.Torrent, torrent: IParsedTorrent): void => { - try { - this.torrentClient.remove(currentTorrent, {destroyStore: true}, () => { - this.logger.debug(`Removed torrent ${torrent.infoHash} from webtorrent client...`); - }); - } catch (error) { - this.logClientErrors(error); - } - }; - private filterVideos = (torrent: IParsedTorrent, torrentFiles: ITorrentFile[]): IFileAttributes[] => { if (torrentFiles.length === 1 && !Number.isInteger(torrentFiles[0].fileIndex)) { return [this.mapTorrentFileToFileAttributes(torrent, torrentFiles[0])]; @@ -179,9 +162,5 @@ export class TorrentDownloadService implements ITorrentDownloadService { path: file.path, size: file.length, }); - - private logClientErrors(errors: Error | string | unknown): void { - this.logger.error(`Error in webtorrent client: ${errors}`); - } } diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 364d853..61a800a 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -56,8 +56,6 @@ export class TorrentFileService implements ITorrentFileService { .catch(() => undefined); if (metadata === undefined || metadata instanceof Error) { - this.logger.warn(`Failed to retrieve metadata for torrent ${torrent.title}`); - this.logger.debug(`Metadata Error: ${torrent.title}`, metadata); return Promise.reject(new Error('Failed to retrieve metadata')); } From ed6b08dbc447ee7dc2ba495766164836327df152 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 08:47:50 +0000 Subject: [PATCH 33/55] switch to yarn --- src/node/consumer/package-lock.json | 7657 --------------------------- src/node/consumer/package.json | 6 +- src/node/consumer/yarn.lock | 4302 +++++++++++++++ 3 files changed, 4304 insertions(+), 7661 deletions(-) delete mode 100644 src/node/consumer/package-lock.json create mode 100644 src/node/consumer/yarn.lock diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json deleted file mode 100644 index 820c26c..0000000 --- a/src/node/consumer/package-lock.json +++ /dev/null @@ -1,7657 +0,0 @@ -{ - "name": "consumer", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "consumer", - "version": "0.0.1", - "license": "MIT", - "dependencies": { - "@tirke/node-cache-manager-mongodb": "^1.6.0", - "amqplib": "^0.10.3", - "axios": "^1.6.1", - "bottleneck": "^2.19.5", - "cache-manager": "^5.4.0", - "google-sr": "^3.2.1", - "inversify": "^6.0.2", - "magnet-uri": "^6.2.0", - "moment": "^2.30.1", - "name-to-imdb": "^3.0.4", - "parse-torrent-title": "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", - "pg": "^8.11.3", - "pg-hstore": "^2.3.4", - "pino": "^8.18.0", - "reflect-metadata": "^0.2.1", - "sequelize": "^6.36.0", - "sequelize-typescript": "^2.1.6", - "torrent-stream": "^1.2.1" - }, - "devDependencies": { - "@types/amqplib": "^0.10.4", - "@types/magnet-uri": "^5.1.5", - "@types/node": "^20.11.16", - "@types/torrent-stream": "^0.0.9", - "@types/validator": "^13.11.8", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", - "concurrently": "^8.2.2", - "esbuild": "^0.20.0", - "eslint": "^8.56.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-import-helpers": "^1.3.1", - "node-gyp": "^10.0.1", - "nodemon": "^3.0.3", - "pino-pretty": "^10.3.1", - "ts-node": "^10.9.2", - "tsconfig-paths": "^4.2.0", - "tsx": "^4.7.0", - "typescript": "^5.3.3" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@acuminous/bitsyntax": { - "version": "0.1.2", - "license": "MIT", - "dependencies": { - "buffer-more-ints": "~1.0.0", - "debug": "^4.3.4", - "safe-buffer": "~5.1.2" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz", - "integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz", - "integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz", - "integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz", - "integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz", - "integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz", - "integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz", - "integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz", - "integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz", - "integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz", - "integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz", - "integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz", - "integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz", - "integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz", - "integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz", - "integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz", - "integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz", - "integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz", - "integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz", - "integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz", - "integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz", - "integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz", - "integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz", - "integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", - "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/fs/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@swc/core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.0.tgz", - "integrity": "sha512-wc5DMI5BJftnK0Fyx9SNJKkA0+BZSJQx8430yutWmsILkHMBD3Yd9GhlMaxasab9RhgKqZp7Ht30hUYO5ZDvQg==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "@swc/counter": "^0.1.1", - "@swc/types": "^0.1.5" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.4.0", - "@swc/core-darwin-x64": "1.4.0", - "@swc/core-linux-arm-gnueabihf": "1.4.0", - "@swc/core-linux-arm64-gnu": "1.4.0", - "@swc/core-linux-arm64-musl": "1.4.0", - "@swc/core-linux-x64-gnu": "1.4.0", - "@swc/core-linux-x64-musl": "1.4.0", - "@swc/core-win32-arm64-msvc": "1.4.0", - "@swc/core-win32-ia32-msvc": "1.4.0", - "@swc/core-win32-x64-msvc": "1.4.0" - }, - "peerDependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-UTJ/Vz+s7Pagef6HmufWt6Rs0aUu+EJF4Pzuwvr7JQQ5b1DZeAAUeUtkUTFx/PvCbM8Xfw4XdKBUZfrIKCfW8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.0.tgz", - "integrity": "sha512-f8v58u2GsGak8EtZFN9guXqE0Ep10Suny6xriaW2d8FGqESPyNrnBzli3aqkSeQk5gGqu2zJ7WiiKp3XoUOidA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-q2KAkBzmPcTnRij/Y1fgHCKAGevUX/H4uUESrw1J5gmUg9Qip6onKV80lTumA1/aooGJ18LOsB31qdbwmZk9OA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-SknGu96W0mzHtLHWm+62fk5+Omp9fMPFO7AWyGFmz2tr8EgRRXtTSrBUnWhAbgcalnhen48GsvtMdxf1KNputg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-/k3TDvpBRMDNskHooNN1KqwUhcwkfBlIYxRTnJvsfT2C7My4pffR+4KXmt0IKynlTTbCdlU/4jgX4801FSuliw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-GYsTMvNt5+WTVlwwQzOOWsPMw6P/F41u5PGHWmfev8Nd4QJ1h3rWPySKk4mV42IJwH9MgQCVSl3ygwNqwl6kFg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-jGVPdM/VwF7kK/uYRW5N6FwzKf/FnDjGIR3RPvQokjYJy7Auk+3Oj21C0Jev7sIT9RYnO/TrFEoEozKeD/z2Qw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-biHYm1AronEKlt47O/H8sSOBM2BKXMmWT+ApvlxUw50m1RGNnVnE0bgY7tylFuuSiWyXsQPJbmUV708JqORXVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-TL5L2tFQb19kJwv6+elToGBj74QXCn9j+hZfwQatvZEJRA5rDK16eH6oAE751dGUArhnWlW3Vj65hViPvTuycw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-e2xVezU7XZ2Stzn4i7TOQe2Kn84oYdG0M3A7XI7oTdcpsKCcKwgiMoroiAhqCv+iN20KNqhnWwJiUiTj/qN5AA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tirke/node-cache-manager-mongodb": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz", - "integrity": "sha512-3eEtfdriTcYq0bIrxFypwUiiah8IX7tSv+OpzZ9v9iZWrXbR54ot7lCF/kj2LpdBDDOX5eZi74LWGrsB2WFSLg==", - "dependencies": { - "mongodb": "^6.0.0" - }, - "engines": { - "node": ">=14.20" - }, - "funding": { - "url": "https://github.com/sponsors/tirke" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/amqplib": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz", - "integrity": "sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/magnet-uri": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", - "integrity": "sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node/node_modules/undici-types": { - "version": "5.26.5", - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", - "dev": true - }, - "node_modules/@types/torrent-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/torrent-stream/-/torrent-stream-0.0.9.tgz", - "integrity": "sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/validator": { - "version": "13.11.8", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", - "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" - }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "license": "MIT" - }, - "node_modules/@types/whatwg-url": { - "version": "11.0.4", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/addr-to-ip-port": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz", - "integrity": "sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg==" - }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amqplib": { - "version": "0.10.3", - "license": "MIT", - "dependencies": { - "@acuminous/bitsyntax": "^0.1.2", - "buffer-more-ints": "~1.0.0", - "readable-stream": "1.x >=1.1.9", - "url-parse": "~1.5.10" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axios": { - "version": "1.6.7", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bencode": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.7.0.tgz", - "integrity": "sha512-MG5AM/hkQIZoz/layZ1JK3xBTfqkLcJ3dJ7u2lx+6vZT1JWyK3OgEFGx1WFzWt6grGH6OSGQvRcCnhWKLp4f1Q==" - }, - "node_modules/bep53-range": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bitfield": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-0.1.0.tgz", - "integrity": "sha512-M15ypXCxXd81FSOWL2ejHpB1TDKmz7Y55/VuqfExJi72sHW0JzE5dfV+hrSZafZtWRg/tdMsdte5dgwrlOM7nA==" - }, - "node_modules/bittorrent-dht": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-6.4.2.tgz", - "integrity": "sha512-DeBunF1nL/ckThYyU3AVtHFR195zNV06Ob6bKNXA1y6X56GSKMfkNCABB45YcbZevGMW1dytFlm59D/fws5lTg==", - "dependencies": { - "bencode": "^0.7.0", - "buffer-equals": "^1.0.3", - "debug": "^2.2.0", - "inherits": "^2.0.1", - "k-bucket": "^0.6.0", - "k-rpc": "^3.6.0", - "lru": "^2.0.0" - } - }, - "node_modules/bittorrent-dht/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/bittorrent-tracker": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/bittorrent-tracker/-/bittorrent-tracker-7.7.0.tgz", - "integrity": "sha512-YFgPTVRhUMncZr8tM3ige7gnViMGhKoGF23qaiISRG8xtYebTGHrMSMXsTXo6O1KbtdEI+4jzvGY1K/wdT9GUA==", - "dependencies": { - "bencode": "^0.8.0", - "bn.js": "^4.4.0", - "compact2string": "^1.2.0", - "debug": "^2.0.0", - "hat": "0.0.3", - "inherits": "^2.0.1", - "ip": "^1.0.1", - "minimist": "^1.1.1", - "once": "^1.3.0", - "random-iterate": "^1.0.1", - "run-parallel": "^1.1.2", - "run-series": "^1.0.2", - "simple-get": "^2.0.0", - "simple-peer": "^6.0.0", - "simple-websocket": "^4.0.0", - "string2compact": "^1.1.1", - "uniq": "^1.0.1", - "ws": "^1.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "bittorrent-tracker": "bin/cmd.js" - } - }, - "node_modules/bittorrent-tracker/node_modules/bencode": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.8.0.tgz", - "integrity": "sha512-MWs3FqaWOGg5l+quIT9JTx7+SlcMbfPqqpWy+GOYi5rjZkX8i03tkNhAQn3pD2GAKENPpP3ScUR97ZUMffhHZA==" - }, - "node_modules/bittorrent-tracker/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/bncode": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.5.3.tgz", - "integrity": "sha512-0P5VuWobU5Gwbeio8n9Jsdv0tE1IikrV9n4f7RsnXHNtxmdd/oeIO6QyoSEUAEyo5P6i3XMfBppi82WqNsT4JA==" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/bson": { - "version": "6.3.0", - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "node_modules/buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/buffer-equals": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", - "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-more-ints": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cache-manager": { - "version": "5.4.0", - "license": "MIT", - "dependencies": { - "lodash.clonedeep": "^4.5.0", - "lru-cache": "^10.1.0", - "promise-coalesce": "^1.1.2" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-dgram": { - "version": "3.0.6", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "run-series": "^1.1.9" - } - }, - "node_modules/chrome-dns": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "chrome-net": "^3.3.2" - } - }, - "node_modules/chrome-net": { - "version": "3.3.4", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/compact2string": { - "version": "1.4.1", - "license": "BSD", - "dependencies": { - "ipaddr.js": ">= 0.1.5" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/concurrently": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", - "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.30.0", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "spawn-command": "0.0.2", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cyclist": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.1.1.tgz", - "integrity": "sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw==" - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge-ts": { - "version": "5.1.0", - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/diacritics": { - "version": "1.3.0", - "license": "MIT" - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dottie": { - "version": "2.0.6", - "license": "MIT" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw==", - "dependencies": { - "once": "~1.3.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/es-abstract": { - "version": "1.22.3", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz", - "integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.0", - "@esbuild/android-arm": "0.20.0", - "@esbuild/android-arm64": "0.20.0", - "@esbuild/android-x64": "0.20.0", - "@esbuild/darwin-arm64": "0.20.0", - "@esbuild/darwin-x64": "0.20.0", - "@esbuild/freebsd-arm64": "0.20.0", - "@esbuild/freebsd-x64": "0.20.0", - "@esbuild/linux-arm": "0.20.0", - "@esbuild/linux-arm64": "0.20.0", - "@esbuild/linux-ia32": "0.20.0", - "@esbuild/linux-loong64": "0.20.0", - "@esbuild/linux-mips64el": "0.20.0", - "@esbuild/linux-ppc64": "0.20.0", - "@esbuild/linux-riscv64": "0.20.0", - "@esbuild/linux-s390x": "0.20.0", - "@esbuild/linux-x64": "0.20.0", - "@esbuild/netbsd-x64": "0.20.0", - "@esbuild/openbsd-x64": "0.20.0", - "@esbuild/sunos-x64": "0.20.0", - "@esbuild/win32-arm64": "0.20.0", - "@esbuild/win32-ia32": "0.20.0", - "@esbuild/win32-x64": "0.20.0" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/node_modules/debug/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import-helpers": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": "5.x - 8.x" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, - "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-redact": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", - "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.0", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fifo": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/fifo/-/fifo-0.1.4.tgz", - "integrity": "sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g==" - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "dev": true, - "license": "ISC" - }, - "node_modules/flatten": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-0.0.1.tgz", - "integrity": "sha512-pzNZh42/A2HmcRIpddSP0T+zBofd119o5rNB2u1YHv36CM2C/ietI2ZsjWZ2LSL7J0BNVkFn1a9Ad+cmO2lDQg==", - "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", - "engines": { - "node": "*" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.5", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-chunk-store": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/fs-chunk-store/-/fs-chunk-store-1.7.0.tgz", - "integrity": "sha512-KhjJmZAs2eqfhCb6PdPx4RcZtheGTz86tpTC5JTvqBn/xda+Nb+0C7dCyjOSN7T76H6a56LvH0SVXQMchLXDRw==", - "dependencies": { - "mkdirp": "^0.5.1", - "random-access-file": "^2.0.1", - "randombytes": "^2.0.3", - "rimraf": "^2.4.2", - "run-parallel": "^1.1.2", - "thunky": "^1.0.1" - } - }, - "node_modules/fs-chunk-store/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-browser-rtc": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/google-sr": { - "version": "3.2.1", - "license": "Apache-2.0", - "dependencies": { - "axios": "^1.4.0", - "cheerio": "1.0.0-rc.12", - "deepmerge-ts": "^5.1.0", - "google-sr-selectors": "^0.0.2", - "tslib": "^2.6.1" - } - }, - "node_modules/google-sr-selectors": { - "version": "0.0.2", - "license": "Apache-2.0" - }, - "node_modules/gopd": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hat": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz", - "integrity": "sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==", - "engines": { - "node": "*" - } - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "dev": true - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/immediate-chunk-store": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/immediate-chunk-store/-/immediate-chunk-store-1.0.8.tgz", - "integrity": "sha512-0tQyTytUaIUskpv5j5L5ZeQuEjYDl9QIekwDUisdqpAM81OZjBaEIriW7hoiRLaLNxj1fXE8e1yx5JaCGrrE7A==" - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflection": { - "version": "1.13.4", - "engines": [ - "node >= 0.4.0" - ], - "license": "MIT" - }, - "node_modules/inflight": { - "version": "1.0.6", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inflight/node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/inversify": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", - "integrity": "sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA==" - }, - "node_modules/ip": { - "version": "1.1.8", - "license": "MIT" - }, - "node_modules/ip-set": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ip-set/-/ip-set-1.0.2.tgz", - "integrity": "sha512-Mb6kv78bTi4RNAIIWL8Bbre7hXOR2pNUi3j8FaQkLaitf/ZWxkq3/iIwXNYk2ACO3IMfdVdQrOkUtwZblO7uBA==", - "dependencies": { - "ip": "^1.1.3" - } - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/k-bucket": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-0.6.0.tgz", - "integrity": "sha512-1zJpqkrLYgolqdO1TE1/FWf+mHfhJKLC2Wpi4JaMFZKi4b6tFEn9/d+JqscBIJw5auWFewp16CSAEetFGEC4NQ==", - "dependencies": { - "buffer-equal": "0.0.1", - "inherits": "^2.0.1" - } - }, - "node_modules/k-rpc": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-3.7.0.tgz", - "integrity": "sha512-XFL8PatIToQ/qhSSAq9FSK73wk4fX4DcHqjnkvSCrWC59PV02Oj1KeYa3KnREAXgA1DlCSzcKjk7M8usnT/dUw==", - "dependencies": { - "buffer-equals": "^1.0.3", - "k-bucket": "^2.0.0", - "k-rpc-socket": "^1.5.0" - } - }, - "node_modules/k-rpc-socket": { - "version": "1.11.1", - "license": "MIT", - "dependencies": { - "bencode": "^2.0.0", - "chrome-dgram": "^3.0.2", - "chrome-dns": "^1.0.0", - "chrome-net": "^3.3.2" - } - }, - "node_modules/k-rpc-socket/node_modules/bencode": { - "version": "2.0.3", - "license": "MIT" - }, - "node_modules/k-rpc/node_modules/k-bucket": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-2.0.1.tgz", - "integrity": "sha512-Xuye90xBBDJJbvNSuy3z/Yl8ceVX02/sopqGUEwJkMgRw+//TQXx0/Hbgp60GsoVfZcCBllQXXp6AWe2INu8pw==", - "dependencies": { - "buffer-equal": "0.0.1", - "randombytes": "^2.0.3" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "license": "MIT" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lru": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/lru/-/lru-2.0.1.tgz", - "integrity": "sha512-JGRd3IHM64MPsGVw1Mqbz2Y2HDIePqi/MLfPtdrkHQwvvJnSrS9b6gM3KS9PFR5xJnufXJczHHZSmGqfuII1ew==", - "dependencies": { - "inherits": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/lru-cache": { - "version": "10.2.0", - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/magnet-uri": { - "version": "6.2.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "bep53-range": "^1.1.0", - "thirty-two": "^1.0.2" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "dev": true, - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "node_modules/moment": { - "version": "2.30.1", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.44", - "license": "MIT", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "6.3.0", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.0", - "bson": "^6.2.0", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.0", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^13.0.0" - } - }, - "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { - "version": "13.0.0", - "license": "MIT", - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/mongodb-connection-string-url/node_modules/whatwg-url/node_modules/tr46": { - "version": "4.1.1", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/mongodb-connection-string-url/node_modules/whatwg-url/node_modules/webidl-conversions": { - "version": "7.0.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/name-to-imdb": { - "version": "3.0.4", - "license": "MIT", - "dependencies": { - "diacritics": "~1.3.0", - "named-queue": "^2.1.0", - "needle": "^1.1.2", - "node-fetch": "^2.2.0" - } - }, - "node_modules/named-queue": { - "version": "2.2.1", - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/needle": { - "version": "1.6.0", - "license": "MIT", - "dependencies": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 0.10.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-fetch/node_modules/whatwg-url/node_modules/tr46": { - "version": "0.0.3", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/whatwg-url/node_modules/webidl-conversions": { - "version": "3.0.1", - "license": "BSD-2-Clause" - }, - "node_modules/node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/node-gyp/node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/node-gyp/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/node-gyp/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/node-gyp/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "dev": true, - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/nodemon": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", - "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.3.3", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-torrent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-4.1.0.tgz", - "integrity": "sha512-FeoGe8bOYmSzxO31kYy44A03FjuULCMOIMom8KyuGvO8/lLVPJyo2nr9CwH/iYmNHm74hk7h70o59DOfk9Rq+A==", - "dependencies": { - "magnet-uri": "^4.0.0", - "parse-torrent-file": "^2.0.0" - }, - "bin": { - "parse-torrent": "bin/cmd.js" - } - }, - "node_modules/parse-torrent-file": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz", - "integrity": "sha512-u2MgLOjZPDDer1oRg1c+H/+54iIQYY5TKgQ5G8KrGLT1Dcwdo7Lj+QfQR123+u8J0AMSFGbQUvsBlSB7uIJcCA==", - "deprecated": "Use the parse-torrent package instead", - "dependencies": { - "bencode": "^0.7.0", - "simple-sha1": "^2.0.0" - }, - "bin": { - "parse-torrent-file": "bin/cmd.js" - } - }, - "node_modules/parse-torrent-title": { - "version": "1.3.0", - "resolved": "git+ssh://git@github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", - "integrity": "sha512-Ja7OfUtTb5UKvcjHLh/va3LGZdE/CiJP6it8lxPWf/N9+4aq1hQGwXw1dnJss5dIINQo4ufyDnT2mOIP+ii/pA==", - "license": "MIT", - "dependencies": { - "moment": "^2.24.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/parse-torrent/node_modules/magnet-uri": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-4.2.3.tgz", - "integrity": "sha512-aHhR49CRBOq3BX6jQOBdGMXhNT2+9LIH3CCIwHlR+aFE8nWMfBD1aNYxfm2u2LsCOwvfPeyCsdIg9KXSwdsOLQ==", - "dependencies": { - "flatten": "0.0.1", - "thirty-two": "^0.0.2", - "xtend": "^4.0.0" - } - }, - "node_modules/parse-torrent/node_modules/thirty-two": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-0.0.2.tgz", - "integrity": "sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA==", - "engines": { - "node": ">=0.2.6" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "license": "MIT", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/peer-wire-protocol": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/peer-wire-protocol/-/peer-wire-protocol-0.7.1.tgz", - "integrity": "sha512-V9oTa/ZcfNNz9fAST28Gg0fXbPeFPk3SBImsYO8GDDG5D0E195vxXmjZ+SPrzr4BJyMQmdDmwUfTf9MZ62z4mw==", - "dependencies": { - "bitfield": "^0.1.0", - "bncode": "^0.2.3", - "buffer-alloc": "^1.1.0", - "buffer-from": "^1.0.0", - "readable-stream": "^1.0.2", - "speedometer": "^0.1.2" - } - }, - "node_modules/peer-wire-protocol/node_modules/bncode": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.2.3.tgz", - "integrity": "sha512-IXGfySD68R/J2X/it8GZqAM+Vb3ByZvAlUi0Gysq4ZACq6hXGQ3YshKo0QS/f3S9wOWKjJnEjP6x3ELxqBnAOA==" - }, - "node_modules/peer-wire-swarm": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/peer-wire-swarm/-/peer-wire-swarm-0.12.2.tgz", - "integrity": "sha512-sIWZ1nTL9l6mI9J18kW1AeByBwagvNzGJlMmQA9pM+otKQtTIwnigK8SR0nEFrNZYqZelI6RQ6g4udvtQ2TI1g==", - "dependencies": { - "buffer-from": "^1.0.0", - "fifo": "^0.1.4", - "once": "^1.1.1", - "peer-wire-protocol": "^0.7.0", - "speedometer": "^0.1.2", - "utp": "0.0.7" - } - }, - "node_modules/pg": { - "version": "8.11.3", - "license": "MIT", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "license": "MIT" - }, - "node_modules/pg-hstore": { - "version": "2.3.4", - "license": "MIT", - "dependencies": { - "underscore": "^1.13.1" - }, - "engines": { - "node": ">= 0.8.x" - } - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-pool": { - "version": "3.6.1", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.6.0", - "license": "MIT" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pino": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", - "integrity": "sha512-Mz/gKiRyuXu4HnpHgi1YWdHQCoWMufapzooisvFn78zl4dZciAxS+YeRkUxXl1ee/SzU80YCz1zpECCh4oC6Aw==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/pino-abstract-transport/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/pino-pretty": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", - "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", - "dev": true, - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dev": true, - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-pretty/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/pino-pretty/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "node_modules/promise-coalesce": { - "version": "1.1.2", - "license": "BSD-3-Clause", - "engines": { - "node": ">=16" - } - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/promise-retry/node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pump/node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/pump/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/queue-tick": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "node_modules/random-access-file": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-2.2.1.tgz", - "integrity": "sha512-RGU0xmDqdOyEiynob1KYSeh8+9c9Td1MJ74GT1viMEYAn8SJ9oBtWCXLsYZukCF46yududHOdM449uRYbzBrZQ==", - "dependencies": { - "mkdirp-classic": "^0.5.2", - "random-access-storage": "^1.1.1" - } - }, - "node_modules/random-access-storage": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-1.4.3.tgz", - "integrity": "sha512-D5e2iIC5dNENWyBxsjhEnNOMCwZZ64TARK6dyMN+3g4OTC4MJxyjh9hKLjTGoNhDOPrgjI+YlFEHFnrp/cSnzQ==", - "dependencies": { - "events": "^3.3.0", - "inherits": "^2.0.3", - "queue-tick": "^1.0.0" - } - }, - "node_modules/random-iterate": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randombytes/node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/re-emitter": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.4.tgz", - "integrity": "sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA==" - }, - "node_modules/readable-stream": { - "version": "1.1.14", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.8", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/retry-as-promised": { - "version": "7.0.4", - "license": "MIT" - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-series": { - "version": "1.1.9", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/rusha": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", - "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sequelize": { - "version": "6.36.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", - "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "dependencies": { - "@types/debug": "^4.1.8", - "@types/validator": "^13.7.17", - "debug": "^4.3.4", - "dottie": "^2.0.6", - "inflection": "^1.13.4", - "lodash": "^4.17.21", - "moment": "^2.29.4", - "moment-timezone": "^0.5.43", - "pg-connection-string": "^2.6.1", - "retry-as-promised": "^7.0.4", - "semver": "^7.5.4", - "sequelize-pool": "^7.1.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.9.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "ibm_db": { - "optional": true - }, - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "snowflake-sdk": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-pool": { - "version": "7.1.0", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize-typescript": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz", - "integrity": "sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ==", - "dependencies": { - "glob": "7.2.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "@types/validator": "*", - "reflect-metadata": "*", - "sequelize": ">=6.20.1" - } - }, - "node_modules/sequelize-typescript/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sequelize/node_modules/semver": { - "version": "7.5.4", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-function-length": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.1", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", - "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-peer": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-6.4.4.tgz", - "integrity": "sha512-sY35UHankz0ba02Dd8YzdyXhEeTAnW6ZUyDfKOSwUht1GLp9VuMT4jQUXF/wG7C9vpwvitV7Ig7a6IkY/qizwg==", - "dependencies": { - "debug": "^2.1.0", - "get-browser-rtc": "^1.0.0", - "inherits": "^2.0.1", - "randombytes": "^2.0.3", - "readable-stream": "^2.0.5" - } - }, - "node_modules/simple-peer/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/simple-peer/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/simple-peer/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/simple-peer/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/simple-sha1": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/simple-sha1/-/simple-sha1-2.1.2.tgz", - "integrity": "sha512-TQl9rm4rdKAVmhO++sXAb8TNN0D6JAD5iyI1mqEPNpxUzTRrtm4aOG1pDf/5W/qCFihiaoK6uuL9rvQz1x1VKw==", - "dependencies": { - "rusha": "^0.8.1" - } - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-websocket": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-4.3.1.tgz", - "integrity": "sha512-knEO6ub2Pw00c7ueOV6snKE1hr7jIdY068+239v0I8DVKofyd7IQmYHXrM9pZL1zuI0H7sd+Y5kedndBi5GXIA==", - "dependencies": { - "debug": "^2.1.3", - "inherits": "^2.0.1", - "randombytes": "^2.0.3", - "readable-stream": "^2.0.5", - "ws": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "node_modules/simple-websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/simple-websocket/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/simple-websocket/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/simple-websocket/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/simple-websocket/node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" - }, - "node_modules/simple-websocket/node_modules/ws": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", - "integrity": "sha512-61a+9LgtYZxTq1hAonhX8Xwpo2riK4IOR/BIVxioFbCfc3QFKmpE4x9dLExfLHKtUfVZigYa36tThVhO57erEw==", - "dependencies": { - "safe-buffer": "~5.0.1", - "ultron": "~1.1.0" - } - }, - "node_modules/simple-websocket/node_modules/ws/node_modules/safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha512-cr7dZWLwOeaFBLTIuZeYdkfO7UzGIKhjYENJFAxUOMKWGaWDm2nJM2rzxNRm5Owu0DH3ApwNo6kx5idXZfb/Iw==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "devOptional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "devOptional": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "devOptional": true - }, - "node_modules/sonic-boom": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", - "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spawn-command": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", - "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", - "dev": true - }, - "node_modules/speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q==" - }, - "node_modules/split2": { - "version": "4.2.0", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "license": "MIT" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string2compact": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-1.3.2.tgz", - "integrity": "sha512-3XUxUgwhj7Eqh2djae35QHZZT4mN3fsO7kagZhSGmhhlrQagVvWSFuuFIWnpxFS0CdTB2PlQcaL16RDi14I8uw==", - "dependencies": { - "addr-to-ip-port": "^1.0.1", - "ipaddr.js": "^2.0.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/thirty-two": { - "version": "1.0.2", - "engines": { - "node": ">=0.2.6" - } - }, - "node_modules/thread-stream": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/to-regex-range": { - "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, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toposort-class": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/torrent-discovery": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/torrent-discovery/-/torrent-discovery-5.4.0.tgz", - "integrity": "sha512-bPTDIA7XEjRlw6vQyt7kM/h1mg1INBsibjbujISITonx4POENZgxfyCSEXZpDhbAkluSPH4HKRKs4/YTmNLC6w==", - "dependencies": { - "bittorrent-dht": "^6.0.0", - "bittorrent-tracker": "^7.0.0", - "debug": "^2.0.0", - "inherits": "^2.0.1", - "re-emitter": "^1.0.0", - "run-parallel": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "node_modules/torrent-discovery/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/torrent-piece": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/torrent-piece/-/torrent-piece-1.1.2.tgz", - "integrity": "sha512-ElXPyXKKG73o+uziHJ8qlYE9EuyDVxnK2zWL+pW/2bma7RsLpSwFFIJAb8Qui7/tel2hsHQW1z3zBnfQNREpWA==" - }, - "node_modules/torrent-stream": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/torrent-stream/-/torrent-stream-1.2.1.tgz", - "integrity": "sha512-F+3tYmXnpO2gyhZQ7o8yakELJH3FtKISI/FU0iWvchOWFUXiFnjbEBoumSzfcK1P71Qxzx2az4lVK4Dkq4KSew==", - "dependencies": { - "bitfield": "^0.1.0", - "bncode": "^0.5.2", - "buffer-from": "^1.0.0", - "end-of-stream": "^0.1.4", - "fs-chunk-store": "^1.3.0", - "hat": "0.0.3", - "immediate-chunk-store": "^1.0.5", - "ip-set": "^1.0.0", - "mkdirp": "^0.3.5", - "parse-torrent": "^4.0.0", - "peer-wire-swarm": "^0.12.0", - "rimraf": "^2.2.5", - "torrent-discovery": "^5.2.0", - "torrent-piece": "^1.0.0" - } - }, - "node_modules/torrent-stream/node_modules/mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)" - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-api-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz", - "integrity": "sha512-d+3WxW4r8WQy2cZWpNRPPGExX8ffOLGcIhheUANKbL5Sqjbhkneki76fRAWeXkaslV2etTb4tSJBSxOsH5+CJw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz", - "integrity": "sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==", - "dev": true, - "dependencies": { - "esbuild": "~0.19.10", - "get-tsconfig": "^4.7.2" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow==" - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.6", - "license": "MIT" - }, - "node_modules/uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" - }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/utp": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/utp/-/utp-0.0.7.tgz", - "integrity": "sha512-2ZLjisH0HQkpqZTg2m7TK0Yn7TETTg7DxM0EpCKIIIV2ky9w9nSxW5a7gzdk4nH2h+pomrrGw0uywrUJfsm2eA==", - "dependencies": { - "cyclist": "~0.1.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/validator": { - "version": "13.11.0", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.14", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "license": "ISC" - }, - "node_modules/ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "dependencies": { - "options": ">=0.0.5", - "ultron": "1.0.x" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index cbfad95..f055bd0 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -7,8 +7,8 @@ "build": "node esbuild.js", "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", "start": "node dist/main.cjs", - "lint": "npx eslint ./src --ext .ts,.js", - "lint-fix": "npm run lint -- --fix" + "lint": "yarn eslint ./src --ext .ts,.js", + "lint-fix": "yarn run lint --fix" }, "license": "MIT", "dependencies": { @@ -39,13 +39,11 @@ "@types/validator": "^13.11.8", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "concurrently": "^8.2.2", "esbuild": "^0.20.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", "node-gyp": "^10.0.1", - "nodemon": "^3.0.3", "pino-pretty": "^10.3.1", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", diff --git a/src/node/consumer/yarn.lock b/src/node/consumer/yarn.lock new file mode 100644 index 0000000..2037980 --- /dev/null +++ b/src/node/consumer/yarn.lock @@ -0,0 +1,4302 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@acuminous/bitsyntax@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz#e0b31b9ee7ad1e4dd840c34864327c33d9f1f653" + integrity sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ== + dependencies: + buffer-more-ints "~1.0.0" + debug "^4.3.4" + safe-buffer "~5.1.2" + +"@babel/runtime@^7.21.0": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== + dependencies: + regenerator-runtime "^0.14.0" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@esbuild/aix-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" + integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== + +"@esbuild/aix-ppc64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz#509621cca4e67caf0d18561a0c56f8b70237472f" + integrity sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw== + +"@esbuild/android-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" + integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== + +"@esbuild/android-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz#109a6fdc4a2783fc26193d2687827045d8fef5ab" + integrity sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q== + +"@esbuild/android-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" + integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== + +"@esbuild/android-arm@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.0.tgz#1397a2c54c476c4799f9b9073550ede496c94ba5" + integrity sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g== + +"@esbuild/android-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" + integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== + +"@esbuild/android-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.0.tgz#2b615abefb50dc0a70ac313971102f4ce2fdb3ca" + integrity sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ== + +"@esbuild/darwin-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" + integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + +"@esbuild/darwin-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz#5c122ed799eb0c35b9d571097f77254964c276a2" + integrity sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ== + +"@esbuild/darwin-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" + integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== + +"@esbuild/darwin-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz#9561d277002ba8caf1524f209de2b22e93d170c1" + integrity sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw== + +"@esbuild/freebsd-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" + integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== + +"@esbuild/freebsd-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz#84178986a3138e8500d17cc380044868176dd821" + integrity sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ== + +"@esbuild/freebsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" + integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== + +"@esbuild/freebsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz#3f9ce53344af2f08d178551cd475629147324a83" + integrity sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ== + +"@esbuild/linux-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" + integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== + +"@esbuild/linux-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz#24efa685515689df4ecbc13031fa0a9dda910a11" + integrity sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw== + +"@esbuild/linux-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" + integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== + +"@esbuild/linux-arm@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz#6b586a488e02e9b073a75a957f2952b3b6e87b4c" + integrity sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg== + +"@esbuild/linux-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" + integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== + +"@esbuild/linux-ia32@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz#84ce7864f762708dcebc1b123898a397dea13624" + integrity sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w== + +"@esbuild/linux-loong64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" + integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== + +"@esbuild/linux-loong64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz#1922f571f4cae1958e3ad29439c563f7d4fd9037" + integrity sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw== + +"@esbuild/linux-mips64el@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" + integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== + +"@esbuild/linux-mips64el@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz#7ca1bd9df3f874d18dbf46af009aebdb881188fe" + integrity sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ== + +"@esbuild/linux-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" + integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== + +"@esbuild/linux-ppc64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz#8f95baf05f9486343bceeb683703875d698708a4" + integrity sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw== + +"@esbuild/linux-riscv64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" + integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== + +"@esbuild/linux-riscv64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz#ca63b921d5fe315e28610deb0c195e79b1a262ca" + integrity sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA== + +"@esbuild/linux-s390x@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" + integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== + +"@esbuild/linux-s390x@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz#cb3d069f47dc202f785c997175f2307531371ef8" + integrity sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ== + +"@esbuild/linux-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" + integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== + +"@esbuild/linux-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz#ac617e0dc14e9758d3d7efd70288c14122557dc7" + integrity sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg== + +"@esbuild/netbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" + integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== + +"@esbuild/netbsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz#6cc778567f1513da6e08060e0aeb41f82eb0f53c" + integrity sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ== + +"@esbuild/openbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" + integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== + +"@esbuild/openbsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz#76848bcf76b4372574fb4d06cd0ed1fb29ec0fbe" + integrity sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA== + +"@esbuild/sunos-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" + integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== + +"@esbuild/sunos-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz#ea4cd0639bf294ad51bc08ffbb2dac297e9b4706" + integrity sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g== + +"@esbuild/win32-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" + integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== + +"@esbuild/win32-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz#a5c171e4a7f7e4e8be0e9947a65812c1535a7cf0" + integrity sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ== + +"@esbuild/win32-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" + integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== + +"@esbuild/win32-ia32@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz#f8ac5650c412d33ea62d7551e0caf82da52b7f85" + integrity sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg== + +"@esbuild/win32-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" + integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== + +"@esbuild/win32-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz#2efddf82828aac85e64cef62482af61c29561bee" + integrity sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.56.0": + version "8.56.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" + integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== + +"@humanwhocodes/config-array@^0.11.13": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@mongodb-js/saslprep@^1.1.0": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz#24ec1c4915a65f5c506bb88c081731450d91bb1c" + integrity sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw== + dependencies: + sparse-bitfield "^3.0.3" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@npmcli/agent@^2.0.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.1.tgz#8aa677d0a4136d57524336a35d5679aedf2d56f7" + integrity sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ== + dependencies: + agent-base "^7.1.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.1" + lru-cache "^10.0.1" + socks-proxy-agent "^8.0.1" + +"@npmcli/fs@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" + integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + dependencies: + semver "^7.3.5" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@tirke/node-cache-manager-mongodb@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz#e730623ae53d4b3e6c6328baab0cff49ed6cb4ce" + integrity sha512-3eEtfdriTcYq0bIrxFypwUiiah8IX7tSv+OpzZ9v9iZWrXbR54ot7lCF/kj2LpdBDDOX5eZi74LWGrsB2WFSLg== + dependencies: + mongodb "^6.0.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/amqplib@^0.10.4": + version "0.10.4" + resolved "https://registry.yarnpkg.com/@types/amqplib/-/amqplib-0.10.4.tgz#0bf1ceefe280c02502b209fa9f06394b0c4cd688" + integrity sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg== + dependencies: + "@types/node" "*" + +"@types/debug@^4.1.8": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== + dependencies: + "@types/ms" "*" + +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/magnet-uri@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.5.tgz#8034da138edb41f007729ff18c76e0454df42438" + integrity sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA== + dependencies: + "@types/node" "*" + +"@types/ms@*": + version "0.7.34" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== + +"@types/node@*", "@types/node@^20.11.16": + version "20.11.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708" + integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ== + dependencies: + undici-types "~5.26.4" + +"@types/semver@^7.5.0": + version "7.5.6" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" + integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== + +"@types/torrent-stream@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/torrent-stream/-/torrent-stream-0.0.9.tgz#3b7b721ee74ab013ff793426b2823d71f4711068" + integrity sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ== + dependencies: + "@types/node" "*" + +"@types/validator@^13.11.8", "@types/validator@^13.7.17": + version "13.11.9" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.11.9.tgz#adfe96520b437a0eaa798a475877bf2f75ee402d" + integrity sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw== + +"@types/webidl-conversions@*": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" + integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== + +"@types/whatwg-url@^11.0.2": + version "11.0.4" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.4.tgz#ffed0dc8d89d91f62e3f368fcbda222a487c4f63" + integrity sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw== + dependencies: + "@types/webidl-conversions" "*" + +"@typescript-eslint/eslint-plugin@^6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== + dependencies: + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== + dependencies: + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== + +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== + dependencies: + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1, acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +addr-to-ip-port@^1.0.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz#9542b1c6219fdb8c9ce6cc72c14ee880ab7ddd88" + integrity sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg== + +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +amqplib@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.10.3.tgz#e186a2f74521eb55ec54db6d25ae82c29c1f911a" + integrity sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw== + dependencies: + "@acuminous/bitsyntax" "^0.1.2" + buffer-more-ints "~1.0.0" + readable-stream "1.x >=1.1.9" + url-parse "~1.5.10" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.filter@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" + integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +array.prototype.findlastindex@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" + integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +available-typed-arrays@^1.0.5, available-typed-arrays@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz#ac812d8ce5a6b976d738e1c45f08d0b00bc7d725" + integrity sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg== + +axios@^1.4.0, axios@^1.6.1: + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bencode@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/bencode/-/bencode-0.7.0.tgz#811ed647c0118945e41bb4bbbdea9a2c78a17083" + integrity sha512-MG5AM/hkQIZoz/layZ1JK3xBTfqkLcJ3dJ7u2lx+6vZT1JWyK3OgEFGx1WFzWt6grGH6OSGQvRcCnhWKLp4f1Q== + +bencode@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/bencode/-/bencode-0.8.0.tgz#3143448e82b0fadc745633ecc2a5f8fa87932f19" + integrity sha512-MWs3FqaWOGg5l+quIT9JTx7+SlcMbfPqqpWy+GOYi5rjZkX8i03tkNhAQn3pD2GAKENPpP3ScUR97ZUMffhHZA== + +bencode@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/bencode/-/bencode-2.0.3.tgz#89b9c80ea1b8573554915a7d0c15f62b0aa7fc52" + integrity sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w== + +bep53-range@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.1.tgz#20fd125b00a413254a77d42f63a43750ca7e64ac" + integrity sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bitfield@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bitfield/-/bitfield-0.1.0.tgz#b05d8b5f0d09f2df35a9db3b3a62d3808c46c457" + integrity sha512-M15ypXCxXd81FSOWL2ejHpB1TDKmz7Y55/VuqfExJi72sHW0JzE5dfV+hrSZafZtWRg/tdMsdte5dgwrlOM7nA== + +bittorrent-dht@^6.0.0: + version "6.4.2" + resolved "https://registry.yarnpkg.com/bittorrent-dht/-/bittorrent-dht-6.4.2.tgz#8b40f8cee6bea87f2b34fd2ae0bd367a8b1247a6" + integrity sha512-DeBunF1nL/ckThYyU3AVtHFR195zNV06Ob6bKNXA1y6X56GSKMfkNCABB45YcbZevGMW1dytFlm59D/fws5lTg== + dependencies: + bencode "^0.7.0" + buffer-equals "^1.0.3" + debug "^2.2.0" + inherits "^2.0.1" + k-bucket "^0.6.0" + k-rpc "^3.6.0" + lru "^2.0.0" + +bittorrent-tracker@^7.0.0: + version "7.7.0" + resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-7.7.0.tgz#ffd2eabc141d36ed5c1817df7e992f91fd7fc65c" + integrity sha512-YFgPTVRhUMncZr8tM3ige7gnViMGhKoGF23qaiISRG8xtYebTGHrMSMXsTXo6O1KbtdEI+4jzvGY1K/wdT9GUA== + dependencies: + bencode "^0.8.0" + bn.js "^4.4.0" + compact2string "^1.2.0" + debug "^2.0.0" + hat "0.0.3" + inherits "^2.0.1" + ip "^1.0.1" + minimist "^1.1.1" + once "^1.3.0" + random-iterate "^1.0.1" + run-parallel "^1.1.2" + run-series "^1.0.2" + simple-get "^2.0.0" + simple-peer "^6.0.0" + simple-websocket "^4.0.0" + string2compact "^1.1.1" + uniq "^1.0.1" + ws "^1.0.0" + xtend "^4.0.0" + +bn.js@^4.4.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bncode@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/bncode/-/bncode-0.2.3.tgz#37f851dc8e47188a83fbc0f6fa4775cacc9a3296" + integrity sha512-IXGfySD68R/J2X/it8GZqAM+Vb3ByZvAlUi0Gysq4ZACq6hXGQ3YshKo0QS/f3S9wOWKjJnEjP6x3ELxqBnAOA== + +bncode@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/bncode/-/bncode-0.5.3.tgz#e16661697452d436bf9886238cc791b08d66a61a" + integrity sha512-0P5VuWobU5Gwbeio8n9Jsdv0tE1IikrV9n4f7RsnXHNtxmdd/oeIO6QyoSEUAEyo5P6i3XMfBppi82WqNsT4JA== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +bottleneck@^2.19.5: + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +bson@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.3.0.tgz#d47acba525ba7d7eb0e816c10538bce26a337fe0" + integrity sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw== + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + integrity sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA== + +buffer-equals@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/buffer-equals/-/buffer-equals-1.0.4.tgz#0353b54fd07fd9564170671ae6f66b9cf10d27f5" + integrity sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA== + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-more-ints@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz#ef4f8e2dddbad429ed3828a9c55d44f05c611422" + integrity sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg== + +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +cacache@^18.0.0: + version "18.0.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.2.tgz#fd527ea0f03a603be5c0da5805635f8eef00c60c" + integrity sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^10.0.1" + minipass "^7.0.3" + minipass-collect "^2.0.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + +cache-manager@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/cache-manager/-/cache-manager-5.4.0.tgz#cec47dbea8e49e0f6970d117be10172b4e621358" + integrity sha512-FS7o8vqJosnLpu9rh2gQTo8EOzCRJLF1BJ4XDEUDMqcfvs7SJZs5iuoFTXLauzQ3S5v8sBAST1pCwMaurpyi1A== + dependencies: + lodash.clonedeep "^4.5.0" + lru-cache "^10.1.0" + promise-coalesce "^1.1.2" + +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.6.tgz#6c46675fc7a5e9de82d75a233d586c8b7ac0d931" + integrity sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.3" + set-function-length "^1.2.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@1.0.0-rc.12: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + +chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-dgram@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/chrome-dgram/-/chrome-dgram-3.0.6.tgz#2288b5c7471f66f073691206d36319dda713cf55" + integrity sha512-bqBsUuaOiXiqxXt/zA/jukNJJ4oaOtc7ciwqJpZVEaaXwwxqgI2/ZdG02vXYWUhHGziDlvGMQWk0qObgJwVYKA== + dependencies: + inherits "^2.0.4" + run-series "^1.1.9" + +chrome-dns@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chrome-dns/-/chrome-dns-1.0.1.tgz#6870af680a40d2c4b2efc2154a378793f5a4ce4b" + integrity sha512-HqsYJgIc8ljJJOqOzLphjAs79EUuWSX3nzZi2LNkzlw3GIzAeZbaSektC8iT/tKvLqZq8yl1GJu5o6doA4TRbg== + dependencies: + chrome-net "^3.3.2" + +chrome-net@^3.3.2: + version "3.3.4" + resolved "https://registry.yarnpkg.com/chrome-net/-/chrome-net-3.3.4.tgz#0e604a31d226ebfb8d2d1c381cab47d35309825d" + integrity sha512-Jzy2EnzmE+ligqIZUsmWnck9RBXLuUy6CaKyuNMtowFG3ZvLt8d+WBJCTPEludV0DHpIKjAOlwjFmTaEdfdWCw== + dependencies: + inherits "^2.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compact2string@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/compact2string/-/compact2string-1.4.1.tgz#8d34929055f8300a13cfc030ad1832e2e53c2e25" + integrity sha512-3D+EY5nsRhqnOwDxveBv5T8wGo4DEvYxjDtPGmdOX+gfr5gE92c2RC0w2wa+xEefm07QuVqqcF3nZJUZ92l/og== + dependencies: + ipaddr.js ">= 0.1.5" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concurrently@^8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.2.2.tgz#353141985c198cfa5e4a3ef90082c336b5851784" + integrity sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg== + dependencies: + chalk "^4.1.2" + date-fns "^2.30.0" + lodash "^4.17.21" + rxjs "^7.8.1" + shell-quote "^1.8.1" + spawn-command "0.0.2" + supports-color "^8.1.1" + tree-kill "^1.2.2" + yargs "^17.7.2" + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cyclist@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.1.1.tgz#1bcfa56b081448cdb5e12bfc1bfad34b47fba8f3" + integrity sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw== + +date-fns@^2.30.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + +debug@4, debug@^4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^2.0.0, debug@^2.1.0, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge-ts@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" + integrity sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw== + +define-data-property@^1.0.1, define-data-property@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.2.tgz#f3c33b4f0102360cd7c0f5f28700f5678510b63a" + integrity sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.2" + gopd "^1.0.1" + has-property-descriptors "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +diacritics@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" + integrity sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +dottie@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4" + integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encoding@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" + integrity sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw== + dependencies: + once "~1.3.0" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + +es-abstract@^1.22.1, es-abstract@^1.22.3: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.5" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.2" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.13" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-errors@^1.0.0, es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-set-tostringtag@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== + dependencies: + get-intrinsic "^1.2.2" + has-tostringtag "^1.0.0" + hasown "^2.0.0" + +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +esbuild@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.0.tgz#a7170b63447286cd2ff1f01579f09970e6965da4" + integrity sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.20.0" + "@esbuild/android-arm" "0.20.0" + "@esbuild/android-arm64" "0.20.0" + "@esbuild/android-x64" "0.20.0" + "@esbuild/darwin-arm64" "0.20.0" + "@esbuild/darwin-x64" "0.20.0" + "@esbuild/freebsd-arm64" "0.20.0" + "@esbuild/freebsd-x64" "0.20.0" + "@esbuild/linux-arm" "0.20.0" + "@esbuild/linux-arm64" "0.20.0" + "@esbuild/linux-ia32" "0.20.0" + "@esbuild/linux-loong64" "0.20.0" + "@esbuild/linux-mips64el" "0.20.0" + "@esbuild/linux-ppc64" "0.20.0" + "@esbuild/linux-riscv64" "0.20.0" + "@esbuild/linux-s390x" "0.20.0" + "@esbuild/linux-x64" "0.20.0" + "@esbuild/netbsd-x64" "0.20.0" + "@esbuild/openbsd-x64" "0.20.0" + "@esbuild/sunos-x64" "0.20.0" + "@esbuild/win32-arm64" "0.20.0" + "@esbuild/win32-ia32" "0.20.0" + "@esbuild/win32-x64" "0.20.0" + +esbuild@~0.19.10: + version "0.19.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" + integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.19.12" + "@esbuild/android-arm" "0.19.12" + "@esbuild/android-arm64" "0.19.12" + "@esbuild/android-x64" "0.19.12" + "@esbuild/darwin-arm64" "0.19.12" + "@esbuild/darwin-x64" "0.19.12" + "@esbuild/freebsd-arm64" "0.19.12" + "@esbuild/freebsd-x64" "0.19.12" + "@esbuild/linux-arm" "0.19.12" + "@esbuild/linux-arm64" "0.19.12" + "@esbuild/linux-ia32" "0.19.12" + "@esbuild/linux-loong64" "0.19.12" + "@esbuild/linux-mips64el" "0.19.12" + "@esbuild/linux-ppc64" "0.19.12" + "@esbuild/linux-riscv64" "0.19.12" + "@esbuild/linux-s390x" "0.19.12" + "@esbuild/linux-x64" "0.19.12" + "@esbuild/netbsd-x64" "0.19.12" + "@esbuild/openbsd-x64" "0.19.12" + "@esbuild/sunos-x64" "0.19.12" + "@esbuild/win32-arm64" "0.19.12" + "@esbuild/win32-ia32" "0.19.12" + "@esbuild/win32-x64" "0.19.12" + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-import-helpers@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import-helpers/-/eslint-plugin-import-helpers-1.3.1.tgz#48721a702e758b5d2220ee119d6199e6e29b6819" + integrity sha512-MrACDozK6TmTJoCFHD71Ew3r5210Za3zlTrhX+fQGsyvxceaFvAI9AcvZ/8oSU0pZ61G3nDEn6mXY0T4S8cJEg== + +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.15.0" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.56.0: + version "8.56.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" + integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.56.0" + "@humanwhocodes/config-array" "^0.11.13" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + +fast-copy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" + integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-redact@^3.1.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634" + integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +fifo@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/fifo/-/fifo-0.1.4.tgz#bf42d87c0ad07b00d0949d12388f6289606ece34" + integrity sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +flatten@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-0.0.1.tgz#554440766da0a0d603999f433453f6c2fc6a75c1" + integrity sha512-pzNZh42/A2HmcRIpddSP0T+zBofd119o5rNB2u1YHv36CM2C/ietI2ZsjWZ2LSL7J0BNVkFn1a9Ad+cmO2lDQg== + +follow-redirects@^1.15.4: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-chunk-store@^1.3.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/fs-chunk-store/-/fs-chunk-store-1.7.0.tgz#1c4bcbe93c99af10aa04b65348f2bb27377a4010" + integrity sha512-KhjJmZAs2eqfhCb6PdPx4RcZtheGTz86tpTC5JTvqBn/xda+Nb+0C7dCyjOSN7T76H6a56LvH0SVXQMchLXDRw== + dependencies: + mkdirp "^0.5.1" + random-access-file "^2.0.1" + randombytes "^2.0.3" + rimraf "^2.4.2" + run-parallel "^1.1.2" + thunky "^1.0.1" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-minipass@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== + dependencies: + minipass "^7.0.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-browser-rtc@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz#d1494e299b00f33fc8e9d6d3343ba4ba99711a2c" + integrity sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-symbol-description@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + dependencies: + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + +get-tsconfig@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce" + integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^10.2.2, glob@^10.3.10: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +google-sr-selectors@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/google-sr-selectors/-/google-sr-selectors-0.0.2.tgz#cbfdabe52d3216ba19dd0dc49d8b384e6bd000b7" + integrity sha512-7h+vo7NSDf+pZB/InDon4mwhXeTvy/9yvAChGnjppcdHgTwlUWDpYPWGUn781J3PrjBj6rZAginsSTGqG5uUZw== + +google-sr@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/google-sr/-/google-sr-3.2.1.tgz#1c9c454de7242b377c7d538b7570c7f754e79664" + integrity sha512-1WGy6mxMTKo+jbIrmq1mwm+2Egvmx9ttsXzCiR0Y2LMcpeG4shqc8C4g12msi4arRn9qEwG1qrFQ1W9jo3dDzw== + dependencies: + axios "^1.4.0" + cheerio "1.0.0-rc.12" + deepmerge-ts "^5.1.0" + google-sr-selectors "^0.0.2" + tslib "^2.6.1" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0, has-tostringtag@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +hat@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" + integrity sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug== + +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + +immediate-chunk-store@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/immediate-chunk-store/-/immediate-chunk-store-1.0.8.tgz#0ecdad0c546332672d7b5b511b26bb18ce56e73f" + integrity sha512-0tQyTytUaIUskpv5j5L5ZeQuEjYDl9QIekwDUisdqpAM81OZjBaEIriW7hoiRLaLNxj1fXE8e1yx5JaCGrrE7A== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflection@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" + integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.0" + side-channel "^1.0.4" + +inversify@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-6.0.2.tgz#dc7fa0348213d789d35ffb719dea9685570989c7" + integrity sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA== + +ip-set@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ip-set/-/ip-set-1.0.2.tgz#be4f119f82c124836455993dfcd554639c7007de" + integrity sha512-Mb6kv78bTi4RNAIIWL8Bbre7hXOR2pNUi3j8FaQkLaitf/ZWxkq3/iIwXNYk2ACO3IMfdVdQrOkUtwZblO7uBA== + dependencies: + ip "^1.1.3" + +ip@^1.0.1, ip@^1.1.3: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + +"ipaddr.js@>= 0.1.5", ipaddr.js@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" + integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + +is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.13, is-typed-array@^1.1.9: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isexe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" + integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== + +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +k-bucket@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/k-bucket/-/k-bucket-0.6.0.tgz#afc532545f69d466293e887b00d5fc73377c3abb" + integrity sha512-1zJpqkrLYgolqdO1TE1/FWf+mHfhJKLC2Wpi4JaMFZKi4b6tFEn9/d+JqscBIJw5auWFewp16CSAEetFGEC4NQ== + dependencies: + buffer-equal "0.0.1" + inherits "^2.0.1" + +k-bucket@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/k-bucket/-/k-bucket-2.0.1.tgz#58cccb244f563326ba893bf5c06a35f644846daa" + integrity sha512-Xuye90xBBDJJbvNSuy3z/Yl8ceVX02/sopqGUEwJkMgRw+//TQXx0/Hbgp60GsoVfZcCBllQXXp6AWe2INu8pw== + dependencies: + buffer-equal "0.0.1" + randombytes "^2.0.3" + +k-rpc-socket@^1.5.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/k-rpc-socket/-/k-rpc-socket-1.11.1.tgz#f14b4b240a716c6cad7b6434b21716dbd7c7b0e8" + integrity sha512-8xtA8oqbZ6v1Niryp2/g4GxW16EQh5MvrUylQoOG+zcrDff5CKttON2XUXvMwlIHq4/2zfPVFiinAccJ+WhxoA== + dependencies: + bencode "^2.0.0" + chrome-dgram "^3.0.2" + chrome-dns "^1.0.0" + chrome-net "^3.3.2" + +k-rpc@^3.6.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/k-rpc/-/k-rpc-3.7.0.tgz#641f99b2825be34b6e7984f22b7962dc1a906c23" + integrity sha512-XFL8PatIToQ/qhSSAq9FSK73wk4fX4DcHqjnkvSCrWC59PV02Oj1KeYa3KnREAXgA1DlCSzcKjk7M8usnT/dUw== + dependencies: + buffer-equals "^1.0.3" + k-bucket "^2.0.0" + k-rpc-socket "^1.5.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^10.0.1, lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lru/-/lru-2.0.1.tgz#f979871e162e3f5ca254be46844c53d4c5364544" + integrity sha512-JGRd3IHM64MPsGVw1Mqbz2Y2HDIePqi/MLfPtdrkHQwvvJnSrS9b6gM3KS9PFR5xJnufXJczHHZSmGqfuII1ew== + dependencies: + inherits "^2.0.1" + +magnet-uri@^4.0.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-4.2.3.tgz#79cc6d65a00bb5b7ef5c25ae60ebbb5d9a7681a8" + integrity sha512-aHhR49CRBOq3BX6jQOBdGMXhNT2+9LIH3CCIwHlR+aFE8nWMfBD1aNYxfm2u2LsCOwvfPeyCsdIg9KXSwdsOLQ== + dependencies: + flatten "0.0.1" + thirty-two "^0.0.2" + xtend "^4.0.0" + +magnet-uri@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-6.2.0.tgz#10f7be050bf23452df210838239b118463c3eeff" + integrity sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ== + dependencies: + bep53-range "^1.1.0" + thirty-two "^1.0.2" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +make-fetch-happen@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0" + integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A== + dependencies: + "@npmcli/agent" "^2.0.0" + cacache "^18.0.0" + http-cache-semantics "^4.1.1" + is-lambda "^1.0.1" + minipass "^7.0.2" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + ssri "^10.0.0" + +memory-pager@^1.0.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" + integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimatch@9.0.3, minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass-collect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" + integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== + dependencies: + minipass "^7.0.3" + +minipass-fetch@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" + integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== + dependencies: + minipass "^7.0.3" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + +minizlib@^2.1.1, minizlib@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" + integrity sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg== + +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +moment-timezone@^0.5.43: + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== + dependencies: + moment "^2.29.4" + +moment@^2.24.0, moment@^2.29.4, moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +mongodb-connection-string-url@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz#b4f87f92fd8593f3b9365f592515a06d304a1e9c" + integrity sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ== + dependencies: + "@types/whatwg-url" "^11.0.2" + whatwg-url "^13.0.0" + +mongodb@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.3.0.tgz#ec9993b19f7ed2ea715b903fcac6171c9d1d38ca" + integrity sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA== + dependencies: + "@mongodb-js/saslprep" "^1.1.0" + bson "^6.2.0" + mongodb-connection-string-url "^3.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +name-to-imdb@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/name-to-imdb/-/name-to-imdb-3.0.4.tgz#1395c27f5b8ee057320a6eee218a86bb3f829034" + integrity sha512-OVmDvWoAZso2eHxK51UK7TMIpUpM4LnI3KhvvZe+JkDatEda9WS3/YXZVQnand5skI38shoniOFcyrw08QsNeA== + dependencies: + diacritics "~1.3.0" + named-queue "^2.1.0" + needle "^1.1.2" + node-fetch "^2.2.0" + +named-queue@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/named-queue/-/named-queue-2.2.1.tgz#1814544553599d5a9e403d0dfa937a4ce0d1e6a7" + integrity sha512-ssW6R5DZza+ixfGgu+piZAqszqRViHNZjjazXknCWyRYZfRJkBmbSPd1nIcH29aejsyBNPNrn3AdMfB+qvb2Hw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +needle@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-1.6.0.tgz#f52a5858972121618e002f8e6384cadac22d624f" + integrity sha512-ogVK1D/Cgemw2vM1KJN6B83DwcKbDepdkMNtVJcXIe+xoaCOdC+aJHzhEov7xjsY9S7rBIuHP59W1fLsbGqDhA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +node-fetch@^2.2.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-gyp@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.1.tgz#205514fc19e5830fa991e4a689f9e81af377a966" + integrity sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^10.3.10" + graceful-fs "^4.2.6" + make-fetch-happen "^13.0.0" + nopt "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + tar "^6.1.2" + which "^4.0.0" + +nodemon@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.3.tgz#244a62d1c690eece3f6165c6cdb0db03ebd80b76" + integrity sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ== + dependencies: + chokidar "^3.5.2" + debug "^4" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +nopt@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" + integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + dependencies: + abbrev "^2.0.0" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.fromentries@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" + integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== + dependencies: + array.prototype.filter "^1.0.3" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.0.0" + +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + +once@^1.1.1, once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + integrity sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w== + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-torrent-file@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz#32d4b6afde631420e5f415919a222b774b575707" + integrity sha512-u2MgLOjZPDDer1oRg1c+H/+54iIQYY5TKgQ5G8KrGLT1Dcwdo7Lj+QfQR123+u8J0AMSFGbQUvsBlSB7uIJcCA== + dependencies: + bencode "^0.7.0" + simple-sha1 "^2.0.0" + +"parse-torrent-title@https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654": + version "1.3.0" + resolved "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654" + dependencies: + moment "^2.24.0" + +parse-torrent@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/parse-torrent/-/parse-torrent-4.1.0.tgz#a814bd8505e8b58e88eb8ff3e2daff5d19a711b7" + integrity sha512-FeoGe8bOYmSzxO31kYy44A03FjuULCMOIMom8KyuGvO8/lLVPJyo2nr9CwH/iYmNHm74hk7h70o59DOfk9Rq+A== + dependencies: + magnet-uri "^4.0.0" + parse-torrent-file "^2.0.0" + +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +peer-wire-protocol@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/peer-wire-protocol/-/peer-wire-protocol-0.7.1.tgz#fdb4a75bfe6b3b84710eb5220ef0ebeed3b63396" + integrity sha512-V9oTa/ZcfNNz9fAST28Gg0fXbPeFPk3SBImsYO8GDDG5D0E195vxXmjZ+SPrzr4BJyMQmdDmwUfTf9MZ62z4mw== + dependencies: + bitfield "^0.1.0" + bncode "^0.2.3" + buffer-alloc "^1.1.0" + buffer-from "^1.0.0" + readable-stream "^1.0.2" + speedometer "^0.1.2" + +peer-wire-swarm@^0.12.0: + version "0.12.2" + resolved "https://registry.yarnpkg.com/peer-wire-swarm/-/peer-wire-swarm-0.12.2.tgz#d7120e083cbd42b1c41c961865e938e747428950" + integrity sha512-sIWZ1nTL9l6mI9J18kW1AeByBwagvNzGJlMmQA9pM+otKQtTIwnigK8SR0nEFrNZYqZelI6RQ6g4udvtQ2TI1g== + dependencies: + buffer-from "^1.0.0" + fifo "^0.1.4" + once "^1.1.1" + peer-wire-protocol "^0.7.0" + speedometer "^0.1.2" + utp "0.0.7" + +pg-cloudflare@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" + integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== + +pg-connection-string@^2.6.1, pg-connection-string@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475" + integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== + +pg-hstore@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.4.tgz#4425e3e2a3e15d2a334c35581186c27cf2e9b8dd" + integrity sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA== + dependencies: + underscore "^1.13.1" + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7" + integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og== + +pg-protocol@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833" + integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^8.11.3: + version "8.11.3" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb" + integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g== + dependencies: + buffer-writer "2.0.0" + packet-reader "1.0.0" + pg-connection-string "^2.6.2" + pg-pool "^3.6.1" + pg-protocol "^1.6.0" + pg-types "^2.1.0" + pgpass "1.x" + optionalDependencies: + pg-cloudflare "^1.1.1" + +pgpass@1.x: + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== + dependencies: + split2 "^4.1.0" + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8" + integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA== + dependencies: + readable-stream "^4.0.0" + split2 "^4.0.0" + +pino-pretty@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.3.1.tgz#e3285a5265211ac6c7cd5988f9e65bf3371a0ca9" + integrity sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.0.0" + pump "^3.0.0" + readable-stream "^4.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^3.0.0" + strip-json-comments "^3.1.1" + +pino-std-serializers@^6.0.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz#d9a9b5f2b9a402486a5fc4db0a737570a860aab3" + integrity sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA== + +pino@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-8.18.0.tgz#f2bfbb4e827ed2049ee1e88372268efdcd1505f6" + integrity sha512-Mz/gKiRyuXu4HnpHgi1YWdHQCoWMufapzooisvFn78zl4dZciAxS+YeRkUxXl1ee/SzU80YCz1zpECCh4oC6Aw== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport v1.1.0 + pino-std-serializers "^6.0.0" + process-warning "^3.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^3.7.0" + thread-stream "^2.0.0" + +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== + +postgres-date@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +proc-log@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" + integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" + integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-coalesce@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/promise-coalesce/-/promise-coalesce-1.1.2.tgz#5d3bc4d0b2cf2e41e9df7cbeb6519b2a09459e3d" + integrity sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0, punycode@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +queue-tick@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +random-access-file@^2.0.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-2.2.1.tgz#071d086d8a92cc65abbd32b42aeba6d1d845d68d" + integrity sha512-RGU0xmDqdOyEiynob1KYSeh8+9c9Td1MJ74GT1viMEYAn8SJ9oBtWCXLsYZukCF46yududHOdM449uRYbzBrZQ== + dependencies: + mkdirp-classic "^0.5.2" + random-access-storage "^1.1.1" + +random-access-storage@^1.1.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/random-access-storage/-/random-access-storage-1.4.3.tgz#277d07005107562dfea84798eb9a6acd47d64b7f" + integrity sha512-D5e2iIC5dNENWyBxsjhEnNOMCwZZ64TARK6dyMN+3g4OTC4MJxyjh9hKLjTGoNhDOPrgjI+YlFEHFnrp/cSnzQ== + dependencies: + events "^3.3.0" + inherits "^2.0.3" + queue-tick "^1.0.0" + +random-iterate@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/random-iterate/-/random-iterate-1.0.1.tgz#f7d97d92dee6665ec5f6da08c7f963cad4b2ac99" + integrity sha512-Jdsdnezu913Ot8qgKgSgs63XkAjEsnMcS1z+cC6D6TNXsUXsMxy0RpclF2pzGZTEiTXL9BiArdGTEexcv4nqcA== + +randombytes@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +re-emitter@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/re-emitter/-/re-emitter-1.1.4.tgz#15bdefca3d47e05d6442838fd26759c8a4eaa236" + integrity sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA== + +"readable-stream@1.x >=1.1.9", readable-stream@^1.0.2: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +reflect-metadata@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.1.tgz#8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74" + integrity sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +retry-as-promised@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" + integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.2.5, rimraf@^2.4.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.2, run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +run-series@^1.0.2, run-series@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.9.tgz#15ba9cb90e6a6c054e67c98e1dc063df0ecc113a" + integrity sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g== + +rusha@^0.8.1: + version "0.8.14" + resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68" + integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA== + +rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-array-concat@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" + integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg== + dependencies: + call-bind "^1.0.5" + get-intrinsic "^1.2.2" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + integrity sha512-cr7dZWLwOeaFBLTIuZeYdkfO7UzGIKhjYENJFAxUOMKWGaWDm2nJM2rzxNRm5Owu0DH3ApwNo6kx5idXZfb/Iw== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex-test@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-regex "^1.1.4" + +safe-stable-stringify@^2.3.1: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +secure-json-parse@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + +sequelize-pool@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-7.1.0.tgz#210b391af4002762f823188fd6ecfc7413020768" + integrity sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg== + +sequelize-typescript@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz#9476c8a2510114ed1c3a26b424c47e05c2e6284e" + integrity sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ== + dependencies: + glob "7.2.0" + +sequelize@^6.36.0: + version "6.36.0" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.36.0.tgz#b824cf2b3b2914a5ee9996f23ff703807f68ec4a" + integrity sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ== + dependencies: + "@types/debug" "^4.1.8" + "@types/validator" "^13.7.17" + debug "^4.3.4" + dottie "^2.0.6" + inflection "^1.13.4" + lodash "^4.17.21" + moment "^2.29.4" + moment-timezone "^0.5.43" + pg-connection-string "^2.6.1" + retry-as-promised "^7.0.4" + semver "^7.5.4" + sequelize-pool "^7.1.0" + toposort-class "^1.0.1" + uuid "^8.3.2" + validator "^13.9.0" + wkx "^0.5.0" + +set-function-length@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" + integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== + dependencies: + define-data-property "^1.1.2" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.1" + +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + +side-channel@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" + integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.0.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-peer@^6.0.0: + version "6.4.4" + resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-6.4.4.tgz#4e421f485ac7b13b08077a4476934d52c5ba3bb3" + integrity sha512-sY35UHankz0ba02Dd8YzdyXhEeTAnW6ZUyDfKOSwUht1GLp9VuMT4jQUXF/wG7C9vpwvitV7Ig7a6IkY/qizwg== + dependencies: + debug "^2.1.0" + get-browser-rtc "^1.0.0" + inherits "^2.0.1" + randombytes "^2.0.3" + readable-stream "^2.0.5" + +simple-sha1@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/simple-sha1/-/simple-sha1-2.1.2.tgz#de40cbd5aae278fde8e3bb3250a35d74c67326b1" + integrity sha512-TQl9rm4rdKAVmhO++sXAb8TNN0D6JAD5iyI1mqEPNpxUzTRrtm4aOG1pDf/5W/qCFihiaoK6uuL9rvQz1x1VKw== + dependencies: + rusha "^0.8.1" + +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + +simple-websocket@^4.0.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/simple-websocket/-/simple-websocket-4.3.1.tgz#5d3d5751bb39aeba2f710d8eec78768df821f38d" + integrity sha512-knEO6ub2Pw00c7ueOV6snKE1hr7jIdY068+239v0I8DVKofyd7IQmYHXrM9pZL1zuI0H7sd+Y5kedndBi5GXIA== + dependencies: + debug "^2.1.3" + inherits "^2.0.1" + randombytes "^2.0.3" + readable-stream "^2.0.5" + ws "^2.0.0" + xtend "^4.0.1" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" + integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + socks "^2.7.1" + +socks@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + +sonic-boom@^3.0.0, sonic-boom@^3.7.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66" + integrity sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA== + dependencies: + atomic-sleep "^1.0.0" + +sparse-bitfield@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" + integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== + dependencies: + memory-pager "^1.0.2" + +spawn-command@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" + integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== + +speedometer@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" + integrity sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q== + +split2@^4.0.0, split2@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +ssri@^10.0.0: + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== + dependencies: + minipass "^7.0.3" + +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string2compact@^1.1.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/string2compact/-/string2compact-1.3.2.tgz#c9d11a13f368404b8025425cc53f9916de1d0b8b" + integrity sha512-3XUxUgwhj7Eqh2djae35QHZZT4mN3fsO7kagZhSGmhhlrQagVvWSFuuFIWnpxFS0CdTB2PlQcaL16RDi14I8uw== + dependencies: + addr-to-ip-port "^1.0.1" + ipaddr.js "^2.0.0" + +string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tar@^6.1.11, tar@^6.1.2: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +thirty-two@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a" + integrity sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA== + +thirty-two@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a" + integrity sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA== + +thread-stream@^2.0.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.1.tgz#6d588b14f0546e59d3f306614f044bc01ce43351" + integrity sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg== + dependencies: + real-require "^0.2.0" + +thunky@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toposort-class@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" + integrity sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg== + +torrent-discovery@^5.2.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/torrent-discovery/-/torrent-discovery-5.4.0.tgz#2d17d82cf669ada7f9dfe75db4b31f7034b71e29" + integrity sha512-bPTDIA7XEjRlw6vQyt7kM/h1mg1INBsibjbujISITonx4POENZgxfyCSEXZpDhbAkluSPH4HKRKs4/YTmNLC6w== + dependencies: + bittorrent-dht "^6.0.0" + bittorrent-tracker "^7.0.0" + debug "^2.0.0" + inherits "^2.0.1" + re-emitter "^1.0.0" + run-parallel "^1.1.2" + xtend "^4.0.0" + +torrent-piece@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/torrent-piece/-/torrent-piece-1.1.2.tgz#774cadac08f65e3d55b84610842171365e349dc6" + integrity sha512-ElXPyXKKG73o+uziHJ8qlYE9EuyDVxnK2zWL+pW/2bma7RsLpSwFFIJAb8Qui7/tel2hsHQW1z3zBnfQNREpWA== + +torrent-stream@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/torrent-stream/-/torrent-stream-1.2.1.tgz#b0add8d5ad2367daeb5a4ddc02bb3203dccf9c9b" + integrity sha512-F+3tYmXnpO2gyhZQ7o8yakELJH3FtKISI/FU0iWvchOWFUXiFnjbEBoumSzfcK1P71Qxzx2az4lVK4Dkq4KSew== + dependencies: + bitfield "^0.1.0" + bncode "^0.5.2" + buffer-from "^1.0.0" + end-of-stream "^0.1.4" + fs-chunk-store "^1.3.0" + hat "0.0.3" + immediate-chunk-store "^1.0.5" + ip-set "^1.0.0" + mkdirp "^0.3.5" + parse-torrent "^4.0.0" + peer-wire-swarm "^0.12.0" + rimraf "^2.2.5" + torrent-discovery "^5.2.0" + torrent-piece "^1.0.0" + +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +ts-api-utils@^1.0.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" + integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.1.0, tslib@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tsx@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.0.tgz#1689cfe7dda495ca1f9a66d4cad79cb57b9f6f4a" + integrity sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg== + dependencies: + esbuild "~0.19.10" + get-tsconfig "^4.7.2" + optionalDependencies: + fsevents "~2.3.3" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-buffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz#0608ffe6bca71bf15a45bff0ca2604107a1325f5" + integrity sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typescript@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + integrity sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +underscore@^1.13.1: + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== + +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@~1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utp@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/utp/-/utp-0.0.7.tgz#ae43eb7745f5fe63dcc2f277cb4164ad27087f30" + integrity sha512-2ZLjisH0HQkpqZTg2m7TK0Yn7TETTg7DxM0EpCKIIIV2ky9w9nSxW5a7gzdk4nH2h+pomrrGw0uywrUJfsm2eA== + dependencies: + cyclist "~0.1.0" + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +validator@^13.9.0: + version "13.11.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" + integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-url@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-13.0.0.tgz#b7b536aca48306394a34e44bda8e99f332410f8f" + integrity sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig== + dependencies: + tr46 "^4.1.1" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.13, which-typed-array@^1.1.14: + version "1.1.14" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.14.tgz#1f78a111aee1e131ca66164d8bdc3ab062c95a06" + integrity sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg== + dependencies: + available-typed-arrays "^1.0.6" + call-bind "^1.0.5" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.1" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + +wkx@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c" + integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg== + dependencies: + "@types/node" "*" + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +ws@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" + integrity sha512-61a+9LgtYZxTq1hAonhX8Xwpo2riK4IOR/BIVxioFbCfc3QFKmpE4x9dLExfLHKtUfVZigYa36tThVhO57erEw== + dependencies: + safe-buffer "~5.0.1" + ultron "~1.1.0" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 4bc4b7958f2647bb32c2017776c7570f12727379 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 12:46:36 +0000 Subject: [PATCH 34/55] switched to yarn, and started adding tests Added tests for process job service so far... its a start.. --- src/node/consumer/.eslintrc | 15 +- src/node/consumer/.nvmrc | 1 + src/node/consumer/jest.config.cjs | 11 + src/node/consumer/package.json | 9 +- .../consumer/test/process_torrent_job.test.ts | 129 ++ src/node/consumer/tsconfig.json | 2 +- src/node/consumer/yarn.lock | 1898 +++++++++++++++-- 7 files changed, 1892 insertions(+), 173 deletions(-) create mode 100644 src/node/consumer/.nvmrc create mode 100644 src/node/consumer/jest.config.cjs create mode 100644 src/node/consumer/test/process_torrent_job.test.ts diff --git a/src/node/consumer/.eslintrc b/src/node/consumer/.eslintrc index fbf723b..f3b4e84 100644 --- a/src/node/consumer/.eslintrc +++ b/src/node/consumer/.eslintrc @@ -67,5 +67,18 @@ "objectLiteralTypeAssertions": "never" } ] - } + }, + "overrides": [ + { + "files": [ + "*.test.ts" + ], + "rules": { + "@typescript-eslint/consistent-type-assertions": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": "off" + } + } + ] } \ No newline at end of file diff --git a/src/node/consumer/.nvmrc b/src/node/consumer/.nvmrc new file mode 100644 index 0000000..a8d3ff9 --- /dev/null +++ b/src/node/consumer/.nvmrc @@ -0,0 +1 @@ +v21.6.1 diff --git a/src/node/consumer/jest.config.cjs b/src/node/consumer/jest.config.cjs new file mode 100644 index 0000000..fa0bd7c --- /dev/null +++ b/src/node/consumer/jest.config.cjs @@ -0,0 +1,11 @@ +const { pathsToModuleNameMapper } = require('ts-jest'); +const { compilerOptions } = require('./tsconfig.json'); + +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/src/' }), + modulePaths: [ + '' + ], +}; \ No newline at end of file diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index f055bd0..53f767c 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -8,7 +8,9 @@ "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", "start": "node dist/main.cjs", "lint": "yarn eslint ./src --ext .ts,.js", - "lint-fix": "yarn run lint --fix" + "lint-fix": "yarn run lint --fix", + "test": "jest", + "test:watch": "jest --watch" }, "license": "MIT", "dependencies": { @@ -33,6 +35,7 @@ }, "devDependencies": { "@types/amqplib": "^0.10.4", + "@types/jest": "^29.5.12", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", "@types/torrent-stream": "^0.0.9", @@ -43,11 +46,13 @@ "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", + "jest": "^29.7.0", "node-gyp": "^10.0.1", "pino-pretty": "^10.3.1", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "tsx": "^4.7.0", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "ts-jest": "^29.1.2" } } diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts new file mode 100644 index 0000000..b38f93f --- /dev/null +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -0,0 +1,129 @@ +import "reflect-metadata"; // required +import { ILoggingService } from '@interfaces/logging_service'; +import { ITorrentProcessingService } from '@interfaces/torrent_processing_service'; +import { ProcessTorrentsJob } from '@jobs/process_torrents_job'; +import { configurationService } from '@services/configuration_service'; +import client, {ConsumeMessage} from 'amqplib'; + +jest.mock('@services/configuration_service', () => { + return { + configurationService: { + rabbitConfig: { + RABBIT_URI: 'amqp://localhost', + QUEUE_NAME: 'test_queue', + }, + jobConfig: { + JOBS_ENABLED: true, + JOB_CONCURRENCY: 1, + }, + } + } +}); + +jest.mock('amqplib', () => { + return { + connect: jest.fn().mockResolvedValue({ + createChannel: jest.fn().mockResolvedValue({ + assertQueue: jest.fn(), + prefetch: jest.fn(), + consume: jest.fn(), + ack: jest.fn(), + }), + }), + }; +}); + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + } +}) + +jest.mock('@services/torrent_processing_service', () => { + return { + processTorrentRecord: jest.fn().mockResolvedValue(undefined), + } +}) + +describe('ProcessTorrentsJob', () => { + let processTorrentsJob: ProcessTorrentsJob, + loggingService: ILoggingService, + torrentProcessingService: ITorrentProcessingService; + + beforeEach(() => { + loggingService = jest.requireMock('@services/logging_service'); + torrentProcessingService = jest.requireMock('@services/torrent_processing_service'); + processTorrentsJob = new ProcessTorrentsJob(torrentProcessingService, loggingService); + }); + + afterEach(() => { + jest.clearAllMocks() + }) + + describe('listenToQueue', () => { + test('should connect to the rabbitmq server and create a channel', async () => { + await processTorrentsJob.listenToQueue(); + expect(client.connect).toHaveBeenCalledWith(configurationService.rabbitConfig.RABBIT_URI); + }); + + test('should log an error if connection or channel setup fails', async () => { + (client.connect as any).mockImplementationOnce(() => { + throw new Error('Connection error'); + }); + + await processTorrentsJob.listenToQueue(); + expect(loggingService.error).toHaveBeenCalledWith('Failed to connect and setup channel', expect.any(Error)); + }); + + test('should process messages from the queue', async () => { + const mockMessage = { + content: Buffer.from(JSON.stringify({ + message: { + name: 'test_name', + source: 'test_source', + category: 'test_category', + infoHash: 'test_hash', + size: 'test_size', + seeders: 0, + leechers: 0, + imdb: 'test_imdb', + processed: false, + } + })), + } as ConsumeMessage; + + (client.connect as any).mockResolvedValue({ + createChannel: jest.fn().mockResolvedValue({ + assertQueue: jest.fn().mockResolvedValue({ + consumerCount: 1, + }), + prefetch: jest.fn(), + consume: jest.fn().mockImplementation((_, callback) => { + callback(mockMessage); + }), + ack: jest.fn(), + }), + }); + + await processTorrentsJob.listenToQueue(); + expect(loggingService.info).toHaveBeenCalledWith('Worker is running! Waiting for new torrents...'); + expect(client.connect).toHaveBeenCalledWith(configurationService.rabbitConfig.RABBIT_URI); + expect(loggingService.error).toBeCalledTimes(0); + + expect(torrentProcessingService.processTorrentRecord).toHaveBeenCalledWith({ + name: 'test_name', + source: 'test_source', + category: 'test_category', + infoHash: 'test_hash', + size: 'test_size', + seeders: 0, + leechers: 0, + imdb: 'test_imdb', + processed: false, + info_hash: 'test_hash' + }); + }); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index fadbe95..e3f3dd3 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -31,6 +31,6 @@ "@jobs/*": ["lib/jobs/*"] } }, - "include": ["src/**/*.ts"], + "include": ["src", "test"], "exclude": ["node_modules"] } \ No newline at end of file diff --git a/src/node/consumer/yarn.lock b/src/node/consumer/yarn.lock index 2037980..90b1c61 100644 --- a/src/node/consumer/yarn.lock +++ b/src/node/consumer/yarn.lock @@ -16,12 +16,300 @@ debug "^4.3.4" safe-buffer "~5.1.2" -"@babel/runtime@^7.21.0": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" - integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== dependencies: - regenerator-runtime "^0.14.0" + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" + integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.9" + "@babel/parser" "^7.23.9" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helpers@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" + integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== + dependencies: + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.3.3": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/traverse@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.3.3": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" @@ -323,12 +611,234 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/resolve-uri@^3.0.3": +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -341,6 +851,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.22" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" + integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@mongodb-js/saslprep@^1.1.0": version "1.1.4" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz#24ec1c4915a65f5c506bb88c081731450d91bb1c" @@ -392,6 +910,25 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@tirke/node-cache-manager-mongodb@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz#e730623ae53d4b3e6c6328baab0cff49ed6cb4ce" @@ -426,6 +963,39 @@ dependencies: "@types/node" "*" +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" + integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== + dependencies: + "@babel/types" "^7.20.7" + "@types/debug@^4.1.8": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" @@ -433,6 +1003,40 @@ dependencies: "@types/ms" "*" +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.12": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/json-schema@^7.0.12": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -467,6 +1071,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + "@types/torrent-stream@^0.0.9": version "0.0.9" resolved "https://registry.yarnpkg.com/@types/torrent-stream/-/torrent-stream-0.0.9.tgz#3b7b721ee74ab013ff793426b2823d71f4711068" @@ -491,6 +1100,18 @@ dependencies: "@types/webidl-conversions" "*" +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" @@ -582,11 +1203,6 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - abbrev@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" @@ -654,6 +1270,13 @@ amqplib@^0.10.3: readable-stream "1.x >=1.1.9" url-parse "~1.5.10" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -664,6 +1287,13 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -671,12 +1301,17 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-styles@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@~3.1.2: +anymatch@^3.0.3: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -689,6 +1324,13 @@ arg@^4.1.0: resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -798,6 +1440,66 @@ axios@^1.4.0, axios@^1.6.1: form-data "^4.0.0" proxy-from-env "^1.1.0" +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -828,11 +1530,6 @@ bep53-range@^1.1.0: resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.1.tgz#20fd125b00a413254a77d42f63a43750ca7e64ac" integrity sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ== -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - bitfield@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/bitfield/-/bitfield-0.1.0.tgz#b05d8b5f0d09f2df35a9db3b3a62d3808c46c457" @@ -916,13 +1613,37 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +browserslist@^4.22.2: + version "4.22.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" + integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A== + dependencies: + caniuse-lite "^1.0.30001580" + electron-to-chromium "^1.4.648" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + bson@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/bson/-/bson-6.3.0.tgz#d47acba525ba7d7eb0e816c10538bce26a337fe0" @@ -1021,7 +1742,31 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -chalk@^4.0.0, chalk@^4.1.2: +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001580: + version "1.0.30001585" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz#0b4e848d84919c783b2a41c13f7de8ce96744401" + integrity sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1029,6 +1774,11 @@ chalk@^4.0.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + cheerio-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" @@ -1054,21 +1804,6 @@ cheerio@1.0.0-rc.12: parse5 "^7.0.0" parse5-htmlparser2-tree-adapter "^7.0.0" -chokidar@^3.5.2: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -1096,6 +1831,16 @@ chrome-net@^3.3.2: dependencies: inherits "^2.0.1" +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -1110,6 +1855,23 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1117,6 +1879,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -1146,32 +1913,35 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concurrently@^8.2.2: - version "8.2.2" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.2.2.tgz#353141985c198cfa5e4a3ef90082c336b5851784" - integrity sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg== - dependencies: - chalk "^4.1.2" - date-fns "^2.30.0" - lodash "^4.17.21" - rxjs "^7.8.1" - shell-quote "^1.8.1" - spawn-command "0.0.2" - supports-color "^8.1.1" - tree-kill "^1.2.2" - yargs "^17.7.2" +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1201,19 +1971,12 @@ cyclist@~0.1.0: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.1.1.tgz#1bcfa56b081448cdb5e12bfc1bfad34b47fba8f3" integrity sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw== -date-fns@^2.30.0: - version "2.30.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" - integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== - dependencies: - "@babel/runtime" "^7.21.0" - dateformat@^4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== -debug@4, debug@^4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1241,6 +2004,11 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -1251,6 +2019,11 @@ deepmerge-ts@^5.1.0: resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" integrity sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw== +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + define-data-property@^1.0.1, define-data-property@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.2.tgz#f3c33b4f0102360cd7c0f5f28700f5678510b63a" @@ -1275,11 +2048,21 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + diacritics@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" integrity sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA== +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -1346,6 +2129,16 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +electron-to-chromium@^1.4.648: + version "1.4.661" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.661.tgz#b28d63468b06e75610ed2b0f8e5f5f669a57bd91" + integrity sha512-AFg4wDHSOk5F+zA8aR+SVIOabu7m0e7BiJnigCvPXzIGy731XENw/lmNxTySpVFtkFEy+eyt4oHhh5FF3NjQNw== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1392,6 +2185,13 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + es-abstract@^1.22.1, es-abstract@^1.22.3: version "1.22.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" @@ -1535,6 +2335,16 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1650,6 +2460,11 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" @@ -1684,6 +2499,37 @@ events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + exponential-backoff@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" @@ -1710,7 +2556,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -1737,6 +2583,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + fifo@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/fifo/-/fifo-0.1.4.tgz#bf42d87c0ad07b00d0949d12388f6289606ece34" @@ -1756,6 +2609,14 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1843,7 +2704,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@^2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -1868,6 +2729,11 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + get-browser-rtc@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz#d1494e299b00f33fc8e9d6d3343ba4ba99711a2c" @@ -1889,6 +2755,16 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" @@ -1905,7 +2781,7 @@ get-tsconfig@^4.7.2: dependencies: resolve-pkg-maps "^1.0.0" -glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1942,7 +2818,7 @@ glob@^10.2.2, glob@^10.3.10: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1954,6 +2830,11 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -2003,7 +2884,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.2.6: +graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -2069,6 +2950,11 @@ help-me@^5.0.0: resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + htmlparser2@^8.0.1: version "8.0.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" @@ -2100,6 +2986,11 @@ https-proxy-agent@^7.0.1: agent-base "^7.0.2" debug "4" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -2119,11 +3010,6 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== - ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -2142,6 +3028,14 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -2214,6 +3108,11 @@ is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: call-bind "^1.0.2" get-intrinsic "^1.2.1" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -2221,13 +3120,6 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -2265,7 +3157,12 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -2314,6 +3211,11 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -2367,6 +3269,59 @@ isexe@^3.1.1: resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -2376,11 +3331,382 @@ jackspeak@^2.3.5: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + joycon@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -2388,11 +3714,21 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2410,7 +3746,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.2: +json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -2457,6 +3793,16 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2465,6 +3811,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2477,6 +3835,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -2492,6 +3855,13 @@ lru-cache@^10.0.1, lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2523,7 +3893,14 @@ magnet-uri@^6.2.0: bep53-range "^1.1.0" thirty-two "^1.0.2" -make-error@^1.1.1: +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -2545,11 +3922,23 @@ make-fetch-happen@^13.0.0: promise-retry "^2.0.1" ssri "^10.0.0" +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + memory-pager@^1.0.2: version "1.5.0" resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -2575,6 +3964,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -2785,21 +4179,15 @@ node-gyp@^10.0.1: tar "^6.1.2" which "^4.0.0" -nodemon@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.3.tgz#244a62d1c690eece3f6165c6cdb0db03ebd80b76" - integrity sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ== - dependencies: - chokidar "^3.5.2" - debug "^4" - ignore-by-default "^1.0.1" - minimatch "^3.1.2" - pstree.remy "^1.1.8" - semver "^7.5.3" - simple-update-notifier "^2.0.0" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.5" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== nopt@^7.0.0: version "7.2.0" @@ -2808,18 +4196,18 @@ nopt@^7.0.0: dependencies: abbrev "^2.0.0" -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== - dependencies: - abbrev "1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: +normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -2895,6 +4283,13 @@ once@~1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -2912,13 +4307,27 @@ options@>=0.0.5: resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== -p-limit@^3.0.2: +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -2933,6 +4342,11 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + packet-reader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" @@ -2945,6 +4359,16 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse-torrent-file@^2.0.0: version "2.1.4" resolved "https://registry.yarnpkg.com/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz#32d4b6afde631420e5f415919a222b774b575707" @@ -2992,7 +4416,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -3104,7 +4528,12 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -3159,6 +4588,18 @@ pino@^8.18.0: sonic-boom "^3.7.0" thread-stream "^2.0.0" +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" @@ -3186,6 +4627,15 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + proc-log@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" @@ -3219,16 +4669,19 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -pstree.remy@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -3242,6 +4695,11 @@ punycode@^2.1.0, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -3296,6 +4754,11 @@ re-emitter@^1.0.0: resolved "https://registry.yarnpkg.com/re-emitter/-/re-emitter-1.1.4.tgz#15bdefca3d47e05d6442838fd26759c8a4eaa236" integrity sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA== +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + "readable-stream@1.x >=1.1.9", readable-stream@^1.0.2: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -3330,13 +4793,6 @@ readable-stream@^4.0.0: process "^0.11.10" string_decoder "^1.3.0" -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" @@ -3347,11 +4803,6 @@ reflect-metadata@^0.2.1: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.1.tgz#8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74" integrity sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw== -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - regexp.prototype.flags@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" @@ -3371,17 +4822,34 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-pkg-maps@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.22.4: +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3436,13 +4904,6 @@ rusha@^0.8.1: resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68" integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA== -rxjs@^7.8.1: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - safe-array-concat@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" @@ -3492,7 +4953,7 @@ secure-json-parse@^2.4.0: resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== -semver@^6.3.1: +semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -3571,11 +5032,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== - side-channel@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" @@ -3586,6 +5042,11 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -3623,13 +5084,6 @@ simple-sha1@^2.0.0: dependencies: rusha "^0.8.1" -simple-update-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" - integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== - dependencies: - semver "^7.5.3" - simple-websocket@^4.0.0: version "4.3.1" resolved "https://registry.yarnpkg.com/simple-websocket/-/simple-websocket-4.3.1.tgz#5d3d5751bb39aeba2f710d8eec78768df821f38d" @@ -3642,6 +5096,11 @@ simple-websocket@^4.0.0: ws "^2.0.0" xtend "^4.0.1" +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3676,6 +5135,19 @@ sonic-boom@^3.0.0, sonic-boom@^3.7.0: dependencies: atomic-sleep "^1.0.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + sparse-bitfield@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" @@ -3683,11 +5155,6 @@ sparse-bitfield@^3.0.3: dependencies: memory-pager "^1.0.2" -spawn-command@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" - integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== - speedometer@^0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" @@ -3698,6 +5165,11 @@ split2@^4.0.0, split2@^4.1.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + ssri@^10.0.0: version "10.0.5" resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" @@ -3705,6 +5177,21 @@ ssri@^10.0.0: dependencies: minipass "^7.0.3" +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -3796,12 +5283,22 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@^5.5.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -3815,7 +5312,7 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.1.1: +supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -3839,6 +5336,15 @@ tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -3866,6 +5372,16 @@ thunky@^1.0.1: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3916,13 +5432,6 @@ torrent-stream@^1.2.1: torrent-discovery "^5.2.0" torrent-piece "^1.0.0" -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - tr46@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" @@ -3935,16 +5444,25 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - ts-api-utils@^1.0.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== +ts-jest@^29.1.2: + version "29.1.2" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" + integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -3983,7 +5501,7 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.1.0, tslib@^2.6.1: +tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -4005,11 +5523,21 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typed-array-buffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz#0608ffe6bca71bf15a45bff0ca2604107a1325f5" @@ -4074,11 +5602,6 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undefsafe@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" - integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== - underscore@^1.13.1: version "1.13.6" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" @@ -4108,6 +5631,14 @@ unique-slug@^4.0.0: dependencies: imurmurhash "^0.1.4" +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4145,11 +5676,27 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + validator@^13.9.0: version "13.11.0" resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -4242,6 +5789,14 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + ws@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" @@ -4268,17 +5823,22 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^21.1.1: +yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.7.2: +yargs@^17.3.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 93085771905108c05a0496cd2db8893d5ded5d55 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 12:52:41 +0000 Subject: [PATCH 35/55] fix small error so typescript knows type assigned --- src/node/consumer/test/process_torrent_job.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts index b38f93f..922e4d3 100644 --- a/src/node/consumer/test/process_torrent_job.test.ts +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -94,7 +94,7 @@ describe('ProcessTorrentsJob', () => { })), } as ConsumeMessage; - (client.connect as any).mockResolvedValue({ + (client.connect as jest.Mock).mockResolvedValue({ createChannel: jest.fn().mockResolvedValue({ assertQueue: jest.fn().mockResolvedValue({ consumerCount: 1, From 39511f6a5b7365e1ba4a2c193161e85defb6040e Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 13:06:54 +0000 Subject: [PATCH 36/55] Add cache service tests --- src/node/consumer/test/cache_service.test.ts | 120 +++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/node/consumer/test/cache_service.test.ts diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/cache_service.test.ts new file mode 100644 index 0000000..ebef771 --- /dev/null +++ b/src/node/consumer/test/cache_service.test.ts @@ -0,0 +1,120 @@ +import "reflect-metadata"; // required +import { ILoggingService } from '@interfaces/logging_service'; +import { CacheService, CacheMethod } from '@services/cache_service'; + +process.env.LOG_LEVEL = 'debug'; + +jest.mock('@services/configuration_service', () => { + return { + configurationService: { + cacheConfig: { + MONGODB_HOST: 'localhost', + MONGODB_PORT: '27017', + MONGODB_DB: 'knightcrawler', + MONGO_INITDB_ROOT_USERNAME: 'mongo', + MONGO_INITDB_ROOT_PASSWORD: 'mongo', + NO_CACHE: false, + COLLECTION_NAME: 'knightcrawler_consumer_collection', + }, + } + } +}); + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + } +}) + +jest.mock('cache-manager', () => { + return { + createCache: jest.fn().mockReturnValue({ + wrap: jest.fn().mockImplementation((_, method) => method()), + }), + memoryStore: jest.fn(), + }; +}); + +jest.mock('@tirke/node-cache-manager-mongodb', () => { + return { + mongoDbStore: jest.fn(), + }; +}); + +describe('CacheService', () => { + let cacheService: CacheService, + loggingService: ILoggingService, + cacheMethod: CacheMethod; + + beforeEach(() => { + loggingService = jest.requireMock('@services/logging_service'); + cacheMethod = jest.fn().mockResolvedValue({}); + cacheService = new CacheService(loggingService); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should cacheWrapImdbId correctly', async () => { + const result = await cacheService.cacheWrapImdbId('testKey', cacheMethod); + expect(result).toBeDefined(); + expect(loggingService.debug).toHaveBeenCalledTimes(3); + }); + + it('should cacheWrapKitsuId correctly', async () => { + const result = await cacheService.cacheWrapKitsuId('testKey', cacheMethod); + expect(result).toBeDefined(); + expect(loggingService.debug).toHaveBeenCalledTimes(3); + }); + + it('should cacheWrapMetadata correctly', async () => { + const result = await cacheService.cacheWrapMetadata('testId', cacheMethod); + expect(result).toBeDefined(); + expect(loggingService.debug).toHaveBeenCalledTimes(3); + }); + + it('should cacheTrackers correctly', async () => { + const result = await cacheService.cacheTrackers(cacheMethod); + expect(result).toBeDefined(); + expect(loggingService.debug).toHaveBeenCalledTimes(3); + }); + + it('should handle error in cacheMethod for cacheWrapImdbId', async () => { + cacheMethod = jest.fn().mockRejectedValue(new Error('Test error')); + await expect(cacheService.cacheWrapImdbId('testKey', cacheMethod)).rejects.toThrow('Test error'); + }); + + it('should handle error in cacheMethod for cacheWrapKitsuId', async () => { + cacheMethod = jest.fn().mockRejectedValue(new Error('Test error')); + await expect(cacheService.cacheWrapKitsuId('testKey', cacheMethod)).rejects.toThrow('Test error'); + }); + + it('should handle error in cacheMethod for cacheWrapMetadata', async () => { + cacheMethod = jest.fn().mockRejectedValue(new Error('Test error')); + await expect(cacheService.cacheWrapMetadata('testId', cacheMethod)).rejects.toThrow('Test error'); + }); + + it('should handle error in cacheMethod for cacheTrackers', async () => { + cacheMethod = jest.fn().mockRejectedValue(new Error('Test error')); + await expect(cacheService.cacheTrackers(cacheMethod)).rejects.toThrow('Test error'); + }); + + it('should handle when cache is disabled', async () => { + jest.mock('@services/configuration_service', () => { + return { + configurationService: { + cacheConfig: { + NO_CACHE: true, + }, + } + } + }); + + cacheService = new CacheService(loggingService); + const result = await cacheService.cacheWrapImdbId('testKey', cacheMethod); + expect(result).toBeDefined(); + }); +}); \ No newline at end of file From 9401b6f8f1b4a3d648f2ba7af17e9500ae03849c Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 13:32:03 +0000 Subject: [PATCH 37/55] Config service tests --- src/node/consumer/test/cache_service.test.ts | 5 +- .../test/configuration_service.test.ts | 85 +++++++++++++++++++ .../consumer/test/process_torrent_job.test.ts | 2 +- 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/node/consumer/test/configuration_service.test.ts diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/cache_service.test.ts index ebef771..3e258b1 100644 --- a/src/node/consumer/test/cache_service.test.ts +++ b/src/node/consumer/test/cache_service.test.ts @@ -2,8 +2,6 @@ import "reflect-metadata"; // required import { ILoggingService } from '@interfaces/logging_service'; import { CacheService, CacheMethod } from '@services/cache_service'; -process.env.LOG_LEVEL = 'debug'; - jest.mock('@services/configuration_service', () => { return { configurationService: { @@ -43,12 +41,13 @@ jest.mock('@tirke/node-cache-manager-mongodb', () => { }; }); -describe('CacheService', () => { +describe('CacheService Tests', () => { let cacheService: CacheService, loggingService: ILoggingService, cacheMethod: CacheMethod; beforeEach(() => { + process.env.LOG_LEVEL = 'debug'; loggingService = jest.requireMock('@services/logging_service'); cacheMethod = jest.fn().mockResolvedValue({}); cacheService = new CacheService(loggingService); diff --git a/src/node/consumer/test/configuration_service.test.ts b/src/node/consumer/test/configuration_service.test.ts new file mode 100644 index 0000000..0ebc311 --- /dev/null +++ b/src/node/consumer/test/configuration_service.test.ts @@ -0,0 +1,85 @@ +describe('Configuration Tests', () => { + let configurationService; + beforeAll(async () => { + process.env.MONGODB_HOST = 'test_mongodb'; + process.env.MONGODB_PORT = '27017'; + process.env.MONGODB_DB = 'knightcrawler'; + process.env.MONGO_INITDB_ROOT_USERNAME = 'mongo'; + process.env.MONGO_INITDB_ROOT_PASSWORD = 'mongo'; + process.env.NO_CACHE = 'false'; + process.env.MONGODB_COLLECTION = 'knightcrawler_consumer_collection'; + process.env.POSTGRES_HOST = 'postgres'; + process.env.POSTGRES_PORT = '5432'; + process.env.POSTGRES_DB = 'knightcrawler'; + process.env.POSTGRES_USER = 'postgres'; + process.env.POSTGRES_PASSWORD = 'postgres'; + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'false'; + process.env.TRACKERS_URL = 'https://ngosang.github.io/trackerslist/trackers_all.txt'; + process.env.UDP_TRACKERS_ENABLED = 'false'; + process.env.MAX_CONNECTIONS_PER_TORRENT = '20'; + process.env.TORRENT_TIMEOUT = '30000'; + process.env.RABBIT_URI = 'amqp://localhost'; + process.env.QUEUE_NAME = 'test-queue'; + process.env.IMDB_CONCURRENT = '1'; + process.env.IMDB_INTERVAL_MS = '1000'; + process.env.JOB_CONCURRENCY = '1'; + process.env.JOBS_ENABLED = 'true'; + + // shitty hack cause jest caches modules and resetModules isnt working + ({ configurationService } = await import("@services/configuration_service")); + }); + + it('should populate cacheConfig correctly', () => { + const { cacheConfig } = configurationService; + expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); + expect(cacheConfig.MONGODB_PORT).toBe('27017'); + expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); + expect(cacheConfig.MONGO_INITDB_ROOT_USERNAME).toBe('mongo'); + expect(cacheConfig.MONGO_INITDB_ROOT_PASSWORD).toBe('mongo'); + expect(cacheConfig.NO_CACHE).toBe(false); + expect(cacheConfig.COLLECTION_NAME).toBe('knightcrawler_consumer_collection'); + expect(cacheConfig.MONGO_URI).toBe('mongodb://mongo:mongo@test_mongodb:27017/knightcrawler?authSource=admin'); + }); + + it('should populate databaseConfig correctly', () => { + const { databaseConfig } = configurationService; + expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); + expect(databaseConfig.POSTGRES_PORT).toBe(5432); + expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); + expect(databaseConfig.POSTGRES_USER).toBe('postgres'); + expect(databaseConfig.POSTGRES_PASSWORD).toBe('postgres'); + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + expect(databaseConfig.POSTGRES_URI).toBe('postgres://postgres:postgres@postgres:5432/knightcrawler'); + }); + + it('should populate jobConfig correctly', () => { + const { jobConfig } = configurationService; + expect(jobConfig.JOB_CONCURRENCY).toBe(1); + expect(jobConfig.JOBS_ENABLED).toBe(true); + }); + + it('should populate metadataConfig correctly', () => { + const { metadataConfig } = configurationService; + expect(metadataConfig.IMDB_CONCURRENT).toBe(1); + expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); + }); + + it('should populate rabbitConfig correctly', () => { + const { rabbitConfig } = configurationService; + expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); + expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); + }); + + it('should populate torrentConfig correctly', () => { + const { torrentConfig } = configurationService; + expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); + expect(torrentConfig.TIMEOUT).toBe(30000); + }); + + it('should populate trackerConfig correctly', () => { + const { trackerConfig } = configurationService; + expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); + expect(trackerConfig.UDP_ENABLED).toBe(false); + }); + +}); \ No newline at end of file diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts index 922e4d3..0b551d6 100644 --- a/src/node/consumer/test/process_torrent_job.test.ts +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -47,7 +47,7 @@ jest.mock('@services/torrent_processing_service', () => { } }) -describe('ProcessTorrentsJob', () => { +describe('ProcessTorrentsJob Tests', () => { let processTorrentsJob: ProcessTorrentsJob, loggingService: ILoggingService, torrentProcessingService: ITorrentProcessingService; From 2b1bb5fb16a3e5f7bc618d56f9c7a8be3f563512 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 13:40:53 +0000 Subject: [PATCH 38/55] logging service tests --- .../test/configuration_service.test.ts | 2 + .../consumer/test/logging_service.test.ts | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/node/consumer/test/logging_service.test.ts diff --git a/src/node/consumer/test/configuration_service.test.ts b/src/node/consumer/test/configuration_service.test.ts index 0ebc311..fc21c39 100644 --- a/src/node/consumer/test/configuration_service.test.ts +++ b/src/node/consumer/test/configuration_service.test.ts @@ -1,3 +1,5 @@ +import "reflect-metadata"; // required + describe('Configuration Tests', () => { let configurationService; beforeAll(async () => { diff --git a/src/node/consumer/test/logging_service.test.ts b/src/node/consumer/test/logging_service.test.ts new file mode 100644 index 0000000..08ffc41 --- /dev/null +++ b/src/node/consumer/test/logging_service.test.ts @@ -0,0 +1,45 @@ +import "reflect-metadata"; // required +import { LoggingService } from '@services/logging_service'; + +jest.mock('pino', () => { + const actualPino = jest.requireActual('pino'); + return { + ...actualPino, + pino: jest.fn().mockImplementation(() => ({ + info: jest.fn(), + error: jest.fn(), + debug: jest.fn(), + warn: jest.fn(), + })), + }; +}); + +describe('LoggingService', () => { + let service: LoggingService, + mockLogger: any; + + beforeEach(() => { + service = new LoggingService(); + mockLogger = (service as any).logger; + }); + + it('should log info', () => { + service.info('test message', { key: 'value' }); + expect(mockLogger.info).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + }); + + it('should log error', () => { + service.error('test message', { key: 'value' }); + expect(mockLogger.error).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + }); + + it('should log debug', () => { + service.debug('test message', { key: 'value' }); + expect(mockLogger.debug).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + }); + + it('should log warn', () => { + service.warn('test message', { key: 'value' }); + expect(mockLogger.warn).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + }) +}); \ No newline at end of file From 373ca4e024e15da60d902cb0d80f440b8ec69884 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 14:52:14 +0000 Subject: [PATCH 39/55] fix dockerfile, add tracker tests --- src/node/consumer/.nvmrc | 2 +- src/node/consumer/Dockerfile | 22 +- src/node/consumer/package.json | 10 +- .../consumer/test/tracker_service.test.ts | 59 +++ src/node/consumer/yarn.lock | 488 ++++++++++++++++-- 5 files changed, 531 insertions(+), 50 deletions(-) create mode 100644 src/node/consumer/test/tracker_service.test.ts diff --git a/src/node/consumer/.nvmrc b/src/node/consumer/.nvmrc index a8d3ff9..016efd8 100644 --- a/src/node/consumer/.nvmrc +++ b/src/node/consumer/.nvmrc @@ -1 +1 @@ -v21.6.1 +v20.10.0 \ No newline at end of file diff --git a/src/node/consumer/Dockerfile b/src/node/consumer/Dockerfile index 8914638..11980e6 100644 --- a/src/node/consumer/Dockerfile +++ b/src/node/consumer/Dockerfile @@ -1,28 +1,24 @@ FROM node:lts-buster-slim as builder -RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y python3 make g++ && \ - rm -rf /var/lib/apt/lists/* - -RUN npm install -g npm@^8 && npm config set python /usr/bin/python3 +RUN apt update && apt install -y git && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY package*.json ./ -RUN npm install +COPY package.json ./ +COPY yarn.lock ./ +RUN yarn install COPY . . -RUN npm run build +RUN yarn run build +RUN yarn install --production -# --- Runtime Stage --- FROM node:lts-buster-slim WORKDIR /app -ENV NODE_ENV production - COPY --from=builder /app ./ -RUN npm prune --omit=dev + +ENV NODE_ENV production +ENV NODE_OPTIONS "--no-deprecation" # CIS-DI-0001 RUN useradd -d /home/consumer -m -s /bin/bash consumer diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 53f767c..7ee62a4 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -6,7 +6,7 @@ "clean": "rm -rf dist", "build": "node esbuild.js", "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", - "start": "node dist/main.cjs", + "start": "node --trace-deprecation dist/main.cjs", "lint": "yarn eslint ./src --ext .ts,.js", "lint-fix": "yarn run lint --fix", "test": "jest", @@ -21,7 +21,7 @@ "cache-manager": "^5.4.0", "google-sr": "^3.2.1", "inversify": "^6.0.2", - "magnet-uri": "^6.2.0", + "magnet-uri": "^7.0.5", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", "parse-torrent-title": "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", @@ -38,6 +38,7 @@ "@types/jest": "^29.5.12", "@types/magnet-uri": "^5.1.5", "@types/node": "^20.11.16", + "@types/pg": "^8.11.0", "@types/torrent-stream": "^0.0.9", "@types/validator": "^13.11.8", "@typescript-eslint/eslint-plugin": "^6.21.0", @@ -47,12 +48,13 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-import-helpers": "^1.3.1", "jest": "^29.7.0", + "msw": "^2.1.7", "node-gyp": "^10.0.1", "pino-pretty": "^10.3.1", + "ts-jest": "^29.1.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "tsx": "^4.7.0", - "typescript": "^5.3.3", - "ts-jest": "^29.1.2" + "typescript": "^5.3.3" } } diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/tracker_service.test.ts new file mode 100644 index 0000000..e233479 --- /dev/null +++ b/src/node/consumer/test/tracker_service.test.ts @@ -0,0 +1,59 @@ +import "reflect-metadata"; // required +import { ICacheService } from '@interfaces/cache_service'; +import { ILoggingService } from '@interfaces/logging_service'; +import { TrackerService } from '@services/tracker_service'; +import { http, HttpResponse } from 'msw' +import { setupServer } from 'msw/node'; + +const server = setupServer( + http.get('https://ngosang.github.io/trackerslist/trackers_all.txt', ({ request, params, cookies }) => { + return HttpResponse.text('http://tracker1.com\nhttp://tracker2.com') + }), +) + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + } +}) + +jest.mock('@services/cache_service', () => { + return { + cacheTrackers: jest.fn().mockImplementation((fn) => fn()), + } +}) + + +beforeAll(() => server.listen()) +beforeEach(() => { + jest.spyOn(Date, 'now').mockImplementation(() => 1234567890); +}) +afterEach(() => () => { + server.resetHandlers() + jest.spyOn(Date, 'now').mockRestore(); +}) +afterAll(() => server.close()) + +describe('TrackerService', () => { + let trackerService: TrackerService, + mockCacheService: ICacheService, + mockLoggingService: ILoggingService; + + beforeEach(() => { + mockCacheService = jest.requireMock('@services/cache_service'); + mockLoggingService = jest.requireMock('@services/logging_service'); + trackerService = new TrackerService(mockCacheService, mockLoggingService); + }); + + it('should get trackers', async () => { + const mockTrackers = ['http://tracker1.com', 'http://tracker2.com']; + + const result = await trackerService.getTrackers(); + + expect(result).toEqual(mockTrackers); + expect(mockLoggingService.info).toHaveBeenCalledWith(`Trackers updated at 1234567890: ${mockTrackers.length} trackers`); + + }); +}); \ No newline at end of file diff --git a/src/node/consumer/yarn.lock b/src/node/consumer/yarn.lock index 90b1c61..393b538 100644 --- a/src/node/consumer/yarn.lock +++ b/src/node/consumer/yarn.lock @@ -311,6 +311,20 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@bundled-es-modules/cookie@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" + integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + dependencies: + cookie "^0.5.0" + +"@bundled-es-modules/statuses@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" + integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== + dependencies: + statuses "^2.0.1" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -866,6 +880,23 @@ dependencies: sparse-bitfield "^3.0.3" +"@mswjs/cookies@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" + integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== + +"@mswjs/interceptors@^0.25.16": + version "0.25.16" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.25.16.tgz#7955fbb8da479bc691df117dd4c8d889e507ecc2" + integrity sha512-8QC8JyKztvoGAdPgyZy49c9vSHHAZjHagwl4RY9E8carULk8ym3iTaiawrT1YoLF/qb449h48f71XDPgkUSOUg== + dependencies: + "@open-draft/deferred-promise" "^2.2.0" + "@open-draft/logger" "^0.3.0" + "@open-draft/until" "^2.0.0" + is-node-process "^1.2.0" + outvariant "^1.2.1" + strict-event-emitter "^0.5.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -905,6 +936,24 @@ dependencies: semver "^7.3.5" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -929,6 +978,13 @@ dependencies: "@sinonjs/commons" "^3.0.0" +"@thaunknown/thirty-two@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@thaunknown/thirty-two/-/thirty-two-1.0.3.tgz#64883031c4444c0fd75436219189ab5816b5b826" + integrity sha512-bD6PvWbaf53JC04O7WnGDjqZBDgja/KT2Jd/6I2vJBIy+DLmQfQJZZ/G+16nAkVq1yGTIkO4rfc4RlH0DmEEqA== + dependencies: + uint8-util "^2.1.9" + "@tirke/node-cache-manager-mongodb@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz#e730623ae53d4b3e6c6328baab0cff49ed6cb4ce" @@ -996,6 +1052,11 @@ dependencies: "@babel/types" "^7.20.7" +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + "@types/debug@^4.1.8": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" @@ -1066,6 +1127,15 @@ dependencies: undici-types "~5.26.4" +"@types/pg@^8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.0.tgz#355a07531d467f2e4fabaa78be087ce2d99fd862" + integrity sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw== + dependencies: + "@types/node" "*" + pg-protocol "*" + pg-types "^4.0.1" + "@types/semver@^7.5.0": version "7.5.6" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" @@ -1076,6 +1146,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/statuses@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.4.tgz#041143ba4a918e8f080f8b0ffbe3d4cb514e2315" + integrity sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw== + "@types/torrent-stream@^0.0.9": version "0.0.9" resolved "https://registry.yarnpkg.com/@types/torrent-stream/-/torrent-stream-0.0.9.tgz#3b7b721ee74ab013ff793426b2823d71f4711068" @@ -1311,7 +1386,7 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@^3.0.3: +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1505,6 +1580,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -1525,10 +1605,15 @@ bencode@^2.0.0: resolved "https://registry.yarnpkg.com/bencode/-/bencode-2.0.3.tgz#89b9c80ea1b8573554915a7d0c15f62b0aa7fc52" integrity sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w== -bep53-range@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.1.tgz#20fd125b00a413254a77d42f63a43750ca7e64ac" - integrity sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ== +bep53-range@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-2.0.0.tgz#a1770475661b4b814c4359e4b66f7cbd88de2b10" + integrity sha512-sMm2sV5PRs0YOVk0LTKtjuIprVzxgTQUsrGX/7Yph2Rm4FO2Fqqtq7hNjsOB5xezM4v4+5rljCgK++UeQJZguA== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bitfield@^0.1.0: version "0.1.0" @@ -1573,6 +1658,15 @@ bittorrent-tracker@^7.0.0: ws "^1.0.0" xtend "^4.0.0" +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bn.js@^4.4.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -1613,7 +1707,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1692,6 +1786,14 @@ buffer-writer@2.0.0: resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -1766,7 +1868,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1779,6 +1881,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + cheerio-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" @@ -1804,6 +1911,21 @@ cheerio@1.0.0-rc.12: parse5 "^7.0.0" parse5-htmlparser2-tree-adapter "^7.0.0" +chokidar@^3.4.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -1846,6 +1968,23 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1855,6 +1994,11 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1918,6 +2062,11 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -2024,6 +2173,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-data-property@^1.0.1, define-data-property@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.2.tgz#f3c33b4f0102360cd7c0f5f28700f5678510b63a" @@ -2535,6 +2691,15 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + fast-copy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" @@ -2595,6 +2760,13 @@ fifo@^0.1.4: resolved "https://registry.yarnpkg.com/fifo/-/fifo-0.1.4.tgz#bf42d87c0ad07b00d0949d12388f6289606ece34" integrity sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g== +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -2704,7 +2876,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.3: +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -2781,7 +2953,7 @@ get-tsconfig@^4.7.2: dependencies: resolve-pkg-maps "^1.0.0" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -2894,6 +3066,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql@^16.8.1: + version "16.8.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -2945,6 +3122,11 @@ hat@0.0.3: resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" integrity sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug== +headers-polyfill@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.2.tgz#9115a76eee3ce8fbf95b6e3c6bf82d936785b44a" + integrity sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw== + help-me@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" @@ -2991,7 +3173,7 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@^0.4.4: +iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3005,7 +3187,7 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -3064,6 +3246,27 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inquirer@^8.2.0: + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + internal-slot@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -3120,6 +3323,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -3162,13 +3372,18 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -3179,6 +3394,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -3237,6 +3457,11 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.13, is-typed dependencies: which-typed-array "^1.1.14" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -3850,6 +4075,14 @@ lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + lru-cache@^10.0.1, lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": version "10.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" @@ -3885,13 +4118,14 @@ magnet-uri@^4.0.0: thirty-two "^0.0.2" xtend "^4.0.0" -magnet-uri@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-6.2.0.tgz#10f7be050bf23452df210838239b118463c3eeff" - integrity sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ== +magnet-uri@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-7.0.5.tgz#7b5143fd5527f3f612959eeeae264d6f4aeff37b" + integrity sha512-Ke+dDiYHK1Rq/ZyGUAgk7NIkoypivxolTj/A0qr60ypP0FjeP+NTUNEhr965HsRan0zGxKEBK73+SsjRyJWkXg== dependencies: - bep53-range "^1.1.0" - thirty-two "^1.0.2" + "@thaunknown/thirty-two" "^1.0.3" + bep53-range "^2.0.0" + uint8-util "^2.1.9" make-dir@^4.0.0: version "4.0.0" @@ -4123,6 +4357,35 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msw@^2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.1.7.tgz#0d7872af286cc5f6621dc40a496f8da8308cd198" + integrity sha512-yTIYqEMqDSrdbVMrfmqP6rTKQsnIbglTvVmAHDWwNegyXPXRcV+RjsaFEqubRS266gwWCDLm9YdOkWSKLdDvJQ== + dependencies: + "@bundled-es-modules/cookie" "^2.0.0" + "@bundled-es-modules/statuses" "^1.0.1" + "@mswjs/cookies" "^1.1.0" + "@mswjs/interceptors" "^0.25.16" + "@open-draft/until" "^2.1.0" + "@types/cookie" "^0.6.0" + "@types/statuses" "^2.0.4" + chalk "^4.1.2" + chokidar "^3.4.2" + graphql "^16.8.1" + headers-polyfill "^4.0.2" + inquirer "^8.2.0" + is-node-process "^1.2.0" + outvariant "^1.4.2" + path-to-regexp "^6.2.0" + strict-event-emitter "^0.5.1" + type-fest "^4.9.0" + yargs "^17.7.2" + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + name-to-imdb@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/name-to-imdb/-/name-to-imdb-3.0.4.tgz#1395c27f5b8ee057320a6eee218a86bb3f829034" @@ -4196,7 +4459,7 @@ nopt@^7.0.0: dependencies: abbrev "^2.0.0" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -4264,6 +4527,11 @@ object.values@^1.1.7: define-properties "^1.2.0" es-abstract "^1.22.1" +obuf@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + on-exit-leak-free@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" @@ -4283,7 +4551,7 @@ once@~1.3.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -4307,6 +4575,31 @@ options@>=0.0.5: resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066" + integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ== + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -4434,6 +4727,11 @@ path-scurry@^1.10.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -4485,12 +4783,17 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== +pg-numeric@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" + integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== + pg-pool@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7" integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og== -pg-protocol@^1.6.0: +pg-protocol@*, pg-protocol@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833" integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== @@ -4506,6 +4809,19 @@ pg-types@^2.1.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" +pg-types@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d" + integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== + dependencies: + pg-int8 "1.0.1" + pg-numeric "1.0.2" + postgres-array "~3.0.1" + postgres-bytea "~3.0.0" + postgres-date "~2.1.0" + postgres-interval "^3.0.0" + postgres-range "^1.1.1" + pg@^8.11.3: version "8.11.3" resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb" @@ -4533,7 +4849,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -4605,16 +4921,33 @@ postgres-array@~2.0.0: resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== +postgres-array@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98" + integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== + postgres-bytea@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== +postgres-bytea@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089" + integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== + dependencies: + obuf "~1.1.2" + postgres-date@~1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== +postgres-date@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0" + integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== + postgres-interval@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" @@ -4622,6 +4955,16 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +postgres-interval@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" + integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== + +postgres-range@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" + integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -4782,6 +5125,15 @@ readable-stream@^2.0.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.0.0: version "4.5.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" @@ -4793,6 +5145,13 @@ readable-stream@^4.0.0: process "^0.11.10" string_decoder "^1.3.0" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" @@ -4858,6 +5217,14 @@ resolve@^1.20.0, resolve@^1.22.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + retry-as-promised@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" @@ -4887,6 +5254,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.2, run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4904,6 +5276,13 @@ rusha@^0.8.1: resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68" integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA== +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" @@ -5042,7 +5421,7 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -5184,6 +5563,16 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +statuses@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -5245,7 +5634,7 @@ string2compact@^1.1.1: addr-to-ip-port "^1.0.1" ipaddr.js "^2.0.0" -string_decoder@^1.3.0: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -5355,11 +5744,6 @@ thirty-two@^0.0.2: resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a" integrity sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA== -thirty-two@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a" - integrity sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA== - thread-stream@^2.0.0: version "2.4.1" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.1.tgz#6d588b14f0546e59d3f306614f044bc01ce43351" @@ -5367,11 +5751,23 @@ thread-stream@^2.0.0: dependencies: real-require "^0.2.0" +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + thunky@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -5501,7 +5897,7 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.6.1: +tslib@^2.1.0, tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -5538,6 +5934,11 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^4.9.0: + version "4.10.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.10.2.tgz#3abdb144d93c5750432aac0d73d3e85fcab45738" + integrity sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw== + typed-array-buffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz#0608ffe6bca71bf15a45bff0ca2604107a1325f5" @@ -5582,6 +5983,13 @@ typescript@^5.3.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +uint8-util@^2.1.9: + version "2.2.4" + resolved "https://registry.yarnpkg.com/uint8-util/-/uint8-util-2.2.4.tgz#4df57c7b25b821d02b1599e80f0f1f5f56bc90e1" + integrity sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA== + dependencies: + base64-arraybuffer "^1.0.2" + ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" @@ -5654,7 +6062,7 @@ url-parse@~1.5.10: querystringify "^2.1.1" requires-port "^1.0.0" -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -5697,6 +6105,13 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -5775,6 +6190,15 @@ wkx@^0.5.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -5838,7 +6262,7 @@ yargs-parser@^21.0.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 8bba2aa2846161d0dc9a34f1439510ad207470b0 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 15:10:21 +0000 Subject: [PATCH 40/55] fix magnet uri by download, and add torrent download service test --- src/node/consumer/package.json | 2 +- .../test/torrent_download_service.test.ts | 141 ++++++++++++++++++ src/node/consumer/yarn.lock | 45 ++---- 3 files changed, 157 insertions(+), 31 deletions(-) create mode 100644 src/node/consumer/test/torrent_download_service.test.ts diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 7ee62a4..d0fa58d 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -21,7 +21,7 @@ "cache-manager": "^5.4.0", "google-sr": "^3.2.1", "inversify": "^6.0.2", - "magnet-uri": "^7.0.5", + "magnet-uri": "^6.2.0", "moment": "^2.30.1", "name-to-imdb": "^3.0.4", "parse-torrent-title": "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/torrent_download_service.test.ts new file mode 100644 index 0000000..7b19925 --- /dev/null +++ b/src/node/consumer/test/torrent_download_service.test.ts @@ -0,0 +1,141 @@ +import "reflect-metadata"; // required +import { ILoggingService } from '@interfaces/logging_service'; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import { TorrentDownloadService } from '@services/torrent_download_service'; +import torrentStream from 'torrent-stream'; + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + } +}) + +jest.mock('torrent-stream', () => { + return jest.fn().mockImplementation(() => ({ + on: jest.fn(), + files: [], + destroy: jest.fn(), + })); +}); + +describe('TorrentDownloadService', () => { + let torrentDownloadService: TorrentDownloadService, + mockLoggingService: ILoggingService; + + beforeEach(() => { + mockLoggingService = jest.requireMock('@services/logging_service'); + torrentDownloadService = new TorrentDownloadService(mockLoggingService); + }); + + it('should get torrent files', async () => { + const mockTorrent: IParsedTorrent = { + size: 123456789, + isPack: false, + imdbId: 'tt1234567', + kitsuId: 1234, + trackers: 'http://tracker1.com,http://tracker2.com', + provider: 'provider1', + infoHash: '1234567890abcdef', + type: 'movie', + uploadDate: new Date(), + seeders: 100, + torrentId: 'torrent1', + fileCollection: { }, + title: 'Test Movie', + year: 2020, + season: 1, + episode: 1, + resolution: '1080p', + codec: 'H.264', + audio: 'AAC', + group: 'GRP', + extended: false, + hardcoded: false, + proper: false, + repack: false, + container: 'mp4', + unrated: false, + }; + + const mockFiles = [ + { + name: 'file1.mp4', + path: '/path/to/file1.mp4', + length: 123456789, + fileIndex: 0, + select: jest.fn(), + deselect: jest.fn(), + createReadStream: jest.fn(), + }, + { + name: 'file2.srt', + path: '/path/to/file2.srt', + length: 987654321, + fileIndex: 1, + select: jest.fn(), + deselect: jest.fn(), + createReadStream: jest.fn(), + }, + ]; + + + const mockEngine = { + on: jest.fn((event, callback) => { + if (event === 'ready') { + callback(); + } + }), + files: mockFiles, + destroy: jest.fn(), + connect: jest.fn(), + disconnect: jest.fn(), + block: jest.fn(), + remove: jest.fn(), + listen: jest.fn(), + swarm: { + downloaded: 2, + }, + infoHash: 'mockInfoHash', + }; + + (torrentStream as jest.MockedFunction).mockReturnValue(mockEngine); + + + const result = await torrentDownloadService.getTorrentFiles(mockTorrent); + + expect(result).toEqual({ + contents: mockFiles.map(file => ({ + path: file.path, + fileIndex: file.fileIndex, + infoHash: mockTorrent.infoHash, + size: file.length + })), + videos: mockFiles.filter(file => file.name.endsWith('.mp4')).map(file => ({ + fileIndex: file.fileIndex, + infoHash: mockTorrent.infoHash, + path: file.path, + size: file.length, + title: file.name.split('.')[0], + extension: file.name.split('.')[1], + container: file.name.split('.')[1], + imdbId: mockTorrent.imdbId, + imdbSeason: mockTorrent.season, + imdbEpisode: mockTorrent.episode, + kitsuId: mockTorrent.kitsuId, + kitsuEpisode: mockTorrent.episode, + })), + subtitles: mockFiles.filter(file => file.name.endsWith('.srt')).map(file => ({ + fileIndex: file.fileIndex, + infoHash: mockTorrent.infoHash, + path: file.path, + title: file.name, + fileId: file.fileIndex, + })), + }); + + expect(torrentStream).toHaveBeenCalledWith(expect.any(String), expect.any(Object)); + expect(mockLoggingService.debug).toHaveBeenCalledWith(`Adding torrent with infoHash ${mockTorrent.infoHash} to torrent engine...`); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/yarn.lock b/src/node/consumer/yarn.lock index 393b538..1869770 100644 --- a/src/node/consumer/yarn.lock +++ b/src/node/consumer/yarn.lock @@ -978,13 +978,6 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@thaunknown/thirty-two@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@thaunknown/thirty-two/-/thirty-two-1.0.3.tgz#64883031c4444c0fd75436219189ab5816b5b826" - integrity sha512-bD6PvWbaf53JC04O7WnGDjqZBDgja/KT2Jd/6I2vJBIy+DLmQfQJZZ/G+16nAkVq1yGTIkO4rfc4RlH0DmEEqA== - dependencies: - uint8-util "^2.1.9" - "@tirke/node-cache-manager-mongodb@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz#e730623ae53d4b3e6c6328baab0cff49ed6cb4ce" @@ -1580,11 +1573,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-arraybuffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" - integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== - base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -1605,10 +1593,10 @@ bencode@^2.0.0: resolved "https://registry.yarnpkg.com/bencode/-/bencode-2.0.3.tgz#89b9c80ea1b8573554915a7d0c15f62b0aa7fc52" integrity sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w== -bep53-range@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-2.0.0.tgz#a1770475661b4b814c4359e4b66f7cbd88de2b10" - integrity sha512-sMm2sV5PRs0YOVk0LTKtjuIprVzxgTQUsrGX/7Yph2Rm4FO2Fqqtq7hNjsOB5xezM4v4+5rljCgK++UeQJZguA== +bep53-range@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.1.tgz#20fd125b00a413254a77d42f63a43750ca7e64ac" + integrity sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ== binary-extensions@^2.0.0: version "2.2.0" @@ -4118,14 +4106,13 @@ magnet-uri@^4.0.0: thirty-two "^0.0.2" xtend "^4.0.0" -magnet-uri@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-7.0.5.tgz#7b5143fd5527f3f612959eeeae264d6f4aeff37b" - integrity sha512-Ke+dDiYHK1Rq/ZyGUAgk7NIkoypivxolTj/A0qr60ypP0FjeP+NTUNEhr965HsRan0zGxKEBK73+SsjRyJWkXg== +magnet-uri@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-6.2.0.tgz#10f7be050bf23452df210838239b118463c3eeff" + integrity sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ== dependencies: - "@thaunknown/thirty-two" "^1.0.3" - bep53-range "^2.0.0" - uint8-util "^2.1.9" + bep53-range "^1.1.0" + thirty-two "^1.0.2" make-dir@^4.0.0: version "4.0.0" @@ -5744,6 +5731,11 @@ thirty-two@^0.0.2: resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a" integrity sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA== +thirty-two@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a" + integrity sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA== + thread-stream@^2.0.0: version "2.4.1" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.1.tgz#6d588b14f0546e59d3f306614f044bc01ce43351" @@ -5983,13 +5975,6 @@ typescript@^5.3.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== -uint8-util@^2.1.9: - version "2.2.4" - resolved "https://registry.yarnpkg.com/uint8-util/-/uint8-util-2.2.4.tgz#4df57c7b25b821d02b1599e80f0f1f5f56bc90e1" - integrity sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA== - dependencies: - base64-arraybuffer "^1.0.2" - ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" From 901186c109cde0a68ae6f0bbbad0abbed8392bdb Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 15:41:03 +0000 Subject: [PATCH 41/55] back to npm --- src/node/consumer/Dockerfile | 9 +- src/node/consumer/package-lock.json | 11050 ++++++++++++++++++++++++++ src/node/consumer/package.json | 4 +- src/node/consumer/yarn.lock | 6271 --------------- 4 files changed, 11056 insertions(+), 6278 deletions(-) create mode 100644 src/node/consumer/package-lock.json delete mode 100644 src/node/consumer/yarn.lock diff --git a/src/node/consumer/Dockerfile b/src/node/consumer/Dockerfile index 11980e6..9474653 100644 --- a/src/node/consumer/Dockerfile +++ b/src/node/consumer/Dockerfile @@ -4,12 +4,11 @@ RUN apt update && apt install -y git && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY package.json ./ -COPY yarn.lock ./ -RUN yarn install +COPY package*.json ./ +RUN npm install COPY . . -RUN yarn run build -RUN yarn install --production +RUN npm run build +RUN npm install --omit=dev FROM node:lts-buster-slim diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json new file mode 100644 index 0000000..8c8ea5c --- /dev/null +++ b/src/node/consumer/package-lock.json @@ -0,0 +1,11050 @@ +{ + "name": "consumer", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "consumer", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "@tirke/node-cache-manager-mongodb": "^1.6.0", + "amqplib": "^0.10.3", + "axios": "^1.6.1", + "bottleneck": "^2.19.5", + "cache-manager": "^5.4.0", + "google-sr": "^3.2.1", + "inversify": "^6.0.2", + "magnet-uri": "^6.2.0", + "moment": "^2.30.1", + "name-to-imdb": "^3.0.4", + "parse-torrent-title": "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", + "pg": "^8.11.3", + "pg-hstore": "^2.3.4", + "pino": "^8.18.0", + "reflect-metadata": "^0.2.1", + "sequelize": "^6.36.0", + "sequelize-typescript": "^2.1.6", + "torrent-stream": "^1.2.1" + }, + "devDependencies": { + "@types/amqplib": "^0.10.4", + "@types/jest": "^29.5.12", + "@types/magnet-uri": "^5.1.5", + "@types/node": "^20.11.16", + "@types/pg": "^8.11.0", + "@types/torrent-stream": "^0.0.9", + "@types/validator": "^13.11.8", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "esbuild": "^0.20.0", + "eslint": "^8.56.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-import-helpers": "^1.3.1", + "jest": "^29.7.0", + "msw": "^2.1.7", + "node-gyp": "^10.0.1", + "pino-pretty": "^10.3.1", + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.7.0", + "typescript": "^5.3.3" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@acuminous/bitsyntax": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz", + "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==", + "dependencies": { + "buffer-more-ints": "~1.0.0", + "debug": "^4.3.4", + "safe-buffer": "~5.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz", + "integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz", + "integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz", + "integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz", + "integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz", + "integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz", + "integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz", + "integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz", + "integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz", + "integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz", + "integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz", + "integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz", + "integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz", + "integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz", + "integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz", + "integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz", + "integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz", + "integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz", + "integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz", + "integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz", + "integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz", + "integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz", + "integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz", + "integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", + "integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@mswjs/cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz", + "integrity": "sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.25.16", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.25.16.tgz", + "integrity": "sha512-8QC8JyKztvoGAdPgyZy49c9vSHHAZjHagwl4RY9E8carULk8ym3iTaiawrT1YoLF/qb449h48f71XDPgkUSOUg==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "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, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "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, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "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, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", + "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tirke/node-cache-manager-mongodb": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz", + "integrity": "sha512-3eEtfdriTcYq0bIrxFypwUiiah8IX7tSv+OpzZ9v9iZWrXbR54ot7lCF/kj2LpdBDDOX5eZi74LWGrsB2WFSLg==", + "dependencies": { + "mongodb": "^6.0.0" + }, + "engines": { + "node": ">=14.20" + }, + "funding": { + "url": "https://github.com/sponsors/tirke" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/amqplib": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.4.tgz", + "integrity": "sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/magnet-uri": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/magnet-uri/-/magnet-uri-5.1.5.tgz", + "integrity": "sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/pg": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.0.tgz", + "integrity": "sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/statuses": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.4.tgz", + "integrity": "sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==", + "dev": true + }, + "node_modules/@types/torrent-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/torrent-stream/-/torrent-stream-0.0.9.tgz", + "integrity": "sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/validator": { + "version": "13.11.9", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", + "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/addr-to-ip-port": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz", + "integrity": "sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg==" + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amqplib": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz", + "integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==", + "dependencies": { + "@acuminous/bitsyntax": "^0.1.2", + "buffer-more-ints": "~1.0.0", + "readable-stream": "1.x >=1.1.9", + "url-parse": "~1.5.10" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bencode": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.7.0.tgz", + "integrity": "sha512-MG5AM/hkQIZoz/layZ1JK3xBTfqkLcJ3dJ7u2lx+6vZT1JWyK3OgEFGx1WFzWt6grGH6OSGQvRcCnhWKLp4f1Q==" + }, + "node_modules/bep53-range": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bep53-range/-/bep53-range-1.1.1.tgz", + "integrity": "sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bitfield": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bitfield/-/bitfield-0.1.0.tgz", + "integrity": "sha512-M15ypXCxXd81FSOWL2ejHpB1TDKmz7Y55/VuqfExJi72sHW0JzE5dfV+hrSZafZtWRg/tdMsdte5dgwrlOM7nA==" + }, + "node_modules/bittorrent-dht": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/bittorrent-dht/-/bittorrent-dht-6.4.2.tgz", + "integrity": "sha512-DeBunF1nL/ckThYyU3AVtHFR195zNV06Ob6bKNXA1y6X56GSKMfkNCABB45YcbZevGMW1dytFlm59D/fws5lTg==", + "dependencies": { + "bencode": "^0.7.0", + "buffer-equals": "^1.0.3", + "debug": "^2.2.0", + "inherits": "^2.0.1", + "k-bucket": "^0.6.0", + "k-rpc": "^3.6.0", + "lru": "^2.0.0" + } + }, + "node_modules/bittorrent-dht/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/bittorrent-dht/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bittorrent-tracker": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/bittorrent-tracker/-/bittorrent-tracker-7.7.0.tgz", + "integrity": "sha512-YFgPTVRhUMncZr8tM3ige7gnViMGhKoGF23qaiISRG8xtYebTGHrMSMXsTXo6O1KbtdEI+4jzvGY1K/wdT9GUA==", + "dependencies": { + "bencode": "^0.8.0", + "bn.js": "^4.4.0", + "compact2string": "^1.2.0", + "debug": "^2.0.0", + "hat": "0.0.3", + "inherits": "^2.0.1", + "ip": "^1.0.1", + "minimist": "^1.1.1", + "once": "^1.3.0", + "random-iterate": "^1.0.1", + "run-parallel": "^1.1.2", + "run-series": "^1.0.2", + "simple-get": "^2.0.0", + "simple-peer": "^6.0.0", + "simple-websocket": "^4.0.0", + "string2compact": "^1.1.1", + "uniq": "^1.0.1", + "ws": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "bittorrent-tracker": "bin/cmd.js" + } + }, + "node_modules/bittorrent-tracker/node_modules/bencode": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-0.8.0.tgz", + "integrity": "sha512-MWs3FqaWOGg5l+quIT9JTx7+SlcMbfPqqpWy+GOYi5rjZkX8i03tkNhAQn3pD2GAKENPpP3ScUR97ZUMffhHZA==" + }, + "node_modules/bittorrent-tracker/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/bittorrent-tracker/node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "node_modules/bittorrent-tracker/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/bncode": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.5.3.tgz", + "integrity": "sha512-0P5VuWobU5Gwbeio8n9Jsdv0tE1IikrV9n4f7RsnXHNtxmdd/oeIO6QyoSEUAEyo5P6i3XMfBppi82WqNsT4JA==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/bson": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz", + "integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-equals": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", + "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buffer-more-ints": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", + "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" + }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/cacache": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", + "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cache-manager": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.4.0.tgz", + "integrity": "sha512-FS7o8vqJosnLpu9rh2gQTo8EOzCRJLF1BJ4XDEUDMqcfvs7SJZs5iuoFTXLauzQ3S5v8sBAST1pCwMaurpyi1A==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "^10.1.0", + "promise-coalesce": "^1.1.2" + } + }, + "node_modules/call-bind": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001585", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz", + "integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-dgram": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/chrome-dgram/-/chrome-dgram-3.0.6.tgz", + "integrity": "sha512-bqBsUuaOiXiqxXt/zA/jukNJJ4oaOtc7ciwqJpZVEaaXwwxqgI2/ZdG02vXYWUhHGziDlvGMQWk0qObgJwVYKA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "inherits": "^2.0.4", + "run-series": "^1.1.9" + } + }, + "node_modules/chrome-dns": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chrome-dns/-/chrome-dns-1.0.1.tgz", + "integrity": "sha512-HqsYJgIc8ljJJOqOzLphjAs79EUuWSX3nzZi2LNkzlw3GIzAeZbaSektC8iT/tKvLqZq8yl1GJu5o6doA4TRbg==", + "dependencies": { + "chrome-net": "^3.3.2" + } + }, + "node_modules/chrome-net": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/chrome-net/-/chrome-net-3.3.4.tgz", + "integrity": "sha512-Jzy2EnzmE+ligqIZUsmWnck9RBXLuUy6CaKyuNMtowFG3ZvLt8d+WBJCTPEludV0DHpIKjAOlwjFmTaEdfdWCw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compact2string": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/compact2string/-/compact2string-1.4.1.tgz", + "integrity": "sha512-3D+EY5nsRhqnOwDxveBv5T8wGo4DEvYxjDtPGmdOX+gfr5gE92c2RC0w2wa+xEefm07QuVqqcF3nZJUZ92l/og==", + "dependencies": { + "ipaddr.js": ">= 0.1.5" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cyclist": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.1.1.tgz", + "integrity": "sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw==" + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge-ts": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", + "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diacritics": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", + "integrity": "sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.661", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.661.tgz", + "integrity": "sha512-AFg4wDHSOk5F+zA8aR+SVIOabu7m0e7BiJnigCvPXzIGy731XENw/lmNxTySpVFtkFEy+eyt4oHhh5FF3NjQNw==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz", + "integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.0", + "@esbuild/android-arm": "0.20.0", + "@esbuild/android-arm64": "0.20.0", + "@esbuild/android-x64": "0.20.0", + "@esbuild/darwin-arm64": "0.20.0", + "@esbuild/darwin-x64": "0.20.0", + "@esbuild/freebsd-arm64": "0.20.0", + "@esbuild/freebsd-x64": "0.20.0", + "@esbuild/linux-arm": "0.20.0", + "@esbuild/linux-arm64": "0.20.0", + "@esbuild/linux-ia32": "0.20.0", + "@esbuild/linux-loong64": "0.20.0", + "@esbuild/linux-mips64el": "0.20.0", + "@esbuild/linux-ppc64": "0.20.0", + "@esbuild/linux-riscv64": "0.20.0", + "@esbuild/linux-s390x": "0.20.0", + "@esbuild/linux-x64": "0.20.0", + "@esbuild/netbsd-x64": "0.20.0", + "@esbuild/openbsd-x64": "0.20.0", + "@esbuild/sunos-x64": "0.20.0", + "@esbuild/win32-arm64": "0.20.0", + "@esbuild/win32-ia32": "0.20.0", + "@esbuild/win32-x64": "0.20.0" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import-helpers": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-helpers/-/eslint-plugin-import-helpers-1.3.1.tgz", + "integrity": "sha512-MrACDozK6TmTJoCFHD71Ew3r5210Za3zlTrhX+fQGsyvxceaFvAI9AcvZ/8oSU0pZ61G3nDEn6mXY0T4S8cJEg==", + "dev": true, + "peerDependencies": { + "eslint": "5.x - 8.x" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fifo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/fifo/-/fifo-0.1.4.tgz", + "integrity": "sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/flatten": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-0.0.1.tgz", + "integrity": "sha512-pzNZh42/A2HmcRIpddSP0T+zBofd119o5rNB2u1YHv36CM2C/ietI2ZsjWZ2LSL7J0BNVkFn1a9Ad+cmO2lDQg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "engines": { + "node": "*" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-chunk-store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/fs-chunk-store/-/fs-chunk-store-1.7.0.tgz", + "integrity": "sha512-KhjJmZAs2eqfhCb6PdPx4RcZtheGTz86tpTC5JTvqBn/xda+Nb+0C7dCyjOSN7T76H6a56LvH0SVXQMchLXDRw==", + "dependencies": { + "mkdirp": "^0.5.1", + "random-access-file": "^2.0.1", + "randombytes": "^2.0.3", + "rimraf": "^2.4.2", + "run-parallel": "^1.1.2", + "thunky": "^1.0.1" + } + }, + "node_modules/fs-chunk-store/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fs-chunk-store/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/google-sr": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/google-sr/-/google-sr-3.2.1.tgz", + "integrity": "sha512-1WGy6mxMTKo+jbIrmq1mwm+2Egvmx9ttsXzCiR0Y2LMcpeG4shqc8C4g12msi4arRn9qEwG1qrFQ1W9jo3dDzw==", + "dependencies": { + "axios": "^1.4.0", + "cheerio": "1.0.0-rc.12", + "deepmerge-ts": "^5.1.0", + "google-sr-selectors": "^0.0.2", + "tslib": "^2.6.1" + } + }, + "node_modules/google-sr-selectors": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-sr-selectors/-/google-sr-selectors-0.0.2.tgz", + "integrity": "sha512-7h+vo7NSDf+pZB/InDon4mwhXeTvy/9yvAChGnjppcdHgTwlUWDpYPWGUn781J3PrjBj6rZAginsSTGqG5uUZw==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hat": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz", + "integrity": "sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==", + "engines": { + "node": "*" + } + }, + "node_modules/headers-polyfill": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.2.tgz", + "integrity": "sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==", + "dev": true + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate-chunk-store": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/immediate-chunk-store/-/immediate-chunk-store-1.0.8.tgz", + "integrity": "sha512-0tQyTytUaIUskpv5j5L5ZeQuEjYDl9QIekwDUisdqpAM81OZjBaEIriW7hoiRLaLNxj1fXE8e1yx5JaCGrrE7A==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inversify": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", + "integrity": "sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true + }, + "node_modules/ip-set": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ip-set/-/ip-set-1.0.2.tgz", + "integrity": "sha512-Mb6kv78bTi4RNAIIWL8Bbre7hXOR2pNUi3j8FaQkLaitf/ZWxkq3/iIwXNYk2ACO3IMfdVdQrOkUtwZblO7uBA==", + "dependencies": { + "ip": "^1.1.3" + } + }, + "node_modules/ip-set/node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/k-bucket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-0.6.0.tgz", + "integrity": "sha512-1zJpqkrLYgolqdO1TE1/FWf+mHfhJKLC2Wpi4JaMFZKi4b6tFEn9/d+JqscBIJw5auWFewp16CSAEetFGEC4NQ==", + "dependencies": { + "buffer-equal": "0.0.1", + "inherits": "^2.0.1" + } + }, + "node_modules/k-rpc": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/k-rpc/-/k-rpc-3.7.0.tgz", + "integrity": "sha512-XFL8PatIToQ/qhSSAq9FSK73wk4fX4DcHqjnkvSCrWC59PV02Oj1KeYa3KnREAXgA1DlCSzcKjk7M8usnT/dUw==", + "dependencies": { + "buffer-equals": "^1.0.3", + "k-bucket": "^2.0.0", + "k-rpc-socket": "^1.5.0" + } + }, + "node_modules/k-rpc-socket": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/k-rpc-socket/-/k-rpc-socket-1.11.1.tgz", + "integrity": "sha512-8xtA8oqbZ6v1Niryp2/g4GxW16EQh5MvrUylQoOG+zcrDff5CKttON2XUXvMwlIHq4/2zfPVFiinAccJ+WhxoA==", + "dependencies": { + "bencode": "^2.0.0", + "chrome-dgram": "^3.0.2", + "chrome-dns": "^1.0.0", + "chrome-net": "^3.3.2" + } + }, + "node_modules/k-rpc-socket/node_modules/bencode": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bencode/-/bencode-2.0.3.tgz", + "integrity": "sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w==" + }, + "node_modules/k-rpc/node_modules/k-bucket": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-2.0.1.tgz", + "integrity": "sha512-Xuye90xBBDJJbvNSuy3z/Yl8ceVX02/sopqGUEwJkMgRw+//TQXx0/Hbgp60GsoVfZcCBllQXXp6AWe2INu8pw==", + "dependencies": { + "buffer-equal": "0.0.1", + "randombytes": "^2.0.3" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lru/-/lru-2.0.1.tgz", + "integrity": "sha512-JGRd3IHM64MPsGVw1Mqbz2Y2HDIePqi/MLfPtdrkHQwvvJnSrS9b6gM3KS9PFR5xJnufXJczHHZSmGqfuII1ew==", + "dependencies": { + "inherits": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/magnet-uri": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-6.2.0.tgz", + "integrity": "sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "bep53-range": "^1.1.0", + "thirty-two": "^1.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "dev": true, + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", + "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msw": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.1.7.tgz", + "integrity": "sha512-yTIYqEMqDSrdbVMrfmqP6rTKQsnIbglTvVmAHDWwNegyXPXRcV+RjsaFEqubRS266gwWCDLm9YdOkWSKLdDvJQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@mswjs/cookies": "^1.1.0", + "@mswjs/interceptors": "^0.25.16", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "chokidar": "^3.4.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "inquirer": "^8.2.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.7.x <= 5.3.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.10.2.tgz", + "integrity": "sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/name-to-imdb": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/name-to-imdb/-/name-to-imdb-3.0.4.tgz", + "integrity": "sha512-OVmDvWoAZso2eHxK51UK7TMIpUpM4LnI3KhvvZe+JkDatEda9WS3/YXZVQnand5skI38shoniOFcyrw08QsNeA==", + "dependencies": { + "diacritics": "~1.3.0", + "named-queue": "^2.1.0", + "needle": "^1.1.2", + "node-fetch": "^2.2.0" + } + }, + "node_modules/named-queue": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/named-queue/-/named-queue-2.2.1.tgz", + "integrity": "sha512-ssW6R5DZza+ixfGgu+piZAqszqRViHNZjjazXknCWyRYZfRJkBmbSPd1nIcH29aejsyBNPNrn3AdMfB+qvb2Hw==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/needle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-1.6.0.tgz", + "integrity": "sha512-ogVK1D/Cgemw2vM1KJN6B83DwcKbDepdkMNtVJcXIe+xoaCOdC+aJHzhEov7xjsY9S7rBIuHP59W1fLsbGqDhA==", + "dependencies": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/needle/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-gyp": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "dev": true, + "dependencies": { + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outvariant": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz", + "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", + "dev": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-torrent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/parse-torrent/-/parse-torrent-4.1.0.tgz", + "integrity": "sha512-FeoGe8bOYmSzxO31kYy44A03FjuULCMOIMom8KyuGvO8/lLVPJyo2nr9CwH/iYmNHm74hk7h70o59DOfk9Rq+A==", + "dependencies": { + "magnet-uri": "^4.0.0", + "parse-torrent-file": "^2.0.0" + }, + "bin": { + "parse-torrent": "bin/cmd.js" + } + }, + "node_modules/parse-torrent-file": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz", + "integrity": "sha512-u2MgLOjZPDDer1oRg1c+H/+54iIQYY5TKgQ5G8KrGLT1Dcwdo7Lj+QfQR123+u8J0AMSFGbQUvsBlSB7uIJcCA==", + "deprecated": "Use the parse-torrent package instead", + "dependencies": { + "bencode": "^0.7.0", + "simple-sha1": "^2.0.0" + }, + "bin": { + "parse-torrent-file": "bin/cmd.js" + } + }, + "node_modules/parse-torrent-title": { + "version": "1.3.0", + "resolved": "git+ssh://git@github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", + "integrity": "sha512-2Y0gkYUyrT5sRo5cnpOt90HpciJk7oqa1iOt/AQxr186oOvth7Llj2+aqDB9MzNHX7IZ3QpfRs5fr9TZ2zAIfg==", + "license": "MIT", + "dependencies": { + "moment": "^2.24.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parse-torrent/node_modules/magnet-uri": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/magnet-uri/-/magnet-uri-4.2.3.tgz", + "integrity": "sha512-aHhR49CRBOq3BX6jQOBdGMXhNT2+9LIH3CCIwHlR+aFE8nWMfBD1aNYxfm2u2LsCOwvfPeyCsdIg9KXSwdsOLQ==", + "dependencies": { + "flatten": "0.0.1", + "thirty-two": "^0.0.2", + "xtend": "^4.0.0" + } + }, + "node_modules/parse-torrent/node_modules/thirty-two": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-0.0.2.tgz", + "integrity": "sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA==", + "engines": { + "node": ">=0.2.6" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/peer-wire-protocol": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/peer-wire-protocol/-/peer-wire-protocol-0.7.1.tgz", + "integrity": "sha512-V9oTa/ZcfNNz9fAST28Gg0fXbPeFPk3SBImsYO8GDDG5D0E195vxXmjZ+SPrzr4BJyMQmdDmwUfTf9MZ62z4mw==", + "dependencies": { + "bitfield": "^0.1.0", + "bncode": "^0.2.3", + "buffer-alloc": "^1.1.0", + "buffer-from": "^1.0.0", + "readable-stream": "^1.0.2", + "speedometer": "^0.1.2" + } + }, + "node_modules/peer-wire-protocol/node_modules/bncode": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/bncode/-/bncode-0.2.3.tgz", + "integrity": "sha512-IXGfySD68R/J2X/it8GZqAM+Vb3ByZvAlUi0Gysq4ZACq6hXGQ3YshKo0QS/f3S9wOWKjJnEjP6x3ELxqBnAOA==" + }, + "node_modules/peer-wire-swarm": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/peer-wire-swarm/-/peer-wire-swarm-0.12.2.tgz", + "integrity": "sha512-sIWZ1nTL9l6mI9J18kW1AeByBwagvNzGJlMmQA9pM+otKQtTIwnigK8SR0nEFrNZYqZelI6RQ6g4udvtQ2TI1g==", + "dependencies": { + "buffer-from": "^1.0.0", + "fifo": "^0.1.4", + "once": "^1.1.1", + "peer-wire-protocol": "^0.7.0", + "speedometer": "^0.1.2", + "utp": "0.0.7" + } + }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-hstore": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.4.tgz", + "integrity": "sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==", + "dependencies": { + "underscore": "^1.13.1" + }, + "engines": { + "node": ">= 0.8.x" + } + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", + "dev": true, + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.1.0", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pg/node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg/node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pino": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.18.0.tgz", + "integrity": "sha512-Mz/gKiRyuXu4HnpHgi1YWdHQCoWMufapzooisvFn78zl4dZciAxS+YeRkUxXl1ee/SzU80YCz1zpECCh4oC6Aw==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/pino-abstract-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/pino-pretty": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", + "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", + "dev": true, + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/pino-pretty/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dev": true, + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postgres-date": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-range": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, + "node_modules/promise-coalesce": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.2.tgz", + "integrity": "sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==", + "engines": { + "node": ">=16" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/random-access-file": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/random-access-file/-/random-access-file-2.2.1.tgz", + "integrity": "sha512-RGU0xmDqdOyEiynob1KYSeh8+9c9Td1MJ74GT1viMEYAn8SJ9oBtWCXLsYZukCF46yududHOdM449uRYbzBrZQ==", + "dependencies": { + "mkdirp-classic": "^0.5.2", + "random-access-storage": "^1.1.1" + } + }, + "node_modules/random-access-storage": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/random-access-storage/-/random-access-storage-1.4.3.tgz", + "integrity": "sha512-D5e2iIC5dNENWyBxsjhEnNOMCwZZ64TARK6dyMN+3g4OTC4MJxyjh9hKLjTGoNhDOPrgjI+YlFEHFnrp/cSnzQ==", + "dependencies": { + "events": "^3.3.0", + "inherits": "^2.0.3", + "queue-tick": "^1.0.0" + } + }, + "node_modules/random-iterate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/random-iterate/-/random-iterate-1.0.1.tgz", + "integrity": "sha512-Jdsdnezu913Ot8qgKgSgs63XkAjEsnMcS1z+cC6D6TNXsUXsMxy0RpclF2pzGZTEiTXL9BiArdGTEexcv4nqcA==" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/re-emitter": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/re-emitter/-/re-emitter-1.1.4.tgz", + "integrity": "sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA==" + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-as-promised": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sequelize": { + "version": "6.36.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.36.0.tgz", + "integrity": "sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "dependencies": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.9.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize-typescript": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz", + "integrity": "sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ==", + "dependencies": { + "glob": "7.2.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "@types/validator": "*", + "reflect-metadata": "*", + "sequelize": ">=6.20.1" + } + }, + "node_modules/sequelize-typescript/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/sequelize-typescript/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sequelize-typescript/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-peer": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-6.4.4.tgz", + "integrity": "sha512-sY35UHankz0ba02Dd8YzdyXhEeTAnW6ZUyDfKOSwUht1GLp9VuMT4jQUXF/wG7C9vpwvitV7Ig7a6IkY/qizwg==", + "dependencies": { + "debug": "^2.1.0", + "get-browser-rtc": "^1.0.0", + "inherits": "^2.0.1", + "randombytes": "^2.0.3", + "readable-stream": "^2.0.5" + } + }, + "node_modules/simple-peer/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/simple-peer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/simple-peer/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/simple-peer/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/simple-sha1": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/simple-sha1/-/simple-sha1-2.1.2.tgz", + "integrity": "sha512-TQl9rm4rdKAVmhO++sXAb8TNN0D6JAD5iyI1mqEPNpxUzTRrtm4aOG1pDf/5W/qCFihiaoK6uuL9rvQz1x1VKw==", + "dependencies": { + "rusha": "^0.8.1" + } + }, + "node_modules/simple-websocket": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-4.3.1.tgz", + "integrity": "sha512-knEO6ub2Pw00c7ueOV6snKE1hr7jIdY068+239v0I8DVKofyd7IQmYHXrM9pZL1zuI0H7sd+Y5kedndBi5GXIA==", + "dependencies": { + "debug": "^2.1.3", + "inherits": "^2.0.1", + "randombytes": "^2.0.3", + "readable-stream": "^2.0.5", + "ws": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/simple-websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/simple-websocket/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/simple-websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/simple-websocket/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/simple-websocket/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/simple-websocket/node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "node_modules/simple-websocket/node_modules/ws": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha512-61a+9LgtYZxTq1hAonhX8Xwpo2riK4IOR/BIVxioFbCfc3QFKmpE4x9dLExfLHKtUfVZigYa36tThVhO57erEw==", + "dependencies": { + "safe-buffer": "~5.0.1", + "ultron": "~1.1.0" + } + }, + "node_modules/simple-websocket/node_modules/ws/node_modules/safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha512-cr7dZWLwOeaFBLTIuZeYdkfO7UzGIKhjYENJFAxUOMKWGaWDm2nJM2rzxNRm5Owu0DH3ApwNo6kx5idXZfb/Iw==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sonic-boom": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", + "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q==" + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string2compact": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/string2compact/-/string2compact-1.3.2.tgz", + "integrity": "sha512-3XUxUgwhj7Eqh2djae35QHZZT4mN3fsO7kagZhSGmhhlrQagVvWSFuuFIWnpxFS0CdTB2PlQcaL16RDi14I8uw==", + "dependencies": { + "addr-to-ip-port": "^1.0.1", + "ipaddr.js": "^2.0.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==", + "engines": { + "node": ">=0.2.6" + } + }, + "node_modules/thread-stream": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", + "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/torrent-discovery": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/torrent-discovery/-/torrent-discovery-5.4.0.tgz", + "integrity": "sha512-bPTDIA7XEjRlw6vQyt7kM/h1mg1INBsibjbujISITonx4POENZgxfyCSEXZpDhbAkluSPH4HKRKs4/YTmNLC6w==", + "dependencies": { + "bittorrent-dht": "^6.0.0", + "bittorrent-tracker": "^7.0.0", + "debug": "^2.0.0", + "inherits": "^2.0.1", + "re-emitter": "^1.0.0", + "run-parallel": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "node_modules/torrent-discovery/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/torrent-discovery/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/torrent-piece": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/torrent-piece/-/torrent-piece-1.1.2.tgz", + "integrity": "sha512-ElXPyXKKG73o+uziHJ8qlYE9EuyDVxnK2zWL+pW/2bma7RsLpSwFFIJAb8Qui7/tel2hsHQW1z3zBnfQNREpWA==" + }, + "node_modules/torrent-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/torrent-stream/-/torrent-stream-1.2.1.tgz", + "integrity": "sha512-F+3tYmXnpO2gyhZQ7o8yakELJH3FtKISI/FU0iWvchOWFUXiFnjbEBoumSzfcK1P71Qxzx2az4lVK4Dkq4KSew==", + "dependencies": { + "bitfield": "^0.1.0", + "bncode": "^0.5.2", + "buffer-from": "^1.0.0", + "end-of-stream": "^0.1.4", + "fs-chunk-store": "^1.3.0", + "hat": "0.0.3", + "immediate-chunk-store": "^1.0.5", + "ip-set": "^1.0.0", + "mkdirp": "^0.3.5", + "parse-torrent": "^4.0.0", + "peer-wire-swarm": "^0.12.0", + "rimraf": "^2.2.5", + "torrent-discovery": "^5.2.0", + "torrent-piece": "^1.0.0" + } + }, + "node_modules/torrent-stream/node_modules/end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw==", + "dependencies": { + "once": "~1.3.0" + } + }, + "node_modules/torrent-stream/node_modules/mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)" + }, + "node_modules/torrent-stream/node_modules/once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/torrent-stream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsx": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz", + "integrity": "sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", + "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow==" + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utp": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/utp/-/utp-0.0.7.tgz", + "integrity": "sha512-2ZLjisH0HQkpqZTg2m7TK0Yn7TETTg7DxM0EpCKIIIV2ky9w9nSxW5a7gzdk4nH2h+pomrrGw0uywrUJfsm2eA==", + "dependencies": { + "cyclist": "~0.1.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dependencies": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index d0fa58d..ecf0674 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -7,8 +7,8 @@ "build": "node esbuild.js", "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", "start": "node --trace-deprecation dist/main.cjs", - "lint": "yarn eslint ./src --ext .ts,.js", - "lint-fix": "yarn run lint --fix", + "lint": "eslint ./src --ext .ts,.js", + "lint-fix": "npm run lint --fix", "test": "jest", "test:watch": "jest --watch" }, diff --git a/src/node/consumer/yarn.lock b/src/node/consumer/yarn.lock deleted file mode 100644 index 1869770..0000000 --- a/src/node/consumer/yarn.lock +++ /dev/null @@ -1,6271 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@acuminous/bitsyntax@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz#e0b31b9ee7ad1e4dd840c34864327c33d9f1f653" - integrity sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ== - dependencies: - buffer-more-ints "~1.0.0" - debug "^4.3.4" - safe-buffer "~5.1.2" - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== - -"@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" - integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.9" - "@babel/parser" "^7.23.9" - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" - integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== - dependencies: - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" - integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.3.3": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" - integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" - -"@babel/traverse@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" - integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.3.3": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" - integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@bundled-es-modules/cookie@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" - integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== - dependencies: - cookie "^0.5.0" - -"@bundled-es-modules/statuses@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" - integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== - dependencies: - statuses "^2.0.1" - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@esbuild/aix-ppc64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" - integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== - -"@esbuild/aix-ppc64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz#509621cca4e67caf0d18561a0c56f8b70237472f" - integrity sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw== - -"@esbuild/android-arm64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" - integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== - -"@esbuild/android-arm64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz#109a6fdc4a2783fc26193d2687827045d8fef5ab" - integrity sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q== - -"@esbuild/android-arm@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" - integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== - -"@esbuild/android-arm@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.0.tgz#1397a2c54c476c4799f9b9073550ede496c94ba5" - integrity sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g== - -"@esbuild/android-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" - integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== - -"@esbuild/android-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.0.tgz#2b615abefb50dc0a70ac313971102f4ce2fdb3ca" - integrity sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ== - -"@esbuild/darwin-arm64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" - integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== - -"@esbuild/darwin-arm64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz#5c122ed799eb0c35b9d571097f77254964c276a2" - integrity sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ== - -"@esbuild/darwin-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" - integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== - -"@esbuild/darwin-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz#9561d277002ba8caf1524f209de2b22e93d170c1" - integrity sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw== - -"@esbuild/freebsd-arm64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" - integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== - -"@esbuild/freebsd-arm64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz#84178986a3138e8500d17cc380044868176dd821" - integrity sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ== - -"@esbuild/freebsd-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" - integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== - -"@esbuild/freebsd-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz#3f9ce53344af2f08d178551cd475629147324a83" - integrity sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ== - -"@esbuild/linux-arm64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" - integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== - -"@esbuild/linux-arm64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz#24efa685515689df4ecbc13031fa0a9dda910a11" - integrity sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw== - -"@esbuild/linux-arm@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" - integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== - -"@esbuild/linux-arm@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz#6b586a488e02e9b073a75a957f2952b3b6e87b4c" - integrity sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg== - -"@esbuild/linux-ia32@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" - integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== - -"@esbuild/linux-ia32@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz#84ce7864f762708dcebc1b123898a397dea13624" - integrity sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w== - -"@esbuild/linux-loong64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" - integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== - -"@esbuild/linux-loong64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz#1922f571f4cae1958e3ad29439c563f7d4fd9037" - integrity sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw== - -"@esbuild/linux-mips64el@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" - integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== - -"@esbuild/linux-mips64el@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz#7ca1bd9df3f874d18dbf46af009aebdb881188fe" - integrity sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ== - -"@esbuild/linux-ppc64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" - integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== - -"@esbuild/linux-ppc64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz#8f95baf05f9486343bceeb683703875d698708a4" - integrity sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw== - -"@esbuild/linux-riscv64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" - integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== - -"@esbuild/linux-riscv64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz#ca63b921d5fe315e28610deb0c195e79b1a262ca" - integrity sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA== - -"@esbuild/linux-s390x@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" - integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== - -"@esbuild/linux-s390x@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz#cb3d069f47dc202f785c997175f2307531371ef8" - integrity sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ== - -"@esbuild/linux-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" - integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== - -"@esbuild/linux-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz#ac617e0dc14e9758d3d7efd70288c14122557dc7" - integrity sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg== - -"@esbuild/netbsd-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" - integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== - -"@esbuild/netbsd-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz#6cc778567f1513da6e08060e0aeb41f82eb0f53c" - integrity sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ== - -"@esbuild/openbsd-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" - integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== - -"@esbuild/openbsd-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz#76848bcf76b4372574fb4d06cd0ed1fb29ec0fbe" - integrity sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA== - -"@esbuild/sunos-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" - integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== - -"@esbuild/sunos-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz#ea4cd0639bf294ad51bc08ffbb2dac297e9b4706" - integrity sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g== - -"@esbuild/win32-arm64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" - integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== - -"@esbuild/win32-arm64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz#a5c171e4a7f7e4e8be0e9947a65812c1535a7cf0" - integrity sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ== - -"@esbuild/win32-ia32@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" - integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== - -"@esbuild/win32-ia32@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz#f8ac5650c412d33ea62d7551e0caf82da52b7f85" - integrity sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg== - -"@esbuild/win32-x64@0.19.12": - version "0.19.12" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" - integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== - -"@esbuild/win32-x64@0.20.0": - version "0.20.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz#2efddf82828aac85e64cef62482af61c29561bee" - integrity sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg== - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.56.0": - version "8.56.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" - integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== - -"@humanwhocodes/config-array@^0.11.13": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" - integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@mongodb-js/saslprep@^1.1.0": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz#24ec1c4915a65f5c506bb88c081731450d91bb1c" - integrity sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw== - dependencies: - sparse-bitfield "^3.0.3" - -"@mswjs/cookies@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" - integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== - -"@mswjs/interceptors@^0.25.16": - version "0.25.16" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.25.16.tgz#7955fbb8da479bc691df117dd4c8d889e507ecc2" - integrity sha512-8QC8JyKztvoGAdPgyZy49c9vSHHAZjHagwl4RY9E8carULk8ym3iTaiawrT1YoLF/qb449h48f71XDPgkUSOUg== - dependencies: - "@open-draft/deferred-promise" "^2.2.0" - "@open-draft/logger" "^0.3.0" - "@open-draft/until" "^2.0.0" - is-node-process "^1.2.0" - outvariant "^1.2.1" - strict-event-emitter "^0.5.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@npmcli/agent@^2.0.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.1.tgz#8aa677d0a4136d57524336a35d5679aedf2d56f7" - integrity sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ== - dependencies: - agent-base "^7.1.0" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.1" - lru-cache "^10.0.1" - socks-proxy-agent "^8.0.1" - -"@npmcli/fs@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" - integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== - dependencies: - semver "^7.3.5" - -"@open-draft/deferred-promise@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" - integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== - -"@open-draft/logger@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" - integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== - dependencies: - is-node-process "^1.2.0" - outvariant "^1.4.0" - -"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" - integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@tirke/node-cache-manager-mongodb@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@tirke/node-cache-manager-mongodb/-/node-cache-manager-mongodb-1.6.0.tgz#e730623ae53d4b3e6c6328baab0cff49ed6cb4ce" - integrity sha512-3eEtfdriTcYq0bIrxFypwUiiah8IX7tSv+OpzZ9v9iZWrXbR54ot7lCF/kj2LpdBDDOX5eZi74LWGrsB2WFSLg== - dependencies: - mongodb "^6.0.0" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/amqplib@^0.10.4": - version "0.10.4" - resolved "https://registry.yarnpkg.com/@types/amqplib/-/amqplib-0.10.4.tgz#0bf1ceefe280c02502b209fa9f06394b0c4cd688" - integrity sha512-Y5Sqquh/LqDxSgxYaAAFNM0M7GyONtSDCcFMJk+DQwYEjibPyW6y+Yu9H9omdkKc3epyXULmFN3GTaeBHhn2Hg== - dependencies: - "@types/node" "*" - -"@types/babel__core@^7.1.14": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== - dependencies: - "@babel/types" "^7.20.7" - -"@types/cookie@^0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" - integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== - -"@types/debug@^4.1.8": - version "4.1.12" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" - integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== - dependencies: - "@types/ms" "*" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.5.12": - version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - -"@types/json-schema@^7.0.12": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/magnet-uri@^5.1.5": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.5.tgz#8034da138edb41f007729ff18c76e0454df42438" - integrity sha512-SbBjlb1KGe38VfjRR+mwqztJd/4skhdKkRbIzPDhTy7IAeEAPZWIVSEkZw00Qr4ZZOGR3/ATJ20WWPBfrKHGdA== - dependencies: - "@types/node" "*" - -"@types/ms@*": - version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" - integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== - -"@types/node@*", "@types/node@^20.11.16": - version "20.11.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708" - integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ== - dependencies: - undici-types "~5.26.4" - -"@types/pg@^8.11.0": - version "8.11.0" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.0.tgz#355a07531d467f2e4fabaa78be087ce2d99fd862" - integrity sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw== - dependencies: - "@types/node" "*" - pg-protocol "*" - pg-types "^4.0.1" - -"@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/statuses@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.4.tgz#041143ba4a918e8f080f8b0ffbe3d4cb514e2315" - integrity sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw== - -"@types/torrent-stream@^0.0.9": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@types/torrent-stream/-/torrent-stream-0.0.9.tgz#3b7b721ee74ab013ff793426b2823d71f4711068" - integrity sha512-SY0K6HNlDdnU7yk4TWpLjlv65/liZnxmftMuOdjRriC2IGExqnAYfl8dprjU1j1KQMPVM/X174cusUPNPloghQ== - dependencies: - "@types/node" "*" - -"@types/validator@^13.11.8", "@types/validator@^13.7.17": - version "13.11.9" - resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.11.9.tgz#adfe96520b437a0eaa798a475877bf2f75ee402d" - integrity sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw== - -"@types/webidl-conversions@*": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" - integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== - -"@types/whatwg-url@^11.0.2": - version "11.0.4" - resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.4.tgz#ffed0dc8d89d91f62e3f368fcbda222a487c4f63" - integrity sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw== - dependencies: - "@types/webidl-conversions" "*" - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" - integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/type-utils" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== - dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - -"@typescript-eslint/type-utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" - integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== - dependencies: - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/utils" "6.21.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== - -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/utils@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" - integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - semver "^7.5.4" - -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== - dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -abbrev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" - integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.4.1, acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -addr-to-ip-port@^1.0.1: - version "1.5.4" - resolved "https://registry.yarnpkg.com/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz#9542b1c6219fdb8c9ce6cc72c14ee880ab7ddd88" - integrity sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg== - -agent-base@^7.0.2, agent-base@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" - integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== - dependencies: - debug "^4.3.4" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -amqplib@^0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.10.3.tgz#e186a2f74521eb55ec54db6d25ae82c29c1f911a" - integrity sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw== - dependencies: - "@acuminous/bitsyntax" "^0.1.2" - buffer-more-ints "~1.0.0" - readable-stream "1.x >=1.1.9" - url-parse "~1.5.10" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-includes@^3.1.7: - version "3.1.7" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" - integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.filter@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" - integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -array.prototype.findlastindex@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" - integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -arraybuffer.prototype.slice@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -atomic-sleep@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" - integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== - -available-typed-arrays@^1.0.5, available-typed-arrays@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz#ac812d8ce5a6b976d738e1c45f08d0b00bc7d725" - integrity sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg== - -axios@^1.4.0, axios@^1.6.1: - version "1.6.7" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" - integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== - dependencies: - follow-redirects "^1.15.4" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bencode@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/bencode/-/bencode-0.7.0.tgz#811ed647c0118945e41bb4bbbdea9a2c78a17083" - integrity sha512-MG5AM/hkQIZoz/layZ1JK3xBTfqkLcJ3dJ7u2lx+6vZT1JWyK3OgEFGx1WFzWt6grGH6OSGQvRcCnhWKLp4f1Q== - -bencode@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/bencode/-/bencode-0.8.0.tgz#3143448e82b0fadc745633ecc2a5f8fa87932f19" - integrity sha512-MWs3FqaWOGg5l+quIT9JTx7+SlcMbfPqqpWy+GOYi5rjZkX8i03tkNhAQn3pD2GAKENPpP3ScUR97ZUMffhHZA== - -bencode@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/bencode/-/bencode-2.0.3.tgz#89b9c80ea1b8573554915a7d0c15f62b0aa7fc52" - integrity sha512-D/vrAD4dLVX23NalHwb8dSvsUsxeRPO8Y7ToKA015JQYq69MLDOMkC0uGZYA/MPpltLO8rt8eqFC2j8DxjTZ/w== - -bep53-range@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.1.tgz#20fd125b00a413254a77d42f63a43750ca7e64ac" - integrity sha512-ct6s33iiwRCUPp9KXnJ4QMWDgHIgaw36caK/5XEQ9L8dCzSQlJt1Vk6VmHh1VD4AlGCAI4C2zmtfItifBBPrhQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bitfield@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bitfield/-/bitfield-0.1.0.tgz#b05d8b5f0d09f2df35a9db3b3a62d3808c46c457" - integrity sha512-M15ypXCxXd81FSOWL2ejHpB1TDKmz7Y55/VuqfExJi72sHW0JzE5dfV+hrSZafZtWRg/tdMsdte5dgwrlOM7nA== - -bittorrent-dht@^6.0.0: - version "6.4.2" - resolved "https://registry.yarnpkg.com/bittorrent-dht/-/bittorrent-dht-6.4.2.tgz#8b40f8cee6bea87f2b34fd2ae0bd367a8b1247a6" - integrity sha512-DeBunF1nL/ckThYyU3AVtHFR195zNV06Ob6bKNXA1y6X56GSKMfkNCABB45YcbZevGMW1dytFlm59D/fws5lTg== - dependencies: - bencode "^0.7.0" - buffer-equals "^1.0.3" - debug "^2.2.0" - inherits "^2.0.1" - k-bucket "^0.6.0" - k-rpc "^3.6.0" - lru "^2.0.0" - -bittorrent-tracker@^7.0.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/bittorrent-tracker/-/bittorrent-tracker-7.7.0.tgz#ffd2eabc141d36ed5c1817df7e992f91fd7fc65c" - integrity sha512-YFgPTVRhUMncZr8tM3ige7gnViMGhKoGF23qaiISRG8xtYebTGHrMSMXsTXo6O1KbtdEI+4jzvGY1K/wdT9GUA== - dependencies: - bencode "^0.8.0" - bn.js "^4.4.0" - compact2string "^1.2.0" - debug "^2.0.0" - hat "0.0.3" - inherits "^2.0.1" - ip "^1.0.1" - minimist "^1.1.1" - once "^1.3.0" - random-iterate "^1.0.1" - run-parallel "^1.1.2" - run-series "^1.0.2" - simple-get "^2.0.0" - simple-peer "^6.0.0" - simple-websocket "^4.0.0" - string2compact "^1.1.1" - uniq "^1.0.1" - ws "^1.0.0" - xtend "^4.0.0" - -bl@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -bn.js@^4.4.0: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bncode@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/bncode/-/bncode-0.2.3.tgz#37f851dc8e47188a83fbc0f6fa4775cacc9a3296" - integrity sha512-IXGfySD68R/J2X/it8GZqAM+Vb3ByZvAlUi0Gysq4ZACq6hXGQ3YshKo0QS/f3S9wOWKjJnEjP6x3ELxqBnAOA== - -bncode@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/bncode/-/bncode-0.5.3.tgz#e16661697452d436bf9886238cc791b08d66a61a" - integrity sha512-0P5VuWobU5Gwbeio8n9Jsdv0tE1IikrV9n4f7RsnXHNtxmdd/oeIO6QyoSEUAEyo5P6i3XMfBppi82WqNsT4JA== - -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== - -bottleneck@^2.19.5: - version "2.19.5" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" - integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.22.2: - version "4.22.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" - integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A== - dependencies: - caniuse-lite "^1.0.30001580" - electron-to-chromium "^1.4.648" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -bson@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/bson/-/bson-6.3.0.tgz#d47acba525ba7d7eb0e816c10538bce26a337fe0" - integrity sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw== - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA== - -buffer-equals@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/buffer-equals/-/buffer-equals-1.0.4.tgz#0353b54fd07fd9564170671ae6f66b9cf10d27f5" - integrity sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA== - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-more-ints@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz#ef4f8e2dddbad429ed3828a9c55d44f05c611422" - integrity sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg== - -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -cacache@^18.0.0: - version "18.0.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.2.tgz#fd527ea0f03a603be5c0da5805635f8eef00c60c" - integrity sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw== - dependencies: - "@npmcli/fs" "^3.1.0" - fs-minipass "^3.0.0" - glob "^10.2.2" - lru-cache "^10.0.1" - minipass "^7.0.3" - minipass-collect "^2.0.1" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - p-map "^4.0.0" - ssri "^10.0.0" - tar "^6.1.11" - unique-filename "^3.0.0" - -cache-manager@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/cache-manager/-/cache-manager-5.4.0.tgz#cec47dbea8e49e0f6970d117be10172b4e621358" - integrity sha512-FS7o8vqJosnLpu9rh2gQTo8EOzCRJLF1BJ4XDEUDMqcfvs7SJZs5iuoFTXLauzQ3S5v8sBAST1pCwMaurpyi1A== - dependencies: - lodash.clonedeep "^4.5.0" - lru-cache "^10.1.0" - promise-coalesce "^1.1.2" - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.6.tgz#6c46675fc7a5e9de82d75a233d586c8b7ac0d931" - integrity sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.3" - set-function-length "^1.2.0" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001580: - version "1.0.30001585" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz#0b4e848d84919c783b2a41c13f7de8ce96744401" - integrity sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -cheerio-select@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" - integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== - dependencies: - boolbase "^1.0.0" - css-select "^5.1.0" - css-what "^6.1.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - -cheerio@1.0.0-rc.12: - version "1.0.0-rc.12" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" - integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== - dependencies: - cheerio-select "^2.1.0" - dom-serializer "^2.0.0" - domhandler "^5.0.3" - domutils "^3.0.1" - htmlparser2 "^8.0.1" - parse5 "^7.0.0" - parse5-htmlparser2-tree-adapter "^7.0.0" - -chokidar@^3.4.2: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -chrome-dgram@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/chrome-dgram/-/chrome-dgram-3.0.6.tgz#2288b5c7471f66f073691206d36319dda713cf55" - integrity sha512-bqBsUuaOiXiqxXt/zA/jukNJJ4oaOtc7ciwqJpZVEaaXwwxqgI2/ZdG02vXYWUhHGziDlvGMQWk0qObgJwVYKA== - dependencies: - inherits "^2.0.4" - run-series "^1.1.9" - -chrome-dns@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chrome-dns/-/chrome-dns-1.0.1.tgz#6870af680a40d2c4b2efc2154a378793f5a4ce4b" - integrity sha512-HqsYJgIc8ljJJOqOzLphjAs79EUuWSX3nzZi2LNkzlw3GIzAeZbaSektC8iT/tKvLqZq8yl1GJu5o6doA4TRbg== - dependencies: - chrome-net "^3.3.2" - -chrome-net@^3.3.2: - version "3.3.4" - resolved "https://registry.yarnpkg.com/chrome-net/-/chrome-net-3.3.4.tgz#0e604a31d226ebfb8d2d1c381cab47d35309825d" - integrity sha512-Jzy2EnzmE+ligqIZUsmWnck9RBXLuUy6CaKyuNMtowFG3ZvLt8d+WBJCTPEludV0DHpIKjAOlwjFmTaEdfdWCw== - dependencies: - inherits "^2.0.1" - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-spinners@^2.5.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" - integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^2.0.7: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -compact2string@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/compact2string/-/compact2string-1.4.1.tgz#8d34929055f8300a13cfc030ad1832e2e53c2e25" - integrity sha512-3D+EY5nsRhqnOwDxveBv5T8wGo4DEvYxjDtPGmdOX+gfr5gE92c2RC0w2wa+xEefm07QuVqqcF3nZJUZ92l/og== - dependencies: - ipaddr.js ">= 0.1.5" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== - dependencies: - boolbase "^1.0.0" - css-what "^6.1.0" - domhandler "^5.0.2" - domutils "^3.0.1" - nth-check "^2.0.1" - -css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cyclist@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.1.1.tgz#1bcfa56b081448cdb5e12bfc1bfad34b47fba8f3" - integrity sha512-w8a8nQk9YSCkMmH2wDbFqpH1XMz7l409mSvWnnG6Iu6D0Ydhvq61XASE7QIaA46FxfG2Ag524ZuGgAy2cXPfsw== - -dateformat@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" - integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== - -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@^2.0.0, debug@^2.1.0, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== - dependencies: - mimic-response "^1.0.0" - -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge-ts@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" - integrity sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -defaults@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" - integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== - dependencies: - clone "^1.0.2" - -define-data-property@^1.0.1, define-data-property@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.2.tgz#f3c33b4f0102360cd7c0f5f28700f5678510b63a" - integrity sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g== - dependencies: - es-errors "^1.3.0" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diacritics@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" - integrity sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA== - -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-serializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.2" - entities "^4.2.0" - -domelementtype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^5.0.2, domhandler@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== - dependencies: - domelementtype "^2.3.0" - -domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== - dependencies: - dom-serializer "^2.0.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - -dottie@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4" - integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -electron-to-chromium@^1.4.648: - version "1.4.661" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.661.tgz#b28d63468b06e75610ed2b0f8e5f5f669a57bd91" - integrity sha512-AFg4wDHSOk5F+zA8aR+SVIOabu7m0e7BiJnigCvPXzIGy731XENw/lmNxTySpVFtkFEy+eyt4oHhh5FF3NjQNw== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -encoding@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - -end-of-stream@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - integrity sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw== - dependencies: - once "~1.3.0" - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -entities@^4.2.0, entities@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -err-code@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" - integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.22.1, es-abstract@^1.22.3: - version "1.22.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" - integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== - dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.2" - available-typed-arrays "^1.0.5" - call-bind "^1.0.5" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.2" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.12" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.1" - safe-array-concat "^1.0.1" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.8" - string.prototype.trimend "^1.0.7" - string.prototype.trimstart "^1.0.7" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.13" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-errors@^1.0.0, es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-set-tostringtag@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" - integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== - dependencies: - get-intrinsic "^1.2.2" - has-tostringtag "^1.0.0" - hasown "^2.0.0" - -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -esbuild@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.0.tgz#a7170b63447286cd2ff1f01579f09970e6965da4" - integrity sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.20.0" - "@esbuild/android-arm" "0.20.0" - "@esbuild/android-arm64" "0.20.0" - "@esbuild/android-x64" "0.20.0" - "@esbuild/darwin-arm64" "0.20.0" - "@esbuild/darwin-x64" "0.20.0" - "@esbuild/freebsd-arm64" "0.20.0" - "@esbuild/freebsd-x64" "0.20.0" - "@esbuild/linux-arm" "0.20.0" - "@esbuild/linux-arm64" "0.20.0" - "@esbuild/linux-ia32" "0.20.0" - "@esbuild/linux-loong64" "0.20.0" - "@esbuild/linux-mips64el" "0.20.0" - "@esbuild/linux-ppc64" "0.20.0" - "@esbuild/linux-riscv64" "0.20.0" - "@esbuild/linux-s390x" "0.20.0" - "@esbuild/linux-x64" "0.20.0" - "@esbuild/netbsd-x64" "0.20.0" - "@esbuild/openbsd-x64" "0.20.0" - "@esbuild/sunos-x64" "0.20.0" - "@esbuild/win32-arm64" "0.20.0" - "@esbuild/win32-ia32" "0.20.0" - "@esbuild/win32-x64" "0.20.0" - -esbuild@~0.19.10: - version "0.19.12" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" - integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== - optionalDependencies: - "@esbuild/aix-ppc64" "0.19.12" - "@esbuild/android-arm" "0.19.12" - "@esbuild/android-arm64" "0.19.12" - "@esbuild/android-x64" "0.19.12" - "@esbuild/darwin-arm64" "0.19.12" - "@esbuild/darwin-x64" "0.19.12" - "@esbuild/freebsd-arm64" "0.19.12" - "@esbuild/freebsd-x64" "0.19.12" - "@esbuild/linux-arm" "0.19.12" - "@esbuild/linux-arm64" "0.19.12" - "@esbuild/linux-ia32" "0.19.12" - "@esbuild/linux-loong64" "0.19.12" - "@esbuild/linux-mips64el" "0.19.12" - "@esbuild/linux-ppc64" "0.19.12" - "@esbuild/linux-riscv64" "0.19.12" - "@esbuild/linux-s390x" "0.19.12" - "@esbuild/linux-x64" "0.19.12" - "@esbuild/netbsd-x64" "0.19.12" - "@esbuild/openbsd-x64" "0.19.12" - "@esbuild/sunos-x64" "0.19.12" - "@esbuild/win32-arm64" "0.19.12" - "@esbuild/win32-ia32" "0.19.12" - "@esbuild/win32-x64" "0.19.12" - -escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-module-utils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" - integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== - dependencies: - debug "^3.2.7" - -eslint-plugin-import-helpers@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import-helpers/-/eslint-plugin-import-helpers-1.3.1.tgz#48721a702e758b5d2220ee119d6199e6e29b6819" - integrity sha512-MrACDozK6TmTJoCFHD71Ew3r5210Za3zlTrhX+fQGsyvxceaFvAI9AcvZ/8oSU0pZ61G3nDEn6mXY0T4S8cJEg== - -eslint-plugin-import@^2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.56.0: - version "8.56.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" - integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.56.0" - "@humanwhocodes/config-array" "^0.11.13" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -events@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.0.0, expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - -exponential-backoff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" - integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-copy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" - integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-redact@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634" - integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ== - -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fifo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/fifo/-/fifo-0.1.4.tgz#bf42d87c0ad07b00d0949d12388f6289606ece34" - integrity sha512-CpKgwraLo4YWY9cUEICNJ1WcOVR2WE1Jvot3Nvr7FGBiGOKgkn1CmF4zuCl9VxvEh1nQsdYXtQg+V0etPiED6g== - -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== - -flatten@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-0.0.1.tgz#554440766da0a0d603999f433453f6c2fc6a75c1" - integrity sha512-pzNZh42/A2HmcRIpddSP0T+zBofd119o5rNB2u1YHv36CM2C/ietI2ZsjWZ2LSL7J0BNVkFn1a9Ad+cmO2lDQg== - -follow-redirects@^1.15.4: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs-chunk-store@^1.3.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/fs-chunk-store/-/fs-chunk-store-1.7.0.tgz#1c4bcbe93c99af10aa04b65348f2bb27377a4010" - integrity sha512-KhjJmZAs2eqfhCb6PdPx4RcZtheGTz86tpTC5JTvqBn/xda+Nb+0C7dCyjOSN7T76H6a56LvH0SVXQMchLXDRw== - dependencies: - mkdirp "^0.5.1" - random-access-file "^2.0.1" - randombytes "^2.0.3" - rimraf "^2.4.2" - run-parallel "^1.1.2" - thunky "^1.0.1" - -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-minipass@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" - integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== - dependencies: - minipass "^7.0.3" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-browser-rtc@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz#d1494e299b00f33fc8e9d6d3343ba4ba99711a2c" - integrity sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce" - integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A== - dependencies: - resolve-pkg-maps "^1.0.0" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^10.2.2, glob@^10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^7.1.3, glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -google-sr-selectors@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/google-sr-selectors/-/google-sr-selectors-0.0.2.tgz#cbfdabe52d3216ba19dd0dc49d8b384e6bd000b7" - integrity sha512-7h+vo7NSDf+pZB/InDon4mwhXeTvy/9yvAChGnjppcdHgTwlUWDpYPWGUn781J3PrjBj6rZAginsSTGqG5uUZw== - -google-sr@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/google-sr/-/google-sr-3.2.1.tgz#1c9c454de7242b377c7d538b7570c7f754e79664" - integrity sha512-1WGy6mxMTKo+jbIrmq1mwm+2Egvmx9ttsXzCiR0Y2LMcpeG4shqc8C4g12msi4arRn9qEwG1qrFQ1W9jo3dDzw== - dependencies: - axios "^1.4.0" - cheerio "1.0.0-rc.12" - deepmerge-ts "^5.1.0" - google-sr-selectors "^0.0.2" - tslib "^2.6.1" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -graphql@^16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" - integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hat@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" - integrity sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug== - -headers-polyfill@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.2.tgz#9115a76eee3ce8fbf95b6e3c6bf82d936785b44a" - integrity sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw== - -help-me@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" - integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -htmlparser2@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" - integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - entities "^4.4.0" - -http-cache-semantics@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http-proxy-agent@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" - integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== - dependencies: - agent-base "^7.1.0" - debug "^4.3.4" - -https-proxy-agent@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" - integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== - dependencies: - agent-base "^7.0.2" - debug "4" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@^0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -ieee754@^1.1.13, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0, ignore@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -immediate-chunk-store@^1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/immediate-chunk-store/-/immediate-chunk-store-1.0.8.tgz#0ecdad0c546332672d7b5b511b26bb18ce56e73f" - integrity sha512-0tQyTytUaIUskpv5j5L5ZeQuEjYDl9QIekwDUisdqpAM81OZjBaEIriW7hoiRLaLNxj1fXE8e1yx5JaCGrrE7A== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflection@^1.13.4: - version "1.13.4" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" - integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inquirer@^8.2.0: - version "8.2.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" - integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.1" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^5.4.1" - run-async "^2.4.0" - rxjs "^7.5.5" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - wrap-ansi "^6.0.1" - -internal-slot@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -inversify@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-6.0.2.tgz#dc7fa0348213d789d35ffb719dea9685570989c7" - integrity sha512-i9m8j/7YIv4mDuYXUAcrpKPSaju/CIly9AHK5jvCBeoiM/2KEsuCQTTP+rzSWWpLYWRukdXFSl6ZTk2/uumbiA== - -ip-set@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ip-set/-/ip-set-1.0.2.tgz#be4f119f82c124836455993dfcd554639c7007de" - integrity sha512-Mb6kv78bTi4RNAIIWL8Bbre7hXOR2pNUi3j8FaQkLaitf/ZWxkq3/iIwXNYk2ACO3IMfdVdQrOkUtwZblO7uBA== - dependencies: - ip "^1.1.3" - -ip@^1.0.1, ip@^1.1.3: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" - integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== - -ip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== - -"ipaddr.js@>= 0.1.5", ipaddr.js@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== - -is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - -is-lambda@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-node-process@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" - integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.13, is-typed-array@^1.1.9: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isexe@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" - integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" - integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" - integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - -jest-util@^29.0.0, jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - -joycon@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -json5@^2.2.2, json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -k-bucket@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/k-bucket/-/k-bucket-0.6.0.tgz#afc532545f69d466293e887b00d5fc73377c3abb" - integrity sha512-1zJpqkrLYgolqdO1TE1/FWf+mHfhJKLC2Wpi4JaMFZKi4b6tFEn9/d+JqscBIJw5auWFewp16CSAEetFGEC4NQ== - dependencies: - buffer-equal "0.0.1" - inherits "^2.0.1" - -k-bucket@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/k-bucket/-/k-bucket-2.0.1.tgz#58cccb244f563326ba893bf5c06a35f644846daa" - integrity sha512-Xuye90xBBDJJbvNSuy3z/Yl8ceVX02/sopqGUEwJkMgRw+//TQXx0/Hbgp60GsoVfZcCBllQXXp6AWe2INu8pw== - dependencies: - buffer-equal "0.0.1" - randombytes "^2.0.3" - -k-rpc-socket@^1.5.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/k-rpc-socket/-/k-rpc-socket-1.11.1.tgz#f14b4b240a716c6cad7b6434b21716dbd7c7b0e8" - integrity sha512-8xtA8oqbZ6v1Niryp2/g4GxW16EQh5MvrUylQoOG+zcrDff5CKttON2XUXvMwlIHq4/2zfPVFiinAccJ+WhxoA== - dependencies: - bencode "^2.0.0" - chrome-dgram "^3.0.2" - chrome-dns "^1.0.0" - chrome-net "^3.3.2" - -k-rpc@^3.6.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/k-rpc/-/k-rpc-3.7.0.tgz#641f99b2825be34b6e7984f22b7962dc1a906c23" - integrity sha512-XFL8PatIToQ/qhSSAq9FSK73wk4fX4DcHqjnkvSCrWC59PV02Oj1KeYa3KnREAXgA1DlCSzcKjk7M8usnT/dUw== - dependencies: - buffer-equals "^1.0.3" - k-bucket "^2.0.0" - k-rpc-socket "^1.5.0" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -lru-cache@^10.0.1, lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lru@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/lru/-/lru-2.0.1.tgz#f979871e162e3f5ca254be46844c53d4c5364544" - integrity sha512-JGRd3IHM64MPsGVw1Mqbz2Y2HDIePqi/MLfPtdrkHQwvvJnSrS9b6gM3KS9PFR5xJnufXJczHHZSmGqfuII1ew== - dependencies: - inherits "^2.0.1" - -magnet-uri@^4.0.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-4.2.3.tgz#79cc6d65a00bb5b7ef5c25ae60ebbb5d9a7681a8" - integrity sha512-aHhR49CRBOq3BX6jQOBdGMXhNT2+9LIH3CCIwHlR+aFE8nWMfBD1aNYxfm2u2LsCOwvfPeyCsdIg9KXSwdsOLQ== - dependencies: - flatten "0.0.1" - thirty-two "^0.0.2" - xtend "^4.0.0" - -magnet-uri@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-6.2.0.tgz#10f7be050bf23452df210838239b118463c3eeff" - integrity sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ== - dependencies: - bep53-range "^1.1.0" - thirty-two "^1.0.2" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -make-error@1.x, make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -make-fetch-happen@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0" - integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A== - dependencies: - "@npmcli/agent" "^2.0.0" - cacache "^18.0.0" - http-cache-semantics "^4.1.1" - is-lambda "^1.0.1" - minipass "^7.0.2" - minipass-fetch "^3.0.0" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.3" - promise-retry "^2.0.1" - ssri "^10.0.0" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -memory-pager@^1.0.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" - integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -minimatch@9.0.3, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -minipass-collect@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" - integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== - dependencies: - minipass "^7.0.3" - -minipass-fetch@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" - integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== - dependencies: - minipass "^7.0.3" - minipass-sized "^1.0.3" - minizlib "^2.1.2" - optionalDependencies: - encoding "^0.1.13" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass-sized@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" - integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" - integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3: - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== - -minizlib@^2.1.1, minizlib@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - -mkdirp@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" - integrity sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg== - -mkdirp@^0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mkdirp@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -moment-timezone@^0.5.43: - version "0.5.45" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" - integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== - dependencies: - moment "^2.29.4" - -moment@^2.24.0, moment@^2.29.4, moment@^2.30.1: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - -mongodb-connection-string-url@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz#b4f87f92fd8593f3b9365f592515a06d304a1e9c" - integrity sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ== - dependencies: - "@types/whatwg-url" "^11.0.2" - whatwg-url "^13.0.0" - -mongodb@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.3.0.tgz#ec9993b19f7ed2ea715b903fcac6171c9d1d38ca" - integrity sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA== - dependencies: - "@mongodb-js/saslprep" "^1.1.0" - bson "^6.2.0" - mongodb-connection-string-url "^3.0.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -msw@^2.1.7: - version "2.1.7" - resolved "https://registry.yarnpkg.com/msw/-/msw-2.1.7.tgz#0d7872af286cc5f6621dc40a496f8da8308cd198" - integrity sha512-yTIYqEMqDSrdbVMrfmqP6rTKQsnIbglTvVmAHDWwNegyXPXRcV+RjsaFEqubRS266gwWCDLm9YdOkWSKLdDvJQ== - dependencies: - "@bundled-es-modules/cookie" "^2.0.0" - "@bundled-es-modules/statuses" "^1.0.1" - "@mswjs/cookies" "^1.1.0" - "@mswjs/interceptors" "^0.25.16" - "@open-draft/until" "^2.1.0" - "@types/cookie" "^0.6.0" - "@types/statuses" "^2.0.4" - chalk "^4.1.2" - chokidar "^3.4.2" - graphql "^16.8.1" - headers-polyfill "^4.0.2" - inquirer "^8.2.0" - is-node-process "^1.2.0" - outvariant "^1.4.2" - path-to-regexp "^6.2.0" - strict-event-emitter "^0.5.1" - type-fest "^4.9.0" - yargs "^17.7.2" - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -name-to-imdb@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/name-to-imdb/-/name-to-imdb-3.0.4.tgz#1395c27f5b8ee057320a6eee218a86bb3f829034" - integrity sha512-OVmDvWoAZso2eHxK51UK7TMIpUpM4LnI3KhvvZe+JkDatEda9WS3/YXZVQnand5skI38shoniOFcyrw08QsNeA== - dependencies: - diacritics "~1.3.0" - named-queue "^2.1.0" - needle "^1.1.2" - node-fetch "^2.2.0" - -named-queue@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/named-queue/-/named-queue-2.2.1.tgz#1814544553599d5a9e403d0dfa937a4ce0d1e6a7" - integrity sha512-ssW6R5DZza+ixfGgu+piZAqszqRViHNZjjazXknCWyRYZfRJkBmbSPd1nIcH29aejsyBNPNrn3AdMfB+qvb2Hw== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -needle@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-1.6.0.tgz#f52a5858972121618e002f8e6384cadac22d624f" - integrity sha512-ogVK1D/Cgemw2vM1KJN6B83DwcKbDepdkMNtVJcXIe+xoaCOdC+aJHzhEov7xjsY9S7rBIuHP59W1fLsbGqDhA== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - -negotiator@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -node-fetch@^2.2.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-gyp@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.1.tgz#205514fc19e5830fa991e4a689f9e81af377a966" - integrity sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg== - dependencies: - env-paths "^2.2.0" - exponential-backoff "^3.1.1" - glob "^10.3.10" - graceful-fs "^4.2.6" - make-fetch-happen "^13.0.0" - nopt "^7.0.0" - proc-log "^3.0.0" - semver "^7.3.5" - tar "^6.1.2" - which "^4.0.0" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -nopt@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" - integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== - dependencies: - abbrev "^2.0.0" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nth-check@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== - dependencies: - boolbase "^1.0.0" - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.fromentries@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" - integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.groupby@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" - integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== - dependencies: - array.prototype.filter "^1.0.3" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.0.0" - -object.values@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" - integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -obuf@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-exit-leak-free@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" - integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== - -once@^1.1.1, once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - integrity sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w== - dependencies: - wrappy "1" - -onetime@^5.1.0, onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" - integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== - -ora@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" - integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== - dependencies: - bl "^4.1.0" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.5.0" - is-interactive "^1.0.0" - is-unicode-supported "^0.1.0" - log-symbols "^4.1.0" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066" - integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ== - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-torrent-file@^2.0.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/parse-torrent-file/-/parse-torrent-file-2.1.4.tgz#32d4b6afde631420e5f415919a222b774b575707" - integrity sha512-u2MgLOjZPDDer1oRg1c+H/+54iIQYY5TKgQ5G8KrGLT1Dcwdo7Lj+QfQR123+u8J0AMSFGbQUvsBlSB7uIJcCA== - dependencies: - bencode "^0.7.0" - simple-sha1 "^2.0.0" - -"parse-torrent-title@https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654": - version "1.3.0" - resolved "https://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654" - dependencies: - moment "^2.24.0" - -parse-torrent@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/parse-torrent/-/parse-torrent-4.1.0.tgz#a814bd8505e8b58e88eb8ff3e2daff5d19a711b7" - integrity sha512-FeoGe8bOYmSzxO31kYy44A03FjuULCMOIMom8KyuGvO8/lLVPJyo2nr9CwH/iYmNHm74hk7h70o59DOfk9Rq+A== - dependencies: - magnet-uri "^4.0.0" - parse-torrent-file "^2.0.0" - -parse5-htmlparser2-tree-adapter@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" - integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== - dependencies: - domhandler "^5.0.2" - parse5 "^7.0.0" - -parse5@^7.0.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" - integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== - dependencies: - entities "^4.4.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-to-regexp@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" - integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -peer-wire-protocol@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/peer-wire-protocol/-/peer-wire-protocol-0.7.1.tgz#fdb4a75bfe6b3b84710eb5220ef0ebeed3b63396" - integrity sha512-V9oTa/ZcfNNz9fAST28Gg0fXbPeFPk3SBImsYO8GDDG5D0E195vxXmjZ+SPrzr4BJyMQmdDmwUfTf9MZ62z4mw== - dependencies: - bitfield "^0.1.0" - bncode "^0.2.3" - buffer-alloc "^1.1.0" - buffer-from "^1.0.0" - readable-stream "^1.0.2" - speedometer "^0.1.2" - -peer-wire-swarm@^0.12.0: - version "0.12.2" - resolved "https://registry.yarnpkg.com/peer-wire-swarm/-/peer-wire-swarm-0.12.2.tgz#d7120e083cbd42b1c41c961865e938e747428950" - integrity sha512-sIWZ1nTL9l6mI9J18kW1AeByBwagvNzGJlMmQA9pM+otKQtTIwnigK8SR0nEFrNZYqZelI6RQ6g4udvtQ2TI1g== - dependencies: - buffer-from "^1.0.0" - fifo "^0.1.4" - once "^1.1.1" - peer-wire-protocol "^0.7.0" - speedometer "^0.1.2" - utp "0.0.7" - -pg-cloudflare@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" - integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== - -pg-connection-string@^2.6.1, pg-connection-string@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475" - integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== - -pg-hstore@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.4.tgz#4425e3e2a3e15d2a334c35581186c27cf2e9b8dd" - integrity sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA== - dependencies: - underscore "^1.13.1" - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-numeric@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" - integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== - -pg-pool@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7" - integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og== - -pg-protocol@*, pg-protocol@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833" - integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg-types@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d" - integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== - dependencies: - pg-int8 "1.0.1" - pg-numeric "1.0.2" - postgres-array "~3.0.1" - postgres-bytea "~3.0.0" - postgres-date "~2.1.0" - postgres-interval "^3.0.0" - postgres-range "^1.1.1" - -pg@^8.11.3: - version "8.11.3" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb" - integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "^2.6.2" - pg-pool "^3.6.1" - pg-protocol "^1.6.0" - pg-types "^2.1.0" - pgpass "1.x" - optionalDependencies: - pg-cloudflare "^1.1.1" - -pgpass@1.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" - integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== - dependencies: - split2 "^4.1.0" - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8" - integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA== - dependencies: - readable-stream "^4.0.0" - split2 "^4.0.0" - -pino-pretty@^10.3.1: - version "10.3.1" - resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.3.1.tgz#e3285a5265211ac6c7cd5988f9e65bf3371a0ca9" - integrity sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g== - dependencies: - colorette "^2.0.7" - dateformat "^4.6.3" - fast-copy "^3.0.0" - fast-safe-stringify "^2.1.1" - help-me "^5.0.0" - joycon "^3.1.1" - minimist "^1.2.6" - on-exit-leak-free "^2.1.0" - pino-abstract-transport "^1.0.0" - pump "^3.0.0" - readable-stream "^4.0.0" - secure-json-parse "^2.4.0" - sonic-boom "^3.0.0" - strip-json-comments "^3.1.1" - -pino-std-serializers@^6.0.0: - version "6.2.2" - resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz#d9a9b5f2b9a402486a5fc4db0a737570a860aab3" - integrity sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA== - -pino@^8.18.0: - version "8.18.0" - resolved "https://registry.yarnpkg.com/pino/-/pino-8.18.0.tgz#f2bfbb4e827ed2049ee1e88372268efdcd1505f6" - integrity sha512-Mz/gKiRyuXu4HnpHgi1YWdHQCoWMufapzooisvFn78zl4dZciAxS+YeRkUxXl1ee/SzU80YCz1zpECCh4oC6Aw== - dependencies: - atomic-sleep "^1.0.0" - fast-redact "^3.1.1" - on-exit-leak-free "^2.1.0" - pino-abstract-transport v1.1.0 - pino-std-serializers "^6.0.0" - process-warning "^3.0.0" - quick-format-unescaped "^4.0.3" - real-require "^0.2.0" - safe-stable-stringify "^2.3.1" - sonic-boom "^3.7.0" - thread-stream "^2.0.0" - -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-array@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98" - integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== - -postgres-bytea@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089" - integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== - dependencies: - obuf "~1.1.2" - -postgres-date@~1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" - integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== - -postgres-date@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0" - integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -postgres-interval@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" - integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== - -postgres-range@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" - integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -pretty-format@^29.0.0, pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -proc-log@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" - integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process-warning@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" - integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -promise-coalesce@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/promise-coalesce/-/promise-coalesce-1.1.2.tgz#5d3bc4d0b2cf2e41e9df7cbeb6519b2a09459e3d" - integrity sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg== - -promise-retry@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" - integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== - dependencies: - err-code "^2.0.2" - retry "^0.12.0" - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^2.1.0, punycode@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -queue-tick@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" - integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== - -quick-format-unescaped@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" - integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== - -random-access-file@^2.0.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-2.2.1.tgz#071d086d8a92cc65abbd32b42aeba6d1d845d68d" - integrity sha512-RGU0xmDqdOyEiynob1KYSeh8+9c9Td1MJ74GT1viMEYAn8SJ9oBtWCXLsYZukCF46yududHOdM449uRYbzBrZQ== - dependencies: - mkdirp-classic "^0.5.2" - random-access-storage "^1.1.1" - -random-access-storage@^1.1.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/random-access-storage/-/random-access-storage-1.4.3.tgz#277d07005107562dfea84798eb9a6acd47d64b7f" - integrity sha512-D5e2iIC5dNENWyBxsjhEnNOMCwZZ64TARK6dyMN+3g4OTC4MJxyjh9hKLjTGoNhDOPrgjI+YlFEHFnrp/cSnzQ== - dependencies: - events "^3.3.0" - inherits "^2.0.3" - queue-tick "^1.0.0" - -random-iterate@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/random-iterate/-/random-iterate-1.0.1.tgz#f7d97d92dee6665ec5f6da08c7f963cad4b2ac99" - integrity sha512-Jdsdnezu913Ot8qgKgSgs63XkAjEsnMcS1z+cC6D6TNXsUXsMxy0RpclF2pzGZTEiTXL9BiArdGTEexcv4nqcA== - -randombytes@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -re-emitter@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/re-emitter/-/re-emitter-1.1.4.tgz#15bdefca3d47e05d6442838fd26759c8a4eaa236" - integrity sha512-C0SIXdXDSus2yqqvV7qifnb4NoWP7mEBXJq3axci301mXHCZb8Djwm4hrEZo4UeXRaEnfjH98uQ8EBppk2oNWA== - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -"readable-stream@1.x >=1.1.9", readable-stream@^1.0.2: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.5: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" - integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -real-require@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" - integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== - -reflect-metadata@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.1.tgz#8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74" - integrity sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw== - -regexp.prototype.flags@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" - integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - set-function-name "^2.0.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - -resolve@^1.20.0, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -retry-as-promised@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" - integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.2.5, rimraf@^2.4.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel@^1.1.2, run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -run-series@^1.0.2, run-series@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.9.tgz#15ba9cb90e6a6c054e67c98e1dc063df0ecc113a" - integrity sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g== - -rusha@^0.8.1: - version "0.8.14" - resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68" - integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA== - -rxjs@^7.5.5: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - -safe-array-concat@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" - integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg== - dependencies: - call-bind "^1.0.5" - get-intrinsic "^1.2.2" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" - integrity sha512-cr7dZWLwOeaFBLTIuZeYdkfO7UzGIKhjYENJFAxUOMKWGaWDm2nJM2rzxNRm5Owu0DH3ApwNo6kx5idXZfb/Iw== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-regex-test@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -safe-stable-stringify@^2.3.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -secure-json-parse@^2.4.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" - integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== - -semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - -sequelize-pool@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-7.1.0.tgz#210b391af4002762f823188fd6ecfc7413020768" - integrity sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg== - -sequelize-typescript@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/sequelize-typescript/-/sequelize-typescript-2.1.6.tgz#9476c8a2510114ed1c3a26b424c47e05c2e6284e" - integrity sha512-Vc2N++3en346RsbGjL3h7tgAl2Y7V+2liYTAOZ8XL0KTw3ahFHsyAUzOwct51n+g70I1TOUDgs06Oh6+XGcFkQ== - dependencies: - glob "7.2.0" - -sequelize@^6.36.0: - version "6.36.0" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.36.0.tgz#b824cf2b3b2914a5ee9996f23ff703807f68ec4a" - integrity sha512-PqOa11EHwA/zLmGDU4aynbsavbHJUlgRvFuC/2cA4LhOuV6NHKcQ0IXB+hNdFrGT3rULmvc4kdIwnfCNsrECMQ== - dependencies: - "@types/debug" "^4.1.8" - "@types/validator" "^13.7.17" - debug "^4.3.4" - dottie "^2.0.6" - inflection "^1.13.4" - lodash "^4.17.21" - moment "^2.29.4" - moment-timezone "^0.5.43" - pg-connection-string "^2.6.1" - retry-as-promised "^7.0.4" - semver "^7.5.4" - sequelize-pool "^7.1.0" - toposort-class "^1.0.1" - uuid "^8.3.2" - validator "^13.9.0" - wkx "^0.5.0" - -set-function-length@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" - integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== - dependencies: - define-data-property "^1.1.2" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -set-function-name@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" - integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== - dependencies: - define-data-property "^1.0.1" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" - integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^2.0.0: - version "2.8.2" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" - integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" - -simple-peer@^6.0.0: - version "6.4.4" - resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-6.4.4.tgz#4e421f485ac7b13b08077a4476934d52c5ba3bb3" - integrity sha512-sY35UHankz0ba02Dd8YzdyXhEeTAnW6ZUyDfKOSwUht1GLp9VuMT4jQUXF/wG7C9vpwvitV7Ig7a6IkY/qizwg== - dependencies: - debug "^2.1.0" - get-browser-rtc "^1.0.0" - inherits "^2.0.1" - randombytes "^2.0.3" - readable-stream "^2.0.5" - -simple-sha1@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/simple-sha1/-/simple-sha1-2.1.2.tgz#de40cbd5aae278fde8e3bb3250a35d74c67326b1" - integrity sha512-TQl9rm4rdKAVmhO++sXAb8TNN0D6JAD5iyI1mqEPNpxUzTRrtm4aOG1pDf/5W/qCFihiaoK6uuL9rvQz1x1VKw== - dependencies: - rusha "^0.8.1" - -simple-websocket@^4.0.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/simple-websocket/-/simple-websocket-4.3.1.tgz#5d3d5751bb39aeba2f710d8eec78768df821f38d" - integrity sha512-knEO6ub2Pw00c7ueOV6snKE1hr7jIdY068+239v0I8DVKofyd7IQmYHXrM9pZL1zuI0H7sd+Y5kedndBi5GXIA== - dependencies: - debug "^2.1.3" - inherits "^2.0.1" - randombytes "^2.0.3" - readable-stream "^2.0.5" - ws "^2.0.0" - xtend "^4.0.1" - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" - integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g== - dependencies: - agent-base "^7.0.2" - debug "^4.3.4" - socks "^2.7.1" - -socks@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" - integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== - dependencies: - ip "^2.0.0" - smart-buffer "^4.2.0" - -sonic-boom@^3.0.0, sonic-boom@^3.7.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66" - integrity sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA== - dependencies: - atomic-sleep "^1.0.0" - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sparse-bitfield@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" - integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== - dependencies: - memory-pager "^1.0.2" - -speedometer@^0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" - integrity sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q== - -split2@^4.0.0, split2@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" - integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -ssri@^10.0.0: - version "10.0.5" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" - integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== - dependencies: - minipass "^7.0.3" - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -statuses@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -strict-event-emitter@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" - integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.trim@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" - integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimend@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" - integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimstart@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" - integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string2compact@^1.1.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/string2compact/-/string2compact-1.3.2.tgz#c9d11a13f368404b8025425cc53f9916de1d0b8b" - integrity sha512-3XUxUgwhj7Eqh2djae35QHZZT4mN3fsO7kagZhSGmhhlrQagVvWSFuuFIWnpxFS0CdTB2PlQcaL16RDi14I8uw== - dependencies: - addr-to-ip-port "^1.0.1" - ipaddr.js "^2.0.0" - -string_decoder@^1.1.1, string_decoder@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tar@^6.1.11, tar@^6.1.2: - version "6.2.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" - integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thirty-two@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-0.0.2.tgz#4253e29d8cb058f0480267c5698c0e4927e54b6a" - integrity sha512-0j1A9eqbP8dSEtkqqEJGpYFN2lPgQR1d0qKS2KNAmIxkK6gV37D5hRa5b/mYzVL1fyAVWBkeUDIXybZdCLVBzA== - -thirty-two@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a" - integrity sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA== - -thread-stream@^2.0.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.1.tgz#6d588b14f0546e59d3f306614f044bc01ce43351" - integrity sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg== - dependencies: - real-require "^0.2.0" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -thunky@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toposort-class@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" - integrity sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg== - -torrent-discovery@^5.2.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/torrent-discovery/-/torrent-discovery-5.4.0.tgz#2d17d82cf669ada7f9dfe75db4b31f7034b71e29" - integrity sha512-bPTDIA7XEjRlw6vQyt7kM/h1mg1INBsibjbujISITonx4POENZgxfyCSEXZpDhbAkluSPH4HKRKs4/YTmNLC6w== - dependencies: - bittorrent-dht "^6.0.0" - bittorrent-tracker "^7.0.0" - debug "^2.0.0" - inherits "^2.0.1" - re-emitter "^1.0.0" - run-parallel "^1.1.2" - xtend "^4.0.0" - -torrent-piece@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/torrent-piece/-/torrent-piece-1.1.2.tgz#774cadac08f65e3d55b84610842171365e349dc6" - integrity sha512-ElXPyXKKG73o+uziHJ8qlYE9EuyDVxnK2zWL+pW/2bma7RsLpSwFFIJAb8Qui7/tel2hsHQW1z3zBnfQNREpWA== - -torrent-stream@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/torrent-stream/-/torrent-stream-1.2.1.tgz#b0add8d5ad2367daeb5a4ddc02bb3203dccf9c9b" - integrity sha512-F+3tYmXnpO2gyhZQ7o8yakELJH3FtKISI/FU0iWvchOWFUXiFnjbEBoumSzfcK1P71Qxzx2az4lVK4Dkq4KSew== - dependencies: - bitfield "^0.1.0" - bncode "^0.5.2" - buffer-from "^1.0.0" - end-of-stream "^0.1.4" - fs-chunk-store "^1.3.0" - hat "0.0.3" - immediate-chunk-store "^1.0.5" - ip-set "^1.0.0" - mkdirp "^0.3.5" - parse-torrent "^4.0.0" - peer-wire-swarm "^0.12.0" - rimraf "^2.2.5" - torrent-discovery "^5.2.0" - torrent-piece "^1.0.0" - -tr46@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" - integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== - dependencies: - punycode "^2.3.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -ts-api-utils@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" - integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== - -ts-jest@^29.1.2: - version "29.1.2" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" - integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" - -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tsconfig-paths@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" - integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== - dependencies: - json5 "^2.2.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^2.1.0, tslib@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tsx@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.0.tgz#1689cfe7dda495ca1f9a66d4cad79cb57b9f6f4a" - integrity sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg== - dependencies: - esbuild "~0.19.10" - get-tsconfig "^4.7.2" - optionalDependencies: - fsevents "~2.3.3" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^4.9.0: - version "4.10.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.10.2.tgz#3abdb144d93c5750432aac0d73d3e85fcab45738" - integrity sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw== - -typed-array-buffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz#0608ffe6bca71bf15a45bff0ca2604107a1325f5" - integrity sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" - integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - -typescript@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== - -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - integrity sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow== - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -underscore@^1.13.1: - version "1.13.6" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" - integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== - -unique-filename@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" - integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== - dependencies: - unique-slug "^4.0.0" - -unique-slug@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" - integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== - dependencies: - imurmurhash "^0.1.4" - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-parse@~1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utp@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/utp/-/utp-0.0.7.tgz#ae43eb7745f5fe63dcc2f277cb4164ad27087f30" - integrity sha512-2ZLjisH0HQkpqZTg2m7TK0Yn7TETTg7DxM0EpCKIIIV2ky9w9nSxW5a7gzdk4nH2h+pomrrGw0uywrUJfsm2eA== - dependencies: - cyclist "~0.1.0" - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - -validator@^13.9.0: - version "13.11.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" - integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -webidl-conversions@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" - integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== - -whatwg-url@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-13.0.0.tgz#b7b536aca48306394a34e44bda8e99f332410f8f" - integrity sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig== - dependencies: - tr46 "^4.1.1" - webidl-conversions "^7.0.0" - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.13, which-typed-array@^1.1.14: - version "1.1.14" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.14.tgz#1f78a111aee1e131ca66164d8bdc3ab062c95a06" - integrity sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg== - dependencies: - available-typed-arrays "^1.0.6" - call-bind "^1.0.5" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.1" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -which@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" - integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== - dependencies: - isexe "^3.1.1" - -wkx@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c" - integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg== - dependencies: - "@types/node" "*" - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -ws@^1.0.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" - integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== - dependencies: - options ">=0.0.5" - ultron "1.0.x" - -ws@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" - integrity sha512-61a+9LgtYZxTq1hAonhX8Xwpo2riK4IOR/BIVxioFbCfc3QFKmpE4x9dLExfLHKtUfVZigYa36tThVhO57erEw== - dependencies: - safe-buffer "~5.0.1" - ultron "~1.1.0" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.0.1, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1, yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 82cf9762738346d2346d76fea4907aeca23370c1 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 18:01:28 +0000 Subject: [PATCH 42/55] start adding metadata tests --- src/node/consumer/jest.config.cjs | 6 +- .../src/lib/interfaces/cache_service.ts | 1 + .../src/lib/interfaces/logging_service.ts | 4 + .../src/lib/services/logging_service.ts | 1 + .../src/lib/services/metadata_service.ts | 15 +- .../lib/services/torrent_download_service.ts | 12 +- .../lib/services/torrent_entries_service.ts | 49 +- .../src/lib/services/torrent_file_service.ts | 32 +- .../lib/services/torrent_subtitle_service.ts | 4 +- .../test/assets/cinemeta-query-response.json | 21006 ++++++++++++++++ .../test/assets/flash-episode-list.json | 232 + .../test/assets/kitsu-naruto-full.json | 2491 ++ .../test/assets/name-to-imdb-flash.json | 111 + .../test/assets/test-cinemata-theflash.json | 373 + .../assets/test-kitsu-search-id-naruto.json | 1060 + src/node/consumer/test/cache_service.test.ts | 12 +- .../test/configuration_service.test.ts | 22 +- .../consumer/test/logging_service.test.ts | 20 +- .../consumer/test/metadata_service.test.ts | 91 + .../mock-responses/metadata_mock_responses.ts | 40 + .../mock-responses/trackers_mock_responses.ts | 5 + .../consumer/test/process_torrent_job.test.ts | 16 +- .../test/torrent_download_service.test.ts | 12 +- .../consumer/test/tracker_service.test.ts | 22 +- src/node/consumer/tsconfig.json | 49 +- 25 files changed, 25567 insertions(+), 119 deletions(-) create mode 100644 src/node/consumer/test/assets/cinemeta-query-response.json create mode 100644 src/node/consumer/test/assets/flash-episode-list.json create mode 100644 src/node/consumer/test/assets/kitsu-naruto-full.json create mode 100644 src/node/consumer/test/assets/name-to-imdb-flash.json create mode 100644 src/node/consumer/test/assets/test-cinemata-theflash.json create mode 100644 src/node/consumer/test/assets/test-kitsu-search-id-naruto.json create mode 100644 src/node/consumer/test/metadata_service.test.ts create mode 100644 src/node/consumer/test/mock-responses/metadata_mock_responses.ts create mode 100644 src/node/consumer/test/mock-responses/trackers_mock_responses.ts diff --git a/src/node/consumer/jest.config.cjs b/src/node/consumer/jest.config.cjs index fa0bd7c..8611f31 100644 --- a/src/node/consumer/jest.config.cjs +++ b/src/node/consumer/jest.config.cjs @@ -1,10 +1,10 @@ -const { pathsToModuleNameMapper } = require('ts-jest'); -const { compilerOptions } = require('./tsconfig.json'); +const {pathsToModuleNameMapper} = require('ts-jest'); +const {compilerOptions} = require('./tsconfig.json'); module.exports = { preset: 'ts-jest', testEnvironment: 'node', - moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/src/' }), + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {prefix: '/src/'}), modulePaths: [ '' ], diff --git a/src/node/consumer/src/lib/interfaces/cache_service.ts b/src/node/consumer/src/lib/interfaces/cache_service.ts index 40d56c6..962de97 100644 --- a/src/node/consumer/src/lib/interfaces/cache_service.ts +++ b/src/node/consumer/src/lib/interfaces/cache_service.ts @@ -7,4 +7,5 @@ export interface ICacheService { cacheWrapMetadata: (id: string, method: CacheMethod) => Promise; cacheTrackers: (method: CacheMethod) => Promise; } + /* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/logging_service.ts b/src/node/consumer/src/lib/interfaces/logging_service.ts index d980b22..19a365e 100644 --- a/src/node/consumer/src/lib/interfaces/logging_service.ts +++ b/src/node/consumer/src/lib/interfaces/logging_service.ts @@ -1,8 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ export interface ILoggingService { info(message: string, ...args: any[]): void; + error(message: string, ...args: any[]): void; + debug(message: string, ...args: any[]): void; + warn(message: string, ...args: any[]): void; } + /* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index 5b2837d..3eef3b8 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -29,4 +29,5 @@ export class LoggingService implements ILoggingService { this.logger.warn(message, args); }; } + /* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index b669339..0faeb4d 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -70,8 +70,15 @@ export class MetadataService implements IMetadataService { const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; const metaType = query.type === TorrentType.Movie ? TorrentType.Movie : TorrentType.Series; - return this.cacheService.cacheWrapMetadata(key.toString(), () => this.requestKitsuMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) - .catch(() => this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/${metaType}/${key}.json`)) + const isImdbId = Boolean(key.toString().match(/^tt\d+$/)); + + return this.cacheService.cacheWrapMetadata(key.toString(), () => { + switch (isImdbId) { + case true: + return this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/imdb/${key}.json`); + default: + return this.requestKitsuMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + }}) .catch(() => { // try different type in case there was a mismatch const otherType = metaType === TorrentType.Movie ? TorrentType.Series : TorrentType.Movie; @@ -79,7 +86,7 @@ export class MetadataService implements IMetadataService { }) .catch((error) => { throw new Error(`failed metadata query ${key} due: ${error.message}`); - })); + }); }; public isEpisodeImdbId = async (imdbId: string | undefined): Promise => { @@ -174,7 +181,7 @@ export class MetadataService implements IMetadataService { .filter(entry => entry.season !== null && entry.season !== 0 && entry.episode !== 0) .sort((a, b) => (a.season || 0) - (b.season || 0)) .reduce((map: Record, next) => { - if(next.season || next.season === 0) { + if (next.season || next.season === 0) { map[next.season] = (map[next.season] || 0) + 1; } return map; diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 3729fae..79bfb63 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -62,7 +62,8 @@ export class TorrentDownloadService implements ITorrentDownloadService { this.logger.debug(`Adding torrent with infoHash ${torrent.infoHash} to torrent engine...`); const timeoutId = setTimeout(() => { - engine.destroy(() => {}); + engine.destroy(() => { + }); reject(new Error('No available connections for torrent!')); }, timeout); @@ -78,7 +79,8 @@ export class TorrentDownloadService implements ITorrentDownloadService { resolve(files); clearTimeout(timeoutId); - engine.destroy(() => {}); + engine.destroy(() => { + }); }); }); }; @@ -94,13 +96,13 @@ export class TorrentDownloadService implements ITorrentDownloadService { const minRedundantRatio = videos.length <= 3 ? 30 : Number.MAX_VALUE; const isSample = (video: ITorrentFile): boolean => video.path?.toString()?.match(/sample|bonus|promo/i) && maxSize / video.length > minSampleRatio || false; - const isRedundant = (video: ITorrentFile):boolean => maxSize / video.length > minRedundantRatio; + const isRedundant = (video: ITorrentFile): boolean => maxSize / video.length > minRedundantRatio; const isExtra = (video: ITorrentFile): boolean => /extras?\//i.test(video.path?.toString() || ""); const isAnimeExtra = (video: ITorrentFile): boolean => { if (!video.path || !video.length) { return false; } - + return video.path.toString()?.match(/(?:\b|_)(?:NC)?(?:ED|OP|PV)(?:v?\d\d?)?(?:\b|_)/i) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio || false; }; @@ -108,7 +110,7 @@ export class TorrentDownloadService implements ITorrentDownloadService { if (!video.path || !video.length) { return false; } - + return video.path.toString()?.match(/^[A-Z-]+(?:\.[A-Z]+)?\.\w{3,4}$/) && maxSize / parseInt(video.length.toString()) > minAnimeExtraRatio || false; } diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 769510e..17124d5 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -45,7 +45,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { this.logger.warn(`No title found for ${torrent.provider} [${torrent.infoHash}]`); return; } - + const titleInfo = parse(torrent.title); if (!torrent.imdbId && torrent.type !== TorrentType.Anime) { @@ -98,7 +98,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { contents: fileCollection.contents, subtitles: fileCollection.subtitles }); - + return this.repository.createTorrent(newTorrent) .then(() => PromiseHelpers.sequence(fileCollection.videos!.map(video => () => { const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; @@ -110,22 +110,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); }; - private assignKitsuId = async (kitsuQuery: IMetaDataQuery, torrent: IParsedTorrent): Promise => { - await this.metadataService.getKitsuId(kitsuQuery) - .then((result: number | Error) => { - if (typeof result === 'number') { - torrent.kitsuId = result; - } else { - torrent.kitsuId = 0; - } - }) - .catch((error: Error) => { - this.logger.debug(`Failed getting kitsuId for ${torrent.title}`, error.message); - torrent.kitsuId = 0; - }); - }; - - public createSkipTorrentEntry: (torrent: Torrent) => Promise<[SkipTorrent, boolean | null]> = async (torrent: Torrent)=> this.repository.createSkipTorrent(torrent.dataValues); + public createSkipTorrentEntry: (torrent: Torrent) => Promise<[SkipTorrent, boolean | null]> = async (torrent: Torrent) => this.repository.createSkipTorrent(torrent.dataValues); public getStoredTorrentEntry = async (torrent: Torrent): Promise => this.repository.getSkipTorrent(torrent.infoHash) .catch(() => this.repository.getTorrent(torrent.dataValues)) @@ -156,7 +141,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { await existingTorrent.save(); this.logger.debug(`Updated [${existingTorrent.infoHash}] ${existingTorrent.title} language to ${torrent.languages}`); } - + return this.createTorrentContents(existingTorrent) .then(() => this.updateTorrentSeeders(existingTorrent.dataValues)) .then(() => Promise.resolve(true)) @@ -177,7 +162,10 @@ export class TorrentEntriesService implements ITorrentEntriesService { const kitsuId: number = PromiseHelpers.mostCommonValue(storedVideos.map(stored => stored.kitsuId || 0)); const fileCollection: ITorrentFileCollection = await this.fileService.parseTorrentFiles(torrent) - .then(torrentContents => notOpenedVideo ? torrentContents : {...torrentContents, videos: storedVideos.map(video => video.dataValues)}) + .then(torrentContents => notOpenedVideo ? torrentContents : { + ...torrentContents, + videos: storedVideos.map(video => video.dataValues) + }) .then(torrentContents => this.subtitleService.assignSubtitles(torrentContents)) .then(torrentContents => this.assignMetaIds(torrentContents, imdbId, kitsuId)) .catch(error => { @@ -230,13 +218,13 @@ export class TorrentEntriesService implements ITorrentEntriesService { if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { return [0]; } - + if (torrent.seeders === undefined) { this.logger.warn(`Seeders not found for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`); return [0]; } - - + + return this.repository.setTorrentSeeders(torrent, torrent.seeders) .catch(error => { this.logger.warn('Failed updating seeders:', error); @@ -244,6 +232,21 @@ export class TorrentEntriesService implements ITorrentEntriesService { }); }; + private assignKitsuId = async (kitsuQuery: IMetaDataQuery, torrent: IParsedTorrent): Promise => { + await this.metadataService.getKitsuId(kitsuQuery) + .then((result: number | Error) => { + if (typeof result === 'number') { + torrent.kitsuId = result; + } else { + torrent.kitsuId = 0; + } + }) + .catch((error: Error) => { + this.logger.debug(`Failed getting kitsuId for ${torrent.title}`, error.message); + torrent.kitsuId = 0; + }); + }; + private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string | undefined, kitsuId: number): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 61a800a..5d40160 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -45,7 +45,7 @@ export class TorrentFileService implements ITorrentFileService { if (!torrent.title) { return Promise.reject(new Error('Torrent title is missing')); } - + const parsedTorrentName = parse(torrent.title); const query: IMetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, @@ -54,7 +54,7 @@ export class TorrentFileService implements ITorrentFileService { const metadata = await this.metadataService.getMetadata(query) .then(meta => Object.assign({}, meta)) .catch(() => undefined); - + if (metadata === undefined || metadata instanceof Error) { return Promise.reject(new Error('Failed to retrieve metadata')); } @@ -83,14 +83,14 @@ export class TorrentFileService implements ITorrentFileService { if (torrent.type === TorrentType.Movie) { return parsedInfo.complete || typeof parsedInfo.year === 'string' || /movies/i.test(torrent.title); } - + const hasMultipleEpisodes = Boolean(parsedInfo.complete || torrent.size || 0 > MULTIPLE_FILES_SIZE || (parsedInfo.seasons && parsedInfo.seasons.length > 1) || (parsedInfo.episodes && parsedInfo.episodes.length > 1) || (parsedInfo.seasons && !parsedInfo.episodes)); const hasSingleEpisode: boolean = Boolean(Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date)); - + return hasMultipleEpisodes && !hasSingleEpisode; }; @@ -107,7 +107,7 @@ export class TorrentFileService implements ITorrentFileService { if (fileCollection.videos === undefined || fileCollection.videos.length === 0) { return {...fileCollection, videos: this.getDefaultFileEntries(torrent)}; } - + const filteredVideos = fileCollection.videos .filter(video => video.size! > MIN_SIZE) .filter(video => !this.isFeaturette(video)); @@ -118,7 +118,7 @@ export class TorrentFileService implements ITorrentFileService { title: video.path || video.title || video.fileName || '', size: video.size || torrent.size, imdbId: torrent.imdbId?.toString() || metadata && metadata.imdbId?.toString(), - kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString() || '0') + kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString() || '0') })); return {...fileCollection, videos: parsedVideos}; } @@ -141,7 +141,7 @@ export class TorrentFileService implements ITorrentFileService { if (fileCollection.videos === undefined || fileCollection.videos.length === 0) { return {...fileCollection, videos: this.getDefaultFileEntries(torrent)}; } - + const parsedVideos: IFileAttributes[] = await Promise.resolve(fileCollection.videos) .then(videos => videos.filter(video => videos?.length === 1 || video.size! > MIN_SIZE)) .then(videos => this.parseSeriesVideos(torrent, videos)) @@ -169,7 +169,7 @@ export class TorrentFileService implements ITorrentFileService { if (files.contents && files.contents.length && !files.videos?.length && this.isDiskTorrent(files.contents)) { files.videos = this.getDefaultFileEntries(torrent); } - + return files; }; @@ -269,7 +269,7 @@ export class TorrentFileService implements ITorrentFileService { }]; }; - private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = {episodeCount: []}):Promise => { + private decomposeEpisodes = async (torrent: IParsedTorrent, files: IFileAttributes[], metadata: IMetadataResponse = {episodeCount: []}): Promise => { if (files.every(file => !file.episodes && !file.date)) { return files; } @@ -370,7 +370,7 @@ export class TorrentFileService implements ITorrentFileService { private isNewEpisodeNotInMetadata = (torrent: IParsedTorrent, video: IFileAttributes, metadata: IMetadataResponse): boolean => { const isAnime = torrent.type === TorrentType.Anime && torrent.kitsuId; - return !!( !isAnime && !video.isMovie && video.episodes && video.season !== 1 + return !!(!isAnime && !video.isMovie && video.episodes && video.season !== 1 && metadata.status && /continuing|current/i.test(metadata.status) && metadata.episodeCount && video.season && video.season >= metadata.episodeCount.length && video.episodes.every(ep => metadata.episodeCount && video.season && ep > (metadata.episodeCount[video.season - 1] || 0))); @@ -410,9 +410,9 @@ export class TorrentFileService implements ITorrentFileService { return !file.season || (metadata.episodeCount[file.season - 1] || 0) < file.episodes[0]; }) .forEach(file => { - if(!file.episodes || !metadata.episodeCount) return; + if (!file.episodes || !metadata.episodeCount) return; - let seasonIdx = metadata.episodeCount + let seasonIdx = metadata.episodeCount .map((_, i) => i) .find(i => metadata.episodeCount && file.episodes && metadata.episodeCount.slice(0, i + 1).reduce((a, b) => a + b) >= file.episodes[0]); @@ -609,7 +609,7 @@ export class TorrentFileService implements ITorrentFileService { }) }; - private findMovieImdbId = (title: IFileAttributes | string):Promise => { + private findMovieImdbId = (title: IFileAttributes | string): Promise => { const parsedTitle = typeof title === 'string' ? parse(title) : title; this.logger.debug(`Finding movie imdbId for ${title}`); return this.imdb_limiter.schedule(async () => { @@ -626,7 +626,7 @@ export class TorrentFileService implements ITorrentFileService { }); }; - private findMovieKitsuId = async (title: IFileAttributes | string):Promise => { + private findMovieKitsuId = async (title: IFileAttributes | string): Promise => { const parsedTitle = typeof title === 'string' ? parse(title) : title; const kitsuQuery = { title: parsedTitle.title, @@ -645,10 +645,10 @@ export class TorrentFileService implements ITorrentFileService { private isSingleMovie = (videos: IFileAttributes[]): boolean => videos.length === 1 || (videos.length === 2 && - videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path!)) && + videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?1\b|^0?1\.\w{2,4}$/i.test(v.path!)) && videos.find(v => /\b(?:part|disc|cd)[ ._-]?0?2\b|^0?2\.\w{2,4}$/i.test(v.path!))) !== undefined; - private isFeaturette = (video: IFileAttributes):boolean => /featurettes?\/|extras-grym/i.test(video.path!); + private isFeaturette = (video: IFileAttributes): boolean => /featurettes?\/|extras-grym/i.test(video.path!); private parseSeriesVideo = (video: IFileAttributes): IFileAttributes => { const videoInfo = parse(video.title); diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index 776bbbd..dccede4 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -40,7 +40,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { }; } - private mostProbableSubtitleVideos = (subtitle: ISubtitleAttributes, parsedVideos: IFileAttributes[]) : IFileAttributes[] => { + private mostProbableSubtitleVideos = (subtitle: ISubtitleAttributes, parsedVideos: IFileAttributes[]): IFileAttributes[] => { const subTitle = (subtitle.title || subtitle.path)?.split('/')?.pop()?.replace(/\.(\w{2,4})$/, '') || ''; const parsedSub = this.parsePath(subtitle.title || subtitle.path); const byFileName = parsedVideos.filter(video => subTitle.includes(video.title!)); @@ -79,7 +79,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return parsedWithEpisode || pathParts[pathParts.length - 1]; } - private parseFilename = (filename: string) : IFileAttributes => { + private parseFilename = (filename: string): IFileAttributes => { const parsedInfo = parse(filename) const titleEpisode = parsedInfo.title.match(/(\d+)$/); if (!parsedInfo.episodes && titleEpisode) { diff --git a/src/node/consumer/test/assets/cinemeta-query-response.json b/src/node/consumer/test/assets/cinemeta-query-response.json new file mode 100644 index 0000000..8b573d4 --- /dev/null +++ b/src/node/consumer/test/assets/cinemeta-query-response.json @@ -0,0 +1,21006 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "_id": "53677f0c847ccc8123a19216", + "imdb_id": "tt3444938", + "name": "The Tonight Show Starring Jimmy Fallon", + "type": "series", + "year": "2014–" + }, + { + "_id": "5507880b711bd19c92ade25c", + "imdb_id": "tt0075474", + "name": "The Old Fox", + "year": "1977–", + "type": "series" + }, + { + "_id": "53677f74847ccc8123a23737", + "imdb_id": "tt3513388", + "name": "Late Night with Seth Meyers", + "type": "series", + "year": "2014–" + }, + { + "_id": "54b28a0b8527d2e0cb50620a", + "imdb_id": "tt3697842", + "name": "The Late Show with Stephen Colbert", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f00847ccc8123a16293", + "imdb_id": "tt2057880", + "name": "Watch What Happens Live with Andy Cohen", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677f05847ccc8123a17631", + "imdb_id": "tt0056751", + "name": "Doctor Who", + "type": "series", + "year": "1963–1989" + }, + { + "_id": "53677efa847ccc8123a1483c", + "imdb_id": "tt0098904", + "name": "Seinfeld", + "type": "series", + "year": "1989–1998" + }, + { + "_id": "5d78fd7dc4ccb5dd92e4d7e2", + "imdb_id": "tt9022950", + "name": "The Kelly Clarkson Show", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef5847ccc8123a1374f", + "imdb_id": "tt0247082", + "name": "CSI: Crime Scene Investigation", + "type": "series", + "year": "2000–2015" + }, + { + "_id": "53677f35847ccc8123a1eabe", + "imdb_id": "tt0121220", + "name": "Dragon Ball Z", + "type": "series", + "year": "1989–1996" + }, + { + "_id": "53677efc847ccc8123a15331", + "imdb_id": "tt0118480", + "name": "Stargate SG-1", + "type": "series", + "year": "1997–2007" + }, + { + "_id": "53677f29847ccc8123a1df0e", + "imdb_id": "tt2467372", + "name": "Brooklyn Nine-Nine", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "576c5a7df0b6c53b3c76ac3a", + "imdb_id": "tt5555260", + "name": "This Is Us", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a1388b", + "imdb_id": "tt1600194", + "name": "Hawaii Five-0", + "type": "series", + "year": "2010–2020" + }, + { + "_id": "5559c147bf6c900d1833cb94", + "imdb_id": "tt4016454", + "name": "Supergirl", + "year": "2015–2021", + "type": "series" + }, + { + "_id": "53677f1d847ccc8123a1bf77", + "imdb_id": "tt0988818", + "name": "Gintama", + "type": "series", + "year": "2005–2021" + }, + { + "_id": "5c0ad5b9173739c9f4d613a1", + "imdb_id": "tt8146760", + "name": "Summer Camp Island", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "5378cbf6847ccc8123ad33c7", + "imdb_id": "tt3205802", + "name": "How to Get Away with Murder", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "53677f02847ccc8123a16d8c", + "imdb_id": "tt0094514", + "name": "Murphy Brown", + "type": "series", + "year": "1988–2018" + }, + { + "_id": "5378cc37847ccc8123ad565c", + "imdb_id": "tt3487356", + "name": "Black-ish", + "type": "series", + "year": "2014–2022" + }, + { + "_id": "53677f4a847ccc8123a20373", + "imdb_id": "tt0055686", + "name": "The Lucy Show", + "type": "series", + "year": "1962–1968" + }, + { + "_id": "53677ef9847ccc8123a13e10", + "imdb_id": "tt1442464", + "name": "The Middle", + "type": "series", + "year": "2009–2018" + }, + { + "_id": "5c194df8173739c9f45aba7f", + "imdb_id": "tt0306368", + "name": "Operación triunfo", + "type": "series", + "year": "2001–" + }, + { + "_id": "53677f20847ccc8123a1c6d5", + "imdb_id": "tt2098220", + "name": "Hunter x Hunter", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677f17847ccc8123a1acad", + "imdb_id": "tt0235918", + "name": "The Fairly OddParents", + "type": "series", + "year": "2001–2017" + }, + { + "_id": "53677f40847ccc8123a1f5e9", + "imdb_id": "tt0090477", + "name": "Lovejoy", + "type": "series", + "year": "1986–1994" + }, + { + "_id": "53677f05847ccc8123a17b19", + "imdb_id": "tt0262151", + "name": "Bob the Builder", + "type": "series", + "year": "1997–2018" + }, + { + "_id": "53677ef9847ccc8123a14032", + "imdb_id": "tt0409591", + "name": "Naruto", + "type": "series", + "year": "2002–2007" + }, + { + "_id": "54fb5f89711bd19c92ad476a", + "imdb_id": "tt0405831", + "name": "Chest imeyu!..", + "year": "2004–", + "type": "series" + }, + { + "_id": "5378cc11847ccc8123ad4b05", + "imdb_id": "tt3514324", + "name": "Scorpion", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "53677ef9847ccc8123a13ee9", + "imdb_id": "tt0367279", + "name": "Arrested Development", + "type": "series", + "year": "2003–2019" + }, + { + "_id": "5c0cd816173739c9f44fb2f9", + "imdb_id": "tt7670568", + "type": "series", + "name": "The Masked Singer", + "year": "2019–2024" + }, + { + "_id": "53677f09847ccc8123a185f2", + "imdb_id": "tt0106028", + "name": "Homicide: Life on the Street", + "type": "series", + "year": "1993–1999" + }, + { + "_id": "53677ef9847ccc8123a137ea", + "imdb_id": "tt1830617", + "name": "Grimm", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "5c0d9f2e173739c9f4e40fcb", + "imdb_id": "tt9111220", + "name": "Hudson & Rex", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f25847ccc8123a1d576", + "imdb_id": "tt0081856", + "name": "Dynasty", + "type": "series", + "year": "1981–1989" + }, + { + "_id": "53677ef9847ccc8123a13873", + "imdb_id": "tt1327801", + "name": "Glee", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "53677efa847ccc8123a14936", + "imdb_id": "tt0050037", + "name": "Maverick", + "type": "series", + "year": "1957–1962" + }, + { + "_id": "53677f04847ccc8123a17491", + "imdb_id": "tt0046617", + "name": "Lassie", + "type": "series", + "year": "1954–1974" + }, + { + "_id": "53677f00847ccc8123a164c7", + "imdb_id": "tt0118375", + "name": "King of the Hill", + "type": "series", + "year": "1997–2010" + }, + { + "_id": "53677ef9847ccc8123a139e3", + "imdb_id": "tt1378167", + "name": "NCIS: Los Angeles", + "type": "series", + "year": "2009–2023" + }, + { + "_id": "53677f0c847ccc8123a19444", + "imdb_id": "tt0068149", + "name": "The Waltons", + "type": "series", + "year": "1972–1981" + }, + { + "_id": "5c2280bc173739c9f4e935e5", + "imdb_id": "tt7124904", + "name": "Tomorrow Is Ours", + "type": "series", + "year": "2017–" + }, + { + "_id": "5c2e3909173739c9f4a109ae", + "imdb_id": "tt3105422", + "name": "Ace of Diamond", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677ef9847ccc8123a13ae5", + "imdb_id": "tt0434665", + "name": "Bleach", + "type": "series", + "year": "2004–2023" + }, + { + "_id": "53677f0f847ccc8123a19a50", + "imdb_id": "tt1865718", + "name": "Gravity Falls", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f05847ccc8123a176f0", + "imdb_id": "tt0088512", + "name": "EastEnders", + "type": "series", + "year": "1985–" + }, + { + "_id": "53677f0f847ccc8123a1996c", + "imdb_id": "tt2261391", + "name": "Chicago Fire", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677ef9847ccc8123a141c4", + "imdb_id": "tt0115270", + "name": "Millennium", + "type": "series", + "year": "1996–1999" + }, + { + "_id": "53677efc847ccc8123a14d23", + "imdb_id": "tt0098844", + "name": "Law & Order", + "type": "series", + "year": "1990–" + }, + { + "_id": "53677f02847ccc8123a16db7", + "imdb_id": "tt0105986", + "name": "Diagnosis Murder", + "type": "series", + "year": "1993–2001" + }, + { + "_id": "53677f00847ccc8123a16678", + "imdb_id": "tt2191671", + "name": "Elementary", + "type": "series", + "year": "2012–2019" + }, + { + "_id": "53677f02847ccc8123a16bb4", + "imdb_id": "tt0106080", + "name": "The Nanny", + "type": "series", + "year": "1993–1999" + }, + { + "_id": "53677f19847ccc8123a1b235", + "imdb_id": "tt0278866", + "name": "Kim Possible", + "type": "series", + "year": "2002–2007" + }, + { + "_id": "53677efc847ccc8123a1523e", + "imdb_id": "tt0053494", + "name": "Coronation Street", + "type": "series", + "year": "1960–" + }, + { + "_id": "53677ef9847ccc8123a1381f", + "imdb_id": "tt0182576", + "name": "Family Guy", + "type": "series", + "year": "1999–" + }, + { + "_id": "57e04e3bd7e54929823e5674", + "imdb_id": "tt5897304", + "name": "Mob Psycho 100", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677eff847ccc8123a160ea", + "imdb_id": "tt0364817", + "name": "Tru Calling", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "554d2d8916e3a4523a768e58", + "imdb_id": "tt3609352", + "name": "Grace and Frankie", + "year": "2015–2022", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a1391a", + "imdb_id": "tt0313043", + "name": "CSI: Miami", + "type": "series", + "year": "2002–2012" + }, + { + "_id": "5a5ea363543165dcd86c3ef8", + "imdb_id": "tt4869896", + "type": "series", + "name": "Overlord", + "year": "2015–2022" + }, + { + "_id": "53677f47847ccc8123a201c0", + "imdb_id": "tt0053525", + "name": "My Three Sons", + "type": "series", + "year": "1960–1972" + }, + { + "_id": "53677ef9847ccc8123a13abb", + "imdb_id": "tt0086759", + "name": "Miami Vice", + "type": "series", + "year": "1984–1989" + }, + { + "_id": "5c0d2135173739c9f4da546a", + "imdb_id": "tt8883922", + "name": "Chronicles of the Sun", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f38847ccc8123a1ee21", + "imdb_id": "tt0101188", + "name": "Rugrats", + "type": "series", + "year": "1991–2006" + }, + { + "_id": "53677ef9847ccc8123a14149", + "imdb_id": "tt0165581", + "name": "The King of Queens", + "type": "series", + "year": "1998–2007" + }, + { + "_id": "5d968228c4ccb5dd92e33091", + "imdb_id": "tt10691888", + "name": "AEW Dynamite", + "type": "series", + "year": "2019–" + }, + { + "_id": "5c4dddfad582b2575688de43", + "imdb_id": "tt0040051", + "name": "Studio One", + "type": "series", + "year": "1948–1958" + }, + { + "_id": "53677f21847ccc8123a1cb4d", + "imdb_id": "tt3107288", + "name": "The Flash", + "type": "series", + "year": "2014–2023" + }, + { + "_id": "53677f4a847ccc8123a203e0", + "imdb_id": "tt0051297", + "name": "Naked City", + "type": "series", + "year": "1958–1963" + }, + { + "_id": "54ce5d26e573cadcfa1f8c17", + "imdb_id": "tt0454349", + "name": "Johnny Test", + "type": "series", + "year": "2005–2014" + }, + { + "_id": "53677f1b847ccc8123a1b80c", + "imdb_id": "tt2230051", + "name": "High School DxD", + "type": "series", + "year": "2012–2018" + }, + { + "_id": "53677efc847ccc8123a14dad", + "imdb_id": "tt2364582", + "name": "Agents of S.H.I.E.L.D.", + "type": "series", + "year": "2013–2020" + }, + { + "_id": "53677ef9847ccc8123a13a48", + "imdb_id": "tt0458290", + "name": "Star Wars: The Clone Wars", + "type": "series", + "year": "2008–2020" + }, + { + "_id": "54ce5d15e573cadcfa1f8bf8", + "imdb_id": "tt3061050", + "name": "Clarence", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677ef9847ccc8123a13cb4", + "imdb_id": "tt0072562", + "name": "Saturday Night Live", + "type": "series", + "year": "1975–" + }, + { + "_id": "53677ef9847ccc8123a137a8", + "imdb_id": "tt0413573", + "name": "Grey's Anatomy", + "type": "series", + "year": "2005–" + }, + { + "_id": "5378cc0a847ccc8123ad473e", + "imdb_id": "tt3566726", + "name": "Jane the Virgin", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "539173bca8f27b1bb90ade63", + "imdb_id": "tt0996695", + "name": "Eyeshield 21", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "53677f07847ccc8123a18177", + "imdb_id": "tt1734537", + "name": "Marple", + "type": "series", + "year": "2004–2013" + }, + { + "_id": "55075d87711bd19c92addeb3", + "imdb_id": "tt2789238", + "name": "Strike the Blood", + "year": "2013–2022", + "type": "series" + }, + { + "_id": "56b8b50ff6b914c6c680f89e", + "imdb_id": "tt2788432", + "name": "American Crime Story", + "year": "2016–", + "type": "series" + }, + { + "_id": "5c4cb888d582b2575615f902", + "imdb_id": "tt0872309", + "name": "Genesis of Aquarion", + "type": "series", + "year": "2005–2015" + }, + { + "_id": "53677ef9847ccc8123a13edf", + "imdb_id": "tt0094455", + "name": "Empty Nest", + "type": "series", + "year": "1988–1995" + }, + { + "_id": "59be2e281712e0f4dd892e90", + "imdb_id": "tt6135682", + "type": "series", + "name": "Spider-Man", + "year": "2017–2020" + }, + { + "_id": "53677f29847ccc8123a1dd90", + "imdb_id": "tt2861424", + "name": "Rick and Morty", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677efc847ccc8123a150eb", + "imdb_id": "tt0892700", + "name": "The Penguins of Madagascar", + "type": "series", + "year": "2008–2015" + }, + { + "_id": "53677f05847ccc8123a17700", + "imdb_id": "tt0118360", + "name": "Johnny Bravo", + "type": "series", + "year": "1997–2004" + }, + { + "_id": "53677f05847ccc8123a179db", + "imdb_id": "tt0493334", + "name": "Yu-Gi-Oh! GX", + "type": "series", + "year": "2004–2008" + }, + { + "_id": "53677f00847ccc8123a1672a", + "imdb_id": "tt1480925", + "name": "Bakemonogatari", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "53677f2c847ccc8123a1e02d", + "imdb_id": "tt2771780", + "name": "Teen Titans Go!", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f59847ccc8123a2192e", + "imdb_id": "tt0118933", + "name": "David", + "type": "series", + "year": "1997" + }, + { + "_id": "53677ef9847ccc8123a13b83", + "imdb_id": "tt0203259", + "name": "Law & Order: Special Victims Unit", + "type": "series", + "year": "1999–" + }, + { + "_id": "53677f19847ccc8123a1b1e3", + "imdb_id": "tt0108894", + "name": "Party of Five", + "type": "series", + "year": "1994–2000" + }, + { + "_id": "5378b8cb847ccc8123ad1826", + "imdb_id": "tt0318913", + "name": "Teenage Mutant Ninja Turtles", + "type": "series", + "year": "2003–2010" + }, + { + "_id": "5c2bcb30173739c9f45daeaf", + "imdb_id": "tt7997010", + "name": "I Live Alone", + "type": "series", + "year": "2013–" + }, + { + "_id": "55089941711bd19c92ade50e", + "imdb_id": "tt0043224", + "name": "The Red Skelton Hour", + "year": "1951–1971", + "type": "series" + }, + { + "_id": "53677f00847ccc8123a165c4", + "imdb_id": "tt0068120", + "name": "The Price is Right", + "type": "series", + "year": "1972–" + }, + { + "_id": "53677efa847ccc8123a149ad", + "imdb_id": "tt1305826", + "name": "Adventure Time", + "type": "series", + "year": "2010–2018" + }, + { + "_id": "53677ef9847ccc8123a13b4f", + "imdb_id": "tt0096697", + "name": "The Simpsons", + "type": "series", + "year": "1989–2025" + }, + { + "_id": "5b2dad2216f4806c2aff7b84", + "imdb_id": "tt4236770", + "type": "series", + "name": "Yellowstone", + "year": "2018–" + }, + { + "_id": "53677ef9847ccc8123a13edd", + "imdb_id": "tt1416765", + "name": "Parenthood", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "5c26ee7e173739c9f4e0a14b", + "imdb_id": "tt7216636", + "name": "Hazbin Hotel", + "type": "series", + "year": "2024–" + }, + { + "_id": "55b96fb2bf6c900d183bed2f", + "imdb_id": "tt4839610", + "name": "We Bare Bears", + "year": "2014–2019", + "type": "series" + }, + { + "_id": "53677f0a847ccc8123a18ac0", + "imdb_id": "tt0070992", + "name": "Happy Days", + "type": "series", + "year": "1974–1984" + }, + { + "_id": "55cb60b8bf6c900d183def29", + "imdb_id": "tt4052886", + "name": "Lucifer", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "5c43e04fd582b257568449df", + "imdb_id": "tt0052445", + "name": "Bat Masterson", + "type": "series", + "year": "1958–1961" + }, + { + "_id": "53677efc847ccc8123a15274", + "imdb_id": "tt0112022", + "name": "JAG", + "type": "series", + "year": "1995–2005" + }, + { + "_id": "57f8c980d7e54929823fa198", + "imdb_id": "tt3398540", + "name": "Haikyu!!", + "year": "2014–2020", + "type": "series" + }, + { + "_id": "53677f23847ccc8123a1cee4", + "imdb_id": "tt0134269", + "name": "V.I.P.", + "type": "series", + "year": "1998–2002" + }, + { + "_id": "53677f05847ccc8123a17bcd", + "imdb_id": "tt2177489", + "name": "Baby Daddy", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "53de7d2ea8f27b1bb90bd552", + "imdb_id": "tt3596174", + "name": "Henry Danger", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "53677f29847ccc8123a1de72", + "imdb_id": "tt2712740", + "name": "The Goldbergs", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "53677ef9847ccc8123a139fe", + "imdb_id": "tt0364782", + "name": "The Apprentice", + "type": "series", + "year": "2004–2017" + }, + { + "_id": "550efc59cc9eee85bb52d997", + "imdb_id": "tt2061527", + "name": "Tiger & Bunny", + "year": "2011–2022", + "type": "series" + }, + { + "_id": "53677f7a847ccc8123a23d0b", + "imdb_id": "tt3502248", + "name": "Bosch", + "type": "series", + "year": "2014–2021" + }, + { + "_id": "53677efa847ccc8123a14639", + "imdb_id": "tt0176385", + "name": "#DUPE#", + "type": "series", + "year": "1997–" + }, + { + "_id": "53677efd847ccc8123a15621", + "imdb_id": "tt0050025", + "name": "Have Gun - Will Travel", + "type": "series", + "year": "1957–1963" + }, + { + "_id": "53677f2c847ccc8123a1df68", + "imdb_id": "tt2185037", + "name": "Running Man", + "type": "series", + "year": "2010–" + }, + { + "_id": "55075d78711bd19c92addd6f", + "imdb_id": "tt0978215", + "name": "Utawarerumono", + "year": "2006", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14ccb", + "imdb_id": "tt2071645", + "name": "The Following", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "5c219b11173739c9f45b31aa", + "imdb_id": "tt0070981", + "name": "Derrick", + "type": "series", + "year": "1974–1998" + }, + { + "_id": "53677ef9847ccc8123a13c01", + "imdb_id": "tt0460091", + "name": "My Name Is Earl", + "type": "series", + "year": "2005–2009" + }, + { + "_id": "53677f19847ccc8123a1b5e2", + "imdb_id": "tt0075592", + "name": "Tales of the Unexpected", + "type": "series", + "year": "1979–1988" + }, + { + "_id": "53677efa847ccc8123a14618", + "imdb_id": "tt0402711", + "name": "Boston Legal", + "type": "series", + "year": "2004–2008" + }, + { + "_id": "53677f23847ccc8123a1cf33", + "imdb_id": "tt2741602", + "name": "The Blacklist", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "53677ef9847ccc8123a13d0d", + "imdb_id": "tt1567432", + "name": "Teen Wolf", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "59b043451712e0f4dd1ff969", + "imdb_id": "tt5515212", + "name": "Big Hero 6: The Series", + "year": "2017–2021", + "type": "series" + }, + { + "_id": "53677f0c847ccc8123a18ecc", + "imdb_id": "tt1308089", + "name": "A Certain Magical Index", + "type": "series", + "year": "2008–2019" + }, + { + "_id": "5f784bf35424253341ead722", + "imdb_id": "tt11858104", + "name": "Dragon Quest: The Adventure of Dai", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "53677f0a847ccc8123a18ae6", + "imdb_id": "tt0366025", + "name": "Hope & Faith", + "type": "series", + "year": "2003–2006" + }, + { + "_id": "53677f02847ccc8123a168bd", + "imdb_id": "tt0108724", + "name": "Chicago Hope", + "type": "series", + "year": "1994–2000" + }, + { + "_id": "53677ef9847ccc8123a144bd", + "imdb_id": "tt1466074", + "name": "Columbo", + "type": "series", + "year": "1971–1978" + }, + { + "_id": "53677ef5847ccc8123a13773", + "imdb_id": "tt0364845", + "name": "NCIS", + "type": "series", + "year": "2003–" + }, + { + "_id": "5a3f61c9543165dcd8e89248", + "imdb_id": "tt6148376", + "type": "series", + "name": "Ben 10", + "year": "2016–2021" + }, + { + "_id": "5c597cb4d582b25756ac7bfd", + "imdb_id": "tt2398674", + "name": "Aikatsu!", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f29847ccc8123a1de6a", + "imdb_id": "tt1710295", + "name": "Doc McStuffins", + "type": "series", + "year": "2012–2022" + }, + { + "_id": "53677f66847ccc8123a229e6", + "imdb_id": "tt2712516", + "name": "The Thundermans", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "5378cc10847ccc8123ad4a01", + "imdb_id": "tt3501584", + "name": "iZombie", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53677f45847ccc8123a1fdfe", + "imdb_id": "tt0317028", + "name": "V Graham Norton", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "53677f00847ccc8123a16287", + "imdb_id": "tt0806910", + "name": "Tatort", + "type": "series", + "year": "1970–" + }, + { + "_id": "53677f0f847ccc8123a197d1", + "imdb_id": "tt2250192", + "name": "Sword Art Online", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677ef9847ccc8123a13a06", + "imdb_id": "tt1196946", + "name": "The Mentalist", + "type": "series", + "year": "2008–2015" + }, + { + "_id": "55075d32711bd19c92addb86", + "imdb_id": "tt0054519", + "name": "Ben Casey", + "year": "1961–1966", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14a28", + "imdb_id": "tt0092400", + "name": "Married... with Children", + "type": "series", + "year": "1987–1997" + }, + { + "_id": "53677ef9847ccc8123a1440e", + "imdb_id": "tt2137109", + "name": "Masters of Sex", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677efa847ccc8123a1494a", + "imdb_id": "tt1632701", + "name": "Suits", + "type": "series", + "year": "2011–2019" + }, + { + "_id": "53677ef9847ccc8123a13858", + "imdb_id": "tt1439629", + "name": "Community", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "614ae5b264ec43ef98728413", + "imdb_id": "tt13622982", + "name": "Star Wars: Visions", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a13ad4", + "imdb_id": "tt1353056", + "name": "RuPaul's Drag Race", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677f07847ccc8123a1817e", + "imdb_id": "tt0481256", + "name": "Fighting Spirit", + "type": "series", + "year": "2000–2002" + }, + { + "_id": "53677f51847ccc8123a20e77", + "imdb_id": "tt0044248", + "name": "Cavalcade of America", + "type": "series", + "year": "1952–1957" + }, + { + "_id": "5c118f3f173739c9f4c485ff", + "imdb_id": "tt8722888", + "name": "Stargirl", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "536907f2847ccc8123acddc5", + "imdb_id": "tt0044259", + "name": "Death Valley Days", + "type": "series", + "year": "1952–1970" + }, + { + "_id": "589329951635517fbf56c91a", + "imdb_id": "tt4859164", + "name": "The Loud House", + "type": "series", + "year": "2014–" + }, + { + "_id": "587fc2541635517fbf569601", + "imdb_id": "tt5011816", + "name": "Sneaky Pete", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53677ef9847ccc8123a137b9", + "imdb_id": "tt0410975", + "name": "Desperate Housewives", + "type": "series", + "year": "2004–2012" + }, + { + "_id": "53677f0a847ccc8123a18917", + "imdb_id": "tt0101120", + "name": "Home Improvement", + "type": "series", + "year": "1991–1999" + }, + { + "_id": "5c26b328173739c9f48399ba", + "imdb_id": "tt2267446", + "name": "Space Brothers", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677ef5847ccc8123a13765", + "imdb_id": "tt0452046", + "name": "Criminal Minds", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677ef9847ccc8123a142f8", + "imdb_id": "tt0112178", + "name": "Star Trek: Voyager", + "type": "series", + "year": "1995–2001" + }, + { + "_id": "53677f52847ccc8123a21014", + "imdb_id": "tt0318252", + "name": "The Twilight Zone", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "53677ef9847ccc8123a13896", + "imdb_id": "tt0463398", + "name": "Dancing with the Stars", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f79847ccc8123a23aed", + "imdb_id": "tt2802850", + "name": "Fargo", + "type": "series", + "year": "2014–2024" + }, + { + "_id": "5429bef3a8f27b1bb90ce418", + "imdb_id": "tt3339966", + "name": "Unbreakable Kimmy Schmidt", + "type": "series", + "year": "2015–2020" + }, + { + "_id": "58c984c91635517fbf56e602", + "imdb_id": "tt5853176", + "name": "The Good Fight", + "type": "series", + "year": "2017–2022" + }, + { + "_id": "5c0fb75e173739c9f4471367", + "imdb_id": "tt5129382", + "name": "The Return of Superman", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677ef9847ccc8123a13c2d", + "imdb_id": "tt0935095", + "name": "In Plain Sight", + "type": "series", + "year": "2008–2012" + }, + { + "_id": "53677f02847ccc8123a16854", + "imdb_id": "tt0115163", + "name": "Early Edition", + "type": "series", + "year": "1996–2000" + }, + { + "_id": "53677efa847ccc8123a145a6", + "imdb_id": "tt0421482", + "name": "Winx Club", + "type": "series", + "year": "2004–2023" + }, + { + "_id": "5c269276173739c9f4403ae7", + "imdb_id": "tt0106097", + "name": "Peak Practice", + "type": "series", + "year": "1993–2002" + }, + { + "_id": "53677ef9847ccc8123a13e2a", + "imdb_id": "tt0988824", + "name": "Naruto: Shippuden", + "type": "series", + "year": "2007–2017" + }, + { + "_id": "5c1bd504173739c9f4fe0a78", + "imdb_id": "tt8322592", + "name": "Fast & Furious Spy Racers", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f03847ccc8123a17310", + "imdb_id": "tt2049323", + "name": "The Jonathan Ross Show", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f23847ccc8123a1cff3", + "imdb_id": "tt2211129", + "name": "The Mindy Project", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "5973f3511635517fbf56e96f", + "imdb_id": "tt6116060", + "name": "The Bold Type", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "62793d6d64ec43ef98dc810a", + "imdb_id": "tt14168162", + "name": "Bosch: Legacy", + "type": "series", + "year": "2022–" + }, + { + "_id": "57f0f4d9d7e54929823f33de", + "imdb_id": "tt0475784", + "name": "Westworld", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677f68847ccc8123a22b07", + "imdb_id": "tt2805096", + "name": "Chicago P.D.", + "type": "series", + "year": "2014–" + }, + { + "_id": "5c12d1e4173739c9f40a8e93", + "imdb_id": "tt4648640", + "name": "Talking Tom and Friends", + "type": "series", + "year": "2014–2021" + }, + { + "_id": "53677f3a847ccc8123a1f0f1", + "imdb_id": "tt0081860", + "name": "A Case for Two", + "type": "series", + "year": "1981–2023" + }, + { + "_id": "53677f0c847ccc8123a19396", + "imdb_id": "tt0212671", + "name": "Malcolm in the Middle", + "type": "series", + "year": "2000–2006" + }, + { + "_id": "53677f0a847ccc8123a18a5c", + "imdb_id": "tt2288064", + "name": "Witches of East End", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "53677f5b847ccc8123a21cf5", + "imdb_id": "tt0041061", + "name": "Suspense", + "type": "series", + "year": "1949–1954" + }, + { + "_id": "54250886a8f27b1bb90cd78d", + "imdb_id": "tt3749900", + "name": "Gotham", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "54fc0959711bd19c92ad4a28", + "imdb_id": "tt0962826", + "name": "Black Lagoon", + "year": "2006", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a1395d", + "imdb_id": "tt0395843", + "name": "CSI: NY", + "type": "series", + "year": "2004–2013" + }, + { + "_id": "54e19896e573cadcfa1fd641", + "imdb_id": "tt0056742", + "name": "Bob Hope Presents the Chrysler Theatre", + "type": "series", + "year": "1963–1967" + }, + { + "_id": "53677efa847ccc8123a1466c", + "imdb_id": "tt0050051", + "name": "Perry Mason", + "type": "series", + "year": "1957–1966" + }, + { + "_id": "551ad095cc9eee85bb52e022", + "imdb_id": "tt4465472", + "name": "Rosewood", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677f09847ccc8123a185da", + "imdb_id": "tt0129717", + "name": "Softly Softly", + "type": "series", + "year": "1966–1969" + }, + { + "_id": "53677f5a847ccc8123a21b11", + "imdb_id": "tt0267212", + "name": "Question Time", + "type": "series", + "year": "1979–" + }, + { + "_id": "53677f08847ccc8123a18506", + "imdb_id": "tt2647544", + "name": "Sleepy Hollow", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "53677ef9847ccc8123a13810", + "imdb_id": "tt1845307", + "name": "2 Broke Girls", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "53677f21847ccc8123a1ca42", + "imdb_id": "tt0071034", + "name": "Police Woman", + "type": "series", + "year": "1974–1978" + }, + { + "_id": "53677ef9847ccc8123a13e37", + "imdb_id": "tt0765425", + "name": "Top Chef", + "type": "series", + "year": "2006–" + }, + { + "_id": "604bb2005424253341252d86", + "imdb_id": "tt14094206", + "name": "Marvel Studios: Assembled", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f08847ccc8123a184e2", + "imdb_id": "tt1751105", + "name": "My Little Pony: Friendship Is Magic", + "type": "series", + "year": "2010–2020" + }, + { + "_id": "53677efc847ccc8123a15081", + "imdb_id": "tt0321021", + "name": "Without a Trace", + "type": "series", + "year": "2002–2009" + }, + { + "_id": "53677f76847ccc8123a23969", + "imdb_id": "tt0159208", + "name": "City Hunter", + "type": "series", + "year": "1987–1991" + }, + { + "_id": "53677f19847ccc8123a1b53b", + "imdb_id": "tt1178180", + "name": "The Marvelous Misadventures of Flapjack", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "5a5dd073543165dcd8707d2f", + "imdb_id": "tt6483832", + "type": "series", + "name": "The Resident", + "year": "2018–2023" + }, + { + "_id": "53677ef9847ccc8123a13d43", + "imdb_id": "tt0397306", + "name": "American Dad!", + "type": "series", + "year": "2005–" + }, + { + "_id": "659fcf59bd36726cbba28e84", + "imdb_id": "tt14824792", + "name": "Ted", + "type": "series", + "year": "2024" + }, + { + "_id": "53677ef9847ccc8123a13845", + "imdb_id": "tt0436992", + "name": "Doctor Who", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f0c847ccc8123a18f16", + "imdb_id": "tt0078569", + "name": "Benson", + "type": "series", + "year": "1979–1986" + }, + { + "_id": "53677f29847ccc8123a1dcb5", + "imdb_id": "tt0055708", + "name": "The Tonight Show Starring Johnny Carson", + "type": "series", + "year": "1962–1992" + }, + { + "_id": "53677efc847ccc8123a150ec", + "imdb_id": "tt0112206", + "name": "Unhappily Ever After", + "type": "series", + "year": "1995–1999" + }, + { + "_id": "55e70875bf6c900d1840c69a", + "imdb_id": "tt4532368", + "name": "DC's Legends of Tomorrow", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677efc847ccc8123a14ddc", + "imdb_id": "tt1325113", + "name": "Childrens Hospital", + "type": "series", + "year": "2008–2016" + }, + { + "_id": "53677ef9847ccc8123a13ab7", + "imdb_id": "tt1842530", + "name": "Unforgettable", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "551e1e99cc9eee85bb52e13c", + "imdb_id": "tt4335742", + "name": "Lip Sync Battle", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a14252", + "imdb_id": "tt0449545", + "name": "Curious George", + "type": "series", + "year": "2006–2022" + }, + { + "_id": "53677ef9847ccc8123a13a8e", + "imdb_id": "tt0350448", + "name": "Real Time with Bill Maher", + "type": "series", + "year": "2003–" + }, + { + "_id": "5ccc3c905111f1a8a3866e86", + "imdb_id": "tt8064302", + "name": "Dead to Me", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "5565dba4bf6c900d18341e74", + "imdb_id": "tt4158110", + "name": "Mr. Robot", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677f1c847ccc8123a1bba1", + "imdb_id": "tt0278238", + "name": "Samurai Jack", + "type": "series", + "year": "2001–2017" + }, + { + "_id": "53677efe847ccc8123a15be6", + "imdb_id": "tt0062539", + "name": "Adam-12", + "type": "series", + "year": "1968–1975" + }, + { + "_id": "53677ef9847ccc8123a13925", + "imdb_id": "tt1722512", + "name": "Ultimate Spider-Man", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "5c1d4816173739c9f496c34d", + "imdb_id": "tt4087032", + "name": "Good Mythical Morning", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f23847ccc8123a1cfd5", + "imdb_id": "tt2632424", + "name": "The Originals", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677f1b847ccc8123a1ba38", + "imdb_id": "tt2234222", + "name": "Orphan Black", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "53677ef9847ccc8123a137c4", + "imdb_id": "tt1429449", + "name": "Lost Girl", + "type": "series", + "year": "2010–2016" + }, + { + "_id": "53677f00847ccc8123a16283", + "imdb_id": "tt0065327", + "name": "Night Gallery", + "type": "series", + "year": "1969–1973" + }, + { + "_id": "5b8e9359173739c9f47db502", + "imdb_id": "tt5715524", + "name": "Mayans M.C.", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "53677f42847ccc8123a1fa06", + "imdb_id": "tt0292414", + "name": "McLeod's Daughters", + "type": "series", + "year": "2001–2009" + }, + { + "_id": "6153c63c64ec43ef9841952d", + "imdb_id": "tt11640018", + "name": "La Brea", + "type": "series", + "year": "2021–2024" + }, + { + "_id": "54ff69e9711bd19c92add0a7", + "imdb_id": "tt0063927", + "name": "Marcus Welby, M.D.", + "year": "1969–1976", + "type": "series" + }, + { + "_id": "53677f2c847ccc8123a1e16c", + "imdb_id": "tt2729716", + "name": "The Haves and the Have Nots", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "53677ef9847ccc8123a14310", + "imdb_id": "tt0972534", + "name": "iCarly", + "type": "series", + "year": "2007–2012" + }, + { + "_id": "53677efd847ccc8123a15716", + "imdb_id": "tt1131746", + "name": "Big Time Rush", + "type": "series", + "year": "2009–2023" + }, + { + "_id": "53ac6496a8f27b1bb90b2fae", + "imdb_id": "tt2699128", + "name": "The Leftovers", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "5c0ddf86173739c9f4421a08", + "imdb_id": "tt0088476", + "name": "Alfred Hitchcock Presents", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "53677ef9847ccc8123a13c8b", + "imdb_id": "tt1586680", + "name": "Shameless", + "type": "series", + "year": "2011–2021" + }, + { + "_id": "53677efa847ccc8123a1465c", + "imdb_id": "tt0092345", + "name": "DuckTales", + "type": "series", + "year": "1987–1990" + }, + { + "_id": "53677f2c847ccc8123a1e318", + "imdb_id": "tt2309295", + "name": "Hemlock Grove", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "54c0f5778527d2e0cb509758", + "imdb_id": "tt3230454", + "name": "The Last Man on Earth", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "5c53554fd582b25756bc86bd", + "imdb_id": "tt0101069", + "name": "The Commish", + "type": "series", + "year": "1991–1996" + }, + { + "_id": "6523e206bd36726cbb910fab", + "imdb_id": "tt2640044", + "name": "Masters of the Air", + "type": "series", + "year": "2024–" + }, + { + "_id": "53677f5a847ccc8123a21afc", + "imdb_id": "tt0434706", + "name": "Monster", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "53677f0c847ccc8123a1912a", + "imdb_id": "tt0106057", + "name": "Lois & Clark: The New Adventures of Superman", + "type": "series", + "year": "1993–1997" + }, + { + "_id": "543d5217a8f27b1bb90d39af", + "imdb_id": "tt2150751", + "name": "Chihayafuru", + "type": "series", + "year": "2011–2020" + }, + { + "_id": "53677f45847ccc8123a1fce0", + "imdb_id": "tt2356777", + "name": "True Detective", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677f0c847ccc8123a191af", + "imdb_id": "tt2193021", + "name": "Arrow", + "type": "series", + "year": "2012–2020" + }, + { + "_id": "53677efd847ccc8123a15806", + "imdb_id": "tt0059978", + "name": "Dark Shadows", + "type": "series", + "year": "1966–1971" + }, + { + "_id": "53677efa847ccc8123a149f1", + "imdb_id": "tt0074074", + "name": "Wonder Woman", + "type": "series", + "year": "1975–1979" + }, + { + "_id": "53677ef9847ccc8123a13812", + "imdb_id": "tt1578873", + "name": "Pretty Little Liars", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "5a13e030543165dcd8f723cd", + "imdb_id": "tt1236246", + "type": "series", + "name": "Runaways", + "year": "2017–2019" + }, + { + "_id": "53677f29847ccc8123a1dbee", + "imdb_id": "tt0111987", + "name": "Goosebumps", + "type": "series", + "year": "1995–1998" + }, + { + "_id": "53677efd847ccc8123a15b66", + "imdb_id": "tt0105946", + "name": "Babylon 5", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "53677ef9847ccc8123a1400b", + "imdb_id": "tt0362359", + "name": "The O.C.", + "type": "series", + "year": "2003–2007" + }, + { + "_id": "53677f0f847ccc8123a199d6", + "imdb_id": "tt2402137", + "name": "Legends", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "586d4c941635517fbf5677ae", + "imdb_id": "tt1734135", + "name": "Trollhunters: Tales of Arcadia", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "558a8c99bf6c900d1837984d", + "imdb_id": "tt0048899", + "name": "The Steve Allen Plymouth Show", + "year": "1956–1960", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13c9d", + "imdb_id": "tt1086761", + "name": "Keeping Up with the Kardashians", + "type": "series", + "year": "2007–2021" + }, + { + "_id": "53677f00847ccc8123a163ae", + "imdb_id": "tt1714204", + "name": "Perception", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677ef9847ccc8123a13990", + "imdb_id": "tt1119176", + "name": "Underbelly", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677f07847ccc8123a180c9", + "imdb_id": "tt0373474", + "name": "1-800-Missing", + "type": "series", + "year": "2003–2006" + }, + { + "_id": "53677f1a847ccc8123a1b685", + "imdb_id": "tt2654620", + "name": "The Strain", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f6d847ccc8123a230d1", + "imdb_id": "tt3121722", + "name": "PAW Patrol", + "type": "series", + "year": "2013–" + }, + { + "_id": "5bab132d173739c9f47613ec", + "imdb_id": "tt7817340", + "name": "New Amsterdam", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "5c0ec329173739c9f4b0fc58", + "imdb_id": "tt7658402", + "name": "Harley Quinn", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a137f5", + "imdb_id": "tt1441109", + "name": "Cougar Town", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "53677ef9847ccc8123a1401e", + "imdb_id": "tt0852863", + "name": "Phineas and Ferb", + "type": "series", + "year": "2007–2024" + }, + { + "_id": "53a5820aa8f27b1bb90b1c89", + "imdb_id": "tt0050066", + "name": "Tales of Wells Fargo", + "type": "series", + "year": "1957–1962" + }, + { + "_id": "53677f02847ccc8123a1700d", + "imdb_id": "tt0081873", + "name": "Hill Street Blues", + "type": "series", + "year": "1981–1987" + }, + { + "_id": "53677ef9847ccc8123a13b23", + "imdb_id": "tt1280822", + "name": "Drop Dead Diva", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "53677f00847ccc8123a16325", + "imdb_id": "tt0411027", + "name": "Strictly Come Dancing", + "type": "series", + "year": "2004–" + }, + { + "_id": "53677ef9847ccc8123a13792", + "imdb_id": "tt0924651", + "name": "The Graham Norton Show", + "type": "series", + "year": "2007–" + }, + { + "_id": "5385c00a847ccc8123ad85be", + "imdb_id": "tt2477230", + "name": "The Night Shift", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f24847ccc8123a1d166", + "imdb_id": "tt0078657", + "name": "Minder", + "type": "series", + "year": "1979–1994" + }, + { + "_id": "53677ef5847ccc8123a13762", + "imdb_id": "tt1839578", + "name": "Person of Interest", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "541c1363a8f27b1bb90cb4f3", + "imdb_id": "tt3187578", + "name": "The Mysteries of Laura", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "53677f0c847ccc8123a19067", + "imdb_id": "tt3032476", + "name": "Better Call Saul", + "type": "series", + "year": "2015–2022" + }, + { + "_id": "53677f26847ccc8123a1d75d", + "imdb_id": "tt0081930", + "name": "Simon & Simon", + "type": "series", + "year": "1981–1989" + }, + { + "_id": "54fb5f5a711bd19c92ad44ce", + "imdb_id": "tt1316554", + "name": "Black Butler", + "year": "2008–2011", + "type": "series" + }, + { + "_id": "5fccc65854242533410f04c2", + "imdb_id": "tt7440726", + "name": "Your Honor", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "64cfc2e6bd36726cbb47fe06", + "imdb_id": "tt1536749", + "name": "Let's Make a Deal", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677efd847ccc8123a159fd", + "imdb_id": "tt0094484", + "name": "In the Heat of the Night", + "type": "series", + "year": "1988–1995" + }, + { + "_id": "564dedcdbb83c664989515f4", + "imdb_id": "tt4655480", + "name": "Chicago Med", + "year": "2015–", + "type": "series" + }, + { + "_id": "53677f08847ccc8123a18587", + "imdb_id": "tt0050073", + "name": "Wagon Train", + "type": "series", + "year": "1957–1965" + }, + { + "_id": "53677ef9847ccc8123a138f6", + "imdb_id": "tt1442462", + "name": "The Good Wife", + "type": "series", + "year": "2009–2016" + }, + { + "_id": "53677ef9847ccc8123a1443d", + "imdb_id": "tt0185103", + "name": "WWE Raw", + "type": "series", + "year": "1993–" + }, + { + "_id": "5f64e3bb54242533411e7c2d", + "imdb_id": "tt10436228", + "name": "Jurassic World: Camp Cretaceous", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "53677ef9847ccc8123a13dbf", + "imdb_id": "tt0052520", + "name": "The Twilight Zone", + "type": "series", + "year": "1959–1964" + }, + { + "_id": "5c0aaed0173739c9f487e905", + "imdb_id": "tt7772602", + "name": "In the Dark", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677f72847ccc8123a2359d", + "imdb_id": "tt2349440", + "name": "Robot and Monster", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677f12847ccc8123a19eff", + "imdb_id": "tt0072574", + "name": "Switch", + "type": "series", + "year": "1975–1978" + }, + { + "_id": "53677f2e847ccc8123a1e472", + "imdb_id": "tt0364774", + "name": "Lilo & Stitch: The Series", + "type": "series", + "year": "2003–2006" + }, + { + "_id": "53677f00847ccc8123a166d0", + "imdb_id": "tt0092359", + "name": "Full House", + "type": "series", + "year": "1987–1995" + }, + { + "_id": "5f7811ea54242533419be55f", + "imdb_id": "tt12343534", + "name": "Jujutsu Kaisen", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677ef9847ccc8123a13d3a", + "imdb_id": "tt0121955", + "name": "South Park", + "type": "series", + "year": "1997–" + }, + { + "_id": "53677f0a847ccc8123a18c00", + "imdb_id": "tt0429455", + "name": "Commander in Chief", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "53677ef9847ccc8123a137d7", + "imdb_id": "tt0096555", + "name": "Casualty", + "type": "series", + "year": "1986–" + }, + { + "_id": "53677efc847ccc8123a15386", + "imdb_id": "tt0426769", + "name": "Peppa Pig", + "type": "series", + "year": "2004–" + }, + { + "_id": "53677efa847ccc8123a14613", + "imdb_id": "tt0364784", + "name": "Austin City Limits", + "type": "series", + "year": "1975–" + }, + { + "_id": "61b1d02d64ec43ef98c4a82b", + "imdb_id": "tt13819960", + "name": "And Just Like That...", + "type": "series", + "year": "2021–" + }, + { + "_id": "54fb5f1a711bd19c92ad42b7", + "imdb_id": "tt0046587", + "name": "Climax!", + "year": "1954–1958", + "type": "series" + }, + { + "_id": "53677efc847ccc8123a14ee5", + "imdb_id": "tt1780441", + "name": "Portlandia", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "53677f2c847ccc8123a1e004", + "imdb_id": "tt2188671", + "name": "Bates Motel", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "59c9a93b1712e0f4dd856e03", + "imdb_id": "tt6226232", + "type": "series", + "name": "Young Sheldon", + "year": "2017–2024" + }, + { + "_id": "54c0f5778527d2e0cb50975a", + "imdb_id": "tt2758770", + "name": "Star vs. the Forces of Evil", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "61f3c70a64ec43ef9835ed7b", + "imdb_id": "tt14169960", + "name": "All of Us Are Dead", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677ef5847ccc8123a1374c", + "imdb_id": "tt1844624", + "name": "American Horror Story", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f72847ccc8123a23530", + "imdb_id": "tt3232262", + "name": "Sonic Boom", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f2c847ccc8123a1e21b", + "imdb_id": "tt2262532", + "name": "The Fosters", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677f02847ccc8123a16d5c", + "imdb_id": "tt0058824", + "name": "Lost in Space", + "type": "series", + "year": "1965–1968" + }, + { + "_id": "615e6a1764ec43ef981b7bb2", + "imdb_id": "tt12887536", + "name": "CSI: Vegas", + "type": "series", + "year": "2021–" + }, + { + "_id": "53f6326fa8f27b1bb90c33c2", + "imdb_id": "tt2930604", + "name": "Star Wars: Rebels", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "53677f07847ccc8123a18227", + "imdb_id": "tt1224144", + "name": "Reborn!", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677ef9847ccc8123a14072", + "imdb_id": "tt0460644", + "name": "Ghost Whisperer", + "type": "series", + "year": "2005–2010" + }, + { + "_id": "5c0bb8cc173739c9f4584c70", + "imdb_id": "tt9288030", + "type": "series", + "name": "Reacher", + "year": "2022–" + }, + { + "_id": "5c3d0203d582b2575697d498", + "imdb_id": "tt0101165", + "name": "The Paradise Club", + "type": "series", + "year": "1989–1990" + }, + { + "_id": "548061978527d2e0cb4fc346", + "imdb_id": "tt0163507", + "name": "Whose Line Is It Anyway?", + "type": "series", + "year": "1998–2007" + }, + { + "_id": "54b28a0c8527d2e0cb50621e", + "imdb_id": "tt3921180", + "name": "Scream: The TV Series", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53677f14847ccc8123a1a4ca", + "imdb_id": "tt1114855", + "name": "Bakugan Battle Brawlers", + "type": "series", + "year": "2007–2011" + }, + { + "_id": "55052246711bd19c92add653", + "imdb_id": "tt3604232", + "name": "Transformers: Robots in Disguise", + "year": "2014–2020", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13d88", + "imdb_id": "tt1828327", + "name": "Last Man Standing", + "type": "series", + "year": "2011–2021" + }, + { + "_id": "53677ef9847ccc8123a13806", + "imdb_id": "tt0944947", + "name": "Game of Thrones", + "type": "series", + "year": "2011–2019" + }, + { + "_id": "53677ef9847ccc8123a13d68", + "imdb_id": "tt1551632", + "name": "Rizzoli & Isles", + "type": "series", + "year": "2010–2016" + }, + { + "_id": "53677efa847ccc8123a149c9", + "imdb_id": "tt1836037", + "name": "Longmire", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "53677f0c847ccc8123a18dd3", + "imdb_id": "tt0135733", + "name": "Match of the Day", + "type": "series", + "year": "1964–" + }, + { + "_id": "5c107cc6173739c9f4d23988", + "imdb_id": "tt2131864", + "name": "Junior Bake Off", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f19847ccc8123a1b435", + "imdb_id": "tt0052461", + "name": "Dennis the Menace", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "542a5ae8a8f27b1bb90ce56d", + "imdb_id": "tt2267661", + "name": "Pointless Celebrities", + "type": "series", + "year": "2010–" + }, + { + "_id": "5c150371173739c9f4da905e", + "imdb_id": "tt0199253", + "name": "Noddy", + "type": "series", + "year": "1998–2000" + }, + { + "_id": "58c984c81635517fbf56e5ff", + "imdb_id": "tt3920596", + "name": "Big Little Lies", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677f22847ccc8123a1cd4d", + "imdb_id": "tt0078610", + "name": "The Facts of Life", + "type": "series", + "year": "1979–1988" + }, + { + "_id": "53677efa847ccc8123a14c2f", + "imdb_id": "tt0052522", + "name": "The Untouchables", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "5378cbd6847ccc8123ad24ec", + "imdb_id": "tt2937900", + "name": "The Knick", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f1b847ccc8123a1b70b", + "imdb_id": "tt0063951", + "name": "Sesame Street", + "type": "series", + "year": "1969–" + }, + { + "_id": "53677ef9847ccc8123a13f18", + "imdb_id": "tt0118401", + "name": "Midsomer Murders", + "type": "series", + "year": "1997–" + }, + { + "_id": "53677ef9847ccc8123a137e7", + "imdb_id": "tt1825133", + "name": "Smash", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "53677f6f847ccc8123a232cd", + "imdb_id": "tt1725902", + "name": "Fish Hooks", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "5bc6a9a3173739c9f4d0c93a", + "imdb_id": "tt7587890", + "name": "The Rookie", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f63847ccc8123a22685", + "imdb_id": "tt0075500", + "name": "Eight Is Enough", + "type": "series", + "year": "1977–1981" + }, + { + "_id": "53677f1d847ccc8123a1beb3", + "imdb_id": "tt0962740", + "name": "Hell Girl", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "5c102970173739c9f426ca72", + "imdb_id": "tt1738419", + "name": "Bakuman.", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "5c25921d173739c9f47f9f44", + "imdb_id": "tt0486171", + "name": "Ikki tousen", + "type": "series", + "year": "2003–" + }, + { + "_id": "5c0a1621173739c9f47a8100", + "imdb_id": "tt8712204", + "name": "Batwoman", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "5bc40456173739c9f46fcfcf", + "imdb_id": "tt6394324", + "name": "Charmed", + "type": "series", + "year": "2018–2022" + }, + { + "_id": "53677f37847ccc8123a1ecc7", + "imdb_id": "tt1460205", + "name": "Dinosaur Train", + "type": "series", + "year": "2009–2023" + }, + { + "_id": "53677ef9847ccc8123a13dde", + "imdb_id": "tt1132290", + "name": "Warehouse 13", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "5c3fd77bd582b25756027e8b", + "imdb_id": "tt3985228", + "name": "Shirobako", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "619f4c7564ec43ef98589687", + "imdb_id": "tt10160804", + "type": "series", + "name": "Hawkeye", + "year": "2021" + }, + { + "_id": "53677f07847ccc8123a181e1", + "imdb_id": "tt0069602", + "name": "Last of the Summer Wine", + "type": "series", + "year": "1973–2010" + }, + { + "_id": "64e355a6bd36726cbbcbc6e5", + "imdb_id": "tt12324366", + "name": "Percy Jackson and the Olympians", + "type": "series", + "year": "2023–" + }, + { + "_id": "64f1690bbd36726cbb004423", + "imdb_id": "tt15248880", + "name": "Adventure Time: Fionna & Cake", + "type": "series", + "year": "2023" + }, + { + "_id": "53677ef9847ccc8123a14167", + "imdb_id": "tt1355642", + "name": "Fullmetal Alchemist: Brotherhood", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "556060ebbf6c900d1833f534", + "imdb_id": "tt4546568", + "name": "Infinite Challenge", + "year": "2005–2018", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a1486d", + "imdb_id": "tt0312172", + "name": "Monk", + "type": "series", + "year": "2002–2009" + }, + { + "_id": "53677ef9847ccc8123a14448", + "imdb_id": "tt0264235", + "name": "Curb Your Enthusiasm", + "type": "series", + "year": "2000–2024" + }, + { + "_id": "570f045f890e549c9a5833d0", + "imdb_id": "tt3846642", + "name": "The Girlfriend Experience", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "53677efc847ccc8123a1501d", + "imdb_id": "tt1388589", + "name": "The Super Hero Squad Show", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "53677efd847ccc8123a159fa", + "imdb_id": "tt0167743", + "name": "The Wild Thornberrys", + "type": "series", + "year": "1998–2004" + }, + { + "_id": "58e7adcc1635517fbf56e713", + "imdb_id": "tt4902964", + "name": "Rapunzel's Tangled Adventure", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677f45847ccc8123a1fdc7", + "imdb_id": "tt0068122", + "name": "The Protectors", + "type": "series", + "year": "1972–1974" + }, + { + "_id": "53677f02847ccc8123a16ccc", + "imdb_id": "tt0083505", + "name": "The Young Ones", + "type": "series", + "year": "1982–1984" + }, + { + "_id": "53677efc847ccc8123a14e3e", + "imdb_id": "tt0084967", + "name": "The A-Team", + "type": "series", + "year": "1983–1987" + }, + { + "_id": "53677f1d847ccc8123a1bd95", + "imdb_id": "tt2306299", + "name": "Vikings", + "type": "series", + "year": "2013–2020" + }, + { + "_id": "53677f57847ccc8123a21683", + "imdb_id": "tt0115200", + "name": "Hey Arnold!", + "type": "series", + "year": "1996–2004" + }, + { + "_id": "53677f19847ccc8123a1b2b4", + "imdb_id": "tt2661044", + "name": "The 100", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "53677ef9847ccc8123a13bbb", + "imdb_id": "tt1663676", + "name": "Awkward.", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "61d3d75a64ec43ef9832f794", + "imdb_id": "tt10023294", + "name": "That's My Jam", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f79847ccc8123a23cbc", + "imdb_id": "tt3559124", + "name": "The Tom and Jerry Show", + "type": "series", + "year": "2011–2022" + }, + { + "_id": "5542e9cfb0c92842850377ce", + "imdb_id": "tt4189022", + "name": "Ash vs Evil Dead", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "549447ca8527d2e0cb5009cc", + "imdb_id": "tt0156214", + "name": "Kamen Rider", + "type": "series", + "year": "1971–1973" + }, + { + "_id": "60efc10764ec43ef981888b3", + "imdb_id": "tt12306692", + "name": "American Horror Stories", + "type": "series", + "year": "2021–" + }, + { + "_id": "61e6578464ec43ef98bd4a09", + "imdb_id": "tt14500082", + "name": "How I Met Your Father", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "5fb4a6e15424253341a3194b", + "imdb_id": "tt11794642", + "name": "Big Sky", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677ef9847ccc8123a13e11", + "imdb_id": "tt0115355", + "name": "Silent Witness", + "type": "series", + "year": "1996–" + }, + { + "_id": "5c0a0623173739c9f4697374", + "imdb_id": "tt5721172", + "name": "The Worst Witch", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f15847ccc8123a1a94e", + "imdb_id": "tt0077008", + "name": "Fantasy Island", + "type": "series", + "year": "1977–1984" + }, + { + "_id": "53677ef9847ccc8123a13c4a", + "imdb_id": "tt0328733", + "name": "Beyblade", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "5ba5acd4173739c9f4ade561", + "imdb_id": "tt4944090", + "name": "Jay Leno's Garage", + "type": "series", + "year": "2015–2022" + }, + { + "_id": "53677f02847ccc8123a16d68", + "imdb_id": "tt1710177", + "name": "The Octonauts", + "type": "series", + "year": "2010–2021" + }, + { + "_id": "53677f17847ccc8123a1aa8b", + "imdb_id": "tt0115088", + "name": "Alarm für Cobra 11 - Die Autobahnpolizei", + "type": "series", + "year": "1996–" + }, + { + "_id": "5c16bc03173739c9f409ac4c", + "imdb_id": "tt0306398", + "name": "Star Academy", + "type": "series", + "year": "2001–" + }, + { + "_id": "53677ef9847ccc8123a13ce1", + "imdb_id": "tt0318912", + "name": "Natural World", + "type": "series", + "year": "1983–" + }, + { + "_id": "57e33ebad7e54929823e7a5b", + "imdb_id": "tt5296406", + "type": "series", + "name": "Designated Survivor", + "year": "2016–2019" + }, + { + "_id": "5c0c1eb2173739c9f42779dd", + "imdb_id": "tt5607976", + "name": "His Dark Materials", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "5fb631a95424253341ec0892", + "imdb_id": "tt7569576", + "name": "The Flight Attendant", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "53677f09847ccc8123a185e7", + "imdb_id": "tt0094582", + "name": "The Wonder Years", + "type": "series", + "year": "1988–1993" + }, + { + "_id": "5f8b993c5424253341a0ed97", + "imdb_id": "tt12287748", + "name": "Yashahime: Princess Half-Demon", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677efa847ccc8123a14a23", + "imdb_id": "tt1837576", + "name": "Scandal", + "type": "series", + "year": "2012–2018" + }, + { + "_id": "53677efd847ccc8123a15afb", + "imdb_id": "tt0106079", + "name": "NYPD Blue", + "type": "series", + "year": "1993–2005" + }, + { + "_id": "53677f0a847ccc8123a1884c", + "imdb_id": "tt0184122", + "name": "Holby City", + "type": "series", + "year": "1999–2022" + }, + { + "_id": "53677ef9847ccc8123a13b12", + "imdb_id": "tt0086815", + "name": "Thomas & Friends", + "type": "series", + "year": "1984–2021" + }, + { + "_id": "53677ef9847ccc8123a13ea2", + "imdb_id": "tt2022170", + "name": "The Client List", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "53677efa847ccc8123a14a3e", + "imdb_id": "tt1545214", + "name": "Kung Fu Panda: Legends of Awesomeness", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "53677f0f847ccc8123a19af9", + "imdb_id": "tt0062568", + "name": "Hawaii Five-O", + "type": "series", + "year": "1968–1980" + }, + { + "_id": "53677f2c847ccc8123a1dfbf", + "imdb_id": "tt2193041", + "name": "Beauty and the Beast", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f1d847ccc8123a1bdcb", + "imdb_id": "tt0105941", + "name": "Animaniacs", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "53677ef9847ccc8123a13c46", + "imdb_id": "tt1839337", + "name": "The Voice", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f68847ccc8123a22c16", + "imdb_id": "tt2573338", + "name": "Mighty Med", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "53677f08847ccc8123a18429", + "imdb_id": "tt0057733", + "name": "Bewitched", + "type": "series", + "year": "1964–1972" + }, + { + "_id": "5a73f3a8543165dcd83504c8", + "imdb_id": "tt6461726", + "type": "series", + "name": "A.P. Bio", + "year": "2018–2021" + }, + { + "_id": "588d421c1635517fbf56ae47", + "imdb_id": "tt6236572", + "name": "Mary Kills People", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677f0c847ccc8123a18eac", + "imdb_id": "tt0981456", + "name": "Baki the Grappler", + "type": "series", + "year": "2001–2007" + }, + { + "_id": "5c0a8c31173739c9f44448b8", + "imdb_id": "tt6156584", + "name": "Snowpiercer", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677ef9847ccc8123a13ac4", + "imdb_id": "tt0131613", + "name": "Teenage Mutant Ninja Turtles", + "type": "series", + "year": "1987–1996" + }, + { + "_id": "53677ef9847ccc8123a13f33", + "imdb_id": "tt0106145", + "name": "Star Trek: Deep Space Nine", + "type": "series", + "year": "1993–1999" + }, + { + "_id": "53677f1c847ccc8123a1bafa", + "imdb_id": "tt0088471", + "name": "A.D.", + "type": "series", + "year": "1985" + }, + { + "_id": "53677f14847ccc8123a1a422", + "imdb_id": "tt0390733", + "name": "Last Exile", + "type": "series", + "year": "2003" + }, + { + "_id": "5c1814b7173739c9f43b44eb", + "imdb_id": "tt9174578", + "name": "Around the World in 80 Days", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a1379c", + "imdb_id": "tt0903747", + "name": "Breaking Bad", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677f79847ccc8123a23c94", + "imdb_id": "tt2904418", + "name": "Free!", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "5c168c11173739c9f4a4b91b", + "imdb_id": "tt0337762", + "name": "G.I. Joe", + "type": "series", + "year": "1990–1992" + }, + { + "_id": "588b16791635517fbf56a99f", + "imdb_id": "tt6264782", + "name": "Mickey and the Roadster Racers", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "53677f32847ccc8123a1e6b0", + "imdb_id": "tt2244495", + "name": "The Eric Andre Show", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f14847ccc8123a1a572", + "imdb_id": "tt0068069", + "name": "Emmerdale Farm", + "type": "series", + "year": "1972–" + }, + { + "_id": "53677f03847ccc8123a171d5", + "imdb_id": "tt0058805", + "name": "Get Smart", + "type": "series", + "year": "1965–1970" + }, + { + "_id": "5c13051d173739c9f4718322", + "imdb_id": "tt0052507", + "name": "The Bullwinkle Show", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "5c1bf2b1173739c9f438ae48", + "imdb_id": "tt4838372", + "name": "Osomatsu-san", + "type": "series", + "year": "2015–2021" + }, + { + "_id": "53677f7c847ccc8123a23e8b", + "imdb_id": "tt3127020", + "name": "Faking It", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "55198016cc9eee85bb52dd78", + "imdb_id": "tt3219170", + "name": "Harvey Beaks", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677f13847ccc8123a1a281", + "imdb_id": "tt0312081", + "name": "8 Simple Rules", + "type": "series", + "year": "2002–2005" + }, + { + "_id": "53677f68847ccc8123a22c3e", + "imdb_id": "tt2252938", + "name": "Wander Over Yonder", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677ef9847ccc8123a140b4", + "imdb_id": "tt0437745", + "name": "Robot Chicken", + "type": "series", + "year": "2001–" + }, + { + "_id": "5c5dd64ad582b257568dd9d7", + "imdb_id": "tt7821582", + "name": "Truth Be Told", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677f00847ccc8123a1631e", + "imdb_id": "tt0162065", + "name": "Angel", + "type": "series", + "year": "1999–2004" + }, + { + "_id": "565dff8dbb83c66498973339", + "imdb_id": "tt4477976", + "name": "Superstore", + "year": "2015–2021", + "type": "series" + }, + { + "_id": "53677f43847ccc8123a1fc19", + "imdb_id": "tt0454656", + "name": "The Wiggles", + "type": "series", + "year": "1993–2022" + }, + { + "_id": "53677f05847ccc8123a1772e", + "imdb_id": "tt0052451", + "name": "Bonanza", + "type": "series", + "year": "1959–1973" + }, + { + "_id": "53677efc847ccc8123a150fe", + "imdb_id": "tt0052504", + "name": "Rawhide", + "type": "series", + "year": "1959–1965" + }, + { + "_id": "53677efa847ccc8123a1477d", + "imdb_id": "tt1055238", + "name": "Would I Lie to You?", + "type": "series", + "year": "2007–" + }, + { + "_id": "5e5e9af0c4ccb5dd92c40be4", + "imdb_id": "tt9193770", + "name": "Isekai Quartet", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a13d06", + "imdb_id": "tt0285331", + "name": "24", + "type": "series", + "year": "2001–2010" + }, + { + "_id": "6576e81ebd36726cbbcf3e52", + "imdb_id": "tt14044212", + "name": "Mr. & Mrs. Smith", + "type": "series", + "year": "2024–" + }, + { + "_id": "53677ef9847ccc8123a140e9", + "imdb_id": "tt0160904", + "name": "MI-5", + "type": "series", + "year": "2002–2011" + }, + { + "_id": "6013950654242533412b1da9", + "imdb_id": "tt13274038", + "name": "True Beauty", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "53677f13847ccc8123a1a35b", + "imdb_id": "tt0106168", + "name": "Walker, Texas Ranger", + "type": "series", + "year": "1993–2001" + }, + { + "_id": "53677eff847ccc8123a15ff1", + "imdb_id": "tt1214085", + "name": "Soul Eater", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "54fb5f21711bd19c92ad42c6", + "imdb_id": "tt0058842", + "name": "Public Eye", + "year": "1965–1975", + "type": "series" + }, + { + "_id": "59b03ef21712e0f4dd1e6822", + "imdb_id": "tt6128300", + "name": "Dynasty", + "year": "2017–2022", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a137ee", + "imdb_id": "tt1988386", + "name": "Miss Fisher's Murder Mysteries", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "5593df94bf6c900d18388e73", + "imdb_id": "tt3250026", + "name": "Zoo", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "58cfe2d01635517fbf56e655", + "imdb_id": "tt5421602", + "name": "Anne with an E", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677ef9847ccc8123a138ad", + "imdb_id": "tt0279600", + "name": "Smallville", + "type": "series", + "year": "2001–2011" + }, + { + "_id": "5c449114d582b2575632d6db", + "imdb_id": "tt0052481", + "name": "Laramie", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "541d9757a8f27b1bb90cbaf2", + "imdb_id": "tt1746428", + "name": "Sidekick", + "type": "series", + "year": "2010–2019" + }, + { + "_id": "5bd2c992173739c9f42e01f3", + "imdb_id": "tt7569592", + "name": "Chilling Adventures of Sabrina", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "53677ef9847ccc8123a13c27", + "imdb_id": "tt0085032", + "name": "Hotel", + "type": "series", + "year": "1983–1988" + }, + { + "_id": "53677ef9847ccc8123a14136", + "imdb_id": "tt0056757", + "name": "The Fugitive", + "type": "series", + "year": "1963–1967" + }, + { + "_id": "5af5eba645a99666bd0c768c", + "imdb_id": "tt0069557", + "type": "series", + "name": "Barnaby Jones", + "year": "1973–1980" + }, + { + "_id": "59b03ef21712e0f4dd1e686c", + "imdb_id": "tt6470478", + "name": "The Good Doctor", + "type": "series", + "year": "2017–2024" + }, + { + "_id": "53677f68847ccc8123a22d11", + "imdb_id": "tt2942218", + "name": "Log Horizon", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "53677ef9847ccc8123a139ad", + "imdb_id": "tt1583607", + "name": "Hot in Cleveland", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677ef9847ccc8123a13a23", + "imdb_id": "tt0458254", + "name": "The Colbert Report", + "type": "series", + "year": "2005–2014" + }, + { + "_id": "57efb835d7e54929823f1ddc", + "imdb_id": "tt4508902", + "name": "One Punch Man", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53677f29847ccc8123a1dd3e", + "imdb_id": "tt2455546", + "name": "Avengers Assemble", + "type": "series", + "year": "2012–2019" + }, + { + "_id": "557ee9fcbf6c900d1835842f", + "imdb_id": "tt4494948", + "name": "Shimmer and Shine", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "53677f2e847ccc8123a1e3bb", + "imdb_id": "tt0217960", + "name": "Something in the Air", + "type": "series", + "year": "2000–2002" + }, + { + "_id": "5c184bde173739c9f4a59a23", + "imdb_id": "tt9016022", + "name": "Basketball: A Love Story", + "type": "series", + "year": "2018–" + }, + { + "_id": "57e5c5ccd7e54929823e9891", + "imdb_id": "tt1399045", + "name": "MacGyver", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "5d8d796fc4ccb5dd9270691c", + "imdb_id": "tt9055008", + "name": "Evil", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a13bed", + "imdb_id": "tt0106179", + "name": "The X-Files", + "type": "series", + "year": "1993–2018" + }, + { + "_id": "53677ef9847ccc8123a13790", + "imdb_id": "tt0460681", + "name": "Supernatural", + "type": "series", + "year": "2005–2020" + }, + { + "_id": "55075dd3711bd19c92ade16d", + "imdb_id": "tt2074035", + "name": "Horizon in the Middle of Nowhere", + "year": "2011–2012", + "type": "series" + }, + { + "_id": "659540d3bd36726cbb050188", + "imdb_id": "tt26628595", + "name": "Marry My Husband", + "type": "series", + "year": "2024–" + }, + { + "_id": "61495a1b64ec43ef98158a74", + "imdb_id": "tt14218674", + "name": "NCIS: Hawai'i", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677efa847ccc8123a14904", + "imdb_id": "tt0364828", + "name": "Las Vegas", + "type": "series", + "year": "2003–2008" + }, + { + "_id": "5c11c3bb173739c9f4315778", + "imdb_id": "tt1413677", + "name": "My Big Big Friend", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "5beb40b9173739c9f438ed10", + "imdb_id": "tt7745956", + "name": "She-Ra and the Princesses of Power", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "53677f21847ccc8123a1ca87", + "imdb_id": "tt0292800", + "name": "The Grim Adventures of Billy & Mandy", + "type": "series", + "year": "2001–2007" + }, + { + "_id": "5ac9f99ba5989fb3214c1873", + "imdb_id": "tt7016936", + "type": "series", + "name": "Killing Eve", + "year": "2018–2022" + }, + { + "_id": "53677f00847ccc8123a16643", + "imdb_id": "tt0279077", + "name": "FLCL", + "type": "series", + "year": "2000–2001" + }, + { + "_id": "53677f32847ccc8123a1e6be", + "imdb_id": "tt2375720", + "name": "The Doctor Blake Mysteries", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677efd847ccc8123a15622", + "imdb_id": "tt0060009", + "name": "Mission: Impossible", + "type": "series", + "year": "1966–1973" + }, + { + "_id": "5eba5d2f5424253341e2819d", + "imdb_id": "tt11886236", + "name": "Princess Connect! Re: Dive", + "type": "series", + "year": "2020–" + }, + { + "_id": "5529420ecc9eee85bb52e2c8", + "imdb_id": "tt4176370", + "name": "Guardians of the Galaxy", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a146a0", + "imdb_id": "tt0362357", + "name": "New Tricks", + "type": "series", + "year": "2003–2015" + }, + { + "_id": "627e4fc664ec43ef987d9245", + "imdb_id": "tt13833978", + "name": "The Lincoln Lawyer", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f6a847ccc8123a22de5", + "imdb_id": "tt3115338", + "name": "Nisekoi", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "60c6205664ec43ef98734b2e", + "imdb_id": "tt13167196", + "name": "Edens Zero", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "55c8a051bf6c900d183dc177", + "imdb_id": "tt4474344", + "name": "Blindspot", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14ce9", + "imdb_id": "tt0056777", + "name": "The Outer Limits", + "type": "series", + "year": "1963–1965" + }, + { + "_id": "55198011cc9eee85bb52dd58", + "imdb_id": "tt3837246", + "name": "Assassination Classroom", + "year": "2013–2016", + "type": "series" + }, + { + "_id": "5ea932805424253341bb230e", + "imdb_id": "tt7826376", + "name": "Upload", + "type": "series", + "year": "2020–" + }, + { + "_id": "588aacf91635517fbf56a921", + "imdb_id": "tt5420376", + "name": "Riverdale", + "type": "series", + "year": "2017–2023" + }, + { + "_id": "6599a6fabd36726cbb2bbc78", + "imdb_id": "tt21209876", + "name": "Solo Leveling", + "type": "series", + "year": "2024–" + }, + { + "_id": "53677efc847ccc8123a153c5", + "imdb_id": "tt0863046", + "name": "Flight of the Conchords", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "57dd5a13d7e54929823e26d9", + "imdb_id": "tt4644488", + "name": "Dragon Ball Super", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "53677f0f847ccc8123a19c5f", + "imdb_id": "tt0061265", + "name": "The Invaders", + "type": "series", + "year": "1967–1968" + }, + { + "_id": "53677ef9847ccc8123a140fa", + "imdb_id": "tt0108778", + "name": "Friends", + "type": "series", + "year": "1994–2004" + }, + { + "_id": "5c0ad577173739c9f4d594b4", + "imdb_id": "tt6874502", + "name": "Unikitty!", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677ef5847ccc8123a13753", + "imdb_id": "tt0185133", + "name": "Yu Yu Hakusho: Ghost Files", + "type": "series", + "year": "1992–1995" + }, + { + "_id": "55197feccc9eee85bb52dd0b", + "imdb_id": "tt1693435", + "name": "MAJOR", + "year": "2004–2012", + "type": "series" + }, + { + "_id": "5c0d5adc173739c9f450c6d8", + "imdb_id": "tt0293737", + "name": "The Proud Family", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "53677efd847ccc8123a15b37", + "imdb_id": "tt0094469", + "name": "Garfield and Friends", + "type": "series", + "year": "1988–1995" + }, + { + "_id": "5378cbf6847ccc8123ad3456", + "imdb_id": "tt3216608", + "name": "Dr. Ken", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677f5a847ccc8123a21bd2", + "imdb_id": "tt0432648", + "name": "Celebrity Fit Club", + "type": "series", + "year": "2005–2010" + }, + { + "_id": "53677ef9847ccc8123a137d3", + "imdb_id": "tt1758772", + "name": "Switched at Birth", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "53677efa847ccc8123a14951", + "imdb_id": "tt1135300", + "name": "Dollhouse", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "58e5f46f1635517fbf56e6c6", + "imdb_id": "tt5722190", + "name": "Brockmire", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "54e19892e573cadcfa1fd63e", + "imdb_id": "tt2357547", + "name": "Jessica Jones", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53677f3a847ccc8123a1ee2c", + "imdb_id": "tt0367439", + "name": "Wolf's Rain", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677f19847ccc8123a1b114", + "imdb_id": "tt0108756", + "name": "Due South", + "type": "series", + "year": "1994–1999" + }, + { + "_id": "6091046264ec43ef98e0d63e", + "imdb_id": "tt12708542", + "name": "Star Wars: The Bad Batch", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f00847ccc8123a162c9", + "imdb_id": "tt0094466", + "name": "Freddy's Nightmares", + "type": "series", + "year": "1988–1990" + }, + { + "_id": "53677f08847ccc8123a1843f", + "imdb_id": "tt0062578", + "name": "Land of the Giants", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "54e70d48417d39942847ac9a", + "imdb_id": "tt3595776", + "name": "The Odd Couple", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677f05847ccc8123a17c55", + "imdb_id": "tt0088559", + "name": "MacGyver", + "type": "series", + "year": "1985–1992" + }, + { + "_id": "53677f05847ccc8123a17b43", + "imdb_id": "tt0091211", + "name": "Fist of the North Star", + "type": "series", + "year": "1984–1988" + }, + { + "_id": "53677f2e847ccc8123a1e458", + "imdb_id": "tt2215842", + "name": "Father Brown", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f00847ccc8123a163e8", + "imdb_id": "tt0088621", + "name": "Taggart", + "type": "series", + "year": "1983–2010" + }, + { + "_id": "53677f40847ccc8123a1f774", + "imdb_id": "tt2395695", + "name": "Cosmos: A Spacetime Odyssey", + "type": "series", + "year": "2014" + }, + { + "_id": "53677f35847ccc8123a1e9c6", + "imdb_id": "tt1833403", + "name": "Captain Jake and the Never Land Pirates", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "53677f05847ccc8123a17b6e", + "imdb_id": "tt0098830", + "name": "In Living Color", + "type": "series", + "year": "1990–1994" + }, + { + "_id": "53677ef9847ccc8123a14165", + "imdb_id": "tt1415889", + "name": "Good Luck Charlie", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "53677f0f847ccc8123a19712", + "imdb_id": "tt0201391", + "name": "Roswell", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5beeab70173739c9f48b6cd2", + "imdb_id": "tt8714904", + "name": "Narcos: Mexico", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "5f1bd08d5424253341724598", + "imdb_id": "tt11448214", + "name": "Rent-a-Girlfriend", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677f00847ccc8123a165ea", + "imdb_id": "tt0103442", + "name": "Highlander", + "type": "series", + "year": "1992–1998" + }, + { + "_id": "53677ef9847ccc8123a13814", + "imdb_id": "tt1073507", + "name": "Party Down", + "type": "series", + "year": "2009–" + }, + { + "_id": "5a94f73f53336c1ba890feba", + "imdb_id": "tt6474378", + "type": "series", + "name": "Good Girls", + "year": "2018–2021" + }, + { + "_id": "5378cc09847ccc8123ad4552", + "imdb_id": "tt3551096", + "name": "Fresh Off the Boat", + "type": "series", + "year": "2015–2020" + }, + { + "_id": "5bdbd2e8173739c9f44d3d0f", + "imdb_id": "tt7008682", + "name": "Homecoming", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "53677f21847ccc8123a1cb8a", + "imdb_id": "tt2189221", + "name": "Defiance", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "539c4866a8f27b1bb90afe5d", + "imdb_id": "tt0075529", + "name": "The Love Boat", + "type": "series", + "year": "1977–1987" + }, + { + "_id": "59b03ef21712e0f4dd1e6622", + "imdb_id": "tt6111130", + "name": "S.W.A.T.", + "type": "series", + "year": "2017–2024" + }, + { + "_id": "53677efc847ccc8123a150f5", + "imdb_id": "tt0306274", + "name": "What's New, Scooby-Doo?", + "type": "series", + "year": "2002–2006" + }, + { + "_id": "53677f05847ccc8123a17684", + "imdb_id": "tt0096579", + "name": "Family Matters", + "type": "series", + "year": "1989–1998" + }, + { + "_id": "53677f1b847ccc8123a1b871", + "imdb_id": "tt0085029", + "name": "Hardcastle and McCormick", + "type": "series", + "year": "1983–1986" + }, + { + "_id": "539c4866a8f27b1bb90afe93", + "imdb_id": "tt3398228", + "name": "BoJack Horseman", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "59c7a0eb1712e0f4dd3ca41b", + "imdb_id": "tt5531466", + "type": "series", + "name": "DuckTales", + "year": "2017–2021" + }, + { + "_id": "53677efc847ccc8123a153e2", + "imdb_id": "tt0285351", + "name": "According to Jim", + "type": "series", + "year": "2001–2009" + }, + { + "_id": "5c0a53c9173739c9f4dc138c", + "imdb_id": "tt8755712", + "type": "series", + "name": "The Shop", + "year": "2018–" + }, + { + "_id": "57fec6d1d7e54929824008c2", + "imdb_id": "tt5912064", + "name": "Kim's Convenience", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "5a742be8543165dcd875c27e", + "imdb_id": "tt2261227", + "type": "series", + "name": "Altered Carbon", + "year": "2018–2020" + }, + { + "_id": "53677f22847ccc8123a1cbe9", + "imdb_id": "tt0096560", + "name": "Coach", + "type": "series", + "year": "1989–1997" + }, + { + "_id": "53677ef9847ccc8123a1443c", + "imdb_id": "tt0765491", + "name": "Eureka Seven", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "5c119552173739c9f4d13d29", + "imdb_id": "tt8111088", + "name": "The Mandalorian", + "type": "series", + "year": "2019–" + }, + { + "_id": "53eb359ea8f27b1bb90c0863", + "imdb_id": "tt3330720", + "name": "The Last Leg", + "type": "series", + "year": "2012–" + }, + { + "_id": "57e1e61ed7e54929823e6ac8", + "imdb_id": "tt5827228", + "name": "Bull", + "type": "series", + "year": "2016–2022" + }, + { + "_id": "53677f09847ccc8123a18633", + "imdb_id": "tt2139371", + "name": "Transformers: Rescue Bots", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "53677ef9847ccc8123a138c7", + "imdb_id": "tt0319931", + "name": "American Idol", + "type": "series", + "year": "2002–" + }, + { + "_id": "53677f07847ccc8123a18135", + "imdb_id": "tt0088503", + "name": "Dempsey and Makepeace", + "type": "series", + "year": "1985–1986" + }, + { + "_id": "55072fe2711bd19c92adda0a", + "imdb_id": "tt3743822", + "name": "Fear the Walking Dead", + "year": "2015–2023", + "type": "series" + }, + { + "_id": "53677f05847ccc8123a176ab", + "imdb_id": "tt2149175", + "name": "The Americans", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677ef9847ccc8123a13a66", + "imdb_id": "tt1699748", + "name": "Hell on Wheels", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "5c18d97f173739c9f4770552", + "imdb_id": "tt6738600", + "name": "All Out", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f02847ccc8123a16f81", + "imdb_id": "tt0059991", + "name": "The Green Hornet", + "type": "series", + "year": "1966–1967" + }, + { + "_id": "5c0ba934173739c9f43b054e", + "imdb_id": "tt7456722", + "name": "Hunters", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "5ab0d0f553336c1ba8a36cd3", + "imdb_id": "tt7808344", + "type": "series", + "name": "Karakai Jouzu no Takagi-san", + "year": "2018–2022" + }, + { + "_id": "53c58b44a8f27b1bb90b7c7d", + "imdb_id": "tt3155320", + "name": "Extant", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "5c0a7fef173739c9f42d21da", + "imdb_id": "tt6357658", + "type": "series", + "name": "Baki", + "year": "2018–2020" + }, + { + "_id": "53677ef9847ccc8123a13b22", + "imdb_id": "tt0123338", + "name": "60 Minutes", + "type": "series", + "year": "1968–" + }, + { + "_id": "53677efa847ccc8123a1487b", + "imdb_id": "tt0052478", + "name": "Johnny Ringo", + "type": "series", + "year": "1959–1960" + }, + { + "_id": "53677f04847ccc8123a1740e", + "imdb_id": "tt0106004", + "name": "Frasier", + "type": "series", + "year": "1993–2004" + }, + { + "_id": "53677ef9847ccc8123a13b32", + "imdb_id": "tt1520211", + "name": "The Walking Dead", + "type": "series", + "year": "2010–2022" + }, + { + "_id": "55984192bf6c900d1838f5f8", + "imdb_id": "tt0437729", + "name": "The Late Late Show with Craig Ferguson", + "year": "2005–2015", + "type": "series" + }, + { + "_id": "5a0c053d543165dcd8f212fc", + "imdb_id": "tt6881870", + "type": "series", + "name": "Frankie Drake Mysteries", + "year": "2017–2021" + }, + { + "_id": "53677efa847ccc8123a14a97", + "imdb_id": "tt0158552", + "name": "Charmed", + "type": "series", + "year": "1998–2006" + }, + { + "_id": "53677ef9847ccc8123a13a6f", + "imdb_id": "tt1595859", + "name": "Blue Bloods", + "type": "series", + "year": "2010–2024" + }, + { + "_id": "6342ccbd64ec43ef98a27ed8", + "imdb_id": "tt15433166", + "name": "Mobile Suit Gundam: The Witch from Mercury", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677f21847ccc8123a1c93f", + "imdb_id": "tt0425720", + "name": "Tom Goes to the Mayor", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "57e0866bd7e54929823e5a7c", + "imdb_id": "tt4955642", + "type": "series", + "name": "The Good Place", + "year": "2016–2020" + }, + { + "_id": "5c0c3c30173739c9f467aea5", + "imdb_id": "tt8772296", + "name": "Euphoria", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f05847ccc8123a17aca", + "imdb_id": "tt0063925", + "name": "Love, American Style", + "type": "series", + "year": "1969–1974" + }, + { + "_id": "567c8a22bb83c664989a183a", + "imdb_id": "tt5193172", + "name": "Dawn of the Croods", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "5c2034b4173739c9f4e5e0f7", + "imdb_id": "tt0338621", + "name": "Kirby: Right Back at Ya!", + "type": "series", + "year": "2001–2003" + }, + { + "_id": "5c163fa4173739c9f40b725d", + "imdb_id": "tt0131160", + "name": "Cat's Eye", + "type": "series", + "year": "1983–1985" + }, + { + "_id": "55075d47711bd19c92addbeb", + "imdb_id": "tt0115082", + "name": "3rd Rock from the Sun", + "year": "1996–2001", + "type": "series" + }, + { + "_id": "53f87474a8f27b1bb90c3b56", + "imdb_id": "tt0140733", + "name": "Crown Court", + "type": "series", + "year": "1972–2007" + }, + { + "_id": "5527c3c7cc9eee85bb52e28d", + "imdb_id": "tt3952746", + "name": "Just Add Magic", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677f02847ccc8123a17092", + "imdb_id": "tt0101114", + "name": "Heartbeat", + "type": "series", + "year": "1992–2010" + }, + { + "_id": "5e581949c4ccb5dd92ae6d11", + "imdb_id": "tt10936342", + "name": "Transplant", + "type": "series", + "year": "2020–2024" + }, + { + "_id": "588b1d821635517fbf56a9a5", + "imdb_id": "tt5419200", + "name": "Justice League Action", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "53677efd847ccc8123a15509", + "imdb_id": "tt0050063", + "name": "Sugarfoot", + "type": "series", + "year": "1957–1961" + }, + { + "_id": "53d3d592a8f27b1bb90bae88", + "imdb_id": "tt0175058", + "name": "The Powerpuff Girls", + "type": "series", + "year": "1998–2004" + }, + { + "_id": "53677f0a847ccc8123a18976", + "imdb_id": "tt0068074", + "name": "Circle of Fear", + "type": "series", + "year": "1972–1973" + }, + { + "_id": "5f79bbac5424253341f27818", + "imdb_id": "tt12311976", + "name": "TONIKAWA: Over the Moon for You", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677efa847ccc8123a1488a", + "imdb_id": "tt0460690", + "name": "The Unit", + "type": "series", + "year": "2006–2009" + }, + { + "_id": "53677ef5847ccc8123a1375b", + "imdb_id": "tt0369179", + "name": "Two and a Half Men", + "type": "series", + "year": "2003–2015" + }, + { + "_id": "600cbfbd54242533411611b6", + "imdb_id": "tt13103134", + "name": "Horimiya", + "type": "series", + "year": "2021" + }, + { + "_id": "53677f00847ccc8123a167c2", + "imdb_id": "tt0084988", + "name": "Blackadder", + "type": "series", + "year": "1982–1983" + }, + { + "_id": "5bc7a7a0173739c9f46eb556", + "imdb_id": "tt8103070", + "name": "Legacies", + "type": "series", + "year": "2018–2022" + }, + { + "_id": "5c17d8a7173739c9f4cde03e", + "imdb_id": "tt3432210", + "name": "Yo-Kai Watch", + "type": "series", + "year": "2014–" + }, + { + "_id": "5c0f98cf173739c9f40d5450", + "imdb_id": "tt0066689", + "name": "The New Dick Van Dyke Show", + "type": "series", + "year": "1971–1974" + }, + { + "_id": "53677f15847ccc8123a1a885", + "imdb_id": "tt2768802", + "name": "Mickey Mouse", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "5c1c83ce173739c9f433bd71", + "imdb_id": "tt7203552", + "name": "The Morning Show", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f2c847ccc8123a1e320", + "imdb_id": "tt1877889", + "name": "Teenage Mutant Ninja Turtles", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "53677ef9847ccc8123a13a39", + "imdb_id": "tt1837642", + "name": "Revenge", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "5600c0da6c6a1c0b815c4f28", + "imdb_id": "tt4384086", + "name": "Life in Pieces", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677f07847ccc8123a18102", + "imdb_id": "tt0077089", + "name": "Taxi", + "type": "series", + "year": "1978–1983" + }, + { + "_id": "53677ef9847ccc8123a13ace", + "imdb_id": "tt1442437", + "name": "Modern Family", + "type": "series", + "year": "2009–2020" + }, + { + "_id": "53677efa847ccc8123a14c22", + "imdb_id": "tt1034201", + "name": "Britain's Got Talent", + "type": "series", + "year": "2007–" + }, + { + "_id": "54fb5f87711bd19c92ad4758", + "imdb_id": "tt3981938", + "name": "Rage of Bahamut: Genesis", + "year": "2014", + "type": "series" + }, + { + "_id": "53677efc847ccc8123a14f8d", + "imdb_id": "tt0206501", + "name": "Nova", + "type": "series", + "year": "1974–" + }, + { + "_id": "53ac6496a8f27b1bb90b2fc0", + "imdb_id": "tt0090418", + "name": "Designing Women", + "type": "series", + "year": "1986–1993" + }, + { + "_id": "5de808acc4ccb5dd92569c67", + "imdb_id": "tt10885406", + "name": "Ascendance of a Bookworm", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "5c1fecd5173739c9f4547637", + "imdb_id": "tt2549176", + "name": "Cardfight!! Vanguard", + "type": "series", + "year": "2011–" + }, + { + "_id": "5c2746ac173739c9f4575b3d", + "imdb_id": "tt9359796", + "name": "Blade Runner: Black Lotus", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677f47847ccc8123a20033", + "imdb_id": "tt0856348", + "name": "Basilisk: The Kouga Ninja Scrolls", + "type": "series", + "year": "2005" + }, + { + "_id": "53677efa847ccc8123a14cda", + "imdb_id": "tt0251497", + "name": "Big Brother", + "type": "series", + "year": "2000–" + }, + { + "_id": "5e5a6a0cc4ccb5dd9248ee4c", + "imdb_id": "tt8050756", + "name": "The Owl House", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "54d7b476e573cadcfa1fb263", + "imdb_id": "tt0245637", + "name": "Little Bear", + "type": "series", + "year": "1995–2003" + }, + { + "_id": "53677f07847ccc8123a17e7b", + "imdb_id": "tt0057751", + "name": "Gilligan's Island", + "type": "series", + "year": "1963–1967" + }, + { + "_id": "5bbdf461173739c9f4fac689", + "imdb_id": "tt0159175", + "name": "Lupin the Third", + "type": "series", + "year": "1971–1972" + }, + { + "_id": "53677ef9847ccc8123a1447f", + "imdb_id": "tt0077000", + "name": "Dallas", + "type": "series", + "year": "1978–1991" + }, + { + "_id": "53677f02847ccc8123a16dd7", + "imdb_id": "tt0086691", + "name": "Crazy Like a Fox", + "type": "series", + "year": "1984–1986" + }, + { + "_id": "53677ef9847ccc8123a1419c", + "imdb_id": "tt1519931", + "name": "Haven", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677f66847ccc8123a229f3", + "imdb_id": "tt2244077", + "name": "Littlest Pet Shop", + "type": "series", + "year": "2012–2022" + }, + { + "_id": "5c2c77cd173739c9f4704c2d", + "imdb_id": "tt0112044", + "name": "Die Harald Schmidt Show", + "type": "series", + "year": "1995–2004" + }, + { + "_id": "53677f03847ccc8123a1727b", + "imdb_id": "tt0047736", + "name": "Gunsmoke", + "type": "series", + "year": "1955–1975" + }, + { + "_id": "541463a2a8f27b1bb90c99c3", + "imdb_id": "tt3843168", + "name": "Z Nation", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "6020b2c954242533419483cc", + "imdb_id": "tt11242246", + "name": "The Equalizer", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a13834", + "imdb_id": "tt1820166", + "name": "Ridiculousness", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f25847ccc8123a1d4cf", + "imdb_id": "tt0452718", + "name": "Surface", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "59ce2a5b067c4652103b9d17", + "imdb_id": "tt6524350", + "type": "series", + "name": "Big Mouth", + "year": "2017–2024" + }, + { + "_id": "65170350bd36726cbb8c457b", + "imdb_id": "tt22248376", + "name": "Frieren: Beyond Journey's End", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c16843d173739c9f494a1f5", + "imdb_id": "tt5023666", + "name": "The Heroic Legend of Arslan", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c1e2260173739c9f40a6df6", + "imdb_id": "tt0111056", + "name": "Gensomaden Saiyuki", + "type": "series", + "year": "2000–2001" + }, + { + "_id": "5c09d277173739c9f41e4009", + "imdb_id": "tt7049682", + "name": "Watchmen", + "type": "series", + "year": "2019" + }, + { + "_id": "53677f29847ccc8123a1da4c", + "imdb_id": "tt0912343", + "name": "Tim and Eric Awesome Show, Great Job!", + "type": "series", + "year": "2007–2017" + }, + { + "_id": "5c0b05c7173739c9f4389f39", + "imdb_id": "tt4563516", + "name": "DD Fist of the North Star", + "type": "series", + "year": "2013–" + }, + { + "_id": "6349699e64ec43ef982dcd7a", + "imdb_id": "tt16764368", + "name": "Urusei Yatsura", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677efa847ccc8123a1475e", + "imdb_id": "tt0115341", + "name": "Sabrina the Teenage Witch", + "type": "series", + "year": "1996–2003" + }, + { + "_id": "53677f4f847ccc8123a20db8", + "imdb_id": "tt3294962", + "name": "Saturday Night Live Korea", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "5c1462fd173739c9f4e758e0", + "imdb_id": "tt1751634", + "name": "The Sandman", + "type": "series", + "year": "2022–" + }, + { + "_id": "61dff46264ec43ef98a24620", + "imdb_id": "tt13146488", + "name": "Peacemaker", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f23847ccc8123a1d063", + "imdb_id": "tt2442560", + "name": "Peaky Blinders", + "type": "series", + "year": "2013–2022" + }, + { + "_id": "53677f45847ccc8123a1fdcb", + "imdb_id": "tt0051290", + "name": "Lawman", + "type": "series", + "year": "1958–1962" + }, + { + "_id": "5c10258f173739c9f41f114f", + "imdb_id": "tt8806524", + "name": "Star Trek: Picard", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "5c0901d5173739c9f4886159", + "imdb_id": "tt7892026", + "name": "La resistencia", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f1f847ccc8123a1c47f", + "imdb_id": "tt2325846", + "name": "DreamWorks Dragons", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "5c14d8c6173739c9f48b7640", + "imdb_id": "tt0042116", + "name": "The Jack Benny Program", + "type": "series", + "year": "1950–1965" + }, + { + "_id": "54ff1e6c711bd19c92adcf4b", + "imdb_id": "tt2891574", + "name": "Ballers", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677f26847ccc8123a1d7ba", + "imdb_id": "tt0206511", + "name": "Even Stevens", + "type": "series", + "year": "2000–2003" + }, + { + "_id": "53677f05847ccc8123a1769e", + "imdb_id": "tt0050035", + "name": "M Squad", + "type": "series", + "year": "1957–1960" + }, + { + "_id": "53677f0a847ccc8123a18c84", + "imdb_id": "tt1132205", + "name": "Minami-ke", + "type": "series", + "year": "2007–" + }, + { + "_id": "53677ef9847ccc8123a1394d", + "imdb_id": "tt0790772", + "name": "Rules of Engagement", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "53677efd847ccc8123a15922", + "imdb_id": "tt0059968", + "name": "Batman", + "type": "series", + "year": "1966–1968" + }, + { + "_id": "632ae2b764ec43ef987db136", + "imdb_id": "tt13207736", + "name": "Monster", + "type": "series", + "year": "2022–2024" + }, + { + "_id": "61f38ea364ec43ef98f1970d", + "imdb_id": "tt11247158", + "name": "The Legend of Vox Machina", + "type": "series", + "year": "2022–" + }, + { + "_id": "62e6bcca64ec43ef981ad1cd", + "imdb_id": "tt14400866", + "name": "A Couple of Cuckoos", + "type": "series", + "year": "2022" + }, + { + "_id": "53677ef9847ccc8123a137e9", + "imdb_id": "tt1724587", + "name": "Green Lantern: The Animated Series", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "5c4f221cd582b2575607dd1d", + "imdb_id": "tt9561862", + "name": "Love, Death & Robots", + "type": "series", + "year": "2019–" + }, + { + "_id": "5d9ee182c4ccb5dd921f763f", + "imdb_id": "tt10313176", + "name": "Nancy Drew", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677efa847ccc8123a147ea", + "imdb_id": "tt0057752", + "name": "Gomer Pyle: USMC", + "type": "series", + "year": "1964–1969" + }, + { + "_id": "5c3380ce173739c9f406e213", + "imdb_id": "tt7050978", + "name": "Dorothy and the Wizard of Oz", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677f38847ccc8123a1ee05", + "imdb_id": "tt0072554", + "name": "One Day at a Time", + "type": "series", + "year": "1975–1984" + }, + { + "_id": "53677ef9847ccc8123a13895", + "imdb_id": "tt0810788", + "name": "Burn Notice", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "53677ef9847ccc8123a13dfb", + "imdb_id": "tt1871731", + "name": "Ninjago: Masters of Spinjitzu", + "type": "series", + "year": "2011–2019" + }, + { + "_id": "53677ef9847ccc8123a13931", + "imdb_id": "tt0496424", + "name": "30 Rock", + "type": "series", + "year": "2006–2013" + }, + { + "_id": "53677f00847ccc8123a163d7", + "imdb_id": "tt0157246", + "name": "Will & Grace", + "type": "series", + "year": "1998–2020" + }, + { + "_id": "53677ef9847ccc8123a13ba3", + "imdb_id": "tt1179817", + "name": "The Secret Life of the American Teenager", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677ef9847ccc8123a1385a", + "imdb_id": "tt0460627", + "name": "Bones", + "type": "series", + "year": "2005–2017" + }, + { + "_id": "53677f08847ccc8123a18396", + "imdb_id": "tt0098936", + "name": "Twin Peaks", + "type": "series", + "year": "1990–1991" + }, + { + "_id": "5c14a50f173739c9f4393288", + "imdb_id": "tt5334292", + "name": "Dimension W", + "type": "series", + "year": "2016–" + }, + { + "_id": "53677f12847ccc8123a1a018", + "imdb_id": "tt0072567", + "name": "Starsky and Hutch", + "type": "series", + "year": "1975–1979" + }, + { + "_id": "5c12728b173739c9f44ac5f4", + "imdb_id": "tt0088610", + "name": "Small Wonder", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "5a7f367c543165dcd8827011", + "imdb_id": "tt7865090", + "type": "series", + "name": "Darling in the Franxx", + "year": "2018" + }, + { + "_id": "54fb5f67711bd19c92ad45a9", + "imdb_id": "tt3398976", + "name": "Knights of Sidonia", + "year": "2014–2015", + "type": "series" + }, + { + "_id": "5c39fbf3d582b25756eea9c9", + "imdb_id": "tt2904426", + "name": "Fate/kaleid liner Prisma Illya", + "type": "series", + "year": "2013–" + }, + { + "_id": "5c0b7953173739c9f4e0ff1c", + "imdb_id": "tt4816058", + "name": "Dragons: Race to the Edge", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "53677efc847ccc8123a14ff9", + "imdb_id": "tt0076987", + "name": "Blake's 7", + "type": "series", + "year": "1978–1981" + }, + { + "_id": "53677f05847ccc8123a1776e", + "imdb_id": "tt0096708", + "name": "Tales from the Crypt", + "type": "series", + "year": "1989–1996" + }, + { + "_id": "53677ef9847ccc8123a14418", + "imdb_id": "tt1641384", + "name": "Young Justice", + "type": "series", + "year": "2010–2022" + }, + { + "_id": "5c2b094a173739c9f4eed5d5", + "imdb_id": "tt0090530", + "name": "Street Legal", + "type": "series", + "year": "1987–1994" + }, + { + "_id": "53677ef9847ccc8123a141bc", + "imdb_id": "tt0187636", + "name": "Farscape", + "type": "series", + "year": "1999–2003" + }, + { + "_id": "5ac8d24ba5989fb3210999dc", + "imdb_id": "tt7741824", + "type": "series", + "name": "The Boss Baby: Back in Business", + "year": "2018–2021" + }, + { + "_id": "53677ef9847ccc8123a13fa0", + "imdb_id": "tt0285403", + "name": "Scrubs", + "type": "series", + "year": "2001–2010" + }, + { + "_id": "53677ef9847ccc8123a13851", + "imdb_id": "tt1723816", + "name": "Girls", + "type": "series", + "year": "2012–2017" + }, + { + "_id": "5c0b0a0e173739c9f440bb70", + "imdb_id": "tt7588054", + "type": "series", + "name": "Roswell, New Mexico", + "year": "2019–2022" + }, + { + "_id": "53677eff847ccc8123a15cb0", + "imdb_id": "tt2100976", + "name": "Impractical Jokers", + "type": "series", + "year": "2011–" + }, + { + "_id": "57667d902e22ea26fe51d397", + "imdb_id": "tt0190924", + "name": "Space Stars", + "year": "1981", + "type": "series" + }, + { + "_id": "569686d7bb83c664989c90cc", + "imdb_id": "tt4145054", + "name": "Shadowhunters", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "5c43cea1d582b257567299e0", + "imdb_id": "tt6741278", + "name": "Invincible", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a13dc7", + "imdb_id": "tt0407362", + "name": "Battlestar Galactica", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "53677f07847ccc8123a1804c", + "imdb_id": "tt0044230", + "name": "The Adventures of Ozzie and Harriet", + "type": "series", + "year": "1952–1966" + }, + { + "_id": "53677ef9847ccc8123a13f0e", + "imdb_id": "tt0374455", + "name": "Stargate: Atlantis", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "53677ef9847ccc8123a13e1c", + "imdb_id": "tt0086659", + "name": "'Allo 'Allo!", + "type": "series", + "year": "1982–1992" + }, + { + "_id": "53677ef9847ccc8123a13f73", + "imdb_id": "tt0083452", + "name": "Nature", + "type": "series", + "year": "1982–" + }, + { + "_id": "56536418bb83c6649895f893", + "imdb_id": "tt3230854", + "name": "The Expanse", + "year": "2015–2022", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13a25", + "imdb_id": "tt1608180", + "name": "Mike & Molly", + "type": "series", + "year": "2010–2016" + }, + { + "_id": "53677ef9847ccc8123a137f1", + "imdb_id": "tt1587678", + "name": "Happy Endings", + "type": "series", + "year": "2011–2020" + }, + { + "_id": "53677ef9847ccc8123a13944", + "imdb_id": "tt1103987", + "name": "Leverage", + "type": "series", + "year": "2008–2012" + }, + { + "_id": "53677ef9847ccc8123a13c6c", + "imdb_id": "tt1986770", + "name": "Anger Management", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677ef9847ccc8123a137b5", + "imdb_id": "tt1830888", + "name": "The Exes", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "54e60074fc2ab98b66971c2a", + "imdb_id": "tt0047757", + "name": "The Mickey Mouse Club", + "type": "series", + "year": "1955–1958" + }, + { + "_id": "53677f4f847ccc8123a20abb", + "imdb_id": "tt0047706", + "name": "The Adventures of Robin Hood", + "type": "series", + "year": "1955–1960" + }, + { + "_id": "5601ff0f6c6a1c0b815c67a7", + "imdb_id": "tt4558858", + "name": "New Looney Tunes", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a14124", + "imdb_id": "tt1622696", + "name": "Ben 10: Ultimate Alien", + "type": "series", + "year": "2010–2012" + }, + { + "_id": "53677ef9847ccc8123a143f1", + "imdb_id": "tt0103491", + "name": "Melrose Place", + "type": "series", + "year": "1992–1999" + }, + { + "_id": "53677f19847ccc8123a1b2a1", + "imdb_id": "tt2183404", + "name": "Rectify", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677f0c847ccc8123a18d80", + "imdb_id": "tt1936532", + "name": "Major Crimes", + "type": "series", + "year": "2012–2018" + }, + { + "_id": "53677f05847ccc8123a176df", + "imdb_id": "tt2710394", + "name": "Reign", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "5c146e78173739c9f4f97163", + "imdb_id": "tt1976753", + "name": "Flor Salvaje", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677ef9847ccc8123a139f9", + "imdb_id": "tt1405406", + "name": "The Vampire Diaries", + "type": "series", + "year": "2009–2017" + }, + { + "_id": "54bacf638527d2e0cb508158", + "imdb_id": "tt1740299", + "name": "The Man in the High Castle", + "type": "series", + "year": "2015–2019" + }, + { + "_id": "53c58b44a8f27b1bb90b7c0f", + "imdb_id": "tt0113483", + "name": "Joseph", + "type": "series", + "year": "1995" + }, + { + "_id": "53677f04847ccc8123a17479", + "imdb_id": "tt0105935", + "name": "Aladdin", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "53677f0a847ccc8123a18bde", + "imdb_id": "tt0096694", + "name": "Saved by the Bell", + "type": "series", + "year": "1989–1992" + }, + { + "_id": "577abba8f0b6c53b3c778716", + "imdb_id": "tt1064899", + "name": "Queen of the South", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13a7c", + "imdb_id": "tt1441135", + "name": "Flashforward", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "53677ef9847ccc8123a13ffa", + "imdb_id": "tt0083437", + "name": "Knight Rider", + "type": "series", + "year": "1982–1986" + }, + { + "_id": "53677f2f847ccc8123a1e4cf", + "imdb_id": "tt0055683", + "name": "The Jetsons", + "type": "series", + "year": "1962–1963" + }, + { + "_id": "5c116a6d173739c9f475df7d", + "imdb_id": "tt0144724", + "name": "Malhação", + "type": "series", + "year": "1995–2020" + }, + { + "_id": "536907fc847ccc8123acde80", + "imdb_id": "tt0058816", + "name": "I Spy", + "type": "series", + "year": "1965–1968" + }, + { + "_id": "53677f0c847ccc8123a193bf", + "imdb_id": "tt0101081", + "name": "Dinosaurs", + "type": "series", + "year": "1991–1994" + }, + { + "_id": "5c2e895d173739c9f4443583", + "imdb_id": "tt0816387", + "name": "Kyô kara maô!", + "type": "series", + "year": "2004–" + }, + { + "_id": "587fc2531635517fbf5695ff", + "imdb_id": "tt4834206", + "name": "A Series of Unfortunate Events", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "570f0577890e549c9a5833f3", + "imdb_id": "tt4718304", + "name": "The Powerpuff Girls", + "year": "2016–2023", + "type": "series" + }, + { + "_id": "64305e9764ec43ef98cfb0d6", + "imdb_id": "tt21209804", + "name": "Mashle: Magic and Muscles", + "type": "series", + "year": "2023–" + }, + { + "_id": "59f2f845067c465210ed1fe5", + "imdb_id": "tt7441658", + "type": "series", + "name": "Black Clover", + "year": "2017–2021" + }, + { + "_id": "557f064fbf6c900d1835848b", + "imdb_id": "tt0042123", + "name": "Lux Video Theatre", + "year": "1950–1959", + "type": "series" + }, + { + "_id": "53677f17847ccc8123a1ab6d", + "imdb_id": "tt0123366", + "name": "The View", + "type": "series", + "year": "1997–" + }, + { + "_id": "57ff6f9ad7e5492982400f39", + "imdb_id": "tt0068044", + "name": "Banacek", + "year": "1972–1974", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a145e5", + "imdb_id": "tt0348913", + "name": "Dead Like Me", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "5c0bdc9d173739c9f49f435e", + "imdb_id": "tt9225320", + "name": "Radiant", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677ef9847ccc8123a137b7", + "imdb_id": "tt1219024", + "name": "Castle", + "type": "series", + "year": "2009–2016" + }, + { + "_id": "631f17cb64ec43ef9821baa8", + "imdb_id": "tt8291284", + "name": "The Peripheral", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f08847ccc8123a183fa", + "imdb_id": "tt0083399", + "name": "Cheers", + "type": "series", + "year": "1982–1993" + }, + { + "_id": "53677ef9847ccc8123a13b8c", + "imdb_id": "tt1587669", + "name": "Body of Proof", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "53677f4f847ccc8123a20abe", + "imdb_id": "tt0122356", + "name": "The Mysterious Cities of Gold", + "type": "series", + "year": "1982–1983" + }, + { + "_id": "53677f15847ccc8123a1a7c9", + "imdb_id": "tt0062572", + "name": "It Takes a Thief", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "53677f79847ccc8123a23b8b", + "imdb_id": "tt2575988", + "name": "Silicon Valley", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "5e9017f105bdfe7d18e27a32", + "imdb_id": "tt8400662", + "name": "Jashin-chan Dropkick", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f05847ccc8123a179eb", + "imdb_id": "tt0069620", + "name": "Police Story", + "type": "series", + "year": "1973–1980" + }, + { + "_id": "57ec8000d7e54929823ef766", + "imdb_id": "tt5024912", + "name": "Insecure", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "53677f20847ccc8123a1c705", + "imdb_id": "tt0167565", + "name": "The Count of Monte Cristo", + "type": "series", + "year": "1998" + }, + { + "_id": "5c390b60d582b25756742d1d", + "imdb_id": "tt8741368", + "name": "Rugrats", + "type": "series", + "year": "2021–" + }, + { + "_id": "575e46152e22ea26fe51773f", + "imdb_id": "tt4878326", + "name": "Wynonna Earp", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "5991bd833e5e4b900ae85c31", + "imdb_id": "tt5761496", + "name": "Get Shorty", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677f54847ccc8123a21295", + "imdb_id": "tt1637574", + "name": "Conan", + "type": "series", + "year": "2010–2021" + }, + { + "_id": "5aa3158153336c1ba83f90ef", + "imdb_id": "tt6461812", + "name": "Deception", + "year": "2018", + "type": "series" + }, + { + "_id": "53677f17847ccc8123a1af45", + "imdb_id": "tt1307224", + "name": "Kid vs. Kat", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "53677efa847ccc8123a14959", + "imdb_id": "tt0088526", + "name": "The Golden Girls", + "type": "series", + "year": "1985–1992" + }, + { + "_id": "5a65d78b543165dcd87cd09a", + "imdb_id": "tt4604612", + "name": "The Alienist", + "year": "2018–2020", + "type": "series" + }, + { + "_id": "57fd9864d7e54929823ff505", + "imdb_id": "tt5396394", + "type": "series", + "name": "American Housewife", + "year": "2016–2021" + }, + { + "_id": "5c0ad5ab173739c9f4d5f86a", + "imdb_id": "tt7713450", + "name": "Craig of the Creek", + "type": "series", + "year": "2018–2024" + }, + { + "_id": "558ece8fbf6c900d18381c2d", + "imdb_id": "tt4507442", + "name": "Best Friends Whenever", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "581ae9d855f8aab460cfc0ca", + "imdb_id": "tt5351176", + "name": "The Circus: Inside the Greatest Political Show on Earth", + "type": "series", + "year": "2016–2023" + }, + { + "_id": "5c118f57173739c9f4c4b9f9", + "imdb_id": "tt8425532", + "name": "Pennyworth", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677ef9847ccc8123a13d20", + "imdb_id": "tt0073972", + "name": "Charlie's Angels", + "type": "series", + "year": "1976–1981" + }, + { + "_id": "5834f3b3b0a40c25066d27c5", + "imdb_id": "tt5460226", + "name": "Search Party", + "type": "series", + "year": "2016–2022" + }, + { + "_id": "62b41ee564ec43ef98526532", + "imdb_id": "tt14452776", + "name": "The Bear", + "type": "series", + "year": "2022–" + }, + { + "_id": "550e2710cc9eee85bb52d935", + "imdb_id": "tt0272388", + "name": "House of Mouse", + "year": "2001–2003", + "type": "series" + }, + { + "_id": "6012427354242533410287da", + "imdb_id": "tt8690918", + "name": "Resident Alien", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677efa847ccc8123a14982", + "imdb_id": "tt0415463", + "name": "Zoey 101", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "53677f19847ccc8123a1b19b", + "imdb_id": "tt2874692", + "name": "When Calls the Heart", + "type": "series", + "year": "2014–" + }, + { + "_id": "5f766dda542425334162173f", + "imdb_id": "tt10148174", + "name": "The Walking Dead: World Beyond", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "5c3a8710d582b25756419cd6", + "imdb_id": "tt9522300", + "name": "Kaguya-sama: Love is War", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "55078876711bd19c92ade321", + "imdb_id": "tt3621796", + "name": "Fate/stay night [Unlimited Blade Works]", + "year": "2014–2015", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a138d6", + "imdb_id": "tt0412142", + "name": "House", + "type": "series", + "year": "2004–2012" + }, + { + "_id": "53677f1d847ccc8123a1bf7e", + "imdb_id": "tt0068067", + "name": "Emergency!", + "type": "series", + "year": "1972–1979" + }, + { + "_id": "53677f32847ccc8123a1e74c", + "imdb_id": "tt0056739", + "name": "Astro Boy", + "type": "series", + "year": "1963–1965" + }, + { + "_id": "53677f43847ccc8123a1fb74", + "imdb_id": "tt0306370", + "name": "The Osbournes", + "type": "series", + "year": "2002–2005" + }, + { + "_id": "53677f0a847ccc8123a18c53", + "imdb_id": "tt0042094", + "name": "The Colgate Comedy Hour", + "type": "series", + "year": "1950–1955" + }, + { + "_id": "551256cbcc9eee85bb52db63", + "imdb_id": "tt3741634", + "name": "Tokyo Ghoul", + "year": "2014", + "type": "series" + }, + { + "_id": "53677ef5847ccc8123a13775", + "imdb_id": "tt1495708", + "name": "Covert Affairs", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "53677f03847ccc8123a1730c", + "imdb_id": "tt0073992", + "name": "Family", + "type": "series", + "year": "1976–1980" + }, + { + "_id": "5c0c53f4173739c9f49a0478", + "imdb_id": "tt6965802", + "name": "OK K.O.! Let's Be Heroes", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "62b58d9664ec43ef98720928", + "imdb_id": "tt14271498", + "name": "Loot", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f13847ccc8123a1a216", + "imdb_id": "tt2243973", + "name": "Hannibal", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "5c0ac062173739c9f4a9e988", + "imdb_id": "tt1190634", + "name": "The Boys", + "type": "series", + "year": "2019–" + }, + { + "_id": "643c056f64ec43ef982924c1", + "imdb_id": "tt15789088", + "name": "Birdie Wing: Golf Girls' Story", + "type": "series", + "year": "2022–" + }, + { + "_id": "555c6d1ebf6c900d1833deea", + "imdb_id": "tt3868848", + "name": "Stitchers", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14617", + "imdb_id": "tt1663641", + "name": "Face Off", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "53677f07847ccc8123a1824c", + "imdb_id": "tt0053534", + "name": "Route 66", + "type": "series", + "year": "1960–1964" + }, + { + "_id": "53677f1e847ccc8123a1c0e2", + "imdb_id": "tt0106126", + "name": "SeaQuest 2032", + "type": "series", + "year": "1993–1996" + }, + { + "_id": "53677f15847ccc8123a1a729", + "imdb_id": "tt0112230", + "name": "Xena: Warrior Princess", + "type": "series", + "year": "1995–2001" + }, + { + "_id": "63b4f18164ec43ef985208b5", + "imdb_id": "tt17543592", + "name": "Will Trent", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f4a847ccc8123a20551", + "imdb_id": "tt0054533", + "name": "The Dick Van Dyke Show", + "type": "series", + "year": "1961–1966" + }, + { + "_id": "629e4d9964ec43ef98dc0412", + "imdb_id": "tt14016500", + "name": "The Summer I Turned Pretty", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c24fd47173739c9f4618358", + "imdb_id": "tt3114358", + "name": "Non Non Biyori", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "53677ef9847ccc8123a13a43", + "imdb_id": "tt0493093", + "name": "Hannah Montana", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "5810b268d7e549298241342b", + "imdb_id": "tt5651844", + "type": "series", + "name": "Travelers", + "year": "2016–2018" + }, + { + "_id": "53677f19847ccc8123a1b448", + "imdb_id": "tt0060018", + "name": "The Rat Patrol", + "type": "series", + "year": "1966–1968" + }, + { + "_id": "608b9ea464ec43ef98ba8210", + "imdb_id": "tt11041132", + "name": "The Mosquito Coast", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677efa847ccc8123a146c2", + "imdb_id": "tt0071042", + "name": "The Rockford Files", + "type": "series", + "year": "1974–1980" + }, + { + "_id": "53677f68847ccc8123a22c9c", + "imdb_id": "tt0108847", + "name": "The Magic School Bus", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677ef9847ccc8123a13a3a", + "imdb_id": "tt1561755", + "name": "Bob's Burgers", + "type": "series", + "year": "2011–" + }, + { + "_id": "6002d5775424253341d08e18", + "imdb_id": "tt13650480", + "name": "Marvel Studios: Legends", + "type": "series", + "year": "2021–" + }, + { + "_id": "5abb0898e0a43c01da219380", + "imdb_id": "tt6492236", + "type": "series", + "name": "Splitting Up Together", + "year": "2018–2019" + }, + { + "_id": "5c0c356a173739c9f459a9a2", + "imdb_id": "tt0284712", + "name": "Captain Caveman and the Teen Angels", + "type": "series", + "year": "1977–1980" + }, + { + "_id": "5e252d93c4ccb5dd92cea584", + "imdb_id": "tt10323338", + "name": "9-1-1: Lone Star", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f00847ccc8123a1630c", + "imdb_id": "tt0096686", + "name": "Ranma ½", + "type": "series", + "year": "1989" + }, + { + "_id": "5c216ec5173739c9f405656c", + "imdb_id": "tt3204810", + "name": "On Cinema", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f0c847ccc8123a190f0", + "imdb_id": "tt0055662", + "name": "The Beverly Hillbillies", + "type": "series", + "year": "1962–1971" + }, + { + "_id": "53677f68847ccc8123a22ce3", + "imdb_id": "tt3306838", + "name": "Hozuki's Coolheadedness", + "type": "series", + "year": "2014–" + }, + { + "_id": "5a0e9a2d543165dcd84f2400", + "imdb_id": "tt5675620", + "type": "series", + "name": "The Punisher", + "year": "2017–2019" + }, + { + "_id": "55075d66711bd19c92addccc", + "imdb_id": "tt1356878", + "name": "Hetalia: Axis Powers", + "year": "2009–2016", + "type": "series" + }, + { + "_id": "6225838964ec43ef98030049", + "imdb_id": "tt10244600", + "name": "Winning Time: The Rise of the Lakers Dynasty", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "6436f70564ec43ef98dd26c2", + "imdb_id": "tt21030032", + "name": "?Oshi No Ko?", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a13dd4", + "imdb_id": "tt0472023", + "name": "So You Think You Can Dance", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f09847ccc8123a185fd", + "imdb_id": "tt0178132", + "name": "Don Matteo", + "type": "series", + "year": "2000–" + }, + { + "_id": "53677ef9847ccc8123a13f85", + "imdb_id": "tt0758737", + "name": "Brothers & Sisters", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "53677f02847ccc8123a1697c", + "imdb_id": "tt2919910", + "name": "Whose Line Is It Anyway?", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "53677efc847ccc8123a14d26", + "imdb_id": "tt0421357", + "name": "Fullmetal Alchemist", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "5a1ae83d543165dcd8ef63b6", + "imdb_id": "tt1043813", + "name": "Titans", + "year": "2018–2023", + "type": "series" + }, + { + "_id": "5ba9a45b173739c9f423e861", + "imdb_id": "tt8421350", + "name": "Manifest", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "5542dff0b0c9284285037694", + "imdb_id": "tt0092484", + "name": "Wiseguy", + "year": "1987–1990", + "type": "series" + }, + { + "_id": "53677f00847ccc8123a1646e", + "imdb_id": "tt0051301", + "name": "Peter Gunn", + "type": "series", + "year": "1958–1961" + }, + { + "_id": "5b988e86173739c9f4237517", + "imdb_id": "tt7660730", + "name": "Black Earth Rising", + "type": "series", + "year": "2018" + }, + { + "_id": "62adf34b64ec43ef98c51cd7", + "imdb_id": "tt15792808", + "name": "Aoashi", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f12847ccc8123a19f11", + "imdb_id": "tt0063929", + "name": "Monty Python's Flying Circus", + "type": "series", + "year": "1969–1974" + }, + { + "_id": "6001bb7f5424253341169581", + "imdb_id": "tt12598008", + "name": "So I'm a Spider, So What?", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c1165f3173739c9f46c5d03", + "imdb_id": "tt0261492", + "name": "Sheena", + "type": "series", + "year": "2000–2002" + }, + { + "_id": "5dbdbad3c4ccb5dd924d79c7", + "imdb_id": "tt7772588", + "name": "For All Mankind", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a14304", + "imdb_id": "tt0275140", + "name": "Law & Order: Criminal Intent", + "type": "series", + "year": "2001–2011" + }, + { + "_id": "5e54cbabc4ccb5dd92b4602e", + "imdb_id": "tt11034066", + "name": "Welcome to Demon-School, Iruma-kun", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "5c12fcb5173739c9f460d99e", + "imdb_id": "tt1407599", + "name": "Queen's Blade: The Exiled Virgin", + "type": "series", + "year": "2009" + }, + { + "_id": "53677f1c847ccc8123a1bb1f", + "imdb_id": "tt0088612", + "name": "Spenser: For Hire", + "type": "series", + "year": "1985–1988" + }, + { + "_id": "53677ef9847ccc8123a13c84", + "imdb_id": "tt1954347", + "name": "Continuum", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677f2c847ccc8123a1e095", + "imdb_id": "tt0144701", + "name": "Barney & Friends", + "type": "series", + "year": "1992–2010" + }, + { + "_id": "53677f0f847ccc8123a19a4d", + "imdb_id": "tt0098900", + "name": "Avonlea", + "type": "series", + "year": "1990–1996" + }, + { + "_id": "57e329a6d7e54929823e7940", + "imdb_id": "tt5592146", + "name": "Speechless", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "53677f0f847ccc8123a19995", + "imdb_id": "tt0106017", + "name": "Grace Under Fire", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "53677f2c847ccc8123a1e231", + "imdb_id": "tt2368645", + "name": "Hit the Floor", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "5f803df654242533412b4d3e", + "imdb_id": "tt7423322", + "name": "The Right Stuff", + "type": "series", + "year": "2020" + }, + { + "_id": "5c1e6490173739c9f487f806", + "imdb_id": "tt9159144", + "name": "Dark Side of the Ring", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f02847ccc8123a16b8b", + "imdb_id": "tt1140100", + "name": "Chowder", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "53677ef9847ccc8123a13eeb", + "imdb_id": "tt1213218", + "name": "Batman: The Brave and the Bold", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "5ad066edf51dd22f67a61a7b", + "imdb_id": "tt5232792", + "type": "series", + "name": "Lost in Space", + "year": "2018–2021" + }, + { + "_id": "53677f0c847ccc8123a18fcc", + "imdb_id": "tt1515996", + "name": "A Certain Scientific Railgun", + "type": "series", + "year": "2009–2020" + }, + { + "_id": "53677f0a847ccc8123a18c86", + "imdb_id": "tt0805905", + "name": "My Friends Tigger & Pooh", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "53677f2c847ccc8123a1e22c", + "imdb_id": "tt1856010", + "name": "House of Cards", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "553693e0cc9eee85bb52e82e", + "imdb_id": "tt4129004", + "name": "School of Rock", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "6192292b64ec43ef98f984ec", + "imdb_id": "tt11712058", + "name": "Mayor of Kingstown", + "type": "series", + "year": "2021–" + }, + { + "_id": "55072f7a711bd19c92add880", + "imdb_id": "tt0081858", + "name": "Falcon Crest", + "year": "1981–1990", + "type": "series" + }, + { + "_id": "53677f08847ccc8123a18430", + "imdb_id": "tt0081954", + "name": "Urusei yatsura", + "type": "series", + "year": "1981–1986" + }, + { + "_id": "55075d4e711bd19c92addc16", + "imdb_id": "tt0808082", + "name": "Magical Girl Lyrical Nanoha", + "year": "2004–", + "type": "series" + }, + { + "_id": "5c119392173739c9f4cd8db0", + "imdb_id": "tt8773420", + "name": "Expats", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677efa847ccc8123a147f9", + "imdb_id": "tt0066625", + "name": "Alias Smith and Jones", + "type": "series", + "year": "1971–1973" + }, + { + "_id": "5c2b6213173739c9f4814a6d", + "imdb_id": "tt9140560", + "name": "WandaVision", + "type": "series", + "year": "2021" + }, + { + "_id": "53677ef9847ccc8123a13dc2", + "imdb_id": "tt1216222", + "name": "To LOVE-Ru", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "53677efc847ccc8123a153b1", + "imdb_id": "tt0066722", + "name": "Upstairs, Downstairs", + "type": "series", + "year": "1971–1975" + }, + { + "_id": "5c2f48b1173739c9f47865ee", + "imdb_id": "tt7899522", + "name": "Gegege no Kitaro", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "5c26770f173739c9f40876e2", + "imdb_id": "tt1783822", + "name": "Babar and the Adventures of Badou", + "type": "series", + "year": "2010–" + }, + { + "_id": "5c0c5f2b173739c9f4b12c8d", + "imdb_id": "tt1806294", + "name": "Kaizoku Sentai Gokaiger", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5d89820cc4ccb5dd92a71e0e", + "imdb_id": "tt10329042", + "name": "All Rise", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677ef9847ccc8123a13b95", + "imdb_id": "tt0115147", + "name": "The Daily Show", + "type": "series", + "year": "1996–" + }, + { + "_id": "54fc0921711bd19c92ad4954", + "imdb_id": "tt0068792", + "name": "Gatchaman", + "year": "1972–1974", + "type": "series" + }, + { + "_id": "59b5d4a71712e0f4dd2507d0", + "imdb_id": "tt5691552", + "type": "series", + "name": "The Orville", + "year": "2017–2022" + }, + { + "_id": "5c109b60173739c9f4017b30", + "imdb_id": "tt6185782", + "name": "Miss Kobayashi's Dragon Maid", + "type": "series", + "year": "2017–2022" + }, + { + "_id": "53677eff847ccc8123a15d18", + "imdb_id": "tt2363624", + "name": "Yu-Gi-Oh! Zexal", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677ef9847ccc8123a13e2e", + "imdb_id": "tt0934814", + "name": "Chuck", + "type": "series", + "year": "2007–2012" + }, + { + "_id": "53677f51847ccc8123a20ea2", + "imdb_id": "tt0078622", + "name": "Hart to Hart", + "type": "series", + "year": "1979–1984" + }, + { + "_id": "53677ef9847ccc8123a140fd", + "imdb_id": "tt0094535", + "name": "Red Dwarf", + "type": "series", + "year": "1988–" + }, + { + "_id": "53677ef9847ccc8123a13b0d", + "imdb_id": "tt0758745", + "name": "Friday Night Lights", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "53677f3d847ccc8123a1f2fd", + "imdb_id": "tt0103405", + "name": "Dr. Quinn, Medicine Woman", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "5c47d54ed582b2575687fe53", + "imdb_id": "tt3703050", + "name": "Duck Quacks Don't Echo", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "5c0b9ed6173739c9f426feca", + "imdb_id": "tt4163486", + "name": "Bee and PuppyCat", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "5c140cac173739c9f434f715", + "imdb_id": "tt9184820", + "name": "Star Trek: Lower Decks", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677efa847ccc8123a14a9b", + "imdb_id": "tt1442065", + "name": "Rookie Blue", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677ef9847ccc8123a139ba", + "imdb_id": "tt0141842", + "name": "The Sopranos", + "type": "series", + "year": "1999–2007" + }, + { + "_id": "5baaf6f6173739c9f452c281", + "imdb_id": "tt7491982", + "name": "FBI", + "type": "series", + "year": "2018–" + }, + { + "_id": "55198016cc9eee85bb52dd7d", + "imdb_id": "tt3225270", + "name": "Noragami", + "year": "2014–2015", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13c57", + "imdb_id": "tt0379632", + "name": "Hustle", + "type": "series", + "year": "2004–2012" + }, + { + "_id": "5c1aff33173739c9f49ae093", + "imdb_id": "tt5817158", + "name": "To Tell the Truth", + "type": "series", + "year": "2016–2022" + }, + { + "_id": "53677ef9847ccc8123a13b78", + "imdb_id": "tt0965394", + "name": "Sanctuary", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "5f29b0eb5424253341a05778", + "imdb_id": "tt10394706", + "name": "Deathstroke: Knights & Dragons", + "type": "series", + "year": "2020" + }, + { + "_id": "60e6b8b964ec43ef98cdfec6", + "imdb_id": "tt10653784", + "name": "Gossip Girl", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "5c3e5e72d582b257563bd122", + "imdb_id": "tt2309408", + "name": "Little Busters!", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "5c181a27173739c9f44570f0", + "imdb_id": "tt1294009", + "name": "Only Connect", + "type": "series", + "year": "2008–" + }, + { + "_id": "53677ef9847ccc8123a1422f", + "imdb_id": "tt0412175", + "name": "Medium", + "type": "series", + "year": "2005–2011" + }, + { + "_id": "53677efa847ccc8123a1484c", + "imdb_id": "tt1600199", + "name": "Franklin & Bash", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "614a90f864ec43ef98060cc9", + "imdb_id": "tt14449470", + "name": "FBI: International", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c3fa828d582b25756e50929", + "imdb_id": "tt3755768", + "name": "Ninku", + "type": "series", + "year": "1994–1996" + }, + { + "_id": "5c139638173739c9f44da51a", + "imdb_id": "tt5240222", + "name": "God Eater", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677efc847ccc8123a14d04", + "imdb_id": "tt1530541", + "name": "Offspring", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "5c1ea640173739c9f40ebbda", + "imdb_id": "tt8528256", + "name": "Dragon Pilot: Hisone and Masotan", + "type": "series", + "year": "2018" + }, + { + "_id": "567c8a03bb83c664989a1832", + "imdb_id": "tt4209256", + "name": "Colony", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "53677f68847ccc8123a22c68", + "imdb_id": "tt0058791", + "name": "The Big Valley", + "type": "series", + "year": "1965–1969" + }, + { + "_id": "65a489adbd36726cbb8758ba", + "imdb_id": "tt29218693", + "name": "Baddies East", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f22847ccc8123a1cc10", + "imdb_id": "tt0055657", + "name": "The Alfred Hitchcock Hour", + "type": "series", + "year": "1962–1965" + }, + { + "_id": "53677efa847ccc8123a14b80", + "imdb_id": "tt1888075", + "name": "Death in Paradise", + "type": "series", + "year": "2011–" + }, + { + "_id": "5e1f72cac4ccb5dd92c4df5e", + "imdb_id": "tt11428630", + "name": "Bofuri: I Don't Want to Get Hurt, So I'll Max Out My Defense", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677ef9847ccc8123a1399c", + "imdb_id": "tt1870479", + "name": "The Newsroom", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677ef9847ccc8123a1384c", + "imdb_id": "tt1442550", + "name": "Shark Tank", + "type": "series", + "year": "2009–" + }, + { + "_id": "5c104377173739c9f45db810", + "imdb_id": "tt0220189", + "name": "The Unfettered Shogun", + "type": "series", + "year": "1978–2008" + }, + { + "_id": "53677f7c847ccc8123a23e85", + "imdb_id": "tt0108787", + "name": "Ghostwriter", + "type": "series", + "year": "1992–1995" + }, + { + "_id": "605e891d54242533410c19b3", + "imdb_id": "tt7939768", + "name": "The Mighty Ducks: Game Changers", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677f7c847ccc8123a23f00", + "imdb_id": "tt3530232", + "name": "Last Week Tonight with John Oliver", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677ef9847ccc8123a14170", + "imdb_id": "tt0367367", + "name": "Max & Ruby", + "type": "series", + "year": "2002–2021" + }, + { + "_id": "5d89d6bfc4ccb5dd9209a351", + "imdb_id": "tt10327354", + "name": "Prodigal Son", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677efa847ccc8123a14531", + "imdb_id": "tt0759364", + "name": "America's Got Talent", + "type": "series", + "year": "2006–" + }, + { + "_id": "5c0a14db173739c9f4792c78", + "imdb_id": "tt3069742", + "name": "Captain Tsubasa: Road to 2002", + "type": "series", + "year": "2001–2002" + }, + { + "_id": "596ffb8e1635517fbf56e954", + "imdb_id": "tt6517102", + "name": "Castlevania", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "53677f4f847ccc8123a20b75", + "imdb_id": "tt2114184", + "name": "The High Fructose Adventures of Annoying Orange", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677efa847ccc8123a14688", + "imdb_id": "tt2543796", + "name": "Girl Meets World", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677efc847ccc8123a153d3", + "imdb_id": "tt1365047", + "name": "Who Do You Think You Are?", + "type": "series", + "year": "2010–" + }, + { + "_id": "5fca055b542425334114064a", + "imdb_id": "tt11252090", + "name": "The Hardy Boys", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "548061968527d2e0cb4fc323", + "imdb_id": "tt2618986", + "name": "Wayward Pines", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c3003a4173739c9f4f7e19b", + "imdb_id": "tt5059866", + "name": "Himouto! Umaru-chan", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677efa847ccc8123a147de", + "imdb_id": "tt0476042", + "name": "Gunslinger Girl", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677ef9847ccc8123a14199", + "imdb_id": "tt1710308", + "name": "Regular Show", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "53677ef9847ccc8123a13920", + "imdb_id": "tt0844441", + "name": "True Blood", + "type": "series", + "year": "2008–2014" + }, + { + "_id": "53677f00847ccc8123a1647f", + "imdb_id": "tt0055701", + "name": "The Saint", + "type": "series", + "year": "1962–1969" + }, + { + "_id": "581c3b7055f8aab460cfd369", + "imdb_id": "tt4786824", + "name": "The Crown", + "type": "series", + "year": "2016–2023" + }, + { + "_id": "5c0e192c173739c9f481385a", + "imdb_id": "tt9140554", + "name": "Loki", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "5d899e42c4ccb5dd92c5162a", + "imdb_id": "tt10329024", + "name": "Bob Hearts Abishola", + "type": "series", + "year": "2019–2024" + }, + { + "_id": "5900197e1635517fbf56e7b5", + "imdb_id": "tt4955480", + "name": "Great News", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677f17847ccc8123a1ab44", + "imdb_id": "tt0465353", + "name": "Sleeper Cell", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "53677f05847ccc8123a17c99", + "imdb_id": "tt1584000", + "name": "Durarara!!", + "type": "series", + "year": "2010" + }, + { + "_id": "5cf145175111f1a8a31cd11f", + "imdb_id": "tt7137906", + "name": "When They See Us", + "type": "series", + "year": "2019" + }, + { + "_id": "5c0c1f74173739c9f42913da", + "imdb_id": "tt0488477", + "name": "XXXHOLiC", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "607b183664ec43ef9804f856", + "imdb_id": "tt12635162", + "name": "Don't Toy with Me, Miss Nagatoro", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "59b10bed1712e0f4dd547e2f", + "imdb_id": "tt4998350", + "type": "series", + "name": "The Deuce", + "year": "2017–2019" + }, + { + "_id": "5a0addf7543165dcd8b97387", + "imdb_id": "tt5363912", + "name": "The Last O.G.", + "year": "2018–2021", + "type": "series" + }, + { + "_id": "550787f3711bd19c92ade21f", + "imdb_id": "tt0370194", + "name": "Reno 911!", + "year": "2003–", + "type": "series" + }, + { + "_id": "53677f09847ccc8123a18626", + "imdb_id": "tt0994314", + "name": "Code Geass", + "type": "series", + "year": "2006–2008" + }, + { + "_id": "53677f45847ccc8123a1ff5d", + "imdb_id": "tt0111945", + "name": "The Drew Carey Show", + "type": "series", + "year": "1995–2004" + }, + { + "_id": "53677efa847ccc8123a148c1", + "imdb_id": "tt0174378", + "name": "Becker", + "type": "series", + "year": "1998–2004" + }, + { + "_id": "5c2cc4da173739c9f4041733", + "imdb_id": "tt2362887", + "name": "Uta no prince-sama - maji love 1000%", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677ef5847ccc8123a13778", + "imdb_id": "tt1843230", + "name": "Once Upon a Time", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "599b6c193e5e4b900ae85c52", + "imdb_id": "tt6311972", + "name": "Raven's Home", + "type": "series", + "year": "2017–" + }, + { + "_id": "54fb5f4b711bd19c92ad4433", + "imdb_id": "tt1163560", + "name": "Maria Watches Over Us", + "year": "2004–", + "type": "series" + }, + { + "_id": "5c1a6d24173739c9f472dcc9", + "imdb_id": "tt0098767", + "name": "Earth Squadron Fiveman", + "type": "series", + "year": "1990–1991" + }, + { + "_id": "53677ef9847ccc8123a137b1", + "imdb_id": "tt1358522", + "name": "White Collar", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "6548d64abd36726cbb376e5e", + "imdb_id": "tt13966962", + "name": "Echo", + "type": "series", + "year": "2023–2024" + }, + { + "_id": "60e28f2664ec43ef9815c6f0", + "imdb_id": "tt5556656", + "name": "Kabaneri of the Iron Fortress", + "type": "series", + "year": "2016" + }, + { + "_id": "5810ef17d7e549298241386d", + "imdb_id": "tt4047038", + "name": "Dirk Gently's Holistic Detective Agency", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f02847ccc8123a1715b", + "imdb_id": "tt0115231", + "name": "Kenan & Kel", + "type": "series", + "year": "1996–2023" + }, + { + "_id": "56c0c506f6b914c6c681d727", + "imdb_id": "tt5444412", + "name": "Bunnicula", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "53677f0a847ccc8123a186ae", + "imdb_id": "tt0057793", + "name": "12 O'Clock High", + "type": "series", + "year": "1964–1967" + }, + { + "_id": "53677eff847ccc8123a15d90", + "imdb_id": "tt2377452", + "name": "K", + "type": "series", + "year": "2012–" + }, + { + "_id": "5c0ad564173739c9f4d56c12", + "imdb_id": "tt7165904", + "name": "Big City Greens", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677ef9847ccc8123a13cf4", + "imdb_id": "tt0115108", + "name": "Beast Wars: Transformers", + "type": "series", + "year": "1996–1999" + }, + { + "_id": "6186946264ec43ef98e4b950", + "imdb_id": "tt11041332", + "name": "Yellowjackets", + "type": "series", + "year": "2021–" + }, + { + "_id": "550819d6711bd19c92ade40b", + "imdb_id": "tt3441810", + "name": "Some Assembly Required", + "year": "2014–2016", + "type": "series" + }, + { + "_id": "5c1a405f173739c9f41b87d5", + "imdb_id": "tt1494569", + "name": "WWF Challenge", + "type": "series", + "year": "1986–" + }, + { + "_id": "559503f3bf6c900d1838933a", + "imdb_id": "tt0054531", + "name": "The Defenders", + "year": "1961–1965", + "type": "series" + }, + { + "_id": "53677f4f847ccc8123a20b5e", + "imdb_id": "tt0062591", + "name": "The Name of the Game", + "type": "series", + "year": "1968–1971" + }, + { + "_id": "5bc0612e173739c9f47909b4", + "imdb_id": "tt6763664", + "name": "The Haunting of Hill House", + "type": "series", + "year": "2018" + }, + { + "_id": "53677f5a847ccc8123a21bca", + "imdb_id": "tt1146333", + "name": "Shark Week", + "type": "series", + "year": "1987–" + }, + { + "_id": "54c0f5788527d2e0cb509789", + "imdb_id": "tt0399977", + "name": "Ich bin ein Star - Holt mich hier raus!", + "type": "series", + "year": "2004–" + }, + { + "_id": "5378cbfc847ccc8123ad3847", + "imdb_id": "tt3288518", + "name": "Younger", + "type": "series", + "year": "2015–2021" + }, + { + "_id": "5c31de8e173739c9f418cecf", + "imdb_id": "tt6460600", + "name": "BanG Dream!", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677f21847ccc8123a1cb30", + "imdb_id": "tt3281796", + "name": "Power", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "53677efd847ccc8123a154a2", + "imdb_id": "tt2089467", + "name": "Talking Dead", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677ef9847ccc8123a13e54", + "imdb_id": "tt0784896", + "name": "Mickey Mouse Clubhouse", + "type": "series", + "year": "2006–2016" + }, + { + "_id": "53677ef9847ccc8123a138d9", + "imdb_id": "tt1195935", + "name": "The Cleveland Show", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "5c0b1b36173739c9f46358fc", + "imdb_id": "tt6740188", + "name": "Sakura Quest", + "type": "series", + "year": "2017–" + }, + { + "_id": "642874a864ec43ef988cba8d", + "imdb_id": "tt22817632", + "name": "Heavenly Delusion", + "type": "series", + "year": "2023" + }, + { + "_id": "6358e57864ec43ef98572c62", + "imdb_id": "tt20723374", + "name": "Tales of the Jedi", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f6d847ccc8123a230ce", + "imdb_id": "tt0387719", + "name": "Astro Boy", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677ef9847ccc8123a1380e", + "imdb_id": "tt1943524", + "name": "The Finder", + "type": "series", + "year": "2012" + }, + { + "_id": "53677ef9847ccc8123a144e7", + "imdb_id": "tt0050032", + "name": "Leave It to Beaver", + "type": "series", + "year": "1957–1963" + }, + { + "_id": "54e3249ce573cadcfa1fdb80", + "imdb_id": "tt0482855", + "name": "Blood+", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "53677f2c847ccc8123a1e127", + "imdb_id": "tt2329077", + "name": "Beware the Batman", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "61447f9764ec43ef9883bb4a", + "imdb_id": "tt10731840", + "name": "The Premise", + "type": "series", + "year": "2021" + }, + { + "_id": "579622e0f0b6c53b3c7942c3", + "imdb_id": "tt4574334", + "name": "Stranger Things", + "year": "2016–2025", + "type": "series" + }, + { + "_id": "578935e8f0b6c53b3c787521", + "imdb_id": "tt5574490", + "name": "Animal Kingdom", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677f02847ccc8123a16d74", + "imdb_id": "tt2281375", + "name": "Nashville", + "type": "series", + "year": "2012–2018" + }, + { + "_id": "54e60054fc2ab98b66971c24", + "imdb_id": "tt0132666", + "name": "The Wonderful World of Disney", + "type": "series", + "year": "1997–2023" + }, + { + "_id": "5c1c283e173739c9f4a41d44", + "imdb_id": "tt0367414", + "name": "Soreike! Anpanman", + "type": "series", + "year": "1988–" + }, + { + "_id": "53677ef9847ccc8123a13a57", + "imdb_id": "tt1615919", + "name": "Raising Hope", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "53677efc847ccc8123a14d30", + "imdb_id": "tt0386950", + "name": "Air Crash Investigation", + "type": "series", + "year": "2003–" + }, + { + "_id": "53677ef9847ccc8123a14489", + "imdb_id": "tt1830491", + "name": "Austin & Ally", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "53677f51847ccc8123a20e26", + "imdb_id": "tt0106102", + "name": "Pie in the Sky", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677f0c847ccc8123a194dc", + "imdb_id": "tt0103484", + "name": "Mad About You", + "type": "series", + "year": "1992–2019" + }, + { + "_id": "6345aa4d64ec43ef989b6337", + "imdb_id": "tt13616990", + "name": "Chainsaw Man", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f26847ccc8123a1d87e", + "imdb_id": "tt0072519", + "name": "The Jeffersons", + "type": "series", + "year": "1975–1985" + }, + { + "_id": "53677f00847ccc8123a16182", + "imdb_id": "tt0433309", + "name": "Numb3rs", + "type": "series", + "year": "2005–2010" + }, + { + "_id": "53677f14847ccc8123a1a4dc", + "imdb_id": "tt0065329", + "name": "The Odd Couple", + "type": "series", + "year": "1970–1975" + }, + { + "_id": "53677efd847ccc8123a15928", + "imdb_id": "tt0103520", + "name": "The Real World", + "type": "series", + "year": "1992–" + }, + { + "_id": "56090a626c6a1c0b815c7993", + "imdb_id": "tt4428122", + "name": "Quantico", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "53677ef5847ccc8123a13780", + "imdb_id": "tt0386676", + "name": "The Office", + "type": "series", + "year": "2005–2013" + }, + { + "_id": "53677f17847ccc8123a1aaf7", + "imdb_id": "tt0092468", + "name": "Tour of Duty", + "type": "series", + "year": "1987–1990" + }, + { + "_id": "5c18e931173739c9f4936db1", + "imdb_id": "tt7772600", + "name": "The Adventures of Paddington", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f48847ccc8123a202f5", + "imdb_id": "tt0149413", + "name": "Almost Live!", + "type": "series", + "year": "1984–1999" + }, + { + "_id": "53677f14847ccc8123a1a503", + "imdb_id": "tt0103512", + "name": "Picket Fences", + "type": "series", + "year": "1992–1996" + }, + { + "_id": "5690d0dfbb83c664989c1705", + "imdb_id": "tt0300839", + "name": "A Place in the Sun", + "year": "2000–", + "type": "series" + }, + { + "_id": "5decfdbdc4ccb5dd926f1193", + "imdb_id": "tt7661384", + "name": "The L Word: Generation Q", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "557a9fa4bf6c900d18355af9", + "imdb_id": "tt3593432", + "name": "Another Period", + "year": "2013–2018", + "type": "series" + }, + { + "_id": "5d8af0b8c4ccb5dd92b10101", + "imdb_id": "tt10276062", + "name": "Mixed-ish", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f14847ccc8123a1a438", + "imdb_id": "tt0367345", + "name": "Joan of Arcadia", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "53677f45847ccc8123a1fc87", + "imdb_id": "tt0111875", + "name": "All That", + "type": "series", + "year": "1994–2020" + }, + { + "_id": "53677f04847ccc8123a174d1", + "imdb_id": "tt1657563", + "name": "Check It Out! with Dr. Steve Brule", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "6166be2d64ec43ef987c7d40", + "imdb_id": "tt0048916", + "name": "Zane Grey Theatre", + "type": "series", + "year": "1956–1961" + }, + { + "_id": "53677f5e847ccc8123a222ef", + "imdb_id": "tt1685078", + "name": "Ek Veer Stree Ki Kahaani... Jhansi Ki Rani", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "541c1363a8f27b1bb90cb4f4", + "imdb_id": "tt0318895", + "name": "Hamtaro", + "type": "series", + "year": "2000–2006" + }, + { + "_id": "53677f14847ccc8123a1a5d8", + "imdb_id": "tt0108927", + "name": "Sister, Sister", + "type": "series", + "year": "1994–1999" + }, + { + "_id": "5c0b0dca173739c9f4481845", + "imdb_id": "tt6396082", + "name": "Carpool Karaoke", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f6d847ccc8123a23154", + "imdb_id": "tt0115157", + "name": "Dexter's Laboratory", + "type": "series", + "year": "1996–2003" + }, + { + "_id": "5e72edf4c4ccb5dd92d7aa77", + "imdb_id": "tt9900092", + "name": "Motherland: Fort Salem", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "555af066bf6c900d1833d57b", + "imdb_id": "tt0108850", + "name": "Marmalade Boy", + "year": "1994–2005", + "type": "series" + }, + { + "_id": "53677f29847ccc8123a1ddd1", + "imdb_id": "tt2608368", + "name": "Real Husbands of Hollywood", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f54847ccc8123a212f9", + "imdb_id": "tt0463826", + "name": "Merlin's Apprentice", + "type": "series", + "year": "2006" + }, + { + "_id": "5c0ce44a173739c9f4667eae", + "imdb_id": "tt8496638", + "name": "Boarding School Juliet", + "type": "series", + "year": "2018" + }, + { + "_id": "53677ef9847ccc8123a142de", + "imdb_id": "tt1797404", + "name": "House of Lies", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f07847ccc8123a17e22", + "imdb_id": "tt0965547", + "name": "Slam Dunk", + "type": "series", + "year": "1993–1996" + }, + { + "_id": "537500c6847ccc8123ad0a11", + "imdb_id": "tt2707408", + "name": "Narcos", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677f05847ccc8123a17685", + "imdb_id": "tt0120570", + "name": "From the Earth to the Moon", + "type": "series", + "year": "1998" + }, + { + "_id": "53677f45847ccc8123a1fca5", + "imdb_id": "tt2273734", + "name": "Crash & Bernstein", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677efd847ccc8123a1555e", + "imdb_id": "tt0086817", + "name": "The Transformers", + "type": "series", + "year": "1984–1987" + }, + { + "_id": "5c09a23d173739c9f4bd7dd5", + "imdb_id": "tt5839732", + "name": "Orange", + "type": "series", + "year": "2016" + }, + { + "_id": "53677ef9847ccc8123a139d6", + "imdb_id": "tt1124373", + "name": "Sons of Anarchy", + "type": "series", + "year": "2008–2014" + }, + { + "_id": "53677ef9847ccc8123a138f1", + "imdb_id": "tt0796264", + "name": "Eureka", + "type": "series", + "year": "2006–2012" + }, + { + "_id": "53677f00847ccc8123a165bd", + "imdb_id": "tt0118437", + "name": "The Practice", + "type": "series", + "year": "1997–2004" + }, + { + "_id": "633dd75264ec43ef98b417b7", + "imdb_id": "tt14115938", + "name": "The Eminence in Shadow", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677ef9847ccc8123a13a50", + "imdb_id": "tt0397442", + "name": "Gossip Girl", + "type": "series", + "year": "2007–2012" + }, + { + "_id": "5c163f12173739c9f40a4b5a", + "imdb_id": "tt0157222", + "name": "Dr. Slump", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "589cda0a1635517fbf56d91c", + "imdb_id": "tt5114356", + "name": "Legion", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "5c2ac8fc173739c9f494f850", + "imdb_id": "tt7482186", + "name": "Cosmic Disclosure", + "type": "series", + "year": "2015–" + }, + { + "_id": "5d97f0ddc4ccb5dd9259fab5", + "imdb_id": "tt8914012", + "name": "The Last Kids on Earth", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f5c847ccc8123a21f7e", + "imdb_id": "tt0224455", + "name": "Angela Anaconda", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5c593300d582b25756573ab7", + "imdb_id": "tt9646546", + "name": "Dimension 20", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f40847ccc8123a1f736", + "imdb_id": "tt0103488", + "name": "Martin", + "type": "series", + "year": "1992–1997" + }, + { + "_id": "5c1bf569173739c9f43e172f", + "imdb_id": "tt0051267", + "name": "The Donna Reed Show", + "type": "series", + "year": "1958–1966" + }, + { + "_id": "5c16cdfa173739c9f42f47da", + "imdb_id": "tt0400998", + "name": "Democracy Now!", + "type": "series", + "year": "2001–" + }, + { + "_id": "53e129b8a8f27b1bb90be13b", + "imdb_id": "tt0348952", + "name": "The File of Young Kindaichi", + "type": "series", + "year": "1997–2000" + }, + { + "_id": "5c323eb4173739c9f4d8daec", + "imdb_id": "tt6591406", + "name": "After the Rain", + "type": "series", + "year": "2018" + }, + { + "_id": "54fc0938711bd19c92ad49ad", + "imdb_id": "tt3114376", + "name": "Beyond the Boundary", + "year": "2013–2014", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13aba", + "imdb_id": "tt1693592", + "name": "Vera", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f17847ccc8123a1af88", + "imdb_id": "tt0367409", + "name": "Shaman King", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "5a577f41543165dcd8c3c7da", + "imdb_id": "tt6987476", + "type": "series", + "name": "Burden of Truth", + "year": "2018–2021" + }, + { + "_id": "6326eb1164ec43ef989d38a3", + "imdb_id": "tt0271894", + "name": "48 Hours", + "type": "series", + "year": "1988–" + }, + { + "_id": "65928125bd36726cbb78ad53", + "imdb_id": "tt5611024", + "name": "Fool Me Once", + "type": "series", + "year": "2024" + }, + { + "_id": "53677ef9847ccc8123a138f3", + "imdb_id": "tt1183865", + "name": "Alphas", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5e3d3318c4ccb5dd92aefb1e", + "imdb_id": "tt3007572", + "name": "Locke & Key", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "54c92d1ce573cadcfa1f770f", + "imdb_id": "tt1930123", + "name": "Web Therapy", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "5bc0612e173739c9f4790a4a", + "imdb_id": "tt8619822", + "name": "Light as a Feather", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677ef9847ccc8123a143d4", + "imdb_id": "tt1612578", + "name": "$#*! My Dad Says", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "621b44ea64ec43ef98d8632c", + "imdb_id": "tt11173006", + "name": "Super Pumped", + "type": "series", + "year": "2022–" + }, + { + "_id": "5e71b2a6c4ccb5dd92887639", + "imdb_id": "tt8089592", + "name": "Little Fires Everywhere", + "type": "series", + "year": "2020" + }, + { + "_id": "5c24cce6173739c9f40253d8", + "imdb_id": "tt7200884", + "name": "Let's Go Luna!", + "type": "series", + "year": "2018–2022" + }, + { + "_id": "5c240c42173739c9f4c6195f", + "imdb_id": "tt0196050", + "name": "Nobody's Boy: Remi", + "type": "series", + "year": "1977–1978" + }, + { + "_id": "576c59c6f0b6c53b3c76ac05", + "imdb_id": "tt3908868", + "name": "Decker", + "year": "2014–2017", + "type": "series" + }, + { + "_id": "65082c74bd36726cbbe151be", + "imdb_id": "tt17220216", + "name": "Monarch: Legacy of Monsters", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c18308e173739c9f470fcb0", + "imdb_id": "tt1276525", + "name": "Chi's Sweet Home", + "type": "series", + "year": "2008" + }, + { + "_id": "53677ef9847ccc8123a13918", + "imdb_id": "tt1552112", + "name": "The Glades", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "53eb359ea8f27b1bb90c0855", + "imdb_id": "tt0177455", + "name": "Oh Yeah! Cartoons", + "type": "series", + "year": "1998–2002" + }, + { + "_id": "5c3e62ffd582b257563fbaa2", + "imdb_id": "tt3247300", + "name": "2 Days 1 Night", + "type": "series", + "year": "2007–" + }, + { + "_id": "53677ef9847ccc8123a13f06", + "imdb_id": "tt0851851", + "name": "Terminator: The Sarah Connor Chronicles", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53677f29847ccc8123a1ded7", + "imdb_id": "tt3061046", + "name": "Steven Universe", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "53677ef9847ccc8123a1418c", + "imdb_id": "tt0421030", + "name": "Big Love", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "5e96f0ea512025562c1bcc9f", + "imdb_id": "tt9244556", + "name": "Mrs. America", + "type": "series", + "year": "2020" + }, + { + "_id": "589e2cbd1635517fbf56db31", + "imdb_id": "tt5212822", + "name": "Imposters", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677efa847ccc8123a147b8", + "imdb_id": "tt1094229", + "name": "Heartland", + "type": "series", + "year": "2007–" + }, + { + "_id": "55075db3711bd19c92ade076", + "imdb_id": "tt4219258", + "name": "The Testament of Sister New Devil", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "53677f20847ccc8123a1c68f", + "imdb_id": "tt0073965", + "name": "The Bionic Woman", + "type": "series", + "year": "1976–1978" + }, + { + "_id": "62da2c6d64ec43ef9826e8b3", + "imdb_id": "tt15975122", + "name": "Call of the Night", + "type": "series", + "year": "2022" + }, + { + "_id": "5e22502fc4ccb5dd9238a907", + "imdb_id": "tt8000674", + "name": "Little America", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "5c1e292d173739c9f416af9e", + "imdb_id": "tt8740790", + "name": "Bridgerton", + "type": "series", + "year": "2020–" + }, + { + "_id": "5c1d5ad2173739c9f4bd300a", + "imdb_id": "tt0059999", + "name": "Jericho", + "type": "series", + "year": "1966–1967" + }, + { + "_id": "5c0d7185173739c9f481efc5", + "imdb_id": "tt8134470", + "name": "The Undoing", + "type": "series", + "year": "2020" + }, + { + "_id": "5c15183b173739c9f40255a4", + "imdb_id": "tt0092492", + "name": "Thirtysomething", + "type": "series", + "year": "1987–1991" + }, + { + "_id": "53677f3f847ccc8123a1f4cb", + "imdb_id": "tt2543378", + "name": "Married to Medicine", + "type": "series", + "year": "2013–" + }, + { + "_id": "5c37afe0d582b25756b62b9f", + "imdb_id": "tt0170994", + "name": "The Paul Daniels Magic Show", + "type": "series", + "year": "1979–1994" + }, + { + "_id": "53677f0c847ccc8123a18fb0", + "imdb_id": "tt0473578", + "name": "Genshiken", + "type": "series", + "year": "2004–2007" + }, + { + "_id": "55a20eafbf6c900d183a68de", + "imdb_id": "tt1502749", + "name": "The Chase", + "year": "2009–", + "type": "series" + }, + { + "_id": "590043b21635517fbf56e7bd", + "imdb_id": "tt4508686", + "name": "Ghost in the Shell Arise: Alternative Architecture", + "type": "series", + "year": "2015" + }, + { + "_id": "53677f0c847ccc8123a193df", + "imdb_id": "tt0247102", + "name": "Girlfriends", + "type": "series", + "year": "2000–2008" + }, + { + "_id": "601d870f54242533416e5ac3", + "imdb_id": "tt3592032", + "name": "Ping Pong the Animation", + "type": "series", + "year": "2014" + }, + { + "_id": "5c2490d7173739c9f48dad35", + "imdb_id": "tt0306365", + "name": "Nintama Rantarô", + "type": "series", + "year": "1993–" + }, + { + "_id": "53677f3d847ccc8123a1f489", + "imdb_id": "tt0047750", + "name": "The Life and Legend of Wyatt Earp", + "type": "series", + "year": "1955–1961" + }, + { + "_id": "6026a81b54242533415ddfe6", + "imdb_id": "tt13714610", + "name": "Steven Universe Future", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "53677efd847ccc8123a1597c", + "imdb_id": "tt1657081", + "name": "Law & Order: LA", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "53677f03847ccc8123a17232", + "imdb_id": "tt3006802", + "name": "Outlander", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677f23847ccc8123a1d155", + "imdb_id": "tt0059982", + "name": "Family Affair", + "type": "series", + "year": "1966–1971" + }, + { + "_id": "54ac200f8527d2e0cb504bf9", + "imdb_id": "tt0096591", + "name": "Nadia: The Secret of Blue Water", + "type": "series", + "year": "1990–2003" + }, + { + "_id": "616adf4164ec43ef9881274b", + "imdb_id": "tt10684374", + "name": "The Ghost and Molly McGee", + "type": "series", + "year": "2021–" + }, + { + "_id": "642b503564ec43ef98d2e0a9", + "imdb_id": "tt7088332", + "name": "Isekai wa smartphone to tomo ni.", + "type": "series", + "year": "2017–2023" + }, + { + "_id": "53677f19847ccc8123a1b45f", + "imdb_id": "tt1799631", + "name": "Blue Exorcist", + "type": "series", + "year": "2011" + }, + { + "_id": "5c0c5c4f173739c9f4ab3e83", + "imdb_id": "tt8456094", + "name": "Scooby-Doo and Guess Who?", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "581919a555f8aab460cfa0d3", + "imdb_id": "tt5057130", + "name": "Medici", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "53677ef9847ccc8123a139af", + "imdb_id": "tt0149460", + "name": "Futurama", + "type": "series", + "year": "1999–" + }, + { + "_id": "53677f21847ccc8123a1c983", + "imdb_id": "tt0167742", + "name": "Where on Earth Is Carmen Sandiego?", + "type": "series", + "year": "1994–1999" + }, + { + "_id": "53677ef9847ccc8123a14383", + "imdb_id": "tt1343865", + "name": "Web Therapy", + "type": "series", + "year": "2008–2014" + }, + { + "_id": "5b8f5553173739c9f4cdfba9", + "imdb_id": "tt6110648", + "name": "The Purge", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677f1d847ccc8123a1bda9", + "imdb_id": "tt0062551", + "name": "The Champions", + "type": "series", + "year": "1968–1969" + }, + { + "_id": "5378cc15847ccc8123ad4dd3", + "imdb_id": "tt3551796", + "name": "American Odyssey", + "type": "series", + "year": "2015" + }, + { + "_id": "53677f26847ccc8123a1d742", + "imdb_id": "tt0043194", + "name": "Dragnet", + "type": "series", + "year": "1951–1959" + }, + { + "_id": "54ac200b8527d2e0cb504ad6", + "imdb_id": "tt3807022", + "name": "All Hail King Julien", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f1b847ccc8123a1b90e", + "imdb_id": "tt1443631", + "name": "Jungle Junction", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677ef9847ccc8123a13843", + "imdb_id": "tt1637727", + "name": "The Killing", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677efa847ccc8123a14a70", + "imdb_id": "tt0318883", + "name": "Everwood", + "type": "series", + "year": "2002–2006" + }, + { + "_id": "53677f54847ccc8123a21374", + "imdb_id": "tt0380113", + "name": "Charcoal Feather Federation", + "type": "series", + "year": "2002" + }, + { + "_id": "53677efc847ccc8123a14e77", + "imdb_id": "tt0874936", + "name": "Life", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "536907ea847ccc8123acdd85", + "imdb_id": "tt0083412", + "name": "Fame", + "type": "series", + "year": "1982–1987" + }, + { + "_id": "53677ef9847ccc8123a137c6", + "imdb_id": "tt1442449", + "name": "Spartacus", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "53677f0f847ccc8123a19a19", + "imdb_id": "tt0083413", + "name": "Family Ties", + "type": "series", + "year": "1982–1989" + }, + { + "_id": "53677efa847ccc8123a14829", + "imdb_id": "tt1299368", + "name": "Southland", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "53677f68847ccc8123a22b14", + "imdb_id": "tt0398413", + "name": "#DUPE#", + "type": "series", + "year": "2002–" + }, + { + "_id": "53677f1c847ccc8123a1bc6f", + "imdb_id": "tt1118804", + "name": "Clannad", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "53677ef9847ccc8123a1414d", + "imdb_id": "tt0290988", + "name": "Trailer Park Boys", + "type": "series", + "year": "2001–2018" + }, + { + "_id": "53677f79847ccc8123a23afc", + "imdb_id": "tt0055689", + "name": "McHale's Navy", + "type": "series", + "year": "1962–1966" + }, + { + "_id": "53677f0e847ccc8123a19583", + "imdb_id": "tt0050079", + "name": "Zorro", + "type": "series", + "year": "1957–1959" + }, + { + "_id": "53677f00847ccc8123a165d6", + "imdb_id": "tt0098762", + "name": "The Adventures of Super Mario Bros. 3", + "type": "series", + "year": "1990" + }, + { + "_id": "57dd11dad7e54929823e232a", + "imdb_id": "tt5028002", + "name": "StartUp", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "53677f1b847ccc8123a1ba11", + "imdb_id": "tt2701582", + "name": "Endeavour", + "type": "series", + "year": "2012–2023" + }, + { + "_id": "55078808711bd19c92ade258", + "imdb_id": "tt0156220", + "name": "Macross 7", + "year": "1994–1995", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a1385e", + "imdb_id": "tt0460649", + "name": "How I Met Your Mother", + "type": "series", + "year": "2005–2014" + }, + { + "_id": "560cebeb6c6a1c0b815c9ba2", + "imdb_id": "tt4816364", + "name": "BattleBots", + "year": "2015–", + "type": "series" + }, + { + "_id": "53677f29847ccc8123a1ddd3", + "imdb_id": "tt2660806", + "name": "Mom", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "5c0b13ae173739c9f4541d0e", + "imdb_id": "tt7908628", + "name": "What We Do in the Shadows", + "type": "series", + "year": "2019–2024" + }, + { + "_id": "561c7bc9ec193d5e9826ded0", + "imdb_id": "tt4094300", + "name": "Crazy Ex-Girlfriend", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677f35847ccc8123a1e9c8", + "imdb_id": "tt0086734", + "name": "Hunter", + "type": "series", + "year": "1984–1991" + }, + { + "_id": "547b3ce4c174e3b3ed251dc9", + "imdb_id": "tt3517010", + "name": "Is the Order a Rabbit?", + "type": "series", + "year": "2014–" + }, + { + "_id": "536907f4847ccc8123acde18", + "imdb_id": "tt0061248", + "name": "Dragnet 1967", + "type": "series", + "year": "1967–1970" + }, + { + "_id": "53677f0f847ccc8123a198c1", + "imdb_id": "tt0053479", + "name": "The Andy Griffith Show", + "type": "series", + "year": "1960–1968" + }, + { + "_id": "5c0c755c173739c9f4d26b72", + "imdb_id": "tt0386993", + "name": "Xiaolin Showdown", + "type": "series", + "year": "2003–2006" + }, + { + "_id": "55089967711bd19c92ade521", + "imdb_id": "tt0115128", + "name": "The Spooktacular New Adventures of Casper", + "year": "1996–1998", + "type": "series" + }, + { + "_id": "53677f63847ccc8123a2289c", + "imdb_id": "tt0122834", + "name": "Samurai Pizza Cats", + "type": "series", + "year": "1990–1991" + }, + { + "_id": "53677f00847ccc8123a164d7", + "imdb_id": "tt0270761", + "name": "Candy Candy", + "type": "series", + "year": "1976–1979" + }, + { + "_id": "5c21ea7f173739c9f4b7290d", + "imdb_id": "tt3909210", + "name": "The Fruit of Grisaia", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "5c2cb6c4173739c9f4e80778", + "imdb_id": "tt6517320", + "name": "Too Old to Die Young", + "type": "series", + "year": "2019" + }, + { + "_id": "53677f03847ccc8123a172cc", + "imdb_id": "tt0108988", + "name": "Weird Science", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "628bc9a464ec43ef98e11218", + "imdb_id": "tt10857160", + "name": "She-Hulk: Attorney at Law", + "type": "series", + "year": "2022" + }, + { + "_id": "53677efa847ccc8123a14a57", + "imdb_id": "tt0465315", + "name": "8 Out of 10 Cats", + "type": "series", + "year": "2005–" + }, + { + "_id": "59c857bb1712e0f4dd08f4fb", + "imdb_id": "tt5171438", + "type": "series", + "name": "Star Trek: Discovery", + "year": "2017–2024" + }, + { + "_id": "53677ef9847ccc8123a13a34", + "imdb_id": "tt0090390", + "name": "ALF", + "type": "series", + "year": "1986–2004" + }, + { + "_id": "5c303ed2173739c9f447152d", + "imdb_id": "tt0086742", + "name": "Kate & Allie", + "type": "series", + "year": "1984–1989" + }, + { + "_id": "53677eff847ccc8123a160bc", + "imdb_id": "tt0197182", + "name": "Third Watch", + "type": "series", + "year": "1999–2005" + }, + { + "_id": "625feb4f64ec43ef982215b6", + "imdb_id": "tt13706018", + "name": "Spy x Family", + "type": "series", + "year": "2022–" + }, + { + "_id": "5fe0c8965424253341943c68", + "imdb_id": "tt11328872", + "name": "In/Spectre", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677efd847ccc8123a156fd", + "imdb_id": "tt0862583", + "name": "How Do They Do It?", + "type": "series", + "year": "2006–" + }, + { + "_id": "53677ef9847ccc8123a13826", + "imdb_id": "tt0804503", + "name": "Mad Men", + "type": "series", + "year": "2007–2015" + }, + { + "_id": "5c37dc65d582b25756dd15ed", + "imdb_id": "tt6556992", + "name": "Hot Ones", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f1e847ccc8123a1c2ab", + "imdb_id": "tt0096542", + "name": "Baywatch", + "type": "series", + "year": "1989–2001" + }, + { + "_id": "5e60cfaac4ccb5dd921d100b", + "imdb_id": "tt8531222", + "name": "Dave", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677efa847ccc8123a145fe", + "imdb_id": "tt0290223", + "name": "Inuyasha", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "53677f6b847ccc8123a22ff7", + "imdb_id": "tt3502172", + "name": "Mozart in the Jungle", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "53677f29847ccc8123a1dbaa", + "imdb_id": "tt0069576", + "name": "Doraemon", + "type": "series", + "year": "1979–2005" + }, + { + "_id": "5c0f5b0f173739c9f4ab8831", + "imdb_id": "tt0262973", + "name": "Elvira's Movie Macabre", + "type": "series", + "year": "1981–1993" + }, + { + "_id": "592fc3701635517fbf56e8c8", + "imdb_id": "tt5722298", + "name": "Private Eyes", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "55c88b8cbf6c900d183db660", + "imdb_id": "tt0040053", + "type": "series", + "year": "1948–1971", + "name": "The Ed Sullivan Show" + }, + { + "_id": "53677f3d847ccc8123a1f2e1", + "imdb_id": "tt0810614", + "name": "ECW on Sci-Fi", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677eff847ccc8123a16097", + "imdb_id": "tt0086765", + "name": "Murder, She Wrote", + "type": "series", + "year": "1984–1996" + }, + { + "_id": "619817e264ec43ef9862f14d", + "imdb_id": "tt13409432", + "name": "Ranking of Kings", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677ef9847ccc8123a13ae8", + "imdb_id": "tt1626038", + "name": "The Avengers: Earth's Mightiest Heroes", + "type": "series", + "year": "2010–2012" + }, + { + "_id": "57e329a6d7e54929823e793f", + "imdb_id": "tt5164196", + "type": "series", + "name": "Lethal Weapon", + "year": "2016–2019" + }, + { + "_id": "542fde99a8f27b1bb90d006e", + "imdb_id": "tt0247882", + "name": "Forensic Files", + "type": "series", + "year": "1996–2011" + }, + { + "_id": "551acfd2cc9eee85bb52df79", + "imdb_id": "tt0367413", + "name": "Sonic X", + "year": "2003–2006", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14793", + "imdb_id": "tt1225901", + "name": "90210", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677f02847ccc8123a16c60", + "imdb_id": "tt0108783", + "name": "Gargoyles", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677f25847ccc8123a1d5c4", + "imdb_id": "tt0061266", + "name": "Ironside", + "type": "series", + "year": "1967–1975" + }, + { + "_id": "548f0c978527d2e0cb4ff963", + "imdb_id": "tt0051308", + "name": "The Rifleman", + "type": "series", + "year": "1958–1963" + }, + { + "_id": "53677efa847ccc8123a14a9d", + "imdb_id": "tt0443370", + "name": "Dragons' Den", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f0f847ccc8123a19a44", + "imdb_id": "tt0130417", + "name": "The New Tom & Jerry Show", + "type": "series", + "year": "1975–1977" + }, + { + "_id": "5f87498354242533413d03d4", + "imdb_id": "tt12415504", + "name": "Kuma Kuma Kuma Bear", + "type": "series", + "year": "2020–" + }, + { + "_id": "58947b581635517fbf56cb90", + "imdb_id": "tt4422950", + "name": "I'm a Celebrity, Get Me Out of Here!", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f17847ccc8123a1ab30", + "imdb_id": "tt0115226", + "name": "The Real Adventures of Jonny Quest", + "type": "series", + "year": "1996–1997" + }, + { + "_id": "53677f02847ccc8123a16937", + "imdb_id": "tt0075472", + "name": "All Creatures Great and Small", + "type": "series", + "year": "1978–1990" + }, + { + "_id": "53677ef9847ccc8123a14325", + "imdb_id": "tt1676701", + "name": "Let's Stay Together", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677ef9847ccc8123a1403e", + "imdb_id": "tt0835434", + "name": "In Treatment", + "type": "series", + "year": "2008–2021" + }, + { + "_id": "53677f1c847ccc8123a1bcb4", + "imdb_id": "tt1942683", + "name": "The Amazing World of Gumball", + "type": "series", + "year": "2011–2019" + }, + { + "_id": "53677f15847ccc8123a1a70a", + "imdb_id": "tt0108895", + "name": "The Pink Panther", + "type": "series", + "year": "1993–1996" + }, + { + "_id": "53677f29847ccc8123a1de5b", + "imdb_id": "tt3056472", + "name": "Total Divas", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "53677f17847ccc8123a1ad0f", + "imdb_id": "tt2712612", + "name": "Drunk History", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "53677f4d847ccc8123a20a0c", + "imdb_id": "tt0088618", + "name": "Street Hawk", + "type": "series", + "year": "1985" + }, + { + "_id": "53677f68847ccc8123a22bb0", + "imdb_id": "tt0068126", + "name": "The Rookies", + "type": "series", + "year": "1972–1976" + }, + { + "_id": "5446aeeca8f27b1bb90d5e87", + "imdb_id": "tt3816666", + "name": "Running Wild with Bear Grylls", + "type": "series", + "year": "2014–" + }, + { + "_id": "5aa3158253336c1ba83f914c", + "imdb_id": "tt7053188", + "name": "Station 19", + "year": "2018–2024", + "type": "series" + }, + { + "_id": "53677f0f847ccc8123a19c86", + "imdb_id": "tt0071054", + "name": "The Six Million Dollar Man", + "type": "series", + "year": "1974–1978" + }, + { + "_id": "5c0baaeb173739c9f43e44dc", + "imdb_id": "tt0106110", + "name": "Ready or Not", + "type": "series", + "year": "1993–1997" + }, + { + "_id": "53677f6a847ccc8123a22d9e", + "imdb_id": "tt3042608", + "name": "Uncle Grandpa", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "53677efd847ccc8123a159eb", + "imdb_id": "tt0375355", + "name": "Joey", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "53677f45847ccc8123a1fd71", + "imdb_id": "tt0127994", + "name": "Figure It Out", + "type": "series", + "year": "1997–2013" + }, + { + "_id": "53677ef9847ccc8123a1425d", + "imdb_id": "tt0244365", + "name": "Star Trek: Enterprise", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "53677efd847ccc8123a15b5b", + "imdb_id": "tt0358856", + "name": "Little Britain", + "type": "series", + "year": "2003–2006" + }, + { + "_id": "53677f22847ccc8123a1cda3", + "imdb_id": "tt2432604", + "name": "Toast of London", + "type": "series", + "year": "2012–2020" + }, + { + "_id": "53677f72847ccc8123a23614", + "imdb_id": "tt2720144", + "name": "Peter Rabbit", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "5ffb746b5424253341ef80c8", + "imdb_id": "tt13293588", + "name": "Mushoku Tensei: Jobless Reincarnation", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c1adfd4173739c9f45bdd4f", + "imdb_id": "tt6881158", + "name": "Corner Gas Animated", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "53677f04847ccc8123a1739f", + "imdb_id": "tt1528406", + "name": "Fairy Tail", + "type": "series", + "year": "2009–2019" + }, + { + "_id": "5a81a13b543165dcd85a3bfa", + "imdb_id": "tt0426666", + "type": "series", + "name": "Cold Case Files", + "year": "1999–" + }, + { + "_id": "53677ef5847ccc8123a1376e", + "imdb_id": "tt0324679", + "name": "Fifth Gear", + "type": "series", + "year": "2002–" + }, + { + "_id": "5985aa872abbe633c58e7aac", + "imdb_id": "tt6048596", + "name": "The Sinner", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "57dd11d9d7e54929823e2321", + "imdb_id": "tt5137338", + "name": "Victoria", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "536907eb847ccc8123acdda1", + "imdb_id": "tt0247120", + "name": "Night Visions", + "type": "series", + "year": "2001–2002" + }, + { + "_id": "56d1d2e6f6aa5b2a5344d0ba", + "imdb_id": "tt3986586", + "name": "Fuller House", + "year": "2016–2020", + "type": "series" + }, + { + "_id": "53d3d592a8f27b1bb90bae1c", + "imdb_id": "tt0292407", + "name": "The Glass House", + "type": "series", + "year": "2001–2006" + }, + { + "_id": "60cb12c964ec43ef9884d634", + "imdb_id": "tt13657062", + "name": "iCarly", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "5c0a27bc173739c9f48d8578", + "imdb_id": "tt8080054", + "name": "Patriot Act with Hasan Minhaj", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "53677ef9847ccc8123a139a4", + "imdb_id": "tt1659175", + "name": "Transformers Prime", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "5f93d89154242533412a84f7", + "imdb_id": "tt10048342", + "name": "The Queen's Gambit", + "type": "series", + "year": "2020" + }, + { + "_id": "53677f12847ccc8123a19cf1", + "imdb_id": "tt0057742", + "name": "Daniel Boone", + "type": "series", + "year": "1964–1970" + }, + { + "_id": "5a326b01543165dcd86b0a2c", + "imdb_id": "tt7235466", + "name": "9-1-1", + "year": "2018–", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a138d3", + "imdb_id": "tt1266020", + "name": "Parks and Recreation", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "53677efd847ccc8123a15921", + "imdb_id": "tt0118421", + "name": "Oz", + "type": "series", + "year": "1997–2003" + }, + { + "_id": "54497386a8f27b1bb90d6c45", + "imdb_id": "tt0078714", + "name": "You Can't Do That on Television", + "type": "series", + "year": "1979–2004" + }, + { + "_id": "5c3946f8d582b257569655b7", + "imdb_id": "tt2090883", + "name": "Hubert ohne Staller", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f0a847ccc8123a18be1", + "imdb_id": "tt0118266", + "name": "The New Batman Adventures", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "5c3a4d9dd582b257561da6d8", + "imdb_id": "tt0431577", + "name": "Tout le monde en parle", + "type": "series", + "year": "2004–" + }, + { + "_id": "53677f00847ccc8123a1651e", + "imdb_id": "tt0168366", + "name": "Pokémon", + "type": "series", + "year": "1997–2023" + }, + { + "_id": "53677ef9847ccc8123a13f7d", + "imdb_id": "tt1586676", + "name": "Fairly Legal", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5c2285fd173739c9f4f4381c", + "imdb_id": "tt1352421", + "name": "Natsume's Book of Friends", + "type": "series", + "year": "2008–2017" + }, + { + "_id": "658ea7fabd36726cbb85ccd2", + "imdb_id": "tt16288804", + "name": "Berlin", + "type": "series", + "year": "2023–" + }, + { + "_id": "54ff1ce4711bd19c92adce91", + "imdb_id": "tt0972713", + "name": "Shakugan No Shana", + "year": "2005–2010", + "type": "series" + }, + { + "_id": "541fe588a8f27b1bb90cc39f", + "imdb_id": "tt3501074", + "name": "Madam Secretary", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "53677f22847ccc8123a1cd03", + "imdb_id": "tt0426719", + "name": "Hunter x Hunter", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "5c1043cb173739c9f45e6e66", + "imdb_id": "tt6994156", + "name": "Close Enough", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "5a4f6c18543165dcd83348a1", + "imdb_id": "tt5180504", + "name": "The Witcher", + "year": "2019–", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a137d2", + "imdb_id": "tt1826940", + "name": "New Girl", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "6125145c64ec43ef98e7fb16", + "imdb_id": "tt11093718", + "name": "Establishment: Osman", + "type": "series", + "year": "2019–" + }, + { + "_id": "61c5bf0c64ec43ef98f594ac", + "imdb_id": "tt15758116", + "name": "Dragons: The Nine Realms", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "615f67c064ec43ef98df4488", + "imdb_id": "tt13676300", + "name": "Platinum End", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "543150fda8f27b1bb90d0602", + "imdb_id": "tt3663490", + "name": "The Librarians", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "53677ef9847ccc8123a13c63", + "imdb_id": "tt1492179", + "name": "Strike Back", + "type": "series", + "year": "2010–2020" + }, + { + "_id": "53677f04847ccc8123a173ff", + "imdb_id": "tt0055710", + "name": "The Virginian", + "type": "series", + "year": "1962–1971" + }, + { + "_id": "53677ef9847ccc8123a13bbc", + "imdb_id": "tt2222135", + "name": "Dog with a Blog", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677efc847ccc8123a15191", + "imdb_id": "tt0085033", + "name": "Inspector Gadget", + "type": "series", + "year": "1983–2023" + }, + { + "_id": "53677f0c847ccc8123a192b7", + "imdb_id": "tt0108967", + "name": "A Touch of Frost", + "type": "series", + "year": "1992–2010" + }, + { + "_id": "53677f0a847ccc8123a189f3", + "imdb_id": "tt0053502", + "name": "The Flintstones", + "type": "series", + "year": "1960–1966" + }, + { + "_id": "53677f07847ccc8123a18081", + "imdb_id": "tt0051327", + "name": "Wanted: Dead or Alive", + "type": "series", + "year": "1958–1961" + }, + { + "_id": "53677f3a847ccc8123a1ee2e", + "imdb_id": "tt2341339", + "name": "Randy Cunningham: 9th Grade Ninja", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677f07847ccc8123a180e6", + "imdb_id": "tt0364151", + "name": "American Masters", + "type": "series", + "year": "1985–" + }, + { + "_id": "63d265fb64ec43ef980bd6f5", + "imdb_id": "tt14269590", + "name": "Poker Face", + "type": "series", + "year": "2023–" + }, + { + "_id": "54fa1bb4711bd19c92accf0f", + "imdb_id": "tt1280627", + "name": "The Rachel Maddow Show", + "year": "2008–", + "type": "series" + }, + { + "_id": "5f852e5e54242533413e8c24", + "imdb_id": "tt12402550", + "name": "Sleepy Princess in the Demon Castle", + "type": "series", + "year": "2020" + }, + { + "_id": "53677f29847ccc8123a1db82", + "imdb_id": "tt0101206", + "name": "Golden Years", + "type": "series", + "year": "1991" + }, + { + "_id": "549483b28527d2e0cb500b3d", + "imdb_id": "tt0220265", + "name": "Iron Chef", + "type": "series", + "year": "1993–2002" + }, + { + "_id": "53677f61847ccc8123a224b1", + "imdb_id": "tt0053540", + "name": "Surfside 6", + "type": "series", + "year": "1960–1962" + }, + { + "_id": "5c50bfabd582b25756382700", + "imdb_id": "tt0096534", + "name": "Anything But Love", + "type": "series", + "year": "1989–1992" + }, + { + "_id": "53677f3a847ccc8123a1f0c2", + "imdb_id": "tt0284718", + "name": "Crossing Jordan", + "type": "series", + "year": "2001–2007" + }, + { + "_id": "536907eb847ccc8123acdd97", + "imdb_id": "tt1694038", + "name": "Seitokai yakuindomo", + "type": "series", + "year": "2010–2020" + }, + { + "_id": "5c2a64fa173739c9f4d0b6b0", + "imdb_id": "tt7126178", + "name": "HeartCatch PreCure!", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "6234c99064ec43ef984ab9c0", + "imdb_id": "tt11447470", + "name": "Welcome to Flatch", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677f25847ccc8123a1d643", + "imdb_id": "tt0045406", + "name": "The Life of Riley", + "type": "series", + "year": "1953–1958" + }, + { + "_id": "54e70d47417d39942847ac8f", + "imdb_id": "tt1899047", + "name": "Toriko", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "6580409fbd36726cbbdd614e", + "imdb_id": "tt26225038", + "name": "Death's Game", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c312930173739c9f40318f4", + "imdb_id": "tt4716268", + "name": "Beat Bugs", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "550787c9711bd19c92ade1b4", + "imdb_id": "tt0047756", + "name": "Matinee Theatre", + "year": "1955–1958", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a14153", + "imdb_id": "tt1800864", + "name": "Gold Rush", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677efc847ccc8123a14dd2", + "imdb_id": "tt0063878", + "name": "The Brady Bunch", + "type": "series", + "year": "1969–1974" + }, + { + "_id": "5c17d24d173739c9f4c29154", + "imdb_id": "tt7316998", + "name": "Richard Osman's House of Games", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f1f847ccc8123a1c4e6", + "imdb_id": "tt2216577", + "name": "Fred: The Show", + "type": "series", + "year": "2012–2023" + }, + { + "_id": "53677f0f847ccc8123a19a76", + "imdb_id": "tt0072472", + "name": "Barney Miller", + "type": "series", + "year": "1975–1982" + }, + { + "_id": "53677f23847ccc8123a1d03a", + "imdb_id": "tt2427220", + "name": "Crossing Lines", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "5505f59b711bd19c92add68b", + "imdb_id": "tt2426288", + "name": "Q&A", + "year": "2008–", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a142fd", + "imdb_id": "tt1001558", + "name": "Raising the Bar", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53677f4a847ccc8123a20544", + "imdb_id": "tt1410218", + "name": "K-On!", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "53677ef9847ccc8123a14006", + "imdb_id": "tt0373732", + "name": "The Boondocks", + "type": "series", + "year": "2005–2014" + }, + { + "_id": "5c13fe4c173739c9f416c280", + "imdb_id": "tt0409548", + "name": "Devilman Lady", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "53677eff847ccc8123a16130", + "imdb_id": "tt0083395", + "name": "Cagney & Lacey", + "type": "series", + "year": "1981–1988" + }, + { + "_id": "53677f6b847ccc8123a22f84", + "imdb_id": "tt3426342", + "name": "Jodha Akbar", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "53677f51847ccc8123a20eb7", + "imdb_id": "tt0168334", + "name": "Furandâsu no inu", + "type": "series", + "year": "1975" + }, + { + "_id": "53677f2e847ccc8123a1e37b", + "imdb_id": "tt2266639", + "name": "1600 Penn", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "5c433281d582b25756e19943", + "imdb_id": "tt0972735", + "name": "SoltyRei", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "53677f17847ccc8123a1ae2c", + "imdb_id": "tt1131751", + "name": "True Jackson, VP", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "53677efa847ccc8123a14887", + "imdb_id": "tt0144700", + "name": "101 Dalmatians: The Series", + "type": "series", + "year": "1997–1998" + }, + { + "_id": "55086ee4711bd19c92ade4aa", + "imdb_id": "tt0108937", + "name": "Space Ghost Coast to Coast", + "year": "1993–2012", + "type": "series" + }, + { + "_id": "5c104569173739c9f461c385", + "imdb_id": "tt0190106", + "name": "Undressed", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5c5abdfed582b257565b9447", + "imdb_id": "tt2230531", + "name": "Senki Zessho Symphogear", + "type": "series", + "year": "2012" + }, + { + "_id": "53677f1b847ccc8123a1b757", + "imdb_id": "tt0284713", + "name": "The Care Bears", + "type": "series", + "year": "1986–1988" + }, + { + "_id": "53677eff847ccc8123a15fe9", + "imdb_id": "tt0877057", + "name": "Death Note", + "type": "series", + "year": "2006–2007" + }, + { + "_id": "5c0ab0a4173739c9f48b55d7", + "imdb_id": "tt1196094", + "name": "Yu-Gi-Oh! 5D's", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "53677f04847ccc8123a174f9", + "imdb_id": "tt1761811", + "name": "Pound Puppies", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "644676b264ec43ef98771ee0", + "imdb_id": "tt13064902", + "name": "FUBAR", + "type": "series", + "year": "2023–" + }, + { + "_id": "5a4115b9543165dcd8f19ee7", + "imdb_id": "tt7326322", + "type": "series", + "name": "The Ancient Magus' Bride", + "year": "2017–" + }, + { + "_id": "5c2b35d2173739c9f430a5e4", + "imdb_id": "tt1687093", + "name": "The Story of Saiunkoku", + "type": "series", + "year": "2006–2008" + }, + { + "_id": "53677f2c847ccc8123a1df58", + "imdb_id": "tt3402548", + "name": "Comedy Nights with Kapil", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677f21847ccc8123a1cb88", + "imdb_id": "tt0046600", + "name": "Father Knows Best", + "type": "series", + "year": "1954–1960" + }, + { + "_id": "53677ef9847ccc8123a13bbf", + "imdb_id": "tt0098924", + "name": "TaleSpin", + "type": "series", + "year": "1990–1991" + }, + { + "_id": "53677efc847ccc8123a15374", + "imdb_id": "tt0976192", + "name": "The Spectacular Spider-Man", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "5c0edd5c173739c9f4e52df5", + "imdb_id": "tt7263328", + "name": "Classroom of the Elite", + "type": "series", + "year": "2017–" + }, + { + "_id": "5c0ce757173739c9f46bf06c", + "imdb_id": "tt0115221", + "name": "The Jamie Foxx Show", + "type": "series", + "year": "1996–2023" + }, + { + "_id": "53677ef9847ccc8123a13bf8", + "imdb_id": "tt1728102", + "name": "Alcatraz", + "type": "series", + "year": "2012" + }, + { + "_id": "53677f0c847ccc8123a194f7", + "imdb_id": "tt0495247", + "name": "The Apprentice: You're Fired!", + "type": "series", + "year": "2006–" + }, + { + "_id": "53677efd847ccc8123a1588f", + "imdb_id": "tt0429318", + "name": "The Biggest Loser", + "type": "series", + "year": "2004–" + }, + { + "_id": "5be4dc7a173739c9f4f56b70", + "imdb_id": "tt4687882", + "name": "Patriot", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "5c1bf01a173739c9f433ac07", + "imdb_id": "tt0314975", + "name": "The Adventures of Paddington Bear", + "type": "series", + "year": "1997–2000" + }, + { + "_id": "5b337fc416f4806c2a072e72", + "imdb_id": "tt7784442", + "type": "series", + "name": "Captain Tsubasa", + "year": "2018–2023" + }, + { + "_id": "5ab881b853336c1ba820e30d", + "imdb_id": "tt2708480", + "type": "series", + "name": "The Terror", + "year": "2018–2019" + }, + { + "_id": "5c100ed0173739c9f4f0c9cd", + "imdb_id": "tt3950084", + "name": "Amagi Brilliant Park", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f07847ccc8123a180c0", + "imdb_id": "tt0103359", + "name": "Batman: The Animated Series", + "type": "series", + "year": "1992–1995" + }, + { + "_id": "55be4c99bf6c900d183c3ad0", + "imdb_id": "tt4591680", + "name": "Bunk'd", + "year": "2015–2024", + "type": "series" + }, + { + "_id": "5c3beecad582b25756039b80", + "imdb_id": "tt0807675", + "name": "Girls Bravo", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "53677f22847ccc8123a1cc16", + "imdb_id": "tt0094481", + "name": "Home and Away", + "type": "series", + "year": "1988–" + }, + { + "_id": "5c537788d582b25756efb21a", + "imdb_id": "tt9170108", + "name": "Raised by Wolves", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "5c4deee3d582b25756a1edee", + "imdb_id": "tt0479783", + "name": "Yakitate!! Japan", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "6333978164ec43ef98a80ebe", + "imdb_id": "tt18076310", + "name": "The Rookie: Feds", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677f3d847ccc8123a1f388", + "imdb_id": "tt0047763", + "name": "The Phil Silvers Show", + "type": "series", + "year": "1955–1959" + }, + { + "_id": "555cc303bf6c900d1833dfc1", + "imdb_id": "tt0096565", + "name": "The Detectives", + "year": "1993–1997", + "type": "series" + }, + { + "_id": "64aad14abd36726cbba1cd50", + "imdb_id": "tt25811262", + "name": "Zom 100: Bucket List of the Dead", + "type": "series", + "year": "2023" + }, + { + "_id": "609d062c64ec43ef981a8089", + "imdb_id": "tt11815682", + "name": "Hacks", + "type": "series", + "year": "2021–" + }, + { + "_id": "63a2cad264ec43ef98787eb1", + "imdb_id": "tt13961348", + "name": "Sonic Prime", + "type": "series", + "year": "2022–" + }, + { + "_id": "5a58a6bb543165dcd82a0d37", + "imdb_id": "tt6045840", + "name": "Black Lightning", + "year": "2017–2021", + "type": "series" + }, + { + "_id": "5f1b43975424253341d90325", + "imdb_id": "tt12464182", + "name": "Uzaki-chan Wants to Hang Out!", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "60b9ffd564ec43ef9820cda3", + "imdb_id": "tt12809988", + "name": "Sweet Tooth", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a14273", + "imdb_id": "tt0839188", + "name": "Metalocalypse", + "type": "series", + "year": "2006–2013" + }, + { + "_id": "53677ef9847ccc8123a13f53", + "imdb_id": "tt0112167", + "name": "Sliders", + "type": "series", + "year": "1995–2000" + }, + { + "_id": "5a0b081b543165dcd8bfe57f", + "imdb_id": "tt4975856", + "type": "series", + "name": "Future Man", + "year": "2017–2020" + }, + { + "_id": "53677f07847ccc8123a18176", + "imdb_id": "tt0948103", + "name": "Gurren Lagann", + "type": "series", + "year": "2007" + }, + { + "_id": "5dd613d7c4ccb5dd927b90e4", + "imdb_id": "tt10937602", + "name": "Ahiru no Sora", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a13e71", + "imdb_id": "tt0472954", + "name": "It's Always Sunny in Philadelphia", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f05847ccc8123a17ac0", + "imdb_id": "tt2049116", + "name": "Gomorrah", + "type": "series", + "year": "2014–2021" + }, + { + "_id": "53677ef9847ccc8123a13e28", + "imdb_id": "tt0418372", + "name": "The Block", + "type": "series", + "year": "2003–" + }, + { + "_id": "5505f5fb711bd19c92add6bd", + "imdb_id": "tt3874528", + "name": "The Irregular at Magic High School", + "year": "2014–", + "type": "series" + }, + { + "_id": "550bfc09cc9eee85bb52d83e", + "imdb_id": "tt0181260", + "name": "This Is Your Life", + "year": "1955–2003", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13f76", + "imdb_id": "tt0081933", + "name": "The Smurfs", + "type": "series", + "year": "1981–1989" + }, + { + "_id": "555a43a3bf6c900d1833cddc", + "imdb_id": "tt4450826", + "name": "Minority Report", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f07847ccc8123a18091", + "imdb_id": "tt0268094", + "name": "Special Unit 2", + "type": "series", + "year": "2001–2002" + }, + { + "_id": "53677ef9847ccc8123a13c2c", + "imdb_id": "tt0759475", + "name": "'Til Death", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677f1c847ccc8123a1bbbd", + "imdb_id": "tt0315081", + "name": "Tripping the Rift", + "type": "series", + "year": "2004–2007" + }, + { + "_id": "5c35ea0c173739c9f4291de5", + "imdb_id": "tt8228732", + "name": "Kakuriyo: Bed & Breakfast for Spirits", + "type": "series", + "year": "2018" + }, + { + "_id": "53677f48847ccc8123a20326", + "imdb_id": "tt0058808", + "name": "Green Acres", + "type": "series", + "year": "1965–1971" + }, + { + "_id": "5bb2cae9173739c9f41e6044", + "imdb_id": "tt7942794", + "name": "The Neighborhood", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f0c847ccc8123a191e3", + "imdb_id": "tt0096688", + "name": "Rescue 911", + "type": "series", + "year": "1989–1996" + }, + { + "_id": "53677efa847ccc8123a1481e", + "imdb_id": "tt0238784", + "name": "Gilmore Girls", + "type": "series", + "year": "2000–2007" + }, + { + "_id": "53677f08847ccc8123a183f8", + "imdb_id": "tt1334722", + "name": "Baccano!", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "65a023c8bd36726cbbd3e4d3", + "imdb_id": "tt16156736", + "name": "Mato Seihei no Slave", + "type": "series", + "year": "2024–" + }, + { + "_id": "53677f24847ccc8123a1d1a9", + "imdb_id": "tt2191148", + "name": "Blue", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677ef9847ccc8123a13bc1", + "imdb_id": "tt0461622", + "name": "Criss Angel Mindfreak", + "type": "series", + "year": "2005–2010" + }, + { + "_id": "5c5caefdd582b25756107e46", + "imdb_id": "tt0101153", + "name": "The New WKRP in Cincinnati", + "type": "series", + "year": "1991–1993" + }, + { + "_id": "53677efc847ccc8123a14fb5", + "imdb_id": "tt1660055", + "name": "Scooby-Doo! Mystery Incorporated", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "53677f2e847ccc8123a1e342", + "imdb_id": "tt2731624", + "name": "Plebs", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "53677efc847ccc8123a14d5f", + "imdb_id": "tt0086814", + "name": "Tales from the Darkside", + "type": "series", + "year": "1983–1988" + }, + { + "_id": "5c40e7e8d582b25756a88cd9", + "imdb_id": "tt2632044", + "name": "Gargantia on the Verdurous Planet", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f05847ccc8123a176ad", + "imdb_id": "tt2085059", + "name": "Black Mirror", + "type": "series", + "year": "2011–" + }, + { + "_id": "5c15b54a173739c9f4437370", + "imdb_id": "tt5955168", + "name": "Classic Albums", + "type": "series", + "year": "1997–" + }, + { + "_id": "55199632cc9eee85bb52de16", + "imdb_id": "tt0257294", + "name": "Betterman", + "year": "1999", + "type": "series" + }, + { + "_id": "5fafb20e5424253341adf1fe", + "imdb_id": "tt0115243", + "name": "Lexx", + "type": "series", + "year": "1996–2002" + }, + { + "_id": "53677f02847ccc8123a16b7a", + "imdb_id": "tt0178149", + "name": "#DUPE#", + "type": "series", + "year": "1996–2002" + }, + { + "_id": "53677f66847ccc8123a22aa5", + "imdb_id": "tt0237987", + "name": "The Weekenders", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "53677ef9847ccc8123a13871", + "imdb_id": "tt0411008", + "name": "Lost", + "type": "series", + "year": "2004–2010" + }, + { + "_id": "56c06e89f6b914c6c681ca36", + "imdb_id": "tt3186130", + "name": "Vinyl", + "year": "2016", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13eac", + "imdb_id": "tt0090466", + "name": "L.A. Law", + "type": "series", + "year": "1986–1994" + }, + { + "_id": "54fb5f64711bd19c92ad4578", + "imdb_id": "tt1424037", + "name": "Kenichi: The Mightiest Disciple", + "year": "2006–2014", + "type": "series" + }, + { + "_id": "5c58b672d582b25756c21eea", + "imdb_id": "tt8879940", + "name": "Mythic Quest", + "type": "series", + "year": "2020–" + }, + { + "_id": "5c0ab2f2173739c9f48fd1d3", + "imdb_id": "tt1674928", + "name": "Beyblade: Metal Fusion", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "53677eff847ccc8123a15e11", + "imdb_id": "tt2980110", + "name": "First Dates", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f52847ccc8123a20f7d", + "imdb_id": "tt0284722", + "name": "Reba", + "type": "series", + "year": "2001–2007" + }, + { + "_id": "53677f0f847ccc8123a19699", + "imdb_id": "tt0281432", + "name": "The Dead Zone", + "type": "series", + "year": "2002–2007" + }, + { + "_id": "53677ef9847ccc8123a138cb", + "imdb_id": "tt0285370", + "name": "The Guardian", + "type": "series", + "year": "2001–2004" + }, + { + "_id": "6036fbf054242533416c6c31", + "imdb_id": "tt10813940", + "name": "Ginny & Georgia", + "type": "series", + "year": "2021–" + }, + { + "_id": "6162eea564ec43ef9818cb04", + "imdb_id": "tt15192340", + "name": "Senpai ga Uzai Kouhai no Hanashi", + "type": "series", + "year": "2021" + }, + { + "_id": "53677f1d847ccc8123a1bd56", + "imdb_id": "tt0081859", + "name": "The Fall Guy", + "type": "series", + "year": "1981–1986" + }, + { + "_id": "53677efd847ccc8123a15600", + "imdb_id": "tt1091909", + "name": "Murdoch Mysteries", + "type": "series", + "year": "2008–" + }, + { + "_id": "5985aa872abbe633c58e7aad", + "imdb_id": "tt6467294", + "name": "Somewhere Between", + "type": "series", + "year": "2017" + }, + { + "_id": "53677ef9847ccc8123a13937", + "imdb_id": "tt0813715", + "name": "Heroes", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677ef9847ccc8123a1378f", + "imdb_id": "tt1604113", + "name": "Friends with Benefits", + "type": "series", + "year": "2011" + }, + { + "_id": "53677f29847ccc8123a1dede", + "imdb_id": "tt2545498", + "name": "Instant Mom", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "53677f07847ccc8123a17e0a", + "imdb_id": "tt0074035", + "name": "The Onedin Line", + "type": "series", + "year": "1971–1980" + }, + { + "_id": "53677f0c847ccc8123a194d8", + "imdb_id": "tt0047758", + "name": "The Millionaire", + "type": "series", + "year": "1955–1960" + }, + { + "_id": "562d6b864da0a59d21473eea", + "imdb_id": "tt0112115", + "name": "The Parent 'Hood", + "year": "1995–1999", + "type": "series" + }, + { + "_id": "65422153bd36726cbb70d403", + "imdb_id": "tt0484918", + "name": "Ulice", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677efd847ccc8123a15589", + "imdb_id": "tt0259733", + "name": "Waking the Dead", + "type": "series", + "year": "2000–2011" + }, + { + "_id": "546391d3b5100012646bf5d4", + "imdb_id": "tt3904078", + "name": "100 Things to Do Before High School", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "53677ef9847ccc8123a1411b", + "imdb_id": "tt0387764", + "name": "Peep Show", + "type": "series", + "year": "2003–2015" + }, + { + "_id": "5801b75fd7e54929824034c3", + "imdb_id": "tt4687880", + "type": "series", + "name": "Goliath", + "year": "2016–2021" + }, + { + "_id": "60a3be6464ec43ef9877af9d", + "imdb_id": "tt14403784", + "name": "Biography: WWE Legends", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677efa847ccc8123a1465f", + "imdb_id": "tt0925266", + "name": "Pushing Daisies", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "5c578c82d582b257565b780b", + "imdb_id": "tt0090407", + "name": "Supernova Flashman", + "type": "series", + "year": "1986–1987" + }, + { + "_id": "5c195a66173739c9f4731dea", + "imdb_id": "tt8788458", + "name": "The Promised Neverland", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f3c847ccc8123a1f1a8", + "imdb_id": "tt0129692", + "name": "Liberty! The American Revolution", + "type": "series", + "year": "1997–" + }, + { + "_id": "5c4cdf22d582b25756522f21", + "imdb_id": "tt0122811", + "name": "The Adventures of Teddy Ruxpin", + "type": "series", + "year": "1987–1988" + }, + { + "_id": "5c094a2c173739c9f40e7bd8", + "imdb_id": "tt8747928", + "name": "SSSS.Gridman", + "type": "series", + "year": "2018" + }, + { + "_id": "64cfc2e6bd36726cbb47fe0f", + "imdb_id": "tt18271440", + "name": "Bill Russell: Legend", + "type": "series", + "year": "2023" + }, + { + "_id": "539c4866a8f27b1bb90afef3", + "imdb_id": "tt1870073", + "name": "Justin Time", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "57e3cb67d7e54929823e7da3", + "imdb_id": "tt0207275", + "name": "The 10th Kingdom", + "year": "2000", + "type": "series" + }, + { + "_id": "5c13d468173739c9f4c3e867", + "imdb_id": "tt7632608", + "name": "Enemigo Íntimo", + "type": "series", + "year": "2018–" + }, + { + "_id": "54b28a0d8527d2e0cb506234", + "imdb_id": "tt3910690", + "name": "Inspector Gadget", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "53677f23847ccc8123a1cfa9", + "imdb_id": "tt0096597", + "name": "Goede tijden, slechte tijden", + "type": "series", + "year": "1990–" + }, + { + "_id": "5b8e9330173739c9f47d67c3", + "imdb_id": "tt5363918", + "name": "Disenchantment", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "53677f7c847ccc8123a23e19", + "imdb_id": "tt3592718", + "name": "Signed, Sealed, Delivered", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "53677efa847ccc8123a14c94", + "imdb_id": "tt0210418", + "name": "Digimon: Digital Monsters", + "type": "series", + "year": "1999–2007" + }, + { + "_id": "53677ef9847ccc8123a1434f", + "imdb_id": "tt0098800", + "name": "The Fresh Prince of Bel-Air", + "type": "series", + "year": "1990–1996" + }, + { + "_id": "53677f05847ccc8123a17ae1", + "imdb_id": "tt0086827", + "name": "Who's the Boss?", + "type": "series", + "year": "1984–1992" + }, + { + "_id": "539c4866a8f27b1bb90afed7", + "imdb_id": "tt2402061", + "name": "Murder in the First", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "561a16cfec193d5e9826b3aa", + "imdb_id": "tt4179452", + "name": "The Last Kingdom", + "year": "2015–2022", + "type": "series" + }, + { + "_id": "603439315424253341dd9e08", + "imdb_id": "tt11192306", + "name": "Superman & Lois", + "type": "series", + "year": "2021–2024" + }, + { + "_id": "53677efc847ccc8123a151b7", + "imdb_id": "tt0154061", + "name": "CatDog", + "type": "series", + "year": "1998–2005" + }, + { + "_id": "53677f08847ccc8123a1843c", + "imdb_id": "tt0058812", + "name": "Hogan's Heroes", + "type": "series", + "year": "1965–1971" + }, + { + "_id": "537500ca847ccc8123ad0af1", + "imdb_id": "tt0165598", + "name": "That '70s Show", + "type": "series", + "year": "1998–2006" + }, + { + "_id": "53677f4f847ccc8123a20d6b", + "imdb_id": "tt0068138", + "name": "The New Temperatures Rising Show", + "type": "series", + "year": "1972–1974" + }, + { + "_id": "5c09a0c8173739c9f4ba7fa2", + "imdb_id": "tt8433216", + "name": "Super Dragon Ball Heroes", + "type": "series", + "year": "2018–" + }, + { + "_id": "5c0d59e4173739c9f44ea620", + "imdb_id": "tt0083475", + "name": "Scooby-Doo and Scrappy-Doo", + "type": "series", + "year": "1979–1983" + }, + { + "_id": "53677ef9847ccc8123a141aa", + "imdb_id": "tt1593823", + "name": "The Cape", + "type": "series", + "year": "2011" + }, + { + "_id": "5c5638e0d582b257569d3ee3", + "imdb_id": "tt0094446", + "name": "Day by Day", + "type": "series", + "year": "1988–1989" + }, + { + "_id": "60f3b83064ec43ef985e1d32", + "imdb_id": "tt11761176", + "name": "Power Book III: Raising Kanan", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677efa847ccc8123a14bc4", + "imdb_id": "tt1553656", + "name": "Under the Dome", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "53677f23847ccc8123a1d08a", + "imdb_id": "tt0283724", + "name": "Doc", + "type": "series", + "year": "2001–2004" + }, + { + "_id": "53677f0c847ccc8123a1909f", + "imdb_id": "tt0080297", + "name": "Tinker Tailor Soldier Spy", + "type": "series", + "year": "1979" + }, + { + "_id": "5c0fb216173739c9f43d470f", + "imdb_id": "tt0185066", + "name": "Galaxy Express 999", + "type": "series", + "year": "1978–1981" + }, + { + "_id": "5c311006173739c9f4cc7026", + "imdb_id": "tt4847134", + "name": "Mighty Magiswords", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "5381e72b847ccc8123ad762a", + "imdb_id": "tt2769458", + "name": "Sheriff Callie's Wild West", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "53677f79847ccc8123a23c19", + "imdb_id": "tt2374744", + "name": "The Next Step", + "type": "series", + "year": "2013–" + }, + { + "_id": "5db1f0e6c4ccb5dd92b1b9cf", + "imdb_id": "tt10973152", + "name": "Assassins Pride", + "type": "series", + "year": "2019" + }, + { + "_id": "53677ef9847ccc8123a13862", + "imdb_id": "tt1837654", + "name": "The Secret Circle", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "6262980e64ec43ef98ea0c77", + "imdb_id": "tt15978212", + "name": "Ya Boy Kongming!", + "type": "series", + "year": "2022" + }, + { + "_id": "5c55faf3d582b25756376226", + "imdb_id": "tt2595474", + "name": "Encouragement of Climb", + "type": "series", + "year": "2013–2018" + }, + { + "_id": "53677f07847ccc8123a18079", + "imdb_id": "tt0129723", + "name": "Z Cars", + "type": "series", + "year": "1962–1978" + }, + { + "_id": "5c1b186b173739c9f4c8db32", + "imdb_id": "tt6763304", + "name": "Monster Hunter Stories: Ride On", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "53677f25847ccc8123a1d5a2", + "imdb_id": "tt0106053", + "name": "Late Show with David Letterman", + "type": "series", + "year": "1993–2015" + }, + { + "_id": "550fb93dcc9eee85bb52da53", + "imdb_id": "tt0058817", + "name": "Kimba the White Lion", + "year": "1965–1967", + "type": "series" + }, + { + "_id": "5e13fd1ac4ccb5dd9220077c", + "imdb_id": "tt9024590", + "name": "Nurses", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "53f6326fa8f27b1bb90c33b8", + "imdb_id": "tt2379308", + "name": "Psycho-Pass", + "type": "series", + "year": "2012–2019" + }, + { + "_id": "5985aa862abbe633c58e7aaa", + "imdb_id": "tt5464086", + "name": "Midnight, Texas", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677f07847ccc8123a1802e", + "imdb_id": "tt0381740", + "name": "Clean House", + "type": "series", + "year": "2003–2011" + }, + { + "_id": "53677f02847ccc8123a17002", + "imdb_id": "tt2176287", + "name": "Comedy Bang! Bang!", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f1a847ccc8123a1b6eb", + "imdb_id": "tt2183641", + "name": "Ripper Street", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53c58b47a8f27b1bb90b7d15", + "imdb_id": "tt1509677", + "name": "Pointless", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677f00847ccc8123a16509", + "imdb_id": "tt0096633", + "name": "Legend of the Galactic Heroes", + "type": "series", + "year": "1988–1997" + }, + { + "_id": "57e3e788d7e54929823e7eb0", + "imdb_id": "tt5562056", + "name": "Easy", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "5c0c80c3173739c9f4e16d57", + "imdb_id": "tt0115215", + "name": "The Incredible Hulk", + "type": "series", + "year": "1996–1998" + }, + { + "_id": "5484ade08527d2e0cb4fd695", + "imdb_id": "tt0058819", + "name": "Laredo", + "type": "series", + "year": "1965–1967" + }, + { + "_id": "53677f29847ccc8123a1db75", + "imdb_id": "tt0078680", + "name": "Rumpole of the Bailey", + "type": "series", + "year": "1978–1992" + }, + { + "_id": "64a2929dbd36726cbb9de3ce", + "imdb_id": "tt0296361", + "name": "Die Johannes B. Kerner Show", + "type": "series", + "year": "1998–" + }, + { + "_id": "53677f2c847ccc8123a1e130", + "imdb_id": "tt2871832", + "name": "Cedar Cove", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "541463a1a8f27b1bb90c9967", + "imdb_id": "tt3645318", + "name": "If Loving You Is Wrong", + "type": "series", + "year": "2014–2020" + }, + { + "_id": "53677f3a847ccc8123a1f01c", + "imdb_id": "tt0118300", + "name": "Dawson's Creek", + "type": "series", + "year": "1998–2003" + }, + { + "_id": "53677ef9847ccc8123a1380b", + "imdb_id": "tt1489428", + "name": "Justified", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677f13847ccc8123a1a377", + "imdb_id": "tt0460631", + "name": "Close to Home", + "type": "series", + "year": "2005–2007" + }, + { + "_id": "53677f07847ccc8123a18130", + "imdb_id": "tt1138475", + "name": "The Guild", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "55071066711bd19c92add7db", + "imdb_id": "tt2425098", + "name": "Magi: The Labyrinth of Magic", + "year": "2012–2014", + "type": "series" + }, + { + "_id": "53677f1e847ccc8123a1c0af", + "imdb_id": "tt0052490", + "name": "The Many Loves of Dobie Gillis", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "53677efa847ccc8123a14af3", + "imdb_id": "tt0094525", + "name": "Poirot", + "type": "series", + "year": "1989–2013" + }, + { + "_id": "53677efa847ccc8123a145f5", + "imdb_id": "tt0239195", + "name": "Survivor", + "type": "series", + "year": "2000–" + }, + { + "_id": "53677ef9847ccc8123a14507", + "imdb_id": "tt1480684", + "name": "The League", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "616499d964ec43ef9845634e", + "imdb_id": "tt15026576", + "name": "The Fruit of Evolution: Before I Knew It, My Life Had It Made", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "642ac38864ec43ef9892c18b", + "imdb_id": "tt14586350", + "name": "Love & Death", + "type": "series", + "year": "2023" + }, + { + "_id": "57e4c19ed7e54929823e8acb", + "imdb_id": "tt5197820", + "type": "series", + "name": "Van Helsing", + "year": "2016–2021" + }, + { + "_id": "53677ef9847ccc8123a13eb5", + "imdb_id": "tt0455275", + "name": "Prison Break", + "type": "series", + "year": "2005–2017" + }, + { + "_id": "5530eddbcc9eee85bb52e4ee", + "imdb_id": "tt1470837", + "name": "The Garfield Show", + "year": "2008–2016", + "type": "series" + }, + { + "_id": "62be25c664ec43ef9874fcde", + "imdb_id": "tt17736234", + "name": "Bastard!! Heavy Metal, Dark Fantasy", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "57f30454d7e54929823f578b", + "imdb_id": "tt5511582", + "type": "series", + "name": "Timeless", + "year": "2016–2018" + }, + { + "_id": "53677ef9847ccc8123a13bf1", + "imdb_id": "tt0363307", + "name": "America's Next Top Model", + "type": "series", + "year": "2003–2018" + }, + { + "_id": "5c15922e173739c9f4042b59", + "imdb_id": "tt0489974", + "name": "Carnival Row", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "5c12dfc3173739c9f4274d0a", + "imdb_id": "tt7712598", + "name": "Blood & Treasure", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677f05847ccc8123a1797f", + "imdb_id": "tt2202488", + "name": "Mountain Men", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f0e847ccc8123a19566", + "imdb_id": "tt0261463", + "name": "Ceres: Celestial Legend", + "type": "series", + "year": "2000" + }, + { + "_id": "53677f43847ccc8123a1fb33", + "imdb_id": "tt0088470", + "name": "227", + "type": "series", + "year": "1985–1990" + }, + { + "_id": "5c377ab6d582b2575686effb", + "imdb_id": "tt0112186", + "name": "The Sylvester & Tweety Mysteries", + "type": "series", + "year": "1995–2002" + }, + { + "_id": "5c0d820a173739c9f4a572dd", + "imdb_id": "tt6488862", + "name": "Eternal Love", + "type": "series", + "year": "2017" + }, + { + "_id": "53677ef9847ccc8123a143e7", + "imdb_id": "tt1235547", + "name": "Better Off Ted", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "6057ebf254242533415940ac", + "imdb_id": "tt11173298", + "name": "Tournament of Champions", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677eff847ccc8123a1607f", + "imdb_id": "tt0066626", + "name": "All in the Family", + "type": "series", + "year": "1971–1979" + }, + { + "_id": "5c0bf99a173739c9f4dbdd7e", + "imdb_id": "tt0062570", + "name": "Here's Lucy", + "type": "series", + "year": "1968–1974" + }, + { + "_id": "5b15abcd16f4806c2a9f656a", + "imdb_id": "tt7660850", + "type": "series", + "name": "Succession", + "year": "2018–2023" + }, + { + "_id": "5c0c26bd173739c9f4399acc", + "imdb_id": "tt0185070", + "name": "UFO Robo Grendizer", + "type": "series", + "year": "1975–1977" + }, + { + "_id": "5bcf266c173739c9f407a564", + "imdb_id": "tt7406320", + "name": "Eli Roth's History of Horror", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "606f33135424253341e633ed", + "imdb_id": "tt9214684", + "name": "Home Economics", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677f02847ccc8123a16f41", + "imdb_id": "tt2401256", + "name": "The Night Of", + "type": "series", + "year": "2016" + }, + { + "_id": "53677f05847ccc8123a17875", + "imdb_id": "tt1409055", + "name": "Dragon Ball Z Kai", + "type": "series", + "year": "2009–2015" + }, + { + "_id": "53677f19847ccc8123a1b393", + "imdb_id": "tt0068128", + "name": "Sanford and Son", + "type": "series", + "year": "1972–1978" + }, + { + "_id": "5c1bf929173739c9f446f0fb", + "imdb_id": "tt2403776", + "name": "Shadow and Bone", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677f40847ccc8123a1f84c", + "imdb_id": "tt0118289", + "name": "Cow and Chicken", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "5c5d4f37d582b25756e004b7", + "imdb_id": "tt0081907", + "name": "Never the Twain", + "type": "series", + "year": "1981–1991" + }, + { + "_id": "5ba4aee2173739c9f4ed963c", + "imdb_id": "tt5580146", + "name": "Maniac", + "type": "series", + "year": "2018" + }, + { + "_id": "53677f4c847ccc8123a2076b", + "imdb_id": "tt0242192", + "name": "Between the Lions", + "type": "series", + "year": "1999–2011" + }, + { + "_id": "5c0d6f77173739c9f47d84e8", + "imdb_id": "tt0486539", + "name": "The Megan Mullally Show", + "type": "series", + "year": "2006–2007" + }, + { + "_id": "624daa9e64ec43ef98908fa5", + "imdb_id": "tt15447890", + "name": "The Greatest Demon Lord Is Reborn as a Typical Nobody", + "type": "series", + "year": "2022" + }, + { + "_id": "5c5f0160d582b2575631d828", + "imdb_id": "tt0043204", + "name": "Goodyear Playhouse", + "type": "series", + "year": "1951–1957" + }, + { + "_id": "53677ef9847ccc8123a13894", + "imdb_id": "tt0830900", + "name": "Saving Grace", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "53677f1d847ccc8123a1bddf", + "imdb_id": "tt0273855", + "name": "My Wife and Kids", + "type": "series", + "year": "2000–2024" + }, + { + "_id": "53677f4f847ccc8123a20baa", + "imdb_id": "tt0084978", + "name": "Automan", + "type": "series", + "year": "1983–1984" + }, + { + "_id": "5c0b1b51173739c9f4638bed", + "imdb_id": "tt1190429", + "name": "Popolocrois monogatari", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "5ff7d19f5424253341f2bdaf", + "imdb_id": "tt10662034", + "name": "Mr. Mayor", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677ef9847ccc8123a13bfa", + "imdb_id": "tt1604099", + "name": "Victorious", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "610bd2f764ec43ef9813d500", + "imdb_id": "tt10168312", + "name": "What If...?", + "type": "series", + "year": "2021–" + }, + { + "_id": "53f7285da8f27b1bb90c3740", + "imdb_id": "tt2644032", + "name": "Barbie: Life in the Dreamhouse", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677f07847ccc8123a17fd0", + "imdb_id": "tt0472252", + "name": "Transformers: Cybertron", + "type": "series", + "year": "2005" + }, + { + "_id": "53677ef9847ccc8123a140f3", + "imdb_id": "tt0088634", + "name": "The Twilight Zone", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "599b6c193e5e4b900ae85c51", + "imdb_id": "tt5618256", + "name": "Manhunt", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677ef9847ccc8123a1419d", + "imdb_id": "tt1991564", + "name": "Lab Rats", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "53677f0c847ccc8123a193b2", + "imdb_id": "tt0086662", + "name": "Airwolf", + "type": "series", + "year": "1984–1986" + }, + { + "_id": "53677ef9847ccc8123a13c30", + "imdb_id": "tt0112095", + "name": "NewsRadio", + "type": "series", + "year": "1995–1999" + }, + { + "_id": "53677ef9847ccc8123a14471", + "imdb_id": "tt1621748", + "name": "Ugly Americans", + "type": "series", + "year": "2010–2012" + }, + { + "_id": "5c1ada1e173739c9f44f32f6", + "imdb_id": "tt6286394", + "name": "WWE: 205 Live", + "type": "series", + "year": "2016–2022" + }, + { + "_id": "62880a6864ec43ef98e00a0f", + "imdb_id": "tt16341212", + "name": "Aharen-san wa hakarenai", + "type": "series", + "year": "2022" + }, + { + "_id": "5c340b93173739c9f41500a8", + "imdb_id": "tt8708280", + "name": "State of the Union", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "6270647364ec43ef98158b1d", + "imdb_id": "tt19869844", + "name": "American Idol", + "type": "series", + "year": "2018–" + }, + { + "_id": "54e600a5fc2ab98b66971c3b", + "imdb_id": "tt0252399", + "name": "Dumbo's Circus", + "type": "series", + "year": "1985–1986" + }, + { + "_id": "53677efd847ccc8123a15531", + "imdb_id": "tt0108717", + "name": "Mystery!: Cadfael", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "5b3614b516f4806c2aac30c3", + "imdb_id": "tt7965802", + "type": "series", + "name": "Megalo Box", + "year": "2018–2021" + }, + { + "_id": "5817dd1955f8aab460cf8baa", + "imdb_id": "tt4695530", + "name": "People of Earth", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f02847ccc8123a16ccb", + "imdb_id": "tt0103522", + "name": "Red Shoe Diaries", + "type": "series", + "year": "1992–1999" + }, + { + "_id": "539173bca8f27b1bb90ade62", + "imdb_id": "tt0101198", + "name": "Silk Stalkings", + "type": "series", + "year": "1991–1999" + }, + { + "_id": "59fd9257543165dcd8886b2f", + "imdb_id": "tt2580046", + "type": "series", + "name": "Miraculous: Tales of Ladybug & Cat Noir", + "year": "2015–" + }, + { + "_id": "62332c5564ec43ef9844e1f3", + "imdb_id": "tt11947418", + "name": "Minx", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677efd847ccc8123a1595b", + "imdb_id": "tt1400819", + "name": "Horrible Histories", + "type": "series", + "year": "2009–2023" + }, + { + "_id": "5c0ef351173739c9f40f6eca", + "imdb_id": "tt2445666", + "name": "Studio C", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677ef9847ccc8123a13905", + "imdb_id": "tt0051311", + "name": "Sea Hunt", + "type": "series", + "year": "1958–1961" + }, + { + "_id": "5c39d26cd582b25756d98683", + "imdb_id": "tt0182633", + "name": "Sergeant Preston of the Yukon", + "type": "series", + "year": "1955–1958" + }, + { + "_id": "5378cc37847ccc8123ad565d", + "imdb_id": "tt3487382", + "name": "Forever", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f08847ccc8123a1852a", + "imdb_id": "tt0857277", + "name": "Back at the Barnyard", + "type": "series", + "year": "2007–2011" + }, + { + "_id": "53677f17847ccc8123a1aaaf", + "imdb_id": "tt2443340", + "name": "Motive", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677f35847ccc8123a1ebd7", + "imdb_id": "tt0092339", + "name": "A Different World", + "type": "series", + "year": "1987–1993" + }, + { + "_id": "53677eff847ccc8123a15ea7", + "imdb_id": "tt0096626", + "name": "The Kids in the Hall", + "type": "series", + "year": "1988–2021" + }, + { + "_id": "586d4c931635517fbf5677ad", + "imdb_id": "tt5638056", + "name": "The Mick", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "5c0e5ae2173739c9f4eee7ca", + "imdb_id": "tt4831392", + "name": "Monster Musume: Everyday Life with Monster Girls", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "5c1ecba4173739c9f45cc34f", + "imdb_id": "tt3850598", + "name": "BMF", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c25e5e2173739c9f4e8d8a3", + "imdb_id": "tt2377276", + "name": "We Got Married", + "type": "series", + "year": "2008–" + }, + { + "_id": "53677f00847ccc8123a16814", + "imdb_id": "tt0101205", + "name": "Step by Step", + "type": "series", + "year": "1991–1998" + }, + { + "_id": "53677f03847ccc8123a1720b", + "imdb_id": "tt1817311", + "name": "64 Zoo Lane", + "type": "series", + "year": "1999–2013" + }, + { + "_id": "568d6cd1bb83c664989bbd02", + "imdb_id": "tt4270492", + "name": "Billions", + "year": "2016–2023", + "type": "series" + }, + { + "_id": "53677f0a847ccc8123a188d8", + "imdb_id": "tt0466352", + "name": "The Prince of Tennis", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "53677efc847ccc8123a14e9a", + "imdb_id": "tt2006005", + "name": "Trollied", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "5c0b59c6173739c9f4bc8c06", + "imdb_id": "tt0105559", + "name": "Tenchi Muyo!", + "type": "series", + "year": "1992–2005" + }, + { + "_id": "55fa7ed3bf6c900d1841f471", + "imdb_id": "tt4422836", + "name": "Limitless", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "53677efc847ccc8123a15220", + "imdb_id": "tt0058815", + "name": "I Dream of Jeannie", + "type": "series", + "year": "1965–1970" + }, + { + "_id": "53677f0c847ccc8123a1918e", + "imdb_id": "tt0090410", + "name": "Crime Story", + "type": "series", + "year": "1986–1988" + }, + { + "_id": "53677f02847ccc8123a17000", + "imdb_id": "tt0955346", + "name": "Moonlight", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "53677eff847ccc8123a15d75", + "imdb_id": "tt0259141", + "name": "Jackie Chan Adventures", + "type": "series", + "year": "2000–2005" + }, + { + "_id": "53677ef9847ccc8123a1383a", + "imdb_id": "tt1606375", + "name": "Downton Abbey", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "54fb5f32711bd19c92ad4345", + "imdb_id": "tt2622982", + "name": "The Devil Is a Part-Timer!", + "year": "2013–2023", + "type": "series" + }, + { + "_id": "5c5f5cfad582b25756c3c687", + "imdb_id": "tt8697870", + "name": "The Nevers", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677f0a847ccc8123a189ac", + "imdb_id": "tt0260615", + "name": "The Forsyte Saga", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "5c155cdc173739c9f492ed6f", + "imdb_id": "tt5330088", + "name": "The $100,000 Pyramid", + "type": "series", + "year": "2016–" + }, + { + "_id": "63d3471264ec43ef9859d0d9", + "imdb_id": "tt15677150", + "name": "Shrinking", + "type": "series", + "year": "2023–" + }, + { + "_id": "54edea533a9a6f404a162e35", + "imdb_id": "tt4136774", + "name": "The Ministry of Time", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "53677f17847ccc8123a1ac5d", + "imdb_id": "tt0409630", + "name": "Texhnolyze", + "type": "series", + "year": "2003" + }, + { + "_id": "53677f08847ccc8123a18574", + "imdb_id": "tt0098878", + "name": "Northern Exposure", + "type": "series", + "year": "1990–1995" + }, + { + "_id": "6348f8c464ec43ef987f4492", + "imdb_id": "tt21929358", + "name": "Akiba Maid War", + "type": "series", + "year": "2022" + }, + { + "_id": "5c0cd610173739c9f44c1241", + "imdb_id": "tt6782014", + "name": "Mystery Science Theater 3000", + "type": "series", + "year": "2017–2022" + }, + { + "_id": "5c0bab0c173739c9f43e820a", + "imdb_id": "tt0086787", + "name": "Punky Brewster", + "type": "series", + "year": "1984–1988" + }, + { + "_id": "5c099da3173739c9f4b44b9b", + "imdb_id": "tt0328738", + "name": "Fruits Basket", + "type": "series", + "year": "2001" + }, + { + "_id": "53677f43847ccc8123a1fabf", + "imdb_id": "tt2474952", + "name": "Bravest Warriors", + "type": "series", + "year": "2009–2018" + }, + { + "_id": "53677f24847ccc8123a1d268", + "imdb_id": "tt0115326", + "name": "PSI Factor: Chronicles of the Paranormal", + "type": "series", + "year": "1996–2000" + }, + { + "_id": "58c984c81635517fbf56e5fe", + "imdb_id": "tt5052460", + "name": "Taken", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "5c15d691173739c9f469cc3e", + "imdb_id": "tt0115144", + "name": "Cosby", + "type": "series", + "year": "1996–2000" + }, + { + "_id": "5c5165ead582b257560e984a", + "imdb_id": "tt8323628", + "name": "My Life with the Walter Boys", + "type": "series", + "year": "2023–" + }, + { + "_id": "54250887a8f27b1bb90cd79b", + "imdb_id": "tt2112923", + "name": "Celebrity Name Game", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f0c847ccc8123a18fed", + "imdb_id": "tt0434725", + "name": "Detective School Q", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677efa847ccc8123a1464a", + "imdb_id": "tt0060028", + "name": "Star Trek", + "type": "series", + "year": "1966–1969" + }, + { + "_id": "53677f15847ccc8123a1a9e8", + "imdb_id": "tt0092379", + "name": "Inspector Morse", + "type": "series", + "year": "1987–2000" + }, + { + "_id": "53677ef9847ccc8123a13c90", + "imdb_id": "tt0330251", + "name": "The L Word", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "5c09b7c0173739c9f4e956fe", + "imdb_id": "tt8699270", + "name": "Ultraman", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677f37847ccc8123a1ed99", + "imdb_id": "tt0068040", + "name": "Are You Being Served?", + "type": "series", + "year": "1972–1985" + }, + { + "_id": "5c3338b8173739c9f476d359", + "imdb_id": "tt9471404", + "name": "The Chosen", + "type": "series", + "year": "2017–" + }, + { + "_id": "5378cc15847ccc8123ad4d22", + "imdb_id": "tt3560084", + "name": "NCIS: New Orleans", + "type": "series", + "year": "2014–2021" + }, + { + "_id": "5c0be08d173739c9f4a7f9f1", + "imdb_id": "tt7817856", + "name": "The Crown of the Kings", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677efd847ccc8123a159fc", + "imdb_id": "tt0084972", + "name": "Alvin & the Chipmunks", + "type": "series", + "year": "1983–1990" + }, + { + "_id": "53677f19847ccc8123a1b253", + "imdb_id": "tt1733785", + "name": "The Bridge", + "type": "series", + "year": "2011–2018" + }, + { + "_id": "59cc5a4c067c4652104aa54c", + "imdb_id": "tt6473344", + "type": "series", + "name": "SEAL Team", + "year": "2017–2024" + }, + { + "_id": "53677ef9847ccc8123a13b0a", + "imdb_id": "tt1694423", + "name": "MasterChef USA", + "type": "series", + "year": "2010–" + }, + { + "_id": "5c3628e9d582b25756447d0e", + "imdb_id": "tt0090479", + "name": "Maison Ikkoku", + "type": "series", + "year": "1986–1988" + }, + { + "_id": "53677f1f847ccc8123a1c552", + "imdb_id": "tt0112221", + "name": "Wedding Peach", + "type": "series", + "year": "1995–1996" + }, + { + "_id": "5c0b9ef8173739c9f4273c33", + "imdb_id": "tt8146754", + "name": "Infinity Train", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677efc847ccc8123a14f5a", + "imdb_id": "tt0098740", + "name": "America's Funniest Home Videos", + "type": "series", + "year": "1989–" + }, + { + "_id": "6534d3c9bd36726cbb4497c3", + "imdb_id": "tt26743760", + "name": "The Apothecary Diaries", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f17847ccc8123a1ae75", + "imdb_id": "tt0259795", + "name": "The Old Grey Whistle Test", + "type": "series", + "year": "1971–2018" + }, + { + "_id": "5c0c8b86173739c9f4ef0698", + "imdb_id": "tt8362852", + "name": "Swamp Thing", + "type": "series", + "year": "2019" + }, + { + "_id": "5884c0e81635517fbf569dd1", + "imdb_id": "tt5994364", + "name": "Guardian: The Lonely and Great God", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f20847ccc8123a1c6d2", + "imdb_id": "tt0089008", + "name": "Deceptions", + "type": "series", + "year": "1985–" + }, + { + "_id": "53677ef9847ccc8123a13b5e", + "imdb_id": "tt1235099", + "name": "Lie to Me", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "53677f12847ccc8123a19fa1", + "imdb_id": "tt0096569", + "name": "Doogie Howser, M.D.", + "type": "series", + "year": "1989–1993" + }, + { + "_id": "53677efd847ccc8123a15a11", + "imdb_id": "tt0377260", + "name": "Shameless", + "type": "series", + "year": "2004–2013" + }, + { + "_id": "53677f19847ccc8123a1b279", + "imdb_id": "tt0145628", + "name": "Popeye the Sailor", + "type": "series", + "year": "1960–1962" + }, + { + "_id": "53677efc847ccc8123a14f75", + "imdb_id": "tt0960136", + "name": "Dirty Sexy Money", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "5c447b69d582b25756110f85", + "imdb_id": "tt0108889", + "name": "One West Waikiki", + "type": "series", + "year": "1994–1996" + }, + { + "_id": "53677efc847ccc8123a15075", + "imdb_id": "tt1971245", + "name": "The Voice UK", + "type": "series", + "year": "2012–" + }, + { + "_id": "5432d88fa8f27b1bb90d0cb4", + "imdb_id": "tt0439341", + "name": "6Teen", + "type": "series", + "year": "2004–2010" + }, + { + "_id": "5c472dbbd582b257568f38c8", + "imdb_id": "tt0111914", + "name": "C.P.W.", + "type": "series", + "year": "1995–1996" + }, + { + "_id": "53677f40847ccc8123a1f53e", + "imdb_id": "tt0080221", + "name": "Galactica 1980", + "type": "series", + "year": "1980" + }, + { + "_id": "537500ca847ccc8123ad0ad6", + "imdb_id": "tt2777882", + "name": "El Señor de los Cielos", + "type": "series", + "year": "2013–" + }, + { + "_id": "56183accec193d5e98269973", + "imdb_id": "tt4215734", + "name": "Be Cool, Scooby-Doo!", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "5c20043b173739c9f486c4a3", + "imdb_id": "tt0054545", + "name": "Hazel", + "type": "series", + "year": "1961–1966" + }, + { + "_id": "53677f22847ccc8123a1ce53", + "imdb_id": "tt0396991", + "name": "LazyTown", + "type": "series", + "year": "2002–2014" + }, + { + "_id": "53677f23847ccc8123a1cf71", + "imdb_id": "tt2292621", + "name": "Burning Love", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "5c3f1bafd582b257569776c6", + "imdb_id": "tt7671598", + "name": "Messiah", + "type": "series", + "year": "2020" + }, + { + "_id": "5c0aad5c173739c9f4852a8d", + "imdb_id": "tt8416494", + "name": "Doom Patrol", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677f1e847ccc8123a1c1fb", + "imdb_id": "tt1409383", + "name": "Big Windup!", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "5c3da367d582b25756e34459", + "imdb_id": "tt0112233", + "name": "Zenki", + "type": "series", + "year": "1995–" + }, + { + "_id": "5c0c3f99173739c9f46e9f7e", + "imdb_id": "tt4858114", + "name": "Hotel Transylvania: The Series", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "651d9d0cbd36726cbb4dbc71", + "imdb_id": "tt28685497", + "name": "Berserk of Gluttony", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a138d1", + "imdb_id": "tt1628033", + "name": "Top Gear", + "type": "series", + "year": "2002–" + }, + { + "_id": "5401f968a8f27b1bb90c5b0b", + "imdb_id": "tt3973820", + "name": "Red Oaks", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "55070fe8711bd19c92add786", + "imdb_id": "tt0388585", + "name": "CentoVetrine", + "year": "2001–", + "type": "series" + }, + { + "_id": "62f7296564ec43ef9890d5a0", + "imdb_id": "tt15669534", + "name": "Tales of the Walking Dead", + "type": "series", + "year": "2022" + }, + { + "_id": "641c255864ec43ef98403a5f", + "imdb_id": "tt13918776", + "name": "The Night Agent", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f3a847ccc8123a1ef34", + "imdb_id": "tt2548200", + "name": "Slugterra", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "5378cbf3847ccc8123ad31e2", + "imdb_id": "tt3358020", + "name": "Parasyte: The Maxim", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677efd847ccc8123a15b1e", + "imdb_id": "tt1639109", + "name": "Angel Beats!", + "type": "series", + "year": "2010" + }, + { + "_id": "53677f74847ccc8123a2375e", + "imdb_id": "tt0098919", + "name": "Swamp Thing", + "type": "series", + "year": "1990–1993" + }, + { + "_id": "53677f72847ccc8123a235b2", + "imdb_id": "tt1299440", + "name": "Fanboy & Chum Chum", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "646d5f7fbd36726cbbeeb560", + "imdb_id": "tt14028208", + "name": "Clone High", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f22847ccc8123a1cd62", + "imdb_id": "tt0149490", + "name": "Meet the Press", + "type": "series", + "year": "1947–" + }, + { + "_id": "6182992764ec43ef98531e65", + "imdb_id": "tt13368190", + "name": "Judy Justice", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f6c847ccc8123a2302d", + "imdb_id": "tt0056774", + "name": "Mr. Novak", + "type": "series", + "year": "1963–1965" + }, + { + "_id": "53677f1d847ccc8123a1bf11", + "imdb_id": "tt0181935", + "name": "Norm", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "5811ba24d7e549298241449f", + "imdb_id": "tt0247081", + "name": "Boston Public", + "type": "series", + "year": "2000–2006" + }, + { + "_id": "53677f45847ccc8123a1ff60", + "imdb_id": "tt0247144", + "name": "Yes, Dear", + "type": "series", + "year": "2000–2006" + }, + { + "_id": "5c157d38173739c9f4d86984", + "imdb_id": "tt8741290", + "name": "Tales from the Loop", + "type": "series", + "year": "2020" + }, + { + "_id": "5543c7c2d728d29134b6e4f7", + "imdb_id": "tt4524056", + "name": "Vis a vis", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13e29", + "imdb_id": "tt0859592", + "name": "Army Wives", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "5c0ee953173739c9f4fc1831", + "imdb_id": "tt9252156", + "name": "Departure", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "5c0f4ca3173739c9f49c6263", + "imdb_id": "tt0307427", + "name": "s-CRY-ed", + "type": "series", + "year": "2001" + }, + { + "_id": "63443b8464ec43ef988a7684", + "imdb_id": "tt19406880", + "name": "Shinmai renkinjutsushi no tenpo keiei", + "type": "series", + "year": "2022" + }, + { + "_id": "61bf074c64ec43ef9855018c", + "imdb_id": "tt13991232", + "name": "1883", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5c0a3f6d173739c9f4b7964b", + "imdb_id": "tt6025022", + "name": "Justice League Unlimited", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "63e5151464ec43ef98ab12f4", + "imdb_id": "tt13433814", + "name": "My Dad the Bounty Hunter", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f48847ccc8123a202d8", + "imdb_id": "tt0169438", + "name": "Dream Team", + "type": "series", + "year": "1997–2007" + }, + { + "_id": "6289ea0c64ec43ef9834724d", + "imdb_id": "tt15686254", + "name": "Summer Time Rendering", + "type": "series", + "year": "2022" + }, + { + "_id": "5819ad5655f8aab460cfa87b", + "imdb_id": "tt5679720", + "name": "Bungo Stray Dogs", + "type": "series", + "year": "2016–" + }, + { + "_id": "5c26b302173739c9f4834fbb", + "imdb_id": "tt1085074", + "name": "Black Cat", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "62c5f85164ec43ef980e367f", + "imdb_id": "tt13628870", + "name": "Harem in the Labyrinth of Another World", + "type": "series", + "year": "2022" + }, + { + "_id": "5bfe18bd173739c9f4e2a479", + "imdb_id": "tt5015548", + "name": "Agatha Raisin", + "type": "series", + "year": "2014–" + }, + { + "_id": "5c0dd1f0173739c9f4311dd0", + "imdb_id": "tt0303503", + "name": "Magical DoReMi", + "type": "series", + "year": "1999–2004" + }, + { + "_id": "53677efc847ccc8123a15135", + "imdb_id": "tt1242441", + "name": "Men of a Certain Age", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "5c240ab8173739c9f4c2c510", + "imdb_id": "tt7520794", + "name": "Russian Doll", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f14847ccc8123a1a4bd", + "imdb_id": "tt0423731", + "name": "Samurai Champloo", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "53677f5e847ccc8123a22213", + "imdb_id": "tt0387714", + "name": "All Grown Up!", + "type": "series", + "year": "2003–2008" + }, + { + "_id": "5c5de778d582b25756aa258b", + "imdb_id": "tt1206627", + "name": "Misutâ ajikko", + "type": "series", + "year": "1987–1989" + }, + { + "_id": "5c3b8aafd582b25756c86bc1", + "imdb_id": "tt0096635", + "name": "Life Goes On", + "type": "series", + "year": "1989–1993" + }, + { + "_id": "642ed49e64ec43ef98ae237f", + "imdb_id": "tt11127388", + "name": "Grease: Rise of the Pink Ladies", + "type": "series", + "year": "2023" + }, + { + "_id": "53677efc847ccc8123a152f6", + "imdb_id": "tt0083455", + "name": "Newhart", + "type": "series", + "year": "1982–1990" + }, + { + "_id": "5c17b109173739c9f487808f", + "imdb_id": "tt0218775", + "name": "Monster Rancher", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "5378cbfe847ccc8123ad3944", + "imdb_id": "tt3305096", + "name": "Galavant", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c1f2b67173739c9f4e83378", + "imdb_id": "tt4584326", + "name": "Seraph of the End", + "type": "series", + "year": "2015" + }, + { + "_id": "53677f3d847ccc8123a1f259", + "imdb_id": "tt0075561", + "name": "The Professionals", + "type": "series", + "year": "1977–1983" + }, + { + "_id": "53677f05847ccc8123a1797d", + "imdb_id": "tt1134000", + "name": "Mobile Suit Gundam 00", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "53677f3a847ccc8123a1ef47", + "imdb_id": "tt0429305", + "name": "American Dragon: Jake Long", + "type": "series", + "year": "2005–2007" + }, + { + "_id": "53677f03847ccc8123a17268", + "imdb_id": "tt1699440", + "name": "The Cat in the Hat Knows a Lot About That!", + "type": "series", + "year": "2010–2018" + }, + { + "_id": "585846791635517fbf561d74", + "imdb_id": "tt4635282", + "name": "The OA", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "5eabd6275424253341d630e2", + "imdb_id": "tt9827854", + "name": "Hollywood", + "type": "series", + "year": "2020" + }, + { + "_id": "54f5b396451edcfca9b1c57c", + "imdb_id": "tt3906732", + "name": "Good Witch", + "year": "2015–2021", + "type": "series" + }, + { + "_id": "5e156ba7c4ccb5dd92bd6aa6", + "imdb_id": "tt9742936", + "name": "FBI: Most Wanted", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f79847ccc8123a23ce4", + "imdb_id": "tt3559912", + "name": "The Carbonaro Effect", + "type": "series", + "year": "2014–" + }, + { + "_id": "56c0c506f6b914c6c681d729", + "imdb_id": "tt4905554", + "name": "Jack Irish", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "53677efa847ccc8123a14786", + "imdb_id": "tt0348914", + "name": "Deadwood", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "55a648a6bf6c900d183ad16a", + "imdb_id": "tt4384306", + "name": "Sound! Euphonium", + "year": "2015–", + "type": "series" + }, + { + "_id": "578e1b38f0b6c53b3c78c740", + "imdb_id": "tt4971144", + "name": "Greenleaf", + "year": "2016–2020", + "type": "series" + }, + { + "_id": "6228edc364ec43ef98f8f7a7", + "imdb_id": "tt15170340", + "name": "Orient", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f63847ccc8123a22858", + "imdb_id": "tt0061240", + "name": "The Carol Burnett Show", + "type": "series", + "year": "1967–1978" + }, + { + "_id": "5dbc2ffac4ccb5dd927d512f", + "imdb_id": "tt7949218", + "name": "See", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677f05847ccc8123a17ce1", + "imdb_id": "tt0280277", + "name": "Mr. Bean: The Animated Series", + "type": "series", + "year": "2002–2019" + }, + { + "_id": "5c48c89bd582b25756cc30d7", + "imdb_id": "tt2649756", + "name": "The Idolm@ster", + "type": "series", + "year": "2011" + }, + { + "_id": "5c5c0797d582b25756259edb", + "imdb_id": "tt5828144", + "name": "Rainbow Ruby", + "type": "series", + "year": "2016–2020" + }, + { + "_id": "54fbb445711bd19c92ad490b", + "imdb_id": "tt0437018", + "name": "Krypto the Superdog", + "year": "2005–2006", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13a97", + "imdb_id": "tt0487831", + "name": "The IT Crowd", + "type": "series", + "year": "2006–2013" + }, + { + "_id": "5c156057173739c9f49a227e", + "imdb_id": "tt6632666", + "type": "series", + "name": "Project Blue Book", + "year": "2019–2020" + }, + { + "_id": "63b9c77e64ec43ef98d2d940", + "imdb_id": "tt18311412", + "name": "NieR:Automata Ver1.1a", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c09e344173739c9f43e1599", + "imdb_id": "tt9304350", + "name": "Fruits Basket", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "601d873a54242533416eb14a", + "imdb_id": "tt1847445", + "name": "The Tatami Galaxy", + "type": "series", + "year": "2010" + }, + { + "_id": "53677efd847ccc8123a155e5", + "imdb_id": "tt0361227", + "name": "Punk'd", + "type": "series", + "year": "2003–2015" + }, + { + "_id": "55a648abbf6c900d183ad16b", + "imdb_id": "tt4584754", + "name": "RIN-NE", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "5c27f682173739c9f4b019a7", + "imdb_id": "tt0105988", + "name": "Droopy: Master Detective", + "type": "series", + "year": "1993–1994" + }, + { + "_id": "53677efa847ccc8123a14890", + "imdb_id": "tt0131179", + "name": "Detective Conan", + "type": "series", + "year": "1996–" + }, + { + "_id": "5c1233bb173739c9f4d635ee", + "imdb_id": "tt0175863", + "name": "Lucky Luke", + "type": "series", + "year": "1983–1984" + }, + { + "_id": "6138ed5d64ec43ef9877132d", + "imdb_id": "tt12225230", + "name": "Doogie Kamealoha, M.D.", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677f2f847ccc8123a1e65e", + "imdb_id": "tt2834032", + "name": "Love Thy Neighbor", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f0c847ccc8123a18f45", + "imdb_id": "tt1129029", + "name": "Satisfaction", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "5378cc09847ccc8123ad45fa", + "imdb_id": "tt3576794", + "name": "Red Band Society", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f07847ccc8123a1813a", + "imdb_id": "tt0086770", + "name": "Night Court", + "type": "series", + "year": "1984–1992" + }, + { + "_id": "53677f5a847ccc8123a21ac8", + "imdb_id": "tt0052442", + "name": "One Step Beyond", + "type": "series", + "year": "1959–1961" + }, + { + "_id": "5f89425554242533410f49d0", + "imdb_id": "tt10266874", + "name": "Helstrom", + "type": "series", + "year": "2020" + }, + { + "_id": "58ff46731635517fbf56e7a1", + "imdb_id": "tt5673782", + "name": "Genius", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f3a847ccc8123a1f053", + "imdb_id": "tt0472642", + "name": "Amar en tiempos revueltos", + "type": "series", + "year": "2005–2024" + }, + { + "_id": "63e4dcd064ec43ef985f07f0", + "imdb_id": "tt18250904", + "name": "Not Dead Yet", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f2c847ccc8123a1e171", + "imdb_id": "tt0472989", + "name": "Wild 'N Out", + "type": "series", + "year": "2005–" + }, + { + "_id": "537afa15847ccc8123ad61fe", + "imdb_id": "tt0077013", + "name": "Future Boy Conan", + "type": "series", + "year": "1978" + }, + { + "_id": "57dd2352d7e54929823e23c9", + "imdb_id": "tt5151816", + "name": "Chesapeake Shores", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "53677f37847ccc8123a1ed26", + "imdb_id": "tt0075513", + "name": "The Hardy Boys/Nancy Drew Mysteries", + "type": "series", + "year": "1977–1979" + }, + { + "_id": "5c0ad5f5173739c9f4d68e82", + "imdb_id": "tt8526988", + "name": "Total DramaRama", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "53677f3a847ccc8123a1f166", + "imdb_id": "tt0169414", + "name": "Arthur", + "type": "series", + "year": "1996–2022" + }, + { + "_id": "5c2bff13173739c9f4d0c140", + "imdb_id": "tt0233033", + "name": "The Berenstain Bears", + "type": "series", + "year": "1985–2004" + }, + { + "_id": "53677ef9847ccc8123a13a47", + "imdb_id": "tt1772752", + "name": "A.N.T. Farm", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677f5e847ccc8123a220bf", + "imdb_id": "tt3114390", + "name": "KILL la KILL", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "5c60ca76d582b25756b54b85", + "imdb_id": "tt2188535", + "name": "Tokumei Sentai Go-Busters", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "53677ef9847ccc8123a138a1", + "imdb_id": "tt0437005", + "name": "Hell's Kitchen", + "type": "series", + "year": "2005–" + }, + { + "_id": "53677f17847ccc8123a1ac21", + "imdb_id": "tt0414766", + "name": "Rebelde", + "type": "series", + "year": "2004–2006" + }, + { + "_id": "5c1f1d23173739c9f4d7caa8", + "imdb_id": "tt2235759", + "name": "The Great", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "56687423bb83c664989838e0", + "imdb_id": "tt4226226", + "name": "Holiday Baking Championship", + "year": "2014–", + "type": "series" + }, + { + "_id": "5e7c93c6733826cd9f6b3153", + "imdb_id": "tt10364808", + "name": "Mao Mao: Heroes of Pure Heart", + "type": "series", + "year": "2014–2024" + }, + { + "_id": "55c8a058bf6c900d183dc183", + "imdb_id": "tt4905966", + "name": "Valerie's Home Cooking", + "year": "2015–2023", + "type": "series" + }, + { + "_id": "5c292c45173739c9f4bd988b", + "imdb_id": "tt9179552", + "name": "Dr. Death", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "5c255be9173739c9f4253112", + "imdb_id": "tt5778326", + "name": "Black Jack", + "type": "series", + "year": "1993–2018" + }, + { + "_id": "53677f66847ccc8123a22a09", + "imdb_id": "tt0247902", + "name": "Yu-Gi-Oh! Duel Monsters", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "541463a1a8f27b1bb90c996b", + "imdb_id": "tt0162796", + "name": "Bump in the Night", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "5c2945fe173739c9f4f42546", + "imdb_id": "tt5737466", + "name": "The History of Comedy", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677f2e847ccc8123a1e377", + "imdb_id": "tt2217759", + "name": "Monday Mornings", + "type": "series", + "year": "2013" + }, + { + "_id": "53677ef9847ccc8123a1433f", + "imdb_id": "tt0362192", + "name": "State of Play", + "type": "series", + "year": "2003" + }, + { + "_id": "53677f79847ccc8123a23cb7", + "imdb_id": "tt2772104", + "name": "Mischievous Kiss: Love in Tokyo", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "53b176e0a8f27b1bb90b4078", + "imdb_id": "tt0805960", + "name": "Speed Grapher", + "type": "series", + "year": "2005" + }, + { + "_id": "6432754464ec43ef9899d2bf", + "imdb_id": "tt21423786", + "name": "The Dangers in My Heart", + "type": "series", + "year": "2023–" + }, + { + "_id": "5401f968a8f27b1bb90c5afb", + "imdb_id": "tt0115420", + "name": "Wind at My Back", + "type": "series", + "year": "1996–2001" + }, + { + "_id": "53677f0a847ccc8123a18824", + "imdb_id": "tt0086681", + "name": "Charles in Charge", + "type": "series", + "year": "1984–1990" + }, + { + "_id": "53677efd847ccc8123a15b83", + "imdb_id": "tt1181917", + "name": "The Suite Life on Deck", + "type": "series", + "year": "2008–2011" + }, + { + "_id": "547726d987010db6f207f53e", + "imdb_id": "tt0077058", + "name": "The Paper Chase", + "type": "series", + "year": "1978–1986" + }, + { + "_id": "53677efa847ccc8123a14a33", + "imdb_id": "tt0176095", + "name": "The Challenge", + "type": "series", + "year": "1998–" + }, + { + "_id": "53677f0a847ccc8123a186a5", + "imdb_id": "tt2177491", + "name": "Ben and Kate", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "539c4866a8f27b1bb90afede", + "imdb_id": "tt2399794", + "name": "Chasing Life", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "5c26864d173739c9f426c778", + "imdb_id": "tt0184169", + "name": "Ultraseven", + "type": "series", + "year": "1967–1968" + }, + { + "_id": "53677f04847ccc8123a17414", + "imdb_id": "tt2406376", + "name": "The Bridge", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "5c56b62dd582b257561d682b", + "imdb_id": "tt9340526", + "name": "P-Valley", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f08847ccc8123a1835d", + "imdb_id": "tt0108684", + "name": "Aaahh!!! Real Monsters", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "5c27f892173739c9f4b4583a", + "imdb_id": "tt8633518", + "name": "Weird City", + "type": "series", + "year": "2019" + }, + { + "_id": "53677f19847ccc8123a1b5ce", + "imdb_id": "tt0327386", + "name": "The Twelve Kingdoms", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "54e9bb50417d39942847b67e", + "imdb_id": "tt0118484", + "name": "Sunset Beach", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "53677f1b847ccc8123a1b96f", + "imdb_id": "tt0841961", + "name": "Kingdom", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "53677eff847ccc8123a16026", + "imdb_id": "tt0112111", + "name": "The Outer Limits", + "type": "series", + "year": "1995–2002" + }, + { + "_id": "53677f00847ccc8123a1652d", + "imdb_id": "tt0922037", + "name": "La que se avecina", + "type": "series", + "year": "2007–" + }, + { + "_id": "53677efd847ccc8123a157ab", + "imdb_id": "tt0760437", + "name": "Ben 10", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "5378cbe4847ccc8123ad28f9", + "imdb_id": "tt3148266", + "name": "12 Monkeys", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "55ed9310bf6c900d18414d84", + "imdb_id": "tt4307902", + "name": "The Carmichael Show", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13d57", + "imdb_id": "tt0462128", + "name": "The New Adventures of Old Christine", + "type": "series", + "year": "2006–2023" + }, + { + "_id": "53677eff847ccc8123a15d07", + "imdb_id": "tt0112047", + "name": "Life with Louie", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "6265215a64ec43ef98f2b152", + "imdb_id": "tt14396202", + "name": "Love After World Domination", + "type": "series", + "year": "2022" + }, + { + "_id": "54c92d1ae573cadcfa1f7701", + "imdb_id": "tt0108876", + "name": "New York Undercover", + "type": "series", + "year": "1994–2024" + }, + { + "_id": "59d2e3bd067c465210833606", + "imdb_id": "tt4396630", + "type": "series", + "name": "The Gifted", + "year": "2017–2019" + }, + { + "_id": "5f3622cb5424253341f5aa02", + "imdb_id": "tt10986410", + "name": "Ted Lasso", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "5c26d135173739c9f4bdf6b0", + "imdb_id": "tt0085109", + "name": "Webster", + "type": "series", + "year": "1983–1989" + }, + { + "_id": "60fa738a64ec43ef98f874d8", + "imdb_id": "tt10826054", + "name": "Masters of the Universe: Revelation", + "type": "series", + "year": "2021" + }, + { + "_id": "58e4edbb1635517fbf56e6b3", + "imdb_id": "tt5788792", + "name": "The Marvelous Mrs. Maisel", + "type": "series", + "year": "2017–2023" + }, + { + "_id": "54df8d65e573cadcfa1fcf3f", + "imdb_id": "tt3138604", + "name": "Thunderbirds Are Go", + "type": "series", + "year": "2015–2020" + }, + { + "_id": "53677ef9847ccc8123a13b63", + "imdb_id": "tt1796960", + "name": "Homeland", + "type": "series", + "year": "2011–2020" + }, + { + "_id": "53677f17847ccc8123a1b00b", + "imdb_id": "tt0362404", + "name": "All of Us", + "type": "series", + "year": "2003–2023" + }, + { + "_id": "5c2763aa173739c9f48c4981", + "imdb_id": "tt7537488", + "name": "Sagrada Reset", + "type": "series", + "year": "2017" + }, + { + "_id": "53677f1c847ccc8123a1bc01", + "imdb_id": "tt0112166", + "name": "The Slayers", + "type": "series", + "year": "1995–2009" + }, + { + "_id": "5bad640e173739c9f4489d7f", + "imdb_id": "tt7845644", + "name": "Single Parents", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "56cff851f6aa5b2a5344a5f1", + "imdb_id": "tt4264096", + "name": "Those Who Can't", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "53677efd847ccc8123a159c5", + "imdb_id": "tt0365969", + "name": "10-8: Officers on Duty", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677f40847ccc8123a1f850", + "imdb_id": "tt0202741", + "name": "The Man Show", + "type": "series", + "year": "1999–2014" + }, + { + "_id": "5bf85dd5173739c9f4848e22", + "imdb_id": "tt7544016", + "name": "The Russell Howard Hour", + "type": "series", + "year": "2017–" + }, + { + "_id": "5f7f920654242533411fe10a", + "imdb_id": "tt12331342", + "name": "Akudama Drive", + "type": "series", + "year": "2020" + }, + { + "_id": "53677efa847ccc8123a146c6", + "imdb_id": "tt0094512", + "name": "Monsters", + "type": "series", + "year": "1988–1990" + }, + { + "_id": "5414639ca8f27b1bb90c984f", + "imdb_id": "tt3293184", + "name": "Penn Zero: Part-Time Hero", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "5c4df4d8d582b25756aa9cd2", + "imdb_id": "tt0983985", + "name": "Sugar Sugar Rune", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "5ec0f0605424253341cc62c0", + "imdb_id": "tt10204658", + "name": "Sing "Yesterday" for Me", + "type": "series", + "year": "2020" + }, + { + "_id": "57fdfad5d7e54929823ff840", + "imdb_id": "tt4934214", + "name": "Taskmaster", + "year": "2015–", + "type": "series" + }, + { + "_id": "53677eff847ccc8123a1612c", + "imdb_id": "tt0112197", + "name": "Timon & Pumbaa", + "type": "series", + "year": "1995–1999" + }, + { + "_id": "5bb7eeae173739c9f40b1115", + "imdb_id": "tt7134908", + "name": "Elite", + "type": "series", + "year": "2018–2024" + }, + { + "_id": "5c0ad5a1173739c9f4d5e345", + "imdb_id": "tt8019790", + "name": "Apple & Onion", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "53677f07847ccc8123a18219", + "imdb_id": "tt0279570", + "name": "Love Hina", + "type": "series", + "year": "2000–2001" + }, + { + "_id": "53677f68847ccc8123a22cd5", + "imdb_id": "tt0065333", + "name": "The Partridge Family", + "type": "series", + "year": "1970–1974" + }, + { + "_id": "53677f42847ccc8123a1f8b2", + "imdb_id": "tt1402156", + "name": "The League of Super Evil", + "type": "series", + "year": "2009–2012" + }, + { + "_id": "628bc9a464ec43ef98e11256", + "imdb_id": "tt11743610", + "name": "The Terminal List", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c1ff1be173739c9f46028fc", + "imdb_id": "tt0300859", + "name": "Madame Peppermint", + "type": "series", + "year": "1983–1984" + }, + { + "_id": "53677f6f847ccc8123a232ac", + "imdb_id": "tt1710310", + "name": "T.U.F.F. Puppy", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "550d26b4cc9eee85bb52d8e9", + "imdb_id": "tt3520702", + "name": "Bloodline", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677f02847ccc8123a16bdb", + "imdb_id": "tt0437043", + "name": "Untold Stories of the ER", + "type": "series", + "year": "2004–2020" + }, + { + "_id": "53677f1d847ccc8123a1bfa7", + "imdb_id": "tt0058853", + "name": "The Wednesday Play", + "type": "series", + "year": "1964–1970" + }, + { + "_id": "53677f17847ccc8123a1ab49", + "imdb_id": "tt0086730", + "name": "Highway to Heaven", + "type": "series", + "year": "1984–1989" + }, + { + "_id": "53677f13847ccc8123a1a2ff", + "imdb_id": "tt0115322", + "name": "Profiler", + "type": "series", + "year": "1996–2000" + }, + { + "_id": "53677f52847ccc8123a20fa3", + "imdb_id": "tt0166420", + "name": "Belphegor", + "type": "series", + "year": "1965" + }, + { + "_id": "53677f05847ccc8123a17c9d", + "imdb_id": "tt1674117", + "name": "Hero 108", + "type": "series", + "year": "2010–2012" + }, + { + "_id": "53677f12847ccc8123a19f5a", + "imdb_id": "tt0096725", + "name": "War and Remembrance", + "type": "series", + "year": "1988–1989" + }, + { + "_id": "53677f0a847ccc8123a1894e", + "imdb_id": "tt0985344", + "name": "Claymore", + "type": "series", + "year": "2007" + }, + { + "_id": "596c4aa11635517fbf56e947", + "imdb_id": "tt6170874", + "name": "Salvation", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53eb359ba8f27b1bb90c073b", + "imdb_id": "tt3742982", + "name": "Akame ga Kill!", + "type": "series", + "year": "2014" + }, + { + "_id": "53677efd847ccc8123a15868", + "imdb_id": "tt1491299", + "name": "Kourtney & Kim Take Miami", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "53677ef9847ccc8123a13e33", + "imdb_id": "tt0866442", + "name": "Eastbound & Down", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "53677ef9847ccc8123a13bc5", + "imdb_id": "tt1841108", + "name": "Femme Fatales", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "53677f74847ccc8123a23660", + "imdb_id": "tt2191991", + "name": "Billy on the Street", + "type": "series", + "year": "2011–" + }, + { + "_id": "5b59111f898916810fd9ad8b", + "imdb_id": "tt6548228", + "type": "series", + "name": "Castle Rock", + "year": "2018–2019" + }, + { + "_id": "5c0bdcb2173739c9f49f6a62", + "imdb_id": "tt7833624", + "name": "Butterbean's Café", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "54fdebc4711bd19c92adc317", + "imdb_id": "tt0042098", + "name": "Danger", + "year": "1950–1955", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13932", + "imdb_id": "tt1320080", + "name": "Celebrity Ghost Stories", + "type": "series", + "year": "2008–" + }, + { + "_id": "5aea4667f51dd22f67d30979", + "imdb_id": "tt7221388", + "type": "series", + "name": "Cobra Kai", + "year": "2018–2024" + }, + { + "_id": "5519963dcc9eee85bb52de1c", + "imdb_id": "tt0143007", + "name": "King of the Braves GaoGaiGar", + "year": "1997–1998", + "type": "series" + }, + { + "_id": "59ebb804067c465210283797", + "imdb_id": "tt4378376", + "type": "series", + "name": "Babylon Berlin", + "year": "2017–" + }, + { + "_id": "53677efc847ccc8123a14e71", + "imdb_id": "tt0496356", + "name": "My Boys", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677f00847ccc8123a1618c", + "imdb_id": "tt0383795", + "name": "The Joy of Painting", + "type": "series", + "year": "1983–1994" + }, + { + "_id": "63bfef1b64ec43ef98a8de62", + "imdb_id": "tt14153790", + "name": "Velma", + "type": "series", + "year": "2023–" + }, + { + "_id": "5ff287c754242533414050ca", + "imdb_id": "tt9140632", + "name": "The Great North", + "type": "series", + "year": "2021–" + }, + { + "_id": "5bb9413e173739c9f4ee2125", + "imdb_id": "tt8690728", + "name": "Goblin Slayer", + "type": "series", + "year": "2018–" + }, + { + "_id": "57dd11dad7e54929823e232b", + "imdb_id": "tt4370596", + "name": "Better Things", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "617e892d64ec43ef98d5ae94", + "imdb_id": "tt13352232", + "name": "High-Rise Invasion", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c4fc1c8d582b25756eedc2c", + "imdb_id": "tt0177458", + "name": "Road Rules", + "type": "series", + "year": "1995–2007" + }, + { + "_id": "5e4d66afc4ccb5dd92751784", + "imdb_id": "tt10850932", + "name": "Crash Landing on You", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "53677efd847ccc8123a15789", + "imdb_id": "tt0213338", + "name": "Cowboy Bebop", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "53677ef9847ccc8123a13d6e", + "imdb_id": "tt1486217", + "name": "Archer", + "type": "series", + "year": "2009–2023" + }, + { + "_id": "53677efa847ccc8123a148d4", + "imdb_id": "tt0417373", + "name": "The Venture Bros.", + "type": "series", + "year": "2003–2018" + }, + { + "_id": "5d38b4465111f1a8a363acc4", + "imdb_id": "tt10584446", + "name": "My Life Is Murder", + "type": "series", + "year": "2019–" + }, + { + "_id": "5a155be3543165dcd828f3d2", + "imdb_id": "tt5516154", + "type": "series", + "name": "Godless", + "year": "2017" + }, + { + "_id": "56aee56bbb83c664989ea6fb", + "imdb_id": "tt3799566", + "name": "Steve Austin's Broken Skull Challenge", + "year": "2014–", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a14001", + "imdb_id": "tt0388629", + "name": "One Piece", + "type": "series", + "year": "1999–" + }, + { + "_id": "5737155b890e549c9a5b774b", + "imdb_id": "tt4488724", + "name": "Stuck in the Middle", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "54ac20028527d2e0cb504a12", + "imdb_id": "tt0103369", + "name": "Sailor Moon", + "type": "series", + "year": "1992–1997" + }, + { + "_id": "5c3a014fd582b25756f15ae8", + "imdb_id": "tt1216124", + "name": "Kanokon", + "type": "series", + "year": "2008" + }, + { + "_id": "53677ef9847ccc8123a14051", + "imdb_id": "tt0092455", + "name": "Star Trek: The Next Generation", + "type": "series", + "year": "1987–1994" + }, + { + "_id": "53677f00847ccc8123a1633e", + "imdb_id": "tt0096707", + "name": "The Super Mario Bros. Super Show!", + "type": "series", + "year": "1989" + }, + { + "_id": "541463a0a8f27b1bb90c98bc", + "imdb_id": "tt0108981", + "name": "The Vicar of Dibley", + "type": "series", + "year": "1994–2020" + }, + { + "_id": "5f76f80154242533410f2729", + "imdb_id": "tt8962124", + "name": "Emily in Paris", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677ef9847ccc8123a13eec", + "imdb_id": "tt0092312", + "name": "21 Jump Street", + "type": "series", + "year": "1987–1991" + }, + { + "_id": "53677efc847ccc8123a150a4", + "imdb_id": "tt0810705", + "name": "Nana", + "type": "series", + "year": "2006–2007" + }, + { + "_id": "53677f04847ccc8123a1739c", + "imdb_id": "tt0142055", + "name": "Teletubbies", + "type": "series", + "year": "1997–2001" + }, + { + "_id": "5c0b78c3173739c9f4e05c09", + "imdb_id": "tt6069250", + "name": "Uchu Sentai Kyuranger", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677f68847ccc8123a22b02", + "imdb_id": "tt2392179", + "name": "Pac-Man and the Ghostly Adventures", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "5c24e04c173739c9f428207b", + "imdb_id": "tt5330856", + "name": "Divine Gate", + "type": "series", + "year": "2016–" + }, + { + "_id": "53677ef9847ccc8123a13e62", + "imdb_id": "tt1819022", + "name": "Mrs. Brown's Boys", + "type": "series", + "year": "2011–" + }, + { + "_id": "5c1283b5173739c9f46c094a", + "imdb_id": "tt9208876", + "name": "The Falcon and the Winter Soldier", + "type": "series", + "year": "2021" + }, + { + "_id": "648af0e0bd36726cbbfc7dcb", + "imdb_id": "tt18546730", + "name": "The Walking Dead: Dead City", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a1387e", + "imdb_id": "tt0306414", + "name": "The Wire", + "type": "series", + "year": "2002–2008" + }, + { + "_id": "59a49aeb3e5e4b900ae85c54", + "imdb_id": "tt5540054", + "name": "The Tick", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "54df8d64e573cadcfa1fceda", + "imdb_id": "tt3314218", + "name": "UnREAL", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "587fc2531635517fbf569600", + "imdb_id": "tt3647998", + "name": "Taboo", + "type": "series", + "year": "2017" + }, + { + "_id": "53677efa847ccc8123a149df", + "imdb_id": "tt3489184", + "name": "Constantine", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "551bf65fcc9eee85bb52e0d7", + "imdb_id": "tt1261559", + "name": "Gemini Division", + "year": "2008", + "type": "series" + }, + { + "_id": "590066de1635517fbf56e7d0", + "imdb_id": "tt5834204", + "name": "The Handmaid's Tale", + "type": "series", + "year": "2017–" + }, + { + "_id": "5d43f812c4ccb5dd92cbad87", + "imdb_id": "tt8050740", + "name": "Amphibia", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "58cf9c781635517fbf56e633", + "imdb_id": "tt5037914", + "name": "Crashing", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "5c431de4d582b25756d65084", + "imdb_id": "tt1409058", + "name": "Guin sâga", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677efa847ccc8123a14998", + "imdb_id": "tt1767256", + "name": "Winners & Losers", + "type": "series", + "year": "2011–2016" + }, + { + "_id": "6265ae5964ec43ef98b00d6d", + "imdb_id": "tt11639300", + "name": "Grace", + "type": "series", + "year": "2021–" + }, + { + "_id": "625fcf1964ec43ef98c5cc36", + "imdb_id": "tt12327578", + "name": "Star Trek: Strange New Worlds", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f47847ccc8123a200a9", + "imdb_id": "tt0288918", + "name": "Big Brother's Little Brother", + "type": "series", + "year": "2001–" + }, + { + "_id": "53677ef9847ccc8123a13f2e", + "imdb_id": "tt0288937", + "name": "Degrassi: The Next Generation", + "type": "series", + "year": "2001–2015" + }, + { + "_id": "56cb645bf6aa5b2a5344447a", + "imdb_id": "tt1399664", + "name": "The Night Manager", + "year": "2016", + "type": "series" + }, + { + "_id": "53677f4f847ccc8123a20cfe", + "imdb_id": "tt0318871", + "name": "Berserk", + "type": "series", + "year": "1997–1998" + }, + { + "_id": "5c2be6c8173739c9f49b5a86", + "imdb_id": "tt1051943", + "name": "Montana Jones", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "64ca97ebbd36726cbbcd7a91", + "imdb_id": "tt19869172", + "name": "My Happy Marriage", + "type": "series", + "year": "2023–" + }, + { + "_id": "617a4c3664ec43ef98391e73", + "imdb_id": "tt9795876", + "name": "Star Trek: Prodigy", + "type": "series", + "year": "2021–2024" + }, + { + "_id": "53f6326fa8f27b1bb90c33a0", + "imdb_id": "tt0062569", + "name": "Here Come the Brides", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "53677f12847ccc8123a19f28", + "imdb_id": "tt0429434", + "name": "Snapped", + "type": "series", + "year": "2004–" + }, + { + "_id": "53677f51847ccc8123a20e38", + "imdb_id": "tt2392261", + "name": "The Lizzie Bennet Diaries", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f4b847ccc8123a206e5", + "imdb_id": "tt0103408", + "name": "Eek! The Cat", + "type": "series", + "year": "1992–1997" + }, + { + "_id": "5c50f9c3d582b2575690adcd", + "imdb_id": "tt6240606", + "name": "The ZhuZhus", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "5c292017173739c9f4a4d81e", + "imdb_id": "tt0353867", + "name": "Peacemakers", + "type": "series", + "year": "2003" + }, + { + "_id": "5c5b6e74d582b257565874da", + "imdb_id": "tt0199356", + "name": "Beggars and Choosers", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "53677efa847ccc8123a14b0e", + "imdb_id": "tt0094540", + "name": "Roseanne", + "type": "series", + "year": "1988–2018" + }, + { + "_id": "53677f02847ccc8123a16fe3", + "imdb_id": "tt0094517", + "name": "Mystery Science Theater 3000", + "type": "series", + "year": "1988–1999" + }, + { + "_id": "53677f05847ccc8123a17703", + "imdb_id": "tt0088582", + "name": "Night Heat", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "53677f35847ccc8123a1eb56", + "imdb_id": "tt0169473", + "name": "Mazinger Z", + "type": "series", + "year": "1972–1974" + }, + { + "_id": "544bbf39a8f27b1bb90d7771", + "imdb_id": "tt0092386", + "name": "Kimagure Orange Road", + "type": "series", + "year": "1985–1988" + }, + { + "_id": "5508198e711bd19c92ade389", + "imdb_id": "tt0112086", + "name": "Murder One", + "year": "1995–1997", + "type": "series" + }, + { + "_id": "6400c76864ec43ef98885fce", + "imdb_id": "tt17221100", + "name": "Kaina of the Great Snow Sea", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a14390", + "imdb_id": "tt0830851", + "name": "The Gadget Show", + "type": "series", + "year": "2004–2023" + }, + { + "_id": "61b0294b64ec43ef98e52524", + "imdb_id": "tt14218830", + "name": "Abbott Elementary", + "type": "series", + "year": "2021–" + }, + { + "_id": "65856b90bd36726cbb8512cd", + "imdb_id": "tt22352854", + "name": "Gyeongseong Creature", + "type": "series", + "year": "2023–" + }, + { + "_id": "54fb89e0711bd19c92ad48df", + "imdb_id": "tt3945802", + "name": "The Stanley Dynamic", + "year": "2014–2017", + "type": "series" + }, + { + "_id": "53677f40847ccc8123a1f54d", + "imdb_id": "tt0061259", + "name": "The Guns of Will Sonnett", + "type": "series", + "year": "1967–1969" + }, + { + "_id": "5baa69e2173739c9f44c244d", + "imdb_id": "tt7472896", + "name": "Mr Inbetween", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "53677f05847ccc8123a17b0d", + "imdb_id": "tt0477543", + "name": "Reservoir Chronicle: Tsubasa", + "type": "series", + "year": "2005–2010" + }, + { + "_id": "53677ef9847ccc8123a138ea", + "imdb_id": "tt0054518", + "name": "The Avengers", + "type": "series", + "year": "1961–1969" + }, + { + "_id": "643d733b64ec43ef982a0ac1", + "imdb_id": "tt27489241", + "name": "Dead Mount Death Play", + "type": "series", + "year": "2023–" + }, + { + "_id": "5381e72c847ccc8123ad7692", + "imdb_id": "tt2543312", + "name": "Halt and Catch Fire", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "5ec4958e5424253341b7a4b1", + "imdb_id": "tt9077540", + "name": "Sweet Magnolias", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677ef9847ccc8123a1408a", + "imdb_id": "tt1759761", + "name": "Veep", + "type": "series", + "year": "2012–2019" + }, + { + "_id": "53677eff847ccc8123a1602f", + "imdb_id": "tt0279550", + "name": "Celebrity Big Brother", + "type": "series", + "year": "2001–" + }, + { + "_id": "53677ef9847ccc8123a138de", + "imdb_id": "tt0773262", + "name": "Dexter", + "type": "series", + "year": "2006–2013" + }, + { + "_id": "53677f02847ccc8123a16c29", + "imdb_id": "tt0086687", + "name": "The Cosby Show", + "type": "series", + "year": "1984–1992" + }, + { + "_id": "53677efc847ccc8123a14e55", + "imdb_id": "tt0914387", + "name": "Damages", + "type": "series", + "year": "2007–2012" + }, + { + "_id": "5c42352ed582b257565363e9", + "imdb_id": "tt0112035", + "name": "Kotikatu", + "type": "series", + "year": "1995–2012" + }, + { + "_id": "5aa8858353336c1ba87aea04", + "imdb_id": "tt6487416", + "type": "series", + "name": "Rise", + "year": "2018" + }, + { + "_id": "53677ef9847ccc8123a14196", + "imdb_id": "tt0108757", + "name": "ER", + "type": "series", + "year": "1994–2009" + }, + { + "_id": "53677efd847ccc8123a15b64", + "imdb_id": "tt1718438", + "name": "Mad", + "type": "series", + "year": "2010–2022" + }, + { + "_id": "53677efa847ccc8123a14b7d", + "imdb_id": "tt0108968", + "name": "Touched by an Angel", + "type": "series", + "year": "1994–2003" + }, + { + "_id": "53677efc847ccc8123a152ed", + "imdb_id": "tt1596561", + "name": "Spliced", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677f00847ccc8123a16689", + "imdb_id": "tt0072500", + "name": "Fawlty Towers", + "type": "series", + "year": "1975–1979" + }, + { + "_id": "5c17ab98173739c9f47d6647", + "imdb_id": "tt7678620", + "name": "Bluey", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f04847ccc8123a1735b", + "imdb_id": "tt1077173", + "name": "Guns", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53677ef9847ccc8123a14231", + "imdb_id": "tt0286486", + "name": "The Shield", + "type": "series", + "year": "2002–2008" + }, + { + "_id": "53677ef9847ccc8123a14453", + "imdb_id": "tt0200276", + "name": "The West Wing", + "type": "series", + "year": "1999–2006" + }, + { + "_id": "5c19be15173739c9f43d819e", + "imdb_id": "tt6197170", + "name": "Scum's Wish", + "type": "series", + "year": "2017" + }, + { + "_id": "53677ef9847ccc8123a13864", + "imdb_id": "tt0458253", + "name": "The Closer", + "type": "series", + "year": "2005–2012" + }, + { + "_id": "5c1ed26d173739c9f46a4442", + "imdb_id": "tt0047702", + "name": "The 20th Century-Fox Hour", + "type": "series", + "year": "1955–1957" + }, + { + "_id": "5c100e8f173739c9f4f040c4", + "imdb_id": "tt2340841", + "name": "Hyouka", + "type": "series", + "year": "2012" + }, + { + "_id": "53677efd847ccc8123a159c7", + "imdb_id": "tt0062552", + "name": "Dad's Army", + "type": "series", + "year": "1968–1977" + }, + { + "_id": "536907f3847ccc8123acddfb", + "imdb_id": "tt0081869", + "name": "Gimme a Break!", + "type": "series", + "year": "1981–1987" + }, + { + "_id": "5c34af09173739c9f40071cd", + "imdb_id": "tt0078562", + "name": "Archie Bunker's Place", + "type": "series", + "year": "1979–1983" + }, + { + "_id": "5378cc0d847ccc8123ad4859", + "imdb_id": "tt3475734", + "name": "Agent Carter", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677f0f847ccc8123a19866", + "imdb_id": "tt0455295", + "name": "Zatch Bell!", + "type": "series", + "year": "2003–2013" + }, + { + "_id": "53677f35847ccc8123a1eb50", + "imdb_id": "tt0285341", + "name": "The Bernie Mac Show", + "type": "series", + "year": "2001–2023" + }, + { + "_id": "53677f19847ccc8123a1b19e", + "imdb_id": "tt0057782", + "name": "The Rogues", + "type": "series", + "year": "1964–1965" + }, + { + "_id": "5a760a09543165dcd8b276b1", + "imdb_id": "tt6663476", + "type": "series", + "name": "Mama June: From Not to Hot", + "year": "2017–" + }, + { + "_id": "53677f00847ccc8123a16564", + "imdb_id": "tt2076610", + "name": "Project Runway All Stars", + "type": "series", + "year": "2012–" + }, + { + "_id": "5a1bf362543165dcd80fb666", + "imdb_id": "tt7230846", + "type": "series", + "name": "No Activity", + "year": "2017–2021" + }, + { + "_id": "5c0dc84e173739c9f425503b", + "imdb_id": "tt5637108", + "name": "Twin Star Exorcists", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f05847ccc8123a17640", + "imdb_id": "tt1765622", + "name": "Kickin' It", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "5c2e4de9173739c9f4ca53df", + "imdb_id": "tt6410184", + "name": "Triage X", + "type": "series", + "year": "2015" + }, + { + "_id": "54d4d7dde573cadcfa1fa6a8", + "imdb_id": "tt0118381", + "name": "The Last Don", + "type": "series", + "year": "1997" + }, + { + "_id": "53677f48847ccc8123a2031c", + "imdb_id": "tt2674806", + "name": "Inside No. 9", + "type": "series", + "year": "2014–" + }, + { + "_id": "54c0f5798527d2e0cb5097d7", + "imdb_id": "tt3596178", + "name": "Bella and the Bulldogs", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677f04847ccc8123a175b7", + "imdb_id": "tt0328739", + "name": "Full Metal Panic!", + "type": "series", + "year": "2002–2006" + }, + { + "_id": "53677f05847ccc8123a17863", + "imdb_id": "tt0108970", + "name": "Tre kronor", + "type": "series", + "year": "1994–1999" + }, + { + "_id": "53677ef9847ccc8123a13a2e", + "imdb_id": "tt1599357", + "name": "The Gates", + "type": "series", + "year": "2010" + }, + { + "_id": "53677ef9847ccc8123a13b9d", + "imdb_id": "tt0955322", + "name": "Reaper", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "53677efc847ccc8123a1534b", + "imdb_id": "tt2400129", + "name": "The Soul Man", + "type": "series", + "year": "2012–2016" + }, + { + "_id": "624b3e3364ec43ef98a96990", + "imdb_id": "tt11198330", + "name": "House of the Dragon", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c0aa5fa173739c9f4763aba", + "imdb_id": "tt5628740", + "name": "Yu-Gi-Oh! Vrains", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "56191493ec193d5e9826b2f1", + "imdb_id": "tt4662888", + "name": "WWE 24", + "year": "2015–", + "type": "series" + }, + { + "_id": "625e7db664ec43ef9852c6d6", + "imdb_id": "tt3613454", + "name": "Terror in Resonance", + "type": "series", + "year": "2014" + }, + { + "_id": "57dd11d9d7e54929823e2329", + "imdb_id": "tt4288182", + "name": "Atlanta", + "year": "2016–2022", + "type": "series" + }, + { + "_id": "611bd06964ec43ef9874bad0", + "imdb_id": "tt10862280", + "name": "Spidey and His Amazing Friends", + "type": "series", + "year": "2021–" + }, + { + "_id": "5b49b10a16f4806c2aa46351", + "imdb_id": "tt7741830", + "type": "series", + "name": "The Epic Tales of Captain Underpants", + "year": "2018–2019" + }, + { + "_id": "5c5877a8d582b25756655d6f", + "imdb_id": "tt0068148", + "name": "Wait Till Your Father Gets Home", + "type": "series", + "year": "1972–1974" + }, + { + "_id": "62469d8164ec43ef9886c4c8", + "imdb_id": "tt5875444", + "name": "Slow Horses", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f12847ccc8123a1a14c", + "imdb_id": "tt0182629", + "name": "Rurouni Kenshin", + "type": "series", + "year": "1996–1998" + }, + { + "_id": "54c268c72cbd12081b8df483", + "imdb_id": "tt4197508", + "name": "Blunt Talk", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677ef9847ccc8123a137cc", + "imdb_id": "tt1949012", + "name": "The Firm", + "type": "series", + "year": "2012" + }, + { + "_id": "53677f02847ccc8123a16d2b", + "imdb_id": "tt0074042", + "name": "Quincy M.E.", + "type": "series", + "year": "1976–1983" + }, + { + "_id": "53677f0e847ccc8123a19609", + "imdb_id": "tt0412148", + "name": "The Inside", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "559e53f4bf6c900d1839e33e", + "imdb_id": "tt3864034", + "name": "The Spoils Before Dying", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f1b847ccc8123a1b960", + "imdb_id": "tt0824043", + "name": "Mai-HiME", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "53677f29847ccc8123a1def5", + "imdb_id": "tt2310212", + "name": "Mr Selfridge", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "5a02ae28543165dcd8bda36c", + "imdb_id": "tt5247622", + "type": "series", + "name": "Knowing Bros", + "year": "2015–" + }, + { + "_id": "5bf1a521173739c9f4a51e55", + "imdb_id": "tt6866266", + "name": "Escape at Dannemora", + "type": "series", + "year": "2018" + }, + { + "_id": "53677efc847ccc8123a14d9b", + "imdb_id": "tt2714046", + "name": "Bad Teacher", + "type": "series", + "year": "2014" + }, + { + "_id": "53677f04847ccc8123a17466", + "imdb_id": "tt0209069", + "name": "Judging Amy", + "type": "series", + "year": "1999–2005" + }, + { + "_id": "5c3ca0d9d582b2575655dba0", + "imdb_id": "tt4197638", + "name": "India's Got Talent", + "type": "series", + "year": "2009–" + }, + { + "_id": "557f0946bf6c900d183584d1", + "imdb_id": "tt4051832", + "name": "Lovesick", + "year": "2014–2018", + "type": "series" + }, + { + "_id": "53677f08847ccc8123a18522", + "imdb_id": "tt0108954", + "name": "Tekkaman Blade", + "type": "series", + "year": "1992–" + }, + { + "_id": "64c79fe7bd36726cbb724ecf", + "imdb_id": "tt13062500", + "name": "The Walking Dead: Daryl Dixon", + "type": "series", + "year": "2023–" + }, + { + "_id": "5ba37886173739c9f4ef4268", + "imdb_id": "tt0295072", + "name": "Burger Quiz", + "type": "series", + "year": "2001–2020" + }, + { + "_id": "5cf504cf5111f1a8a3639b11", + "imdb_id": "tt8912384", + "name": "Perpetual Grace, LTD", + "type": "series", + "year": "2019" + }, + { + "_id": "5385c00a847ccc8123ad85b6", + "imdb_id": "tt0108949", + "name": "Sweet Valley High", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "5c099c0a173739c9f4b11e9e", + "imdb_id": "tt7671068", + "name": "Grand Hotel", + "type": "series", + "year": "2019" + }, + { + "_id": "5b8eab8b173739c9f495d38c", + "imdb_id": "tt6149182", + "name": "Heathers", + "type": "series", + "year": "2018" + }, + { + "_id": "53677f71847ccc8123a234a7", + "imdb_id": "tt0103417", + "name": "Forever Knight", + "type": "series", + "year": "1992–1996" + }, + { + "_id": "53677efd847ccc8123a15b9c", + "imdb_id": "tt0874608", + "name": "Inspector Lewis", + "type": "series", + "year": "2006–2015" + }, + { + "_id": "5c4cc191d582b257562418df", + "imdb_id": "tt9584920", + "name": "The Quintessential Quintuplets", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "5c0beb62173739c9f4be9425", + "imdb_id": "tt4958580", + "name": "Gate", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677ef9847ccc8123a13838", + "imdb_id": "tt1592154", + "name": "Nikita", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "53b176e2a8f27b1bb90b40c4", + "imdb_id": "tt0105982", + "name": "Dave's World", + "type": "series", + "year": "1993–1997" + }, + { + "_id": "5c1fc645173739c9f4044f17", + "imdb_id": "tt0111973", + "name": "Fushigi Yûgi - The Mysterious Play", + "type": "series", + "year": "1995–2002" + }, + { + "_id": "53677f42847ccc8123a1f9d4", + "imdb_id": "tt0411024", + "name": "Complete Savages", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "649972fbbd36726cbb2f76ea", + "imdb_id": "tt11737520", + "name": "One Piece", + "type": "series", + "year": "2023–" + }, + { + "_id": "63118a0264ec43ef9864227f", + "imdb_id": "tt11680642", + "name": "Pantheon", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "54250887a8f27b1bb90cd7a7", + "imdb_id": "tt0329938", + "name": "Transformers: Armada", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "6218bc6564ec43ef98b9a2a4", + "imdb_id": "tt11311302", + "name": "Vikings: Valhalla", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677ef9847ccc8123a13815", + "imdb_id": "tt1819509", + "name": "Don't Trust the B---- in Apartment 23", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "53677ef9847ccc8123a1401a", + "imdb_id": "tt0368479", + "name": "Cold Case", + "type": "series", + "year": "2003–2010" + }, + { + "_id": "5c1ec500173739c9f44f56eb", + "imdb_id": "tt0365991", + "name": "Canadian Idol", + "type": "series", + "year": "2003–" + }, + { + "_id": "5c2bcdc8173739c9f4633302", + "imdb_id": "tt1785869", + "name": "Dennis & Gnasher", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "54b586208527d2e0cb506d5e", + "imdb_id": "tt0419315", + "name": "Camp Lazlo!", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "53677efc847ccc8123a14f30", + "imdb_id": "tt1865769", + "name": "Jessie", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "53677efa847ccc8123a1451c", + "imdb_id": "tt1783495", + "name": "NTSF:SD:SUV", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "5c3d34a5d582b25756b3be0b", + "imdb_id": "tt1245698", + "name": "Birdy the Mighty Decode", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53de7d2ea8f27b1bb90bd566", + "imdb_id": "tt0179618", + "name": "The Twisted Tales of Felix the Cat", + "type": "series", + "year": "1995–1997" + }, + { + "_id": "5b9630a0173739c9f424a586", + "imdb_id": "tt7335184", + "name": "You", + "type": "series", + "year": "2018–2024" + }, + { + "_id": "58a559241635517fbf56e544", + "imdb_id": "tt5370118", + "name": "Konosuba: God's Blessing on This Wonderful World!", + "type": "series", + "year": "2016–2023" + }, + { + "_id": "558401aabf6c900d1837111d", + "imdb_id": "tt3530726", + "name": "The Astronaut Wives Club", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f2c847ccc8123a1dfa5", + "imdb_id": "tt2136138", + "name": "Sofia the First", + "type": "series", + "year": "2012–2018" + }, + { + "_id": "5c243023173739c9f40f1e60", + "imdb_id": "tt1746043", + "name": "Princess Jellyfish", + "type": "series", + "year": "2010" + }, + { + "_id": "53677ef9847ccc8123a139d1", + "imdb_id": "tt0077053", + "name": "Mork & Mindy", + "type": "series", + "year": "1978–1982" + }, + { + "_id": "5c1d191b173739c9f439d540", + "imdb_id": "tt7555294", + "name": "L.A.'s Finest", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "53677f05847ccc8123a1795f", + "imdb_id": "tt1583638", + "name": "Mr. Sunshine", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5c0c7488173739c9f4d16a7c", + "imdb_id": "tt0063887", + "name": "The Courtship of Eddie's Father", + "type": "series", + "year": "1969–1972" + }, + { + "_id": "53677f72847ccc8123a23629", + "imdb_id": "tt1166893", + "name": "Law & Order: UK", + "type": "series", + "year": "2009–2014" + }, + { + "_id": "53677efd847ccc8123a15a0f", + "imdb_id": "tt0251439", + "name": "Trigun", + "type": "series", + "year": "1998" + }, + { + "_id": "53677f72847ccc8123a2363d", + "imdb_id": "tt0062597", + "name": "The Outsider", + "type": "series", + "year": "1968–1969" + }, + { + "_id": "62a20c9264ec43ef98e8c5a2", + "imdb_id": "tt15830678", + "name": "Tomodachi Game", + "type": "series", + "year": "2022" + }, + { + "_id": "5c2e09af173739c9f44578a3", + "imdb_id": "tt1163573", + "name": "Mord mit Aussicht", + "type": "series", + "year": "2008–2024" + }, + { + "_id": "53677f66847ccc8123a229f7", + "imdb_id": "tt2758950", + "name": "Helix", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "5c09ffc5173739c9f46179c1", + "imdb_id": "tt4864850", + "name": "For My Man", + "type": "series", + "year": "2015–" + }, + { + "_id": "5c0aa765173739c9f478f7ac", + "imdb_id": "tt3446786", + "name": "Neste sommer", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677ef9847ccc8123a1387d", + "imdb_id": "tt0383126", + "name": "MythBusters", + "type": "series", + "year": "2003–2018" + }, + { + "_id": "54b6a80a8527d2e0cb507182", + "imdb_id": "tt3526078", + "name": "Schitt's Creek", + "type": "series", + "year": "2015–2020" + }, + { + "_id": "5c1903ff173739c9f4c54d27", + "imdb_id": "tt0446584", + "name": "Ragnarok: The Animation", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677f0a847ccc8123a18881", + "imdb_id": "tt0284770", + "name": "One on One", + "type": "series", + "year": "2001–2006" + }, + { + "_id": "53677ef9847ccc8123a13d55", + "imdb_id": "tt0787490", + "name": "Life on Mars", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53677ef9847ccc8123a141f2", + "imdb_id": "tt1661326", + "name": "Shake It Up", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "5378cbf2847ccc8123ad30c0", + "imdb_id": "tt3228904", + "name": "Empire", + "type": "series", + "year": "2015–2020" + }, + { + "_id": "63b7b0ea64ec43ef98ef20ca", + "imdb_id": "tt15428778", + "name": "Mayfair Witches", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677efa847ccc8123a14be7", + "imdb_id": "tt0068098", + "name": "M*A*S*H", + "type": "series", + "year": "1972–1983" + }, + { + "_id": "57df7b29d7e54929823e4ca1", + "imdb_id": "tt0078509", + "name": "A Woman Called Moses", + "year": "1978", + "type": "series" + }, + { + "_id": "5ad2531df51dd22f67ef0332", + "imdb_id": "tt7978710", + "type": "series", + "name": "Sword Art Online Alternative: Gun Gale Online", + "year": "2018" + }, + { + "_id": "5d9170c9c4ccb5dd922f01f4", + "imdb_id": "tt9068332", + "name": "Bless the Harts", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f14847ccc8123a1a57c", + "imdb_id": "tt0043208", + "name": "I Love Lucy", + "type": "series", + "year": "1951–1957" + }, + { + "_id": "536907ea847ccc8123acdd6a", + "imdb_id": "tt1594381", + "name": "Team Umizoomi", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "5c2d7894173739c9f460497d", + "imdb_id": "tt0075471", + "name": "ABC Weekend Specials", + "type": "series", + "year": "1977–1995" + }, + { + "_id": "63042a9964ec43ef98234285", + "imdb_id": "tt15238968", + "name": "Darby and Joan", + "type": "series", + "year": "2022–" + }, + { + "_id": "550dfc6dcc9eee85bb52d928", + "imdb_id": "tt0169477", + "name": "The New Adventures of He-Man", + "year": "1990–1991", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13dc3", + "imdb_id": "tt0491738", + "name": "Psych", + "type": "series", + "year": "2006–2014" + }, + { + "_id": "596ffb8d1635517fbf56e953", + "imdb_id": "tt6439752", + "name": "Snowfall", + "type": "series", + "year": "2017–2023" + }, + { + "_id": "53677efc847ccc8123a15150", + "imdb_id": "tt0398417", + "name": "The Batman", + "type": "series", + "year": "2004–2008" + }, + { + "_id": "53677efc847ccc8123a15294", + "imdb_id": "tt0078607", + "name": "The Dukes of Hazzard", + "type": "series", + "year": "1979–1985" + }, + { + "_id": "5c2eb01c173739c9f4937c9e", + "imdb_id": "tt0111959", + "name": "Faust", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "5c55ad6bd582b25756c18e2f", + "imdb_id": "tt0493094", + "name": "Harry and His Bucket Full of Dinosaurs", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "57e4f9d5d7e54929823e8bc6", + "imdb_id": "tt5672036", + "name": "Chelsea", + "year": "2016–2017", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13ca4", + "imdb_id": "tt0459159", + "name": "The Thick of It", + "type": "series", + "year": "2005–2012" + }, + { + "_id": "5c0c3a4a173739c9f463d064", + "imdb_id": "tt9251798", + "name": "Ragnarok", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677f19847ccc8123a1b398", + "imdb_id": "tt2122656", + "name": "Guilty Crown", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "63f30a6c64ec43ef98224b91", + "imdb_id": "tt18412092", + "name": "The Company You Keep", + "type": "series", + "year": "2023" + }, + { + "_id": "5c2e5c13173739c9f4e5be26", + "imdb_id": "tt0442722", + "name": "The Doodlebops", + "type": "series", + "year": "2004–2007" + }, + { + "_id": "5c09c19d173739c9f4fd4232", + "imdb_id": "tt5475704", + "name": "Dream Corp LLC", + "type": "series", + "year": "2016–" + }, + { + "_id": "53677ef9847ccc8123a13cf1", + "imdb_id": "tt0904208", + "name": "Californication", + "type": "series", + "year": "2007–2014" + }, + { + "_id": "5bfff84b173739c9f4fd71f5", + "imdb_id": "tt7817930", + "name": "Ruyi's Royal Love in the Palace", + "type": "series", + "year": "2018" + }, + { + "_id": "5c454a5cd582b25756396d21", + "imdb_id": "tt7186588", + "type": "series", + "name": "I Am the Night", + "year": "2019" + }, + { + "_id": "5368e83b847ccc8123acdbfd", + "imdb_id": "tt0809815", + "name": "Tenjo Tenge", + "type": "series", + "year": "2004" + }, + { + "_id": "64c79fe7bd36726cbb724ed0", + "imdb_id": "tt13159924", + "name": "Gen V", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c1a78de173739c9f48ae3e7", + "imdb_id": "tt0101133", + "name": "Lightning Force", + "type": "series", + "year": "1991–1992" + }, + { + "_id": "5c57674fd582b257562842d4", + "imdb_id": "tt0062567", + "name": "The Good Guys", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "62a772e064ec43ef9873f5cb", + "imdb_id": "tt13443470", + "name": "Wednesday", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677efa847ccc8123a14b00", + "imdb_id": "tt0380136", + "name": "QI", + "type": "series", + "year": "2003–" + }, + { + "_id": "5c438a57d582b2575624cada", + "imdb_id": "tt9532342", + "name": "Layton Mystery Tanteisha: Katori no Nazotoki File", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677efc847ccc8123a15103", + "imdb_id": "tt1408430", + "name": "30 for 30", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677ef9847ccc8123a13b96", + "imdb_id": "tt1199099", + "name": "Merlin", + "type": "series", + "year": "2008–2012" + }, + { + "_id": "53677f0f847ccc8123a19779", + "imdb_id": "tt0098784", + "name": "E.N.G.", + "type": "series", + "year": "1989–1994" + }, + { + "_id": "5c220f57173739c9f4fc2fe4", + "imdb_id": "tt4302062", + "name": "Paradise City", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f0c847ccc8123a19383", + "imdb_id": "tt0352110", + "name": "TV Burp", + "type": "series", + "year": "2001–2012" + }, + { + "_id": "54b6a80a8527d2e0cb50717c", + "imdb_id": "tt2348803", + "name": "Kuroko's Basketball", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "5c0be707173739c9f4b5800f", + "imdb_id": "tt0341985", + "name": "Ultimate Muscle: The Kinnikuman Legacy", + "type": "series", + "year": "2002–2004" + }, + { + "_id": "5902ef561635517fbf56e839", + "imdb_id": "tt5707802", + "name": "Dear White People", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "5e74795dc4ccb5dd92bbc13c", + "imdb_id": "tt6157190", + "name": "Dr. Romantic", + "type": "series", + "year": "2016–2023" + }, + { + "_id": "6127999364ec43ef98bdfdc1", + "imdb_id": "tt12882132", + "name": "Hitori No Shita - The Outcast", + "type": "series", + "year": "2015–2023" + }, + { + "_id": "53677f26847ccc8123a1d9db", + "imdb_id": "tt1124358", + "name": "Yattâman", + "type": "series", + "year": "2008–" + }, + { + "_id": "53677f2c847ccc8123a1e136", + "imdb_id": "tt2401525", + "name": "Upper Middle Bogan", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "5c3eeda0d582b25756857f5e", + "imdb_id": "tt6511722", + "name": "School of Roars", + "type": "series", + "year": "2017–" + }, + { + "_id": "5c437259d582b25756077f06", + "imdb_id": "tt0112028", + "name": "Saint Tail", + "type": "series", + "year": "1995–1996" + }, + { + "_id": "53677f22847ccc8123a1cbc8", + "imdb_id": "tt0092469", + "name": "The Tracey Ullman Show", + "type": "series", + "year": "1987–1990" + }, + { + "_id": "548061988527d2e0cb4fc358", + "imdb_id": "tt3061830", + "name": "Togetherness", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5432dae8a8f27b1bb90d0ce0", + "imdb_id": "tt2699110", + "name": "The Affair", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "553019c0cc9eee85bb52e4a9", + "imdb_id": "tt3895150", + "name": "Your Lie in April", + "year": "2014–2018", + "type": "series" + }, + { + "_id": "53677f47847ccc8123a20027", + "imdb_id": "tt0499383", + "name": "Dancing on Ice", + "type": "series", + "year": "2006–" + }, + { + "_id": "53677f0e847ccc8123a19593", + "imdb_id": "tt0092357", + "name": "Friday the 13th: The Series", + "type": "series", + "year": "1987–1990" + }, + { + "_id": "5c23c6fb173739c9f432606d", + "imdb_id": "tt9140108", + "name": "Carol's Second Act", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "6066d0895424253341d04d4a", + "imdb_id": "tt12502782", + "name": "Shaman King", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5c167948173739c9f47e790e", + "imdb_id": "tt0118378", + "name": "Coast Guard", + "type": "series", + "year": "1997–2016" + }, + { + "_id": "53677f08847ccc8123a18496", + "imdb_id": "tt0978553", + "name": "The Familiar of Zero", + "type": "series", + "year": "2006" + }, + { + "_id": "55199655cc9eee85bb52de33", + "imdb_id": "tt0813711", + "name": "Guy's Big Bite", + "year": "2006–", + "type": "series" + }, + { + "_id": "53677f03847ccc8123a17295", + "imdb_id": "tt1159996", + "name": "Less Than Kind", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "62ff34f864ec43ef98baef8f", + "imdb_id": "tt21230432", + "name": "The Yakuza's Guide to Babysitting", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f1b847ccc8123a1b7cd", + "imdb_id": "tt0111970", + "name": "Freakazoid!", + "type": "series", + "year": "1995–1997" + }, + { + "_id": "5c19be45173739c9f43ddcc4", + "imdb_id": "tt1356884", + "name": "White Album", + "type": "series", + "year": "2009" + }, + { + "_id": "53677ef9847ccc8123a137b4", + "imdb_id": "tt1475582", + "name": "Sherlock", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "5c149a08173739c9f42d933d", + "imdb_id": "tt8819906", + "name": "Love Island", + "type": "series", + "year": "2019–" + }, + { + "_id": "54f9481f711bd19c92accdbd", + "imdb_id": "tt0235916", + "name": "ChalkZone", + "year": "2002–2009", + "type": "series" + }, + { + "_id": "53677f0f847ccc8123a19c0f", + "imdb_id": "tt3158246", + "name": "Space Dandy", + "type": "series", + "year": "2014" + }, + { + "_id": "53677efa847ccc8123a14cfc", + "imdb_id": "tt0118276", + "name": "Buffy the Vampire Slayer", + "type": "series", + "year": "1997–2003" + }, + { + "_id": "5991bd823e5e4b900ae85c2f", + "imdb_id": "tt6315640", + "name": "Atypical", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "5c294be8173739c9f4007bab", + "imdb_id": "tt0056778", + "name": "The Patty Duke Show", + "type": "series", + "year": "1963–1966" + }, + { + "_id": "53677f40847ccc8123a1f7f9", + "imdb_id": "tt0062601", + "name": "Rowan & Martin's Laugh-In", + "type": "series", + "year": "1967–1973" + }, + { + "_id": "53677f07847ccc8123a18109", + "imdb_id": "tt0173548", + "name": "Fort Boyard", + "type": "series", + "year": "1990–" + }, + { + "_id": "64e5c0fcbd36726cbb4e9cdf", + "imdb_id": "tt0101223", + "name": "The Torkelsons", + "type": "series", + "year": "1991–1992" + }, + { + "_id": "53677ef9847ccc8123a144d8", + "imdb_id": "tt1843323", + "name": "Up All Night", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5c3f388ad582b25756a557f0", + "imdb_id": "tt5839706", + "name": "91 Days", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "59b920671712e0f4dd96a361", + "imdb_id": "tt6483836", + "type": "series", + "name": "Gone", + "year": "2017–" + }, + { + "_id": "60e03d5264ec43ef984b13c3", + "imdb_id": "tt14664414", + "name": "Young Royals", + "type": "series", + "year": "2021–" + }, + { + "_id": "5576e6b9bf6c900d183543ba", + "imdb_id": "tt4324796", + "name": "Odd Mom Out", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677f79847ccc8123a23c4e", + "imdb_id": "tt3451870", + "name": "Captain Earth", + "type": "series", + "year": "2014" + }, + { + "_id": "5c1f90f1173739c9f49a0423", + "imdb_id": "tt2321542", + "name": "Love, Chunibyo & Other Delusions", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "5c0db4e4173739c9f40c9c1d", + "imdb_id": "tt0111890", + "name": "Band of Gold", + "type": "series", + "year": "1995–1997" + }, + { + "_id": "5c4dc4a9d582b2575663d9c6", + "imdb_id": "tt0074072", + "name": "When the Boat Comes In", + "type": "series", + "year": "1976–1981" + }, + { + "_id": "53677f0f847ccc8123a19a67", + "imdb_id": "tt0184111", + "name": "Ed, Edd n Eddy", + "type": "series", + "year": "1999–2008" + }, + { + "_id": "53677f40847ccc8123a1f78f", + "imdb_id": "tt0105943", + "name": "As Time Goes By", + "type": "series", + "year": "1992–2005" + }, + { + "_id": "53677f66847ccc8123a229e8", + "imdb_id": "tt0054557", + "name": "Mister Ed", + "type": "series", + "year": "1961–1966" + }, + { + "_id": "5c2eae41173739c9f48fcaca", + "imdb_id": "tt8948436", + "name": "Douluo Dalu", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "53677f29847ccc8123a1deac", + "imdb_id": "tt0118346", + "name": "The Hunger", + "type": "series", + "year": "1997–2000" + }, + { + "_id": "55075d64711bd19c92addcb7", + "imdb_id": "tt1690397", + "name": "Tomorrow's Joe", + "year": "1970–1971", + "type": "series" + }, + { + "_id": "5c0fd7ea173739c9f4847f0d", + "imdb_id": "tt0813971", + "name": "Witchblade", + "type": "series", + "year": "2006" + }, + { + "_id": "5c1c5905173739c9f4033f84", + "imdb_id": "tt0429363", + "name": "Get Backers", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "55072f75711bd19c92add860", + "imdb_id": "tt0437700", + "name": "America's Test Kitchen", + "year": "2000–", + "type": "series" + }, + { + "_id": "5feccde954242533410dae8c", + "imdb_id": "tt10723804", + "name": "A Miracle", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f5b847ccc8123a21d01", + "imdb_id": "tt1409066", + "name": "#DUPE#", + "type": "series", + "year": "2008–2015" + }, + { + "_id": "5c13ac0d173739c9f475cc7f", + "imdb_id": "tt0928099", + "name": "Nodame kantâbire", + "type": "series", + "year": "2007–2010" + }, + { + "_id": "5381e72c847ccc8123ad7670", + "imdb_id": "tt1882240", + "name": "Beelzebub", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5aba43b8e0a43c01da06652e", + "imdb_id": "tt7651892", + "type": "series", + "name": "One Strange Rock", + "year": "2018" + }, + { + "_id": "5c1fc86d173739c9f408a74f", + "imdb_id": "tt1514753", + "name": "Three Kingdoms", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677ef9847ccc8123a14195", + "imdb_id": "tt1596356", + "name": "Hellcats", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c33d7fb173739c9f4b61bcd", + "imdb_id": "tt0062561", + "name": "The First Lady", + "type": "series", + "year": "1968–1969" + }, + { + "_id": "60e62bbc64ec43ef98002f1d", + "imdb_id": "tt13311344", + "name": "Tsukimichi: Moonlit Fantasy", + "type": "series", + "year": "2021–2024" + }, + { + "_id": "5a782e79543165dcd8429908", + "imdb_id": "tt5249462", + "type": "series", + "name": "Erased", + "year": "2016" + }, + { + "_id": "53677efc847ccc8123a14f7b", + "imdb_id": "tt0061263", + "name": "The High Chaparral", + "type": "series", + "year": "1967–1971" + }, + { + "_id": "5c24f408173739c9f44fd21a", + "imdb_id": "tt7462410", + "name": "The Wheel of Time", + "type": "series", + "year": "2021–" + }, + { + "_id": "6334956a64ec43ef98ee120f", + "imdb_id": "tt21958588", + "name": "Cake Week", + "type": "series", + "year": "2022" + }, + { + "_id": "5b42b71916f4806c2aadc7b8", + "imdb_id": "tt2649356", + "type": "series", + "name": "Sharp Objects", + "year": "2018" + }, + { + "_id": "61b474c564ec43ef98ce444f", + "imdb_id": "tt15790598", + "name": "Queen of the Universe", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "63aaf2a764ec43ef98d28193", + "imdb_id": "tt22443832", + "name": "Arknights: Prelude to Dawn", + "type": "series", + "year": "2022" + }, + { + "_id": "55e3faf2bf6c900d18409c15", + "imdb_id": "tt4481322", + "name": "The Grinder", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "53677f37847ccc8123a1ec0a", + "imdb_id": "tt0098888", + "name": "Parker Lewis Can't Lose", + "type": "series", + "year": "1990–1993" + }, + { + "_id": "53677ef9847ccc8123a13ed6", + "imdb_id": "tt1720601", + "name": "The Real Housewives of Beverly Hills", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677efd847ccc8123a159b7", + "imdb_id": "tt1625724", + "name": "Love/Hate", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "53677ef9847ccc8123a13a5f", + "imdb_id": "tt0898266", + "name": "The Big Bang Theory", + "type": "series", + "year": "2007–2019" + }, + { + "_id": "5f8429c05424253341c17b1b", + "imdb_id": "tt10970552", + "type": "series", + "name": "The Haunting of Bly Manor", + "year": "2020" + }, + { + "_id": "5c1c6981173739c9f4176f7a", + "imdb_id": "tt0103434", + "name": "Gute Zeiten, schlechte Zeiten", + "type": "series", + "year": "1992–" + }, + { + "_id": "5c378179d582b257568cb53b", + "imdb_id": "tt2450588", + "name": "Football Night in America", + "type": "series", + "year": "2006–" + }, + { + "_id": "53677efc847ccc8123a1542a", + "imdb_id": "tt0386180", + "name": "Drawn Together", + "type": "series", + "year": "2004–2007" + }, + { + "_id": "5c0c2075173739c9f42b3bc9", + "imdb_id": "tt3390892", + "name": "The Last Tycoon", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f05847ccc8123a17cc9", + "imdb_id": "tt0068135", + "name": "The Streets of San Francisco", + "type": "series", + "year": "1972–1977" + }, + { + "_id": "55271a0acc9eee85bb52e275", + "imdb_id": "tt0163929", + "name": "Blue's Clues", + "year": "1995–2007", + "type": "series" + }, + { + "_id": "5c48f0abd582b2575608abe3", + "imdb_id": "tt0260662", + "name": "The Zeta Project", + "type": "series", + "year": "2001–2003" + }, + { + "_id": "55fb4ec4bf6c900d18422fa4", + "imdb_id": "tt4671682", + "name": "Ties That Bind", + "year": "2015", + "type": "series" + }, + { + "_id": "5c1a83d5173739c9f4a090cc", + "imdb_id": "tt0181255", + "name": "So Graham Norton", + "type": "series", + "year": "1998–2002" + }, + { + "_id": "5c1db6ae173739c9f4675782", + "imdb_id": "tt5141800", + "name": "Nirvana in Fire", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "53677f0a847ccc8123a18784", + "imdb_id": "tt0294023", + "name": "Captain Tsubasa", + "type": "series", + "year": "1983–1995" + }, + { + "_id": "5c16b5ee173739c9f4fd1d12", + "imdb_id": "tt2531336", + "name": "Lupin", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677ef9847ccc8123a14386", + "imdb_id": "tt0133302", + "name": "Frontline", + "type": "series", + "year": "1983–" + }, + { + "_id": "53677f60847ccc8123a22377", + "imdb_id": "tt0159933", + "name": "Ronin Warriors", + "type": "series", + "year": "1988–1995" + }, + { + "_id": "55f2e4cabf6c900d18419b7e", + "imdb_id": "tt3787754", + "name": "Total Drama Presents: The Ridonculous Race", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f1d847ccc8123a1be5d", + "imdb_id": "tt0098957", + "name": "Zorro", + "type": "series", + "year": "1990–1993" + }, + { + "_id": "53677f32847ccc8123a1e737", + "imdb_id": "tt0048848", + "name": "Broken Arrow", + "type": "series", + "year": "1956–1958" + }, + { + "_id": "5c416e51d582b25756f0af19", + "imdb_id": "tt0285371", + "name": "Heathcliff & the Catillac Cats", + "type": "series", + "year": "1984–1987" + }, + { + "_id": "5c434df7d582b25756f1af27", + "imdb_id": "tt0074002", + "name": "3000 Leagues in Search of Mother", + "type": "series", + "year": "1976" + }, + { + "_id": "53677f0a847ccc8123a18ca9", + "imdb_id": "tt1441480", + "name": "AIBOU: Tokyo Detective Duo", + "type": "series", + "year": "2000–" + }, + { + "_id": "53677ef9847ccc8123a13b7b", + "imdb_id": "tt0096563", + "name": "Cops", + "type": "series", + "year": "1989–2023" + }, + { + "_id": "53677f02847ccc8123a16948", + "imdb_id": "tt0441059", + "name": "Kaamelott", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "5c18e870173739c9f491fc37", + "imdb_id": "tt6369836", + "name": "Documental", + "type": "series", + "year": "2016–" + }, + { + "_id": "5c0a6af1173739c9f4063006", + "imdb_id": "tt6601082", + "name": "Rise of the Teenage Mutant Ninja Turtles", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "55a20f7dbf6c900d183a6ae5", + "imdb_id": "tt4192782", + "name": "Glitch", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "5c0b5cd6173739c9f4bfdf88", + "imdb_id": "tt7736544", + "type": "series", + "name": "3Below: Tales of Arcadia", + "year": "2018–2019" + }, + { + "_id": "53677efd847ccc8123a1587a", + "imdb_id": "tt0115167", + "name": "Everybody Loves Raymond", + "type": "series", + "year": "1996–2005" + }, + { + "_id": "5c26bceb173739c9f49706e9", + "imdb_id": "tt0181923", + "name": "The Great Grape Ape Show", + "type": "series", + "year": "1975" + }, + { + "_id": "620d37a364ec43ef9858eafc", + "imdb_id": "tt14599438", + "name": "Jeen-yuhs: A Kanye Trilogy", + "type": "series", + "year": "2022" + }, + { + "_id": "5c107ca3173739c9f4d1f9b9", + "imdb_id": "tt0456029", + "name": "Blue Water High", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "53677f1a847ccc8123a1b6bf", + "imdb_id": "tt0050069", + "name": "Tombstone Territory", + "type": "series", + "year": "1957–1960" + }, + { + "_id": "54fb5f68711bd19c92ad45ac", + "imdb_id": "tt1458518", + "name": "Olivia", + "year": "2009–2015", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13c56", + "imdb_id": "tt0772137", + "name": "The Game", + "type": "series", + "year": "2006–2015" + }, + { + "_id": "5c0f1a52173739c9f45a1bc3", + "imdb_id": "tt5502900", + "name": "The Real Marigold Hotel", + "type": "series", + "year": "2016–" + }, + { + "_id": "5a212b53543165dcd8f53dfe", + "imdb_id": "tt5753856", + "type": "series", + "name": "Dark", + "year": "2017–2020" + }, + { + "_id": "53677eff847ccc8123a16006", + "imdb_id": "tt2104664", + "name": "The Heart, She Holler", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "5c0a00c9173739c9f4636a62", + "imdb_id": "tt9288848", + "name": "Pacific Rim: The Black", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677efc847ccc8123a15205", + "imdb_id": "tt0085017", + "name": "Fraggle Rock", + "type": "series", + "year": "1983–1987" + }, + { + "_id": "5c0ef165173739c9f40bb65d", + "imdb_id": "tt6928178", + "name": "Monster High", + "type": "series", + "year": "2010–2017" + }, + { + "_id": "611f3a9464ec43ef981f7cdb", + "imdb_id": "tt13851952", + "name": "The Aquatope on White Sand", + "type": "series", + "year": "2021–" + }, + { + "_id": "620fa3cc64ec43ef9817de45", + "imdb_id": "tt10611608", + "name": "The Cuphead Show!", + "type": "series", + "year": "2022" + }, + { + "_id": "5c427ef4d582b257567ff007", + "imdb_id": "tt1050880", + "name": "George of the Jungle", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "5c28184f173739c9f4f57c52", + "imdb_id": "tt0081837", + "name": "Bret Maverick", + "type": "series", + "year": "1981–1982" + }, + { + "_id": "59b043451712e0f4dd1febb9", + "imdb_id": "tt6688750", + "name": "Puppy Dog Pals", + "year": "2017–2023", + "type": "series" + }, + { + "_id": "53677f4f847ccc8123a20b3c", + "imdb_id": "tt0287196", + "name": "Big Brother", + "type": "series", + "year": "2001–2023" + }, + { + "_id": "5a7df30b543165dcd8032284", + "imdb_id": "tt7948268", + "type": "series", + "name": "Celebrity Big Brother", + "year": "2018–" + }, + { + "_id": "56f4c9aff6aa5b2a534758a6", + "imdb_id": "tt5127574", + "name": "LEGO Nexo Knights", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "5c109d43173739c9f4039677", + "imdb_id": "tt1831804", + "name": "The Stand", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "53677efd847ccc8123a1592e", + "imdb_id": "tt1114705", + "name": "Celebrity Rehab with Dr. Drew", + "type": "series", + "year": "2008–" + }, + { + "_id": "5c164d8e173739c9f426567e", + "imdb_id": "tt7380366", + "name": "True Lies", + "type": "series", + "year": "2023" + }, + { + "_id": "65229026bd36726cbbb2f6c7", + "imdb_id": "tt28776190", + "name": "Shangri-La Frontier", + "type": "series", + "year": "2023" + }, + { + "_id": "61b86ba964ec43ef9883a208", + "imdb_id": "tt11717610", + "name": "American Auto", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "53677eff847ccc8123a15cac", + "imdb_id": "tt0154094", + "name": "Where the Heart Is", + "type": "series", + "year": "1997–2006" + }, + { + "_id": "5c3f8096d582b25756cf2c1d", + "imdb_id": "tt0083431", + "name": "It Takes Two", + "type": "series", + "year": "1982–1983" + }, + { + "_id": "5c5a0958d582b257567acc88", + "imdb_id": "tt0115283", + "name": "The Mystery Files of Shelby Woo", + "type": "series", + "year": "1996–1999" + }, + { + "_id": "568fc86abb83c664989bf6f0", + "imdb_id": "tt1051220", + "name": "The Shannara Chronicles", + "year": "2016–2017", + "type": "series" + }, + { + "_id": "53677f3a847ccc8123a1ef1b", + "imdb_id": "tt0426711", + "name": "Hikaru no Go", + "type": "series", + "year": "2001–2003" + }, + { + "_id": "53d3d591a8f27b1bb90badd1", + "imdb_id": "tt0096543", + "name": "Beetlejuice", + "type": "series", + "year": "1989–1991" + }, + { + "_id": "6066b45354242533419fd683", + "imdb_id": "tt11116204", + "name": "United States of Al", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5c21b80d173739c9f47cbf6a", + "imdb_id": "tt8060322", + "name": "Littlest Pet Shop: A World of Our Own", + "type": "series", + "year": "2017–" + }, + { + "_id": "6568f159bd36726cbbb2e72b", + "imdb_id": "tt22485826", + "name": "Bookie", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c42f698d582b25756bcc78b", + "imdb_id": "tt2800436", + "name": "The Laughing Salesman", + "type": "series", + "year": "1989–1992" + }, + { + "_id": "53677f1c847ccc8123a1bc87", + "imdb_id": "tt1985299", + "name": "Bade Achhe Lagte Hain", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "5c0c7810173739c9f4d628a0", + "imdb_id": "tt0115372", + "name": "The Steve Harvey Show", + "type": "series", + "year": "1996–2002" + }, + { + "_id": "53677f04847ccc8123a17369", + "imdb_id": "tt0460651", + "name": "Invasion", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "5c155b7a173739c9f48fc2b1", + "imdb_id": "tt0276732", + "name": "State of Grace", + "type": "series", + "year": "2001–2004" + }, + { + "_id": "53677f0e847ccc8123a1959c", + "imdb_id": "tt2326517", + "name": "Finding Your Roots with Henry Louis Gates, Jr.", + "type": "series", + "year": "2012–" + }, + { + "_id": "5c23de90173739c9f4630636", + "imdb_id": "tt8496508", + "name": "The Heights", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "5c409e8ed582b257567ee469", + "imdb_id": "tt1291491", + "name": "Princess Resurrection", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "53677f05847ccc8123a17674", + "imdb_id": "tt0235119", + "name": "Casshern Sins", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "5924c2ee1635517fbf56e872", + "imdb_id": "tt5650650", + "name": "Jamestown", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "542d1637a8f27b1bb90cf467", + "imdb_id": "tt0056752", + "name": "The Doctors", + "type": "series", + "year": "1963–1982" + }, + { + "_id": "53677f74847ccc8123a2385f", + "imdb_id": "tt0068072", + "name": "Fat Albert and the Cosby Kids", + "type": "series", + "year": "1972–1985" + }, + { + "_id": "5c290dfe173739c9f47e88a4", + "imdb_id": "tt2360110", + "name": "Senran Kagura: Ninja Flash!", + "type": "series", + "year": "2013" + }, + { + "_id": "53677f0c847ccc8123a19260", + "imdb_id": "tt0075525", + "name": "The Life and Times of Grizzly Adams", + "type": "series", + "year": "1977–1978" + }, + { + "_id": "5c113304173739c9f4045aea", + "imdb_id": "tt6932244", + "name": "Hanna", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "5c40fcd5d582b25756b598dd", + "imdb_id": "tt8129446", + "name": "Lights Out with David Spade", + "type": "series", + "year": "2019–" + }, + { + "_id": "649ac498bd36726cbbe2393f", + "imdb_id": "tt26693803", + "name": "King the Land", + "type": "series", + "year": "2023–" + }, + { + "_id": "5378cc0e847ccc8123ad48f5", + "imdb_id": "tt3484406", + "name": "The Jim Gaffigan Show", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677f29847ccc8123a1dc22", + "imdb_id": "tt0084987", + "name": "The Bill", + "type": "series", + "year": "1984–2010" + }, + { + "_id": "53677f35847ccc8123a1eb73", + "imdb_id": "tt1524993", + "name": "Dinosaur King", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "53677f0a847ccc8123a189fa", + "imdb_id": "tt0208614", + "name": "Celebrity Deathmatch", + "type": "series", + "year": "1998–2007" + }, + { + "_id": "56904d99bb83c664989c0e19", + "imdb_id": "tt3323254", + "name": "Bordertown", + "year": "2016", + "type": "series" + }, + { + "_id": "53677f02847ccc8123a16bfb", + "imdb_id": "tt2733252", + "name": "The Musketeers", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "53677ef5847ccc8123a1376b", + "imdb_id": "tt1059475", + "name": "Flashpoint", + "type": "series", + "year": "2008–2012" + }, + { + "_id": "55d78a85bf6c900d183f3518", + "imdb_id": "tt1152296", + "name": "Who Do You Think You Are?", + "year": "2008–", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a137bb", + "imdb_id": "tt1119644", + "name": "Fringe", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677f32847ccc8123a1e851", + "imdb_id": "tt0063948", + "name": "Room 222", + "type": "series", + "year": "1969–1974" + }, + { + "_id": "53677f13847ccc8123a1a21a", + "imdb_id": "tt1349600", + "name": "Les petits meurtres d'Agatha Christie", + "type": "series", + "year": "2009–" + }, + { + "_id": "5bc6fe2f173739c9f44a5296", + "imdb_id": "tt3600266", + "name": "Super Wings!", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f0a847ccc8123a18a8f", + "imdb_id": "tt0115369", + "name": "Spin City", + "type": "series", + "year": "1996–2002" + }, + { + "_id": "617143fd64ec43ef98dd3dea", + "imdb_id": "tt14626352", + "name": "Komi Can't Communicate", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677f00847ccc8123a163f0", + "imdb_id": "tt0426371", + "name": "The Suite Life of Zack & Cody", + "type": "series", + "year": "2005–2008" + }, + { + "_id": "5c27f363173739c9f4a9b721", + "imdb_id": "tt0353048", + "name": "Champs-Elysées", + "type": "series", + "year": "1982–2013" + }, + { + "_id": "53677f68847ccc8123a22d10", + "imdb_id": "tt2222352", + "name": "Cuckoo", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f07847ccc8123a182e8", + "imdb_id": "tt0460673", + "name": "Rock Star: INXS", + "type": "series", + "year": "2005–" + }, + { + "_id": "5c44fa01d582b25756e2eda4", + "imdb_id": "tt0168371", + "name": "Romeo and the Black Brothers", + "type": "series", + "year": "1995" + }, + { + "_id": "5e71cf1ac4ccb5dd929f752a", + "imdb_id": "tt8610082", + "name": "Monsters at Work", + "type": "series", + "year": "2021–" + }, + { + "_id": "63204e2264ec43ef98f5400a", + "imdb_id": "tt12590266", + "name": "Cyberpunk: Edgerunners", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f18847ccc8123a1b039", + "imdb_id": "tt0476918", + "name": "Loonatics Unleashed", + "type": "series", + "year": "2005–2007" + }, + { + "_id": "61262afd64ec43ef98951129", + "imdb_id": "tt7797662", + "name": "One Room", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "6016ffc35424253341c968bb", + "imdb_id": "tt13186542", + "name": "Kemono Jihen", + "type": "series", + "year": "2021" + }, + { + "_id": "54ac200f8527d2e0cb504c19", + "imdb_id": "tt0805448", + "name": "Saint Seiya: The Hades Chapter - Sanctuary", + "type": "series", + "year": "2002–2008" + }, + { + "_id": "53677f1c847ccc8123a1bba8", + "imdb_id": "tt0088571", + "name": "Moonlighting", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "59bf55781712e0f4ddedac8e", + "imdb_id": "tt5711280", + "type": "series", + "name": "Electric Dreams", + "year": "2017–2018" + }, + { + "_id": "5c61c4d6d582b25756e0ffa2", + "imdb_id": "tt0115202", + "name": "High Incident", + "type": "series", + "year": "1996–1997" + }, + { + "_id": "5c575349d582b257560abf5f", + "imdb_id": "tt1441939", + "name": "Titan Maximum", + "type": "series", + "year": "2009" + }, + { + "_id": "5c34c032173739c9f41ee61c", + "imdb_id": "tt0071032", + "name": "Petrocelli", + "type": "series", + "year": "1974–1976" + }, + { + "_id": "53677efc847ccc8123a152ae", + "imdb_id": "tt2295809", + "name": "Mistresses", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "536907f1847ccc8123acddb7", + "imdb_id": "tt0092332", + "name": "The Charmings", + "type": "series", + "year": "1987–1988" + }, + { + "_id": "53677f20847ccc8123a1c813", + "imdb_id": "tt0126158", + "name": "He-Man and the Masters of the Universe", + "type": "series", + "year": "1983–1985" + }, + { + "_id": "53677f6f847ccc8123a232d9", + "imdb_id": "tt0060025", + "name": "Skippy", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "53677f05847ccc8123a17735", + "imdb_id": "tt0213327", + "name": "Andromeda", + "type": "series", + "year": "2000–2005" + }, + { + "_id": "53677f0f847ccc8123a19bdc", + "imdb_id": "tt2303687", + "name": "Line of Duty", + "type": "series", + "year": "2012–2021" + }, + { + "_id": "536907ea847ccc8123acdd7d", + "imdb_id": "tt0074016", + "name": "Laverne & Shirley", + "type": "series", + "year": "1976–1983" + }, + { + "_id": "53677f1a847ccc8123a1b639", + "imdb_id": "tt0123816", + "name": "Earth: Final Conflict", + "type": "series", + "year": "1997–2002" + }, + { + "_id": "5c428744d582b2575683cc5b", + "imdb_id": "tt0843548", + "name": "Kaiketsu Zoro", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677f23847ccc8123a1cf27", + "imdb_id": "tt2660734", + "name": "The Tomorrow People", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "54cb9986e573cadcfa1f8098", + "imdb_id": "tt0433723", + "name": "Mr. Men and Little Miss", + "type": "series", + "year": "1995–1998" + }, + { + "_id": "53677f42847ccc8123a1fa50", + "imdb_id": "tt0083377", + "name": "Nine to Five", + "type": "series", + "year": "1982–1988" + }, + { + "_id": "53677f14847ccc8123a1a4e1", + "imdb_id": "tt0175738", + "name": "Histeria!", + "type": "series", + "year": "1998–2000" + }, + { + "_id": "55435a03b0c9284285038c85", + "imdb_id": "tt3894916", + "name": "Terra Formars", + "year": "2014–2016", + "type": "series" + }, + { + "_id": "557c1f8cbf6c900d18356aa5", + "imdb_id": "tt4159076", + "name": "Dark Matter", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677f5a847ccc8123a21aaa", + "imdb_id": "tt0423713", + "name": "Plus belle la vie", + "type": "series", + "year": "2004–2022" + }, + { + "_id": "53677ef9847ccc8123a13a07", + "imdb_id": "tt0096684", + "name": "Quantum Leap", + "type": "series", + "year": "1989–1993" + }, + { + "_id": "58d37c681635517fbf56e66e", + "imdb_id": "tt5093452", + "name": "Shots Fired", + "type": "series", + "year": "2017" + }, + { + "_id": "640f111c64ec43ef98a8e37c", + "imdb_id": "tt14688458", + "name": "Silo", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c0d39be173739c9f40bce18", + "imdb_id": "tt0217941", + "name": "Jayce and the Wheeled Warriors", + "type": "series", + "year": "1985–1986" + }, + { + "_id": "61debe4a64ec43ef981f04b3", + "imdb_id": "tt13956466", + "name": "The Genius Prince's Guide to Raising a Nation Out of Debt", + "type": "series", + "year": "2022" + }, + { + "_id": "5e4a1843c4ccb5dd929f31c8", + "imdb_id": "tt9073898", + "name": "Duncanville", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "53677f6a847ccc8123a22e98", + "imdb_id": "tt0106014", + "name": "Goodnight Sweetheart", + "type": "series", + "year": "1993–2016" + }, + { + "_id": "536907e7847ccc8123acdcfc", + "imdb_id": "tt0071003", + "name": "Kolchak: The Night Stalker", + "type": "series", + "year": "1974–1975" + }, + { + "_id": "53677ef5847ccc8123a13760", + "imdb_id": "tt0105950", + "name": "Beavis and Butt-Head", + "type": "series", + "year": "1993–2011" + }, + { + "_id": "62d0017464ec43ef98ae4888", + "imdb_id": "tt19848112", + "name": "My Stepmom's Daughter Is My Ex", + "type": "series", + "year": "2022" + }, + { + "_id": "5c16cdde173739c9f42f0e31", + "imdb_id": "tt6425462", + "name": "Hanazuki: Full of Treasures", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677f08847ccc8123a1839e", + "imdb_id": "tt1786209", + "name": "Så mycket bättre", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677f0c847ccc8123a19398", + "imdb_id": "tt3279494", + "name": "@midnight", + "type": "series", + "year": "2013–2017" + }, + { + "_id": "578bb69ff0b6c53b3c789f67", + "imdb_id": "tt4168956", + "name": "Wrecked", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "5fde28f1542425334161edf2", + "imdb_id": "tt11612120", + "name": "Sweet Home", + "type": "series", + "year": "2020–" + }, + { + "_id": "581c498355f8aab460cfd39e", + "imdb_id": "tt5787720", + "name": "Dead Silent", + "type": "series", + "year": "2016–" + }, + { + "_id": "5c33f657173739c9f4f2b3af", + "imdb_id": "tt2334330", + "name": "Tegami Bachi Reverse", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "53677f0f847ccc8123a19c4c", + "imdb_id": "tt0426745", + "name": "Maya & Miguel", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "5c1afcd4173739c9f4961bfa", + "imdb_id": "tt3105452", + "name": "Golden Time", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "55c21813bf6c900d183c94da", + "imdb_id": "tt4406352", + "name": "Endangered Species", + "year": "2014–2015", + "type": "series" + }, + { + "_id": "5c1cdd07173739c9f4c73013", + "imdb_id": "tt2703720", + "name": "My Teen Romantic Comedy SNAFU", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "5ea3ce6b5424253341fc456c", + "imdb_id": "tt11187480", + "name": "RuPaul's Secret Celebrity Drag Race", + "type": "series", + "year": "2020–" + }, + { + "_id": "5f95bb185424253341438b28", + "imdb_id": "tt12831098", + "name": "Moriarty the Patriot", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "5c4db36dd582b257564ba9d6", + "imdb_id": "tt0305095", + "name": "Die Rosenheim-Cops", + "type": "series", + "year": "2002–" + }, + { + "_id": "53677f05847ccc8123a175e2", + "imdb_id": "tt1339238", + "name": "Sekirei", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "5c0f477b173739c9f4965aef", + "imdb_id": "tt0159193", + "name": "Mobile Suit Gundam Wing", + "type": "series", + "year": "1995–1996" + }, + { + "_id": "53677f23847ccc8123a1d014", + "imdb_id": "tt3037520", + "name": "Hollywood Game Night", + "type": "series", + "year": "2013–2020" + }, + { + "_id": "53677f23847ccc8123a1cf26", + "imdb_id": "tt2293002", + "name": "Ben 10: Omniverse", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "54bacf638527d2e0cb50815d", + "imdb_id": "tt3807034", + "name": "The Adventures of Puss in Boots", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "53677ef9847ccc8123a13e43", + "imdb_id": "tt0159206", + "name": "Sex and the City", + "type": "series", + "year": "1998–2004" + }, + { + "_id": "5fcda80254242533414f1613", + "imdb_id": "tt10795658", + "name": "Alice in Borderland", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f1d847ccc8123a1be25", + "imdb_id": "tt0320808", + "name": "The Adventures of Jimmy Neutron, Boy Genius", + "type": "series", + "year": "2002–2006" + }, + { + "_id": "5cf0634b5111f1a8a3f25436", + "imdb_id": "tt1869454", + "name": "Good Omens", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "5b9df59d173739c9f4b8041d", + "imdb_id": "tt8673610", + "name": "Cells at Work!", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "55fada67bf6c900d1842157e", + "imdb_id": "tt4218618", + "name": "The Bastard Executioner", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f08847ccc8123a182f8", + "imdb_id": "tt0290983", + "name": "Spider-Man", + "type": "series", + "year": "2003" + }, + { + "_id": "5c0ac693173739c9f4b6c4af", + "imdb_id": "tt6352180", + "name": "Little Witch Academia", + "type": "series", + "year": "2017" + }, + { + "_id": "5530edd5cc9eee85bb52e4ec", + "imdb_id": "tt0465327", + "name": "The Emperor's New School", + "year": "2006–2008", + "type": "series" + }, + { + "_id": "6201dfec64ec43ef986ef369", + "imdb_id": "tt11092482", + "name": "AEW Dark", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677ef9847ccc8123a13a9b", + "imdb_id": "tt2187850", + "name": "Pablo Escobar: El Patrón del Mal", + "type": "series", + "year": "2012" + }, + { + "_id": "610db99864ec43ef984fc938", + "imdb_id": "tt14809614", + "name": "Hart to Heart", + "type": "series", + "year": "2021–" + }, + { + "_id": "5368e83b847ccc8123acdc18", + "imdb_id": "tt3322314", + "name": "Luke Cage", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "53677f24847ccc8123a1d323", + "imdb_id": "tt0056768", + "name": "Kraft Suspense Theatre", + "type": "series", + "year": "1963–1965" + }, + { + "_id": "53677f3c847ccc8123a1f1bd", + "imdb_id": "tt0111964", + "name": "Flipper", + "type": "series", + "year": "1995–2000" + }, + { + "_id": "5c22b7a6173739c9f4628751", + "imdb_id": "tt0062577", + "name": "Lancer", + "type": "series", + "year": "1968–1970" + }, + { + "_id": "53677efa847ccc8123a14baf", + "imdb_id": "tt0058855", + "name": "The Wild Wild West", + "type": "series", + "year": "1965–1969" + }, + { + "_id": "53677f74847ccc8123a2381f", + "imdb_id": "tt3463606", + "name": "Welcome to Sweden", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "64a74cb3bd36726cbbf5e74e", + "imdb_id": "tt22249034", + "name": "Rurouni Kenshin", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f45847ccc8123a1ffc3", + "imdb_id": "tt0098763", + "name": "Captain Planet and the Planeteers", + "type": "series", + "year": "1990–1996" + }, + { + "_id": "55075dd1711bd19c92ade169", + "imdb_id": "tt2069441", + "name": "The Future Diary", + "year": "2011–2013", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13b98", + "imdb_id": "tt1641349", + "name": "Terra Nova", + "type": "series", + "year": "2011" + }, + { + "_id": "53677f0a847ccc8123a1886a", + "imdb_id": "tt0115317", + "name": "Poltergeist: The Legacy", + "type": "series", + "year": "1996–1999" + }, + { + "_id": "53677f15847ccc8123a1aa25", + "imdb_id": "tt1765510", + "name": "R.L. Stine's the Haunting Hour", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "53677ef9847ccc8123a14465", + "imdb_id": "tt1771072", + "name": "Common Law", + "type": "series", + "year": "2012" + }, + { + "_id": "53677f29847ccc8123a1dc18", + "imdb_id": "tt2345459", + "name": "8 Out of 10 Cats Does Countdown", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f17847ccc8123a1afb0", + "imdb_id": "tt0094433", + "name": "China Beach", + "type": "series", + "year": "1988–1991" + }, + { + "_id": "5d8c0ac1c4ccb5dd9251ab02", + "imdb_id": "tt10313066", + "name": "Stumptown", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "634b9dd464ec43ef987245dd", + "imdb_id": "tt21345944", + "name": "Beast Tamer", + "type": "series", + "year": "2022" + }, + { + "_id": "588497131635517fbf569d8a", + "imdb_id": "tt5809150", + "name": "Ransom", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "53677f29847ccc8123a1de54", + "imdb_id": "tt2799012", + "name": "Ravenswood", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "592db27d1635517fbf56e897", + "imdb_id": "tt4326894", + "name": "F Is for Family", + "type": "series", + "year": "2015–2021" + }, + { + "_id": "53677f23847ccc8123a1d054", + "imdb_id": "tt3212600", + "name": "Mahabharat", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "5c19e4fb173739c9f47a5e11", + "imdb_id": "tt0434670", + "name": "Chrono Crusade", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "5c2ffa20173739c9f4e4c867", + "imdb_id": "tt0090444", + "name": "Head of the Class", + "type": "series", + "year": "1986–1991" + }, + { + "_id": "53677f20847ccc8123a1c715", + "imdb_id": "tt0056747", + "name": "The Dakotas", + "type": "series", + "year": "1962–1963" + }, + { + "_id": "55091930711bd19c92ade63c", + "imdb_id": "tt3501016", + "name": "One Big Happy", + "year": "2015", + "type": "series" + }, + { + "_id": "632859d264ec43ef98af4c3e", + "imdb_id": "tt17047510", + "name": "The Santa Clauses", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "6345e2c364ec43ef98fc7a3b", + "imdb_id": "tt21345876", + "name": "Shinobi no Ittoki", + "type": "series", + "year": "2022" + }, + { + "_id": "54ff6a66711bd19c92add0dc", + "imdb_id": "tt0845738", + "name": "When They Cry", + "year": "2006", + "type": "series" + }, + { + "_id": "53677f72847ccc8123a23537", + "imdb_id": "tt2141913", + "name": "Review", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "536907ea847ccc8123acdd74", + "imdb_id": "tt0161952", + "name": "Saint Seiya: Knights of the Zodiac", + "type": "series", + "year": "1986–1989" + }, + { + "_id": "53677f24847ccc8123a1d361", + "imdb_id": "tt0166910", + "name": "Dennis the Menace", + "type": "series", + "year": "1986–1988" + }, + { + "_id": "53677ef9847ccc8123a1397e", + "imdb_id": "tt1963853", + "name": "South Beach Tow", + "type": "series", + "year": "2011–" + }, + { + "_id": "5c19d378173739c9f465ad24", + "imdb_id": "tt0219446", + "name": "The Oblongs", + "type": "series", + "year": "2001–2002" + }, + { + "_id": "56fe8e05f6aa5b2a53480a55", + "imdb_id": "tt4789576", + "name": "The Path", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "5c1c24db173739c9f49d6d79", + "imdb_id": "tt2349912", + "name": "Doctor X", + "type": "series", + "year": "2012–" + }, + { + "_id": "5c1bf45c173739c9f43bf732", + "imdb_id": "tt1177054", + "name": "Der Bergdoktor", + "type": "series", + "year": "2008–" + }, + { + "_id": "5bceb591173739c9f454d2e1", + "imdb_id": "tt7153034", + "name": "The Bureau of Magical Things", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "53677f40847ccc8123a1f780", + "imdb_id": "tt0255734", + "name": "Grounded for Life", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "5d0473295111f1a8a3783733", + "imdb_id": "tt8594276", + "name": "Jett", + "type": "series", + "year": "2019" + }, + { + "_id": "576c5a65f0b6c53b3c76ac24", + "imdb_id": "tt5016504", + "name": "Preacher", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "53677f02847ccc8123a16acb", + "imdb_id": "tt0078692", + "name": "Star Blazers", + "type": "series", + "year": "1979–1984" + }, + { + "_id": "53677f6f847ccc8123a23366", + "imdb_id": "tt2781848", + "name": "Mushibugyo", + "type": "series", + "year": "2013–2015" + }, + { + "_id": "55084476711bd19c92ade464", + "imdb_id": "tt4341500", + "name": "Wet Hot American Summer: First Day of Camp", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f4c847ccc8123a207c0", + "imdb_id": "tt0052506", + "name": "Riverboat", + "type": "series", + "year": "1959–1961" + }, + { + "_id": "6458d1cd64ec43ef98272319", + "imdb_id": "tt14261112", + "name": "Twisted Metal", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c0b5650173739c9f4b88bcc", + "imdb_id": "tt0108921", + "name": "The Secret World of Alex Mack", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "5c0a1796173739c9f47bfdbd", + "imdb_id": "tt2198870", + "name": "Red Table Talk", + "type": "series", + "year": "2018–2022" + }, + { + "_id": "54ff1e79711bd19c92adcf77", + "imdb_id": "tt3532752", + "name": "Trinity Seven", + "year": "2014–2015", + "type": "series" + }, + { + "_id": "642fee0964ec43ef9825fe66", + "imdb_id": "tt22074164", + "name": "Jury Duty", + "type": "series", + "year": "2023–" + }, + { + "_id": "536907f2847ccc8123acddda", + "imdb_id": "tt1735517", + "name": "Ask Rhod Gilbert", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "53677f57847ccc8123a216e7", + "imdb_id": "tt2934286", + "name": "Halo", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c50e413d582b25756709a51", + "imdb_id": "tt9077530", + "name": "Virgin River", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f23847ccc8123a1cee9", + "imdb_id": "tt0063941", + "name": "Please Sir!", + "type": "series", + "year": "1968–1972" + }, + { + "_id": "5d26d82e5111f1a8a3bac9d9", + "imdb_id": "tt9153270", + "name": "Family Reunion", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677f3a847ccc8123a1eefb", + "imdb_id": "tt0163438", + "name": "C.O.P.S.", + "type": "series", + "year": "1988–1989" + }, + { + "_id": "5c394eb2d582b257569b5a8c", + "imdb_id": "tt8042500", + "name": "Y: The Last Man", + "type": "series", + "year": "2021" + }, + { + "_id": "54fc0952711bd19c92ad4a0c", + "imdb_id": "tt1751305", + "name": "Ore no imouto ga konna ni kawaii wake ga nai", + "year": "2010–2013", + "type": "series" + }, + { + "_id": "567d5bf5bb83c664989a2579", + "imdb_id": "tt4378456", + "name": "Second Chance", + "year": "2016", + "type": "series" + }, + { + "_id": "5c24deb0173739c9f425044a", + "imdb_id": "tt0274279", + "name": "Leipzig Homicide", + "type": "series", + "year": "2001–" + }, + { + "_id": "594053ab1635517fbf56e925", + "imdb_id": "tt5640558", + "name": "Claws", + "type": "series", + "year": "2017–2022" + }, + { + "_id": "55072fb5711bd19c92add983", + "imdb_id": "tt1655610", + "name": "Baka and Test", + "year": "2010–2011", + "type": "series" + }, + { + "_id": "63cc769a64ec43ef98ac57a0", + "imdb_id": "tt21608762", + "name": "Saving 80,000 Gold in Another World for my Retirement", + "type": "series", + "year": "2023" + }, + { + "_id": "53677efa847ccc8123a1456b", + "imdb_id": "tt0976014", + "name": "Greek", + "type": "series", + "year": "2007–2011" + }, + { + "_id": "63c4c51464ec43ef981f5bcf", + "imdb_id": "tt21844644", + "name": "Handyman Saitou in another world", + "type": "series", + "year": "2023" + }, + { + "_id": "550787d0711bd19c92ade1d8", + "imdb_id": "tt0305046", + "name": "Android Kikaider: The Animation", + "year": "2000–2001", + "type": "series" + }, + { + "_id": "53677f5c847ccc8123a21dd2", + "imdb_id": "tt0222518", + "name": "Adventures of Sonic the Hedgehog", + "type": "series", + "year": "1993" + }, + { + "_id": "659167afbd36726cbbd87938", + "imdb_id": "tt29899652", + "name": "Night Has Come", + "type": "series", + "year": "2023–" + }, + { + "_id": "63317f7d64ec43ef98b42013", + "imdb_id": "tt13444912", + "name": "The Midnight Club", + "type": "series", + "year": "2022" + }, + { + "_id": "5c0e9e8c173739c9f46b21e1", + "imdb_id": "tt4574736", + "name": "Charlotte", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c170dbc173739c9f493d8d8", + "imdb_id": "tt7243884", + "name": "Catherine the Great", + "type": "series", + "year": "2019" + }, + { + "_id": "5c59386fd582b257565b22f9", + "imdb_id": "tt0790397", + "name": "VH-1 Where Are They Now?", + "type": "series", + "year": "1999–2004" + }, + { + "_id": "57dee079d7e54929823e410b", + "imdb_id": "tt5607616", + "name": "Re: Zero, Starting Life in Another World", + "year": "2016–", + "type": "series" + }, + { + "_id": "652c2326bd36726cbb36e284", + "imdb_id": "tt28919914", + "name": "The 100 Girlfriends Who Really, Really, Really, Really, REALLY Love You", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a137cf", + "imdb_id": "tt1319735", + "name": "Royal Pains", + "type": "series", + "year": "2009–2016" + }, + { + "_id": "53677f1f847ccc8123a1c5ac", + "imdb_id": "tt0288987", + "name": "Magical Angel Creamy Mami", + "type": "series", + "year": "1983–1984" + }, + { + "_id": "621ad42164ec43ef986a7b7c", + "imdb_id": "tt15407098", + "name": "Sister Boniface Mysteries", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f02847ccc8123a16fcf", + "imdb_id": "tt0098882", + "name": "One Foot in the Grave", + "type": "series", + "year": "1990–2001" + }, + { + "_id": "53677ef9847ccc8123a1393e", + "imdb_id": "tt0297494", + "name": "Aqua Teen Hunger Force", + "type": "series", + "year": "2000–2023" + }, + { + "_id": "53677f0c847ccc8123a190ad", + "imdb_id": "tt0305033", + "name": "Grimm's Fairy Tale Classics", + "type": "series", + "year": "1987–1989" + }, + { + "_id": "53677f02847ccc8123a170ab", + "imdb_id": "tt0169247", + "name": "So Weird", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "53677efd847ccc8123a15553", + "imdb_id": "tt0108992", + "name": "Wycliffe", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "64f9a83cbd36726cbbf4d525", + "imdb_id": "tt27974068", + "name": "Destined with You", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c0a0bbf173739c9f46f7078", + "imdb_id": "tt7736558", + "name": "Wizards", + "type": "series", + "year": "2020" + }, + { + "_id": "53677ef9847ccc8123a140f0", + "imdb_id": "tt0081912", + "name": "Only Fools and Horses", + "type": "series", + "year": "1981–2003" + }, + { + "_id": "5893e07e1635517fbf56cadf", + "imdb_id": "tt5083928", + "name": "Powerless", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "5fff6b6a54242533415a628f", + "imdb_id": "tt13370404", + "name": "Redo of Healer", + "type": "series", + "year": "2021" + }, + { + "_id": "59cdf21c067c46521001d2cc", + "imdb_id": "tt4379632", + "type": "series", + "name": "Blood Blockade Battlefront", + "year": "2015–2017" + }, + { + "_id": "53677f57847ccc8123a21643", + "imdb_id": "tt0096679", + "name": "Press Gang", + "type": "series", + "year": "1989–1993" + }, + { + "_id": "551bcc5acc9eee85bb52e0ce", + "imdb_id": "tt2320220", + "name": "Kamisama Kiss", + "year": "2012–2016", + "type": "series" + }, + { + "_id": "5c1c1ee5173739c9f4917570", + "imdb_id": "tt0144050", + "name": "Hinter Gittern - Der Frauenknast", + "type": "series", + "year": "1997–2010" + }, + { + "_id": "5ea690815424253341d2fe3b", + "imdb_id": "tt10062292", + "name": "Never Have I Ever", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "5c2a50f3173739c9f4aa264a", + "imdb_id": "tt0338614", + "name": "House Doctor", + "type": "series", + "year": "1998–" + }, + { + "_id": "53677efd847ccc8123a1558f", + "imdb_id": "tt0115286", + "name": "Never Mind the Buzzcocks", + "type": "series", + "year": "1996–2023" + }, + { + "_id": "53677ef9847ccc8123a13f78", + "imdb_id": "tt1344204", + "name": "Blue Mountain State", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "6562e52dbd36726cbb960e9b", + "imdb_id": "tt29569035", + "name": "My Demon", + "type": "series", + "year": "2023–" + }, + { + "_id": "53de7d2ea8f27b1bb90bd50f", + "imdb_id": "tt0807832", + "name": "Mushi-Shi", + "type": "series", + "year": "2005–2014" + }, + { + "_id": "53677ef9847ccc8123a13c0e", + "imdb_id": "tt0108758", + "name": "Earth 2", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "623c2b6664ec43ef98c5396a", + "imdb_id": "tt18314214", + "name": "Is It Cake?", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f0a847ccc8123a18887", + "imdb_id": "tt0098749", + "name": "Beverly Hills, 90210", + "type": "series", + "year": "1990–2000" + }, + { + "_id": "5c265231173739c9f4bed263", + "imdb_id": "tt5747326", + "name": "The Kapil Sharma Show", + "type": "series", + "year": "2016–" + }, + { + "_id": "63514ae064ec43ef98952cc4", + "imdb_id": "tt18566706", + "name": "Immoral Guild", + "type": "series", + "year": "2022" + }, + { + "_id": "5c23419f173739c9f42e1045", + "imdb_id": "tt8878996", + "name": "The Hills: New Beginnings", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "5c4cfa81d582b257567af4c0", + "imdb_id": "tt0052501", + "name": "Philip Marlowe", + "type": "series", + "year": "1959–1960" + }, + { + "_id": "536907f4847ccc8123acde1e", + "imdb_id": "tt0450373", + "name": "Bobobo-bo Bo-bobo", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "557ebe06bf6c900d1835836a", + "imdb_id": "tt4122068", + "name": "Humans", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "56183acdec193d5e98269975", + "imdb_id": "tt4458594", + "name": "Blaze and the Monster Machines", + "year": "2014–2023", + "type": "series" + }, + { + "_id": "53677f66847ccc8123a229b4", + "imdb_id": "tt0054539", + "name": "Follow the Sun", + "type": "series", + "year": "1961–1962" + }, + { + "_id": "53677ef9847ccc8123a13b05", + "imdb_id": "tt0805669", + "name": "Ugly Betty", + "type": "series", + "year": "2006–2010" + }, + { + "_id": "53677f03847ccc8123a17241", + "imdb_id": "tt0060034", + "name": "That Girl", + "type": "series", + "year": "1966–1971" + }, + { + "_id": "60659a445424253341a195d7", + "imdb_id": "tt7808566", + "name": "Made for Love", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677f22847ccc8123a1cccb", + "imdb_id": "tt3503520", + "name": "Ronja, the Robber's Daughter", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f1f847ccc8123a1c374", + "imdb_id": "tt0086696", + "name": "Double Trouble", + "type": "series", + "year": "1984–1985" + }, + { + "_id": "543d5216a8f27b1bb90d38f6", + "imdb_id": "tt2465992", + "name": "Gunshi Kanbee", + "type": "series", + "year": "2014" + }, + { + "_id": "62caef7364ec43ef98337432", + "imdb_id": "tt18574004", + "name": "Parallel World Pharmacy", + "type": "series", + "year": "2022" + }, + { + "_id": "5e865fa405bdfe7d18c1da35", + "imdb_id": "tt11833388", + "name": "Danger Force", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "552de977cc9eee85bb52e390", + "imdb_id": "tt0045373", + "name": "The Bob Hope Show", + "year": "1950–", + "type": "series" + }, + { + "_id": "6468512bbd36726cbb9721a4", + "imdb_id": "tt13373182", + "name": "Unicorn: Warriors Eternal", + "type": "series", + "year": "2023–" + }, + { + "_id": "578935e8f0b6c53b3c787523", + "imdb_id": "tt5363766", + "name": "Feed the Beast", + "year": "2016", + "type": "series" + }, + { + "_id": "620b585964ec43ef984171a8", + "imdb_id": "tt14321914", + "name": "The Chelsea Detective", + "type": "series", + "year": "2022–" + }, + { + "_id": "62e80f6d64ec43ef98eea0b8", + "imdb_id": "tt14921986", + "name": "Interview with the Vampire", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c0a6506173739c9f4fb5ff1", + "imdb_id": "tt7836688", + "name": "A Place Further Than the Universe", + "type": "series", + "year": "2018" + }, + { + "_id": "55948f29bf6c900d183890ce", + "imdb_id": "tt3295542", + "name": "Have You Been Paying Attention?", + "year": "2013–", + "type": "series" + }, + { + "_id": "54fdebf2711bd19c92adc379", + "imdb_id": "tt0108845", + "name": "Madison", + "year": "1993–1997", + "type": "series" + }, + { + "_id": "57e04e3ad7e54929823e5673", + "imdb_id": "tt5725682", + "name": "Ozzy & Jack's World Detour", + "year": "2016–", + "type": "series" + }, + { + "_id": "5c3681e7d582b2575695edb4", + "imdb_id": "tt3196310", + "name": "Outbreak Company", + "type": "series", + "year": "2013" + }, + { + "_id": "53677ef9847ccc8123a13e06", + "imdb_id": "tt0920448", + "name": "Flikken Maastricht", + "type": "series", + "year": "2007–" + }, + { + "_id": "61ff73a364ec43ef986c7a11", + "imdb_id": "tt11761194", + "name": "Power Book IV: Force", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f0e847ccc8123a1959d", + "imdb_id": "tt0806901", + "name": "Police Call 110", + "type": "series", + "year": "1971–" + }, + { + "_id": "5543fb55d728d29134b6e5a4", + "imdb_id": "tt1216159", + "name": "Nabari no Ou", + "year": "2008", + "type": "series" + }, + { + "_id": "5c34ae23173739c9f4fee162", + "imdb_id": "tt0319987", + "name": "Dragnet", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "576c5a05f0b6c53b3c76ac11", + "imdb_id": "tt4229954", + "name": "Outcast", + "year": "2016–2017", + "type": "series" + }, + { + "_id": "5b9c6a6c173739c9f44f1ca6", + "imdb_id": "tt2177461", + "name": "A Discovery of Witches", + "type": "series", + "year": "2018–2022" + }, + { + "_id": "53677ef9847ccc8123a14000", + "imdb_id": "tt1548850", + "name": "Misfits", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "605c55d55424253341ee51bf", + "imdb_id": "tt14069590", + "name": "Dota: Dragon's Blood", + "type": "series", + "year": "2021–" + }, + { + "_id": "59bbb5571712e0f4dd91f618", + "imdb_id": "tt5669272", + "type": "series", + "name": "Wet Hot American Summer: Ten Years Later", + "year": "2017" + }, + { + "_id": "5c245e86173739c9f44a9ee8", + "imdb_id": "tt0057741", + "name": "Crossroads", + "type": "series", + "year": "1964–1988" + }, + { + "_id": "53677f47847ccc8123a20014", + "imdb_id": "tt0264970", + "name": "Crossroads", + "type": "series", + "year": "2001–2003" + }, + { + "_id": "5c1f2bd1173739c9f4e92f45", + "imdb_id": "tt6128376", + "name": "The Gong Show", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677f68847ccc8123a22bf9", + "imdb_id": "tt2375692", + "name": "Black Sails", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "53677f60847ccc8123a22304", + "imdb_id": "tt0070991", + "name": "Good Times", + "type": "series", + "year": "1974–1979" + }, + { + "_id": "64b6cd0ebd36726cbb6bbf17", + "imdb_id": "tt13111078", + "name": "Special Ops: Lioness", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f3a847ccc8123a1f082", + "imdb_id": "tt2551252", + "name": "It's a Date", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "5c33c6f5173739c9f492b6f8", + "imdb_id": "tt0054568", + "name": "Tales of the Wizard of Oz", + "type": "series", + "year": "1961–" + }, + { + "_id": "55fa7ed3bf6c900d1841f472", + "imdb_id": "tt4452630", + "name": "Code Black", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "5c493af9d582b2575671ba8c", + "imdb_id": "tt0086744", + "name": "Kids Incorporated", + "type": "series", + "year": "1984–1993" + }, + { + "_id": "53677f24847ccc8123a1d172", + "imdb_id": "tt0055666", + "name": "Combat!", + "type": "series", + "year": "1962–1967" + }, + { + "_id": "5c09a6b0173739c9f4c672d1", + "imdb_id": "tt0165593", + "name": "BBC Play of the Month", + "type": "series", + "year": "1965–1983" + }, + { + "_id": "5ab881b853336c1ba820e2e1", + "imdb_id": "tt5664952", + "type": "series", + "name": "Trust", + "year": "2018" + }, + { + "_id": "633870e664ec43ef98304f3a", + "imdb_id": "tt15533960", + "name": "I'm the Villainess, So I'm Taming the Final Boss", + "type": "series", + "year": "2022" + }, + { + "_id": "5c2933ee173739c9f4cd4a12", + "imdb_id": "tt1762503", + "name": "Carpool", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c26c580173739c9f4a7e0ec", + "imdb_id": "tt5194792", + "name": "NOS4A2", + "type": "series", + "year": "2019–2020" + }, + { + "_id": "53677f1f847ccc8123a1c48b", + "imdb_id": "tt0072511", + "name": "Secret Squadron Gorenger", + "type": "series", + "year": "1975–1977" + }, + { + "_id": "53677efd847ccc8123a1566b", + "imdb_id": "tt0077031", + "name": "The Incredible Hulk", + "type": "series", + "year": "1977–1982" + }, + { + "_id": "53677ef9847ccc8123a143da", + "imdb_id": "tt0823333", + "name": "Blade: The Series", + "type": "series", + "year": "2006" + }, + { + "_id": "5c426644d582b2575671b271", + "imdb_id": "tt2291137", + "name": "Folktales from Japan", + "type": "series", + "year": "2012–" + }, + { + "_id": "54fc0929711bd19c92ad496d", + "imdb_id": "tt0405520", + "name": "Best Week Ever with Paul F. Tompkins", + "year": "2004–", + "type": "series" + }, + { + "_id": "5c0bd9c1173739c9f499848e", + "imdb_id": "tt6964748", + "name": "Alex Rider", + "type": "series", + "year": "2020–" + }, + { + "_id": "5378cbe6847ccc8123ad2a32", + "imdb_id": "tt3186138", + "name": "Finding Carter", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677efa847ccc8123a149ce", + "imdb_id": "tt1727387", + "name": "GCB", + "type": "series", + "year": "2012" + }, + { + "_id": "54b28a0b8527d2e0cb50620f", + "imdb_id": "tt0112057", + "name": "Magic Knight Rayearth", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "635cdd1d64ec43ef986b9607", + "imdb_id": "tt21991254", + "name": "Romantic Killer", + "type": "series", + "year": "2022" + }, + { + "_id": "6072f1a3542425334181628f", + "imdb_id": "tt13196080", + "name": "Tokyo Revengers", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f0c847ccc8123a18e82", + "imdb_id": "tt0103477", + "name": "The Little Mermaid", + "type": "series", + "year": "1992–1994" + }, + { + "_id": "541463a1a8f27b1bb90c9975", + "imdb_id": "tt0085088", + "name": "Scarecrow and Mrs. King", + "type": "series", + "year": "1983–1987" + }, + { + "_id": "53677f0c847ccc8123a18ff0", + "imdb_id": "tt0272988", + "name": "Phantom Thief Jeanne", + "type": "series", + "year": "1999–" + }, + { + "_id": "62d8307a64ec43ef981d2c4e", + "imdb_id": "tt15219320", + "name": "Uncle from Another World", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677f15847ccc8123a1a7e1", + "imdb_id": "tt0069599", + "name": "Kojak", + "type": "series", + "year": "1973–1978" + }, + { + "_id": "53677ef9847ccc8123a13d1c", + "imdb_id": "tt0844653", + "name": "Legend of the Seeker", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "651bf68fbd36726cbbb216c8", + "imdb_id": "tt10551640", + "name": "The Longest Day in Chang'an", + "type": "series", + "year": "2019" + }, + { + "_id": "570f058b890e549c9a5833f5", + "imdb_id": "tt4903242", + "name": "The Detour", + "year": "2016–2019", + "type": "series" + }, + { + "_id": "6307407764ec43ef986b2064", + "imdb_id": "tt14674086", + "name": "Welcome to Wrexham", + "type": "series", + "year": "2022–" + }, + { + "_id": "550787e0711bd19c92ade1fc", + "imdb_id": "tt0115417", + "name": "Water Rats", + "year": "1996–2001", + "type": "series" + }, + { + "_id": "53677f07847ccc8123a180ae", + "imdb_id": "tt0126171", + "name": "She-Ra: Princess of Power", + "type": "series", + "year": "1985–1987" + }, + { + "_id": "53677efa847ccc8123a14a77", + "imdb_id": "tt0262150", + "name": "Black Books", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "5bfd6f75173739c9f4a8138c", + "imdb_id": "tt7945720", + "name": "Dirty John", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "53677f0c847ccc8123a19149", + "imdb_id": "tt0108903", + "name": "ReBoot", + "type": "series", + "year": "1994–2001" + }, + { + "_id": "5c0f0582173739c9f4326b1a", + "imdb_id": "tt7814574", + "name": "Junji Itô: Korekushon", + "type": "series", + "year": "2018–" + }, + { + "_id": "624419cc64ec43ef98aa4cac", + "imdb_id": "tt10234724", + "name": "Moon Knight", + "type": "series", + "year": "2022" + }, + { + "_id": "56cd7161f6aa5b2a534468ce", + "imdb_id": "tt4816626", + "name": "Outsiders", + "year": "2016–2017", + "type": "series" + }, + { + "_id": "5c0f5547173739c9f4a570fa", + "imdb_id": "tt8328460", + "name": "Busted!", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "5c0d0dbc173739c9f4b3b250", + "imdb_id": "tt6461346", + "name": "Stranger", + "type": "series", + "year": "2017–" + }, + { + "_id": "5c6099e2d582b257566eba7f", + "imdb_id": "tt0285342", + "name": "Bob Patterson", + "type": "series", + "year": "2001" + }, + { + "_id": "625feb4f64ec43ef98221617", + "imdb_id": "tt15723722", + "name": "I'm Quitting Heroing", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f05847ccc8123a179ab", + "imdb_id": "tt2912216", + "name": "Fatal Attraction", + "type": "series", + "year": "2013–" + }, + { + "_id": "53677f05847ccc8123a17ae8", + "imdb_id": "tt0318997", + "name": "Angels in America", + "type": "series", + "year": "2003" + }, + { + "_id": "59b03ef21712e0f4dd1e6b30", + "imdb_id": "tt4571004", + "name": "Meurtres à...", + "year": "2013–", + "type": "series" + }, + { + "_id": "5c2a939a173739c9f42c32c5", + "imdb_id": "tt8388390", + "name": "Chucky", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677efa847ccc8123a14b26", + "imdb_id": "tt0115227", + "name": "Judge Judy", + "type": "series", + "year": "1996–2021" + }, + { + "_id": "543d5216a8f27b1bb90d38c3", + "imdb_id": "tt2301643", + "name": "Halloween Wars", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677f38847ccc8123a1ee17", + "imdb_id": "tt0235911", + "name": "As Told by Ginger", + "type": "series", + "year": "2000–2009" + }, + { + "_id": "5c1c1c63173739c9f48cb4c4", + "imdb_id": "tt5603140", + "name": "The Restaurant", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f0c847ccc8123a1904c", + "imdb_id": "tt0364863", + "name": "RahXephon", + "type": "series", + "year": "2002" + }, + { + "_id": "53677f0f847ccc8123a1987b", + "imdb_id": "tt0204087", + "name": "Those Who Hunt Elves", + "type": "series", + "year": "1996–1997" + }, + { + "_id": "53677f04847ccc8123a17345", + "imdb_id": "tt2693776", + "name": "Intelligence", + "type": "series", + "year": "2014" + }, + { + "_id": "5c12b3e3173739c9f4cc1a71", + "imdb_id": "tt2301807", + "name": "Naruto SD: Rock Lee & His Ninja Pals", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "576c5a7df0b6c53b3c76ac2f", + "imdb_id": "tt5376862", + "name": "Guilt", + "year": "2016", + "type": "series" + }, + { + "_id": "53677f20847ccc8123a1c67e", + "imdb_id": "tt1447723", + "name": "The Fresh Beat Band", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "643453a864ec43ef983658f0", + "imdb_id": "tt27417996", + "name": "I Got a Cheat Skill in Another World and Became Unrivaled in the Real World, Too", + "type": "series", + "year": "2023" + }, + { + "_id": "5c17ea15173739c9f4ede08f", + "imdb_id": "tt6074794", + "name": "March Comes in Like a Lion", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "5c0a7c0f173739c9f425f4e7", + "imdb_id": "tt6354518", + "name": "The Disastrous Life of Saiki K.", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "53677f22847ccc8123a1ce40", + "imdb_id": "tt0075596", + "name": "Three's Company", + "type": "series", + "year": "1976–1984" + }, + { + "_id": "53677f29847ccc8123a1dde4", + "imdb_id": "tt0103511", + "name": "Phoenix", + "type": "series", + "year": "1992–1993" + }, + { + "_id": "536907e8847ccc8123acdd31", + "imdb_id": "tt1382157", + "name": "That Metal Show", + "type": "series", + "year": "2008–2015" + }, + { + "_id": "5c0fc241173739c9f45c563d", + "imdb_id": "tt0247729", + "name": "Static Shock", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "53a5820aa8f27b1bb90b1c86", + "imdb_id": "tt0361140", + "name": ".hack//SIGN", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "62f5d6c164ec43ef98511661", + "imdb_id": "tt3283594", + "name": "Five Days at Memorial", + "type": "series", + "year": "2022" + }, + { + "_id": "55075d94711bd19c92addf42", + "imdb_id": "tt2902582", + "name": "Danganronpa: The Animation", + "year": "2013", + "type": "series" + }, + { + "_id": "53677ef9847ccc8123a13c47", + "imdb_id": "tt1192169", + "name": "Ben 10: Alien Force", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "5bf4bafe173739c9f4cfd159", + "imdb_id": "tt5924572", + "name": "Deadly Class", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "5c3b49f4d582b25756a20699", + "imdb_id": "tt0108800", + "name": "Heartbreak High", + "type": "series", + "year": "1994–1999" + }, + { + "_id": "5c0bbf14173739c9f464a399", + "imdb_id": "tt0073974", + "name": "City of Angels", + "type": "series", + "year": "1976–" + }, + { + "_id": "53677eff847ccc8123a15ffc", + "imdb_id": "tt0058814", + "name": "Honey West", + "type": "series", + "year": "1965–1966" + }, + { + "_id": "53677f2c847ccc8123a1e13b", + "imdb_id": "tt2384811", + "name": "Utopia", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "53677f19847ccc8123a1b3a9", + "imdb_id": "tt0052485", + "name": "Lock Up", + "type": "series", + "year": "1959–1961" + }, + { + "_id": "582f4439b0a40c25066cc743", + "imdb_id": "tt4118466", + "name": "Incorporated", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677ef9847ccc8123a13867", + "imdb_id": "tt1332030", + "name": "Make It or Break It", + "type": "series", + "year": "2009–2012" + }, + { + "_id": "53677ef9847ccc8123a13d2e", + "imdb_id": "tt0914829", + "name": "Bad Girls Club", + "type": "series", + "year": "2006–" + }, + { + "_id": "554359c7b0c9284285038c20", + "imdb_id": "tt2309320", + "name": "From the New World", + "year": "2012–2013", + "type": "series" + }, + { + "_id": "5d503945c4ccb5dd924b2c72", + "imdb_id": "tt9698520", + "name": "A Black Lady Sketch Show", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "62ca29e964ec43ef98a8e500", + "imdb_id": "tt16755706", + "name": "Lycoris Recoil", + "type": "series", + "year": "2022" + }, + { + "_id": "652ab4ffbd36726cbb0b0ee4", + "imdb_id": "tt29171919", + "name": "The Vexations of a Shut-In Vampire Princess", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677efc847ccc8123a1537b", + "imdb_id": "tt2191567", + "name": "Wicked Tuna", + "type": "series", + "year": "2012–" + }, + { + "_id": "5c28cab5173739c9f4f8aaaf", + "imdb_id": "tt0094434", + "name": "Chouju Sentai Liveman", + "type": "series", + "year": "1988–1989" + }, + { + "_id": "55dec9cebf6c900d183fa369", + "imdb_id": "tt0081961", + "name": "Wetten, dass..?", + "year": "1981–", + "type": "series" + }, + { + "_id": "53677f1c847ccc8123a1ba9e", + "imdb_id": "tt1910272", + "name": "Steins;Gate", + "type": "series", + "year": "2011–2015" + }, + { + "_id": "5378cbf8847ccc8123ad34da", + "imdb_id": "tt3230780", + "name": "The Returned", + "type": "series", + "year": "2015" + }, + { + "_id": "53677f21847ccc8123a1cafa", + "imdb_id": "tt0077082", + "name": "The South Bank Show", + "type": "series", + "year": "1978–" + }, + { + "_id": "53677f00847ccc8123a163f8", + "imdb_id": "tt1344970", + "name": "Rob Dyrdek's Fantasy Factory", + "type": "series", + "year": "2009–" + }, + { + "_id": "53677f02847ccc8123a16c0d", + "imdb_id": "tt1780262", + "name": "Is this a Zombie?", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "53677f2f847ccc8123a1e606", + "imdb_id": "tt0481440", + "name": "Britain's Next Top Model", + "type": "series", + "year": "2005–" + }, + { + "_id": "5c0ea739173739c9f47c0fa1", + "imdb_id": "tt0101115", + "name": "Herman's Head", + "type": "series", + "year": "1991–1994" + }, + { + "_id": "57eb3d86d7e54929823ee933", + "imdb_id": "tt5797772", + "type": "series", + "name": "Aftermath", + "year": "2016" + }, + { + "_id": "6262437c64ec43ef98851005", + "imdb_id": "tt13223570", + "name": "The First Lady", + "type": "series", + "year": "2022" + }, + { + "_id": "5c0cd442173739c9f448a7cf", + "imdb_id": "tt2953250", + "name": "Shining Girls", + "type": "series", + "year": "2022" + }, + { + "_id": "55c392abbf6c900d183cafba", + "imdb_id": "tt4380272", + "name": "Gamer's Guide to Pretty Much Everything", + "year": "2015–2017", + "type": "series" + }, + { + "_id": "53677f05847ccc8123a17cc7", + "imdb_id": "tt1295036", + "name": "Seth MacFarlane's Cavalcade of Cartoon Comedy", + "type": "series", + "year": "2008–2010" + }, + { + "_id": "5c1585f4173739c9f4ea828d", + "imdb_id": "tt6428088", + "name": "Charlie Golf One", + "type": "series", + "year": "2016–2020" + }, + { + "_id": "613c32e064ec43ef9833ce7d", + "imdb_id": "tt12994356", + "name": "The Cleaner", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f23847ccc8123a1cf59", + "imdb_id": "tt0874679", + "name": "Son of the Dragon", + "type": "series", + "year": "2006" + }, + { + "_id": "6182b55a64ec43ef985e2d88", + "imdb_id": "tt7492014", + "name": "Fairfax", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677f0c847ccc8123a193bd", + "imdb_id": "tt0112090", + "name": "The Naked Truth", + "type": "series", + "year": "1995–1998" + }, + { + "_id": "53677eff847ccc8123a15dfb", + "imdb_id": "tt0419326", + "name": "Foster's Home for Imaginary Friends", + "type": "series", + "year": "2004–2009" + }, + { + "_id": "5c0ae374173739c9f4f3176d", + "imdb_id": "tt0101068", + "name": "Cluedo", + "type": "series", + "year": "1990–1993" + }, + { + "_id": "53677f03847ccc8123a17326", + "imdb_id": "tt0112123", + "name": "Pinky and the Brain", + "type": "series", + "year": "1995–1998" + }, + { + "_id": "635650afe49da23b4660db4d", + "name": "Beavis and Butt-Head", + "imdb_id": "tt20859904", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f51847ccc8123a20e46", + "imdb_id": "tt0500092", + "name": "Serial Experiments Lain", + "type": "series", + "year": "1998" + }, + { + "_id": "53677f22847ccc8123a1ccc6", + "imdb_id": "tt0084976", + "name": "Aura Battler Dunbine", + "type": "series", + "year": "1983–1984" + }, + { + "_id": "53677ef9847ccc8123a13876", + "imdb_id": "tt0445912", + "name": "The Ultimate Fighter", + "type": "series", + "year": "2005–" + }, + { + "_id": "5c0be6f3173739c9f4b55b10", + "imdb_id": "tt0178148", + "name": "Kinnikuman", + "type": "series", + "year": "1983–1986" + }, + { + "_id": "53677f40847ccc8123a1f660", + "imdb_id": "tt1198372", + "name": "Mujeres asesinas", + "type": "series", + "year": "2008–" + }, + { + "_id": "55072f71711bd19c92add84d", + "imdb_id": "tt0429416", + "name": "Project ARMS", + "year": "2001–2002", + "type": "series" + }, + { + "_id": "53677f15847ccc8123a1a8bc", + "imdb_id": "tt0118475", + "name": "Spawn", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "53677f13847ccc8123a1a2df", + "imdb_id": "tt0075578", + "name": "SCTV", + "type": "series", + "year": "1976–1981" + }, + { + "_id": "54f8f399711bd19c92accdb2", + "imdb_id": "tt3560060", + "name": "CSI: Cyber", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "54c92d23e573cadcfa1f7761", + "imdb_id": "tt0434693", + "name": "Sergeant Keroro", + "type": "series", + "year": "2004–2011" + }, + { + "_id": "5c449e05d582b2575647fad0", + "imdb_id": "tt9547400", + "name": "Magia Record: Puella Magi Madoka Magica Side Story", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "5f5d0ae254242533418b4d3c", + "imdb_id": "tt12432936", + "name": "The Misfit of Demon King Academy", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677f61847ccc8123a2244d", + "imdb_id": "tt2703708", + "name": "Ginga Kikoutai: Majestic Prince", + "type": "series", + "year": "2013–" + }, + { + "_id": "53eb359ea8f27b1bb90c0817", + "imdb_id": "tt3781836", + "name": "Botched", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677f1e847ccc8123a1c123", + "imdb_id": "tt0899258", + "name": "D.Gray-man", + "type": "series", + "year": "2006–2008" + }, + { + "_id": "53677efd847ccc8123a15b5f", + "imdb_id": "tt0081871", + "name": "The Greatest American Hero", + "type": "series", + "year": "1981–1983" + }, + { + "_id": "53677efc847ccc8123a15242", + "imdb_id": "tt1695360", + "name": "The Legend of Korra", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "5aa2cf0353336c1ba8ef7fa3", + "imdb_id": "tt6470396", + "type": "series", + "name": "Champions", + "year": "2018" + }, + { + "_id": "5c3f9357d582b25756d89188", + "imdb_id": "tt6889072", + "name": "The Best Hit", + "type": "series", + "year": "2017" + }, + { + "_id": "53677f19847ccc8123a1b559", + "imdb_id": "tt1329466", + "name": "Sukippu bîto!", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "5c2280af173739c9f4e91855", + "imdb_id": "tt0085075", + "name": "Reading Rainbow", + "type": "series", + "year": "1983–2006" + }, + { + "_id": "53677f0a847ccc8123a18789", + "imdb_id": "tt1634208", + "name": "Maid Sama!", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c5ee358d582b2575606f15e", + "imdb_id": "tt8466564", + "name": "Obi-Wan Kenobi", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f5e847ccc8123a222db", + "imdb_id": "tt0101059", + "name": "Chances", + "type": "series", + "year": "1991–1992" + }, + { + "_id": "53677f03847ccc8123a17252", + "imdb_id": "tt0108761", + "name": "Ellen", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "53677f0a847ccc8123a1895f", + "imdb_id": "tt0118303", + "name": "Dharma & Greg", + "type": "series", + "year": "1997–2002" + }, + { + "_id": "56701a6dbb83c6649898e672", + "imdb_id": "tt3793630", + "name": "The Lion Guard", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "6261b65564ec43ef98ebfbbe", + "imdb_id": "tt15766292", + "name": "Mahoutsukai Reimeiki", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c2188b3173739c9f43919a4", + "imdb_id": "tt0122813", + "name": "Bob and Margaret", + "type": "series", + "year": "1993–2001" + }, + { + "_id": "53677f4a847ccc8123a204d9", + "imdb_id": "tt0072504", + "name": "Get Some In!", + "type": "series", + "year": "1975–1978" + }, + { + "_id": "593196611635517fbf56e8e5", + "imdb_id": "tt6905508", + "name": "Growing Up Hip Hop: Atlanta", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677efc847ccc8123a14d01", + "imdb_id": "tt0799922", + "name": "Wizards of Waverly Place", + "type": "series", + "year": "2007–2012" + }, + { + "_id": "53677ef9847ccc8123a1424e", + "imdb_id": "tt2334429", + "name": "The Voice", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677eff847ccc8123a15cd7", + "imdb_id": "tt1807824", + "name": "Wakfu", + "type": "series", + "year": "2008–2017" + }, + { + "_id": "5f64e3bb54242533411e7cb7", + "imdb_id": "tt7294498", + "name": "Frankie Boyle's New World Order", + "type": "series", + "year": "2017–2022" + }, + { + "_id": "5c4244aad582b257565df2d6", + "imdb_id": "tt0086660", + "name": "1st & Ten", + "type": "series", + "year": "1984–1991" + }, + { + "_id": "5c0c13a8173739c9f41024cf", + "imdb_id": "tt6300838", + "name": "Tiger Mask W", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "582f4b41b0a40c25066cc7f0", + "imdb_id": "tt4181172", + "name": "Shooter", + "type": "series", + "year": "2016–2018" + }, + { + "_id": "6425d15c64ec43ef9859cc72", + "imdb_id": "tt22059768", + "name": "Digman!", + "type": "series", + "year": "2023–" + }, + { + "_id": "55c8a056bf6c900d183dc17d", + "imdb_id": "tt4677934", + "name": "Documentary Now!", + "year": "2015–", + "type": "series" + }, + { + "_id": "5c0b0cab173739c9f445cc04", + "imdb_id": "tt6922826", + "name": "Once", + "type": "series", + "year": "2017–2019" + }, + { + "_id": "5c09bc2d173739c9f4f25c08", + "imdb_id": "tt7529770", + "name": "Miracle Workers", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677f07847ccc8123a17df7", + "imdb_id": "tt0094559", + "name": "Superboy", + "type": "series", + "year": "1988–1992" + }, + { + "_id": "5bc68d57173739c9f49846f2", + "imdb_id": "tt8595140", + "name": "The Conners", + "type": "series", + "year": "2018–" + }, + { + "_id": "5d559e45c4ccb5dd92ab7447", + "imdb_id": "tt9054904", + "name": "Why Women Kill", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "53677f66847ccc8123a22ad9", + "imdb_id": "tt0204777", + "name": "The Secret Files of the SpyDogs", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "570f05b3890e549c9a5833fa", + "imdb_id": "tt5269594", + "name": "Marcella", + "year": "2016–2021", + "type": "series" + }, + { + "_id": "5c3592da173739c9f49b8315", + "imdb_id": "tt0249313", + "name": "Resurrection Blvd.", + "type": "series", + "year": "2000–2002" + }, + { + "_id": "53677f1e847ccc8123a1c0d9", + "imdb_id": "tt1101237", + "name": "Imagination Movers", + "type": "series", + "year": "2008–2013" + }, + { + "_id": "53677ef9847ccc8123a139bd", + "imdb_id": "tt0065314", + "name": "The Mary Tyler Moore Show", + "type": "series", + "year": "1970–1977" + }, + { + "_id": "5433a646a8f27b1bb90d1074", + "imdb_id": "tt3747572", + "name": "Grantchester", + "type": "series", + "year": "2014–2023" + }, + { + "_id": "5455eb37a8f27b1bb90da50a", + "imdb_id": "tt0080242", + "name": "The Martian Chronicles", + "type": "series", + "year": "1980" + }, + { + "_id": "53677ef9847ccc8123a13f8a", + "imdb_id": "tt1593756", + "name": "Outsourced", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "61e852ff64ec43ef98d395ef", + "imdb_id": "tt14506186", + "name": "In the Land of Leadale", + "type": "series", + "year": "2022" + }, + { + "_id": "5c2ef15d173739c9f4ebb806", + "imdb_id": "tt0309221", + "name": "Tom Stone", + "type": "series", + "year": "2002–2003" + }, + { + "_id": "53677f03847ccc8123a171b1", + "imdb_id": "tt0101178", + "name": "The Ren & Stimpy Show", + "type": "series", + "year": "1991–1996" + }, + { + "_id": "53677f02847ccc8123a1694c", + "imdb_id": "tt0387736", + "name": "Farscape: The Peacekeeper Wars", + "type": "series", + "year": "2004" + }, + { + "_id": "53677f48847ccc8123a20357", + "imdb_id": "tt0118492", + "name": "Timecop", + "type": "series", + "year": "1997–1998" + }, + { + "_id": "59b100bf1712e0f4dd4a74f0", + "imdb_id": "tt0078701", + "type": "series", + "name": "This Old House", + "year": "1979–" + }, + { + "_id": "53677f2c847ccc8123a1e188", + "imdb_id": "tt0115285", + "name": "Nash Bridges", + "type": "series", + "year": "1996–2001" + }, + { + "_id": "5c60538cd582b25756029c23", + "imdb_id": "tt0385411", + "name": "A Wonderful Country", + "type": "series", + "year": "2003–" + }, + { + "_id": "5378cc0a847ccc8123ad46df", + "imdb_id": "tt3594982", + "name": "Sex & Drugs & Rock & Roll", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c0acd30173739c9f4c478fd", + "imdb_id": "tt7431994", + "name": "The Pit", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "5c235bfc173739c9f45ea32b", + "imdb_id": "tt4721442", + "name": "Tanglin", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f1b847ccc8123a1b848", + "imdb_id": "tt0131664", + "name": "The Angry Beavers", + "type": "series", + "year": "1997–2001" + }, + { + "_id": "5c35e878173739c9f4264157", + "imdb_id": "tt5334364", + "name": "Undefeated Bahamut Chronicle", + "type": "series", + "year": "2016" + }, + { + "_id": "5c1adb10173739c9f4511bcc", + "imdb_id": "tt0293741", + "name": "Shinzo", + "type": "series", + "year": "2000–2001" + }, + { + "_id": "53677f0a847ccc8123a18766", + "imdb_id": "tt1842715", + "name": "CSI: Crime Scene Talks", + "type": "series", + "year": "2011–" + }, + { + "_id": "53677ef9847ccc8123a13bf5", + "imdb_id": "tt0453422", + "name": "Doctor Who Confidential", + "type": "series", + "year": "2005–2011" + }, + { + "_id": "5c0eaa0b173739c9f4813472", + "imdb_id": "tt7767422", + "type": "series", + "name": "Sex Education", + "year": "2019–2023" + }, + { + "_id": "6530fab0bd36726cbbc0f4e2", + "imdb_id": "tt18347622", + "name": "Bodies", + "type": "series", + "year": "2023" + }, + { + "_id": "5c24dd3d173739c9f42240b8", + "imdb_id": "tt2294764", + "name": "De slimste mens ter wereld", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f07847ccc8123a17f7c", + "imdb_id": "tt0122336", + "name": "Captain Future", + "type": "series", + "year": "1978–1979" + }, + { + "_id": "634b493b64ec43ef98144644", + "imdb_id": "tt12464204", + "name": "Peter Grill to Kenja no Jikan", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f15847ccc8123a1a7c1", + "imdb_id": "tt1893520", + "name": "C", + "type": "series", + "year": "2011–" + }, + { + "_id": "659fb334bd36726cbb93c407", + "imdb_id": "tt21153032", + "name": "The Scooby-Doo Show", + "type": "series", + "year": "1978–2021" + }, + { + "_id": "60f2859f64ec43ef9879fda9", + "imdb_id": "tt13463778", + "name": "Girlfriend, Girlfriend", + "type": "series", + "year": "2021–" + }, + { + "_id": "6367555864ec43ef98da0744", + "imdb_id": "tt11755260", + "name": "The Daily Life of the Immortal King", + "type": "series", + "year": "2020–" + }, + { + "_id": "5c1d5677173739c9f4b4b214", + "imdb_id": "tt2404499", + "name": "Kingdom", + "type": "series", + "year": "2012–" + }, + { + "_id": "53677f26847ccc8123a1d73a", + "imdb_id": "tt0896667", + "name": "Donna Leon", + "type": "series", + "year": "2000–" + }, + { + "_id": "54fb89a1711bd19c92ad484d", + "imdb_id": "tt0440987", + "name": "Fafner", + "year": "2004", + "type": "series" + }, + { + "_id": "5c0ceef9173739c9f479f599", + "imdb_id": "tt8354062", + "name": "One Of Us Is Lying", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5c308ea6173739c9f4c4dda1", + "imdb_id": "tt0423730", + "name": "SOKO Wismar", + "type": "series", + "year": "2004–" + }, + { + "_id": "53677f54847ccc8123a2149f", + "imdb_id": "tt1188927", + "name": "Criminal Justice", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "53677efa847ccc8123a14871", + "imdb_id": "tt1170858", + "name": "Dragons' Den", + "type": "series", + "year": "2006–" + }, + { + "_id": "5f676d1354242533417474e7", + "imdb_id": "tt11710130", + "name": "I Can See Your Voice", + "type": "series", + "year": "2020–" + }, + { + "_id": "615ef99564ec43ef980fb3fa", + "imdb_id": "tt13241650", + "name": "Ada Twist, Scientist", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c3473c7173739c9f499062f", + "imdb_id": "tt0103426", + "name": "The Golden Palace", + "type": "series", + "year": "1992–1993" + }, + { + "_id": "5e748bc6ee95f208ea3ebff2", + "imdb_id": "tt11405370", + "name": "Nekopara", + "type": "series", + "year": "2020–" + }, + { + "_id": "5c54459cd582b25756ef3048", + "imdb_id": "tt1741602", + "name": "Natholdet - med Anders Breinholt", + "type": "series", + "year": "2010–" + }, + { + "_id": "61138d7c64ec43ef98bc70ed", + "imdb_id": "tt13784584", + "name": "Fantasy Island", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "5c2dfa82173739c9f428a1e1", + "imdb_id": "tt3612626", + "name": "Saekano: How to Raise a Boring Girlfriend", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677f29847ccc8123a1dc8f", + "imdb_id": "tt0272376", + "name": "The Division", + "type": "series", + "year": "2001–2004" + }, + { + "_id": "5f89d6845424253341f41240", + "imdb_id": "tt12457334", + "name": "Wandering Witch: The Journey of Elaina", + "type": "series", + "year": "2020–" + }, + { + "_id": "5897f8c81635517fbf56d41c", + "imdb_id": "tt5345490", + "name": "24: Legacy", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f12847ccc8123a19fb7", + "imdb_id": "tt0168375", + "name": "A Little Princess Sara", + "type": "series", + "year": "1985" + }, + { + "_id": "5a184531543165dcd875d624", + "imdb_id": "tt6468322", + "type": "series", + "name": "Money Heist", + "year": "2017–2021" + }, + { + "_id": "53677f0c847ccc8123a192d0", + "imdb_id": "tt0200369", + "name": "Redwall", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "53677f21847ccc8123a1c9fe", + "imdb_id": "tt2226342", + "name": "Devious Maids", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "543ad2fca8f27b1bb90d2d1a", + "imdb_id": "tt0190178", + "name": "Denver, the Last Dinosaur", + "type": "series", + "year": "1988–1990" + }, + { + "_id": "5c1304a2173739c9f47091a0", + "imdb_id": "tt8271124", + "name": "The Adventures of Rocky and Bullwinkle", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677ef9847ccc8123a14155", + "imdb_id": "tt0808013", + "name": "Blood Ties", + "type": "series", + "year": "2007" + }, + { + "_id": "53677f0a847ccc8123a1865d", + "imdb_id": "tt0376390", + "name": "Duck Dodgers", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "5c0c4210173739c9f473dc48", + "imdb_id": "tt0159178", + "name": "Maigret", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "53677f3a847ccc8123a1f0cf", + "imdb_id": "tt0275848", + "name": "Lloyd in Space", + "type": "series", + "year": "2001–2004" + }, + { + "_id": "606c8cb9542425334140d5c2", + "imdb_id": "tt7475590", + "name": "Kung Fu", + "type": "series", + "year": "2021–2023" + }, + { + "_id": "536907e6847ccc8123acdcd2", + "imdb_id": "tt0283744", + "name": "James Bond Jr.", + "type": "series", + "year": "1991–1992" + }, + { + "_id": "5811c12cd7e54929824144e0", + "imdb_id": "tt6015808", + "name": "Doctor Doctor", + "type": "series", + "year": "2016–2021" + }, + { + "_id": "63ca43e064ec43ef9841533f", + "imdb_id": "tt11349866", + "name": "Sorcerous Stabber Orphen: Battle of Kimluck", + "type": "series", + "year": "2020–" + }, + { + "_id": "5ab0283653336c1ba8e424ef", + "imdb_id": "tt6461824", + "type": "series", + "name": "The Crossing", + "year": "2018" + }, + { + "_id": "58199f4555f8aab460cfa82c", + "imdb_id": "tt0106056", + "name": "Living Single", + "type": "series", + "year": "1993–1998" + }, + { + "_id": "548f0c978527d2e0cb4ff996", + "imdb_id": "tt0149534", + "name": "Thuis", + "type": "series", + "year": "1995–" + }, + { + "_id": "53677f02847ccc8123a16bbe", + "imdb_id": "tt1991410", + "name": "Dance Moms", + "type": "series", + "year": "2011–2019" + }, + { + "_id": "5a155be3543165dcd828f406", + "imdb_id": "tt5311790", + "type": "series", + "name": "The A Word", + "year": "2016–" + }, + { + "_id": "53677ef9847ccc8123a13dc6", + "imdb_id": "tt1279972", + "name": "Treme", + "type": "series", + "year": "2010–2013" + }, + { + "_id": "5aa5114953336c1ba887f73b", + "imdb_id": "tt0320970", + "name": "Still Standing", + "year": "2002–2006", + "type": "series" + }, + { + "_id": "5c570fe6d582b257569b1e28", + "imdb_id": "tt1727444", + "name": "Panty & Stocking with Garterbelt", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c09b3b2173739c9f4e13131", + "imdb_id": "tt7865962", + "name": "Run BTS!", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677ef9847ccc8123a1418f", + "imdb_id": "tt1832668", + "name": "How the Universe Works", + "type": "series", + "year": "2010–" + }, + { + "_id": "53eb359ca8f27b1bb90c0794", + "imdb_id": "tt3589872", + "name": "Black Jesus", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "53677f60847ccc8123a22320", + "imdb_id": "tt1898069", + "name": "American Gods", + "type": "series", + "year": "2017–2021" + }, + { + "_id": "5c617f20d582b2575681f45d", + "imdb_id": "tt5659248", + "name": "The Daltons", + "type": "series", + "year": "2010–2016" + }, + { + "_id": "548f0c958527d2e0cb4ff924", + "imdb_id": "tt0211882", + "name": "Watership Down", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "65978fecbd36726cbb24025f", + "imdb_id": "tt21621494", + "name": "Delicious in Dungeon", + "type": "series", + "year": "2024–" + }, + { + "_id": "54fc094a711bd19c92ad49f5", + "imdb_id": "tt0791163", + "name": "Trinity Blood", + "year": "2005", + "type": "series" + }, + { + "_id": "602c9ac95424253341132438", + "imdb_id": "tt10312854", + "name": "Kenan", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5aaf1d0853336c1ba8b5266b", + "imdb_id": "tt4124758", + "type": "series", + "name": "Instinct", + "year": "2018–2019" + }, + { + "_id": "53677efd847ccc8123a1554f", + "imdb_id": "tt0476922", + "name": "Moral Orel", + "type": "series", + "year": "2005–2009" + }, + { + "_id": "53677f66847ccc8123a22acb", + "imdb_id": "tt2578560", + "name": "Broad City", + "type": "series", + "year": "2014–2019" + }, + { + "_id": "5c0b0b3a173739c9f442f79a", + "imdb_id": "tt8515016", + "name": "Banana Fish", + "type": "series", + "year": "2018" + }, + { + "_id": "53677f79847ccc8123a23c1f", + "imdb_id": "tt1666209", + "name": "Dong Yi", + "type": "series", + "year": "2010" + }, + { + "_id": "61d9e5db64ec43ef98732168", + "imdb_id": "tt15765670", + "name": "My Dress-Up Darling", + "type": "series", + "year": "2022" + }, + { + "_id": "63bf0e0464ec43ef989710f0", + "imdb_id": "tt21210326", + "name": "Tomo-chan Is a Girl!", + "type": "series", + "year": "2023" + }, + { + "_id": "60570a325424253341b61fd8", + "imdb_id": "tt13129190", + "name": "SK8 the Infinity", + "type": "series", + "year": "2021" + }, + { + "_id": "53677efc847ccc8123a14f7a", + "imdb_id": "tt1055335", + "name": "Transformers: Animated", + "type": "series", + "year": "2007–2009" + }, + { + "_id": "5b45925916f4806c2ac6e8eb", + "imdb_id": "tt7612548", + "type": "series", + "name": "The Outpost", + "year": "2018–2021" + }, + { + "_id": "577abf11f0b6c53b3c778799", + "imdb_id": "tt4113078", + "name": "Westside", + "year": "2015–", + "type": "series" + }, + { + "_id": "53677f48847ccc8123a20252", + "imdb_id": "tt0052462", + "name": "The Deputy", + "type": "series", + "year": "1959–1961" + }, + { + "_id": "53677ef9847ccc8123a13902", + "imdb_id": "tt0146386", + "name": "National Geographic Explorer", + "type": "series", + "year": "1985–" + }, + { + "_id": "604b0a0f5424253341ec3696", + "imdb_id": "tt10115054", + "name": "Lost Treasures of Egypt", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "53677ef9847ccc8123a13c60", + "imdb_id": "tt0086661", + "name": "The Adventures of Sherlock Holmes", + "type": "series", + "year": "1984–1985" + }, + { + "_id": "5d9649c2c4ccb5dd927e9bda", + "imdb_id": "tt9780442", + "name": "RuPaul's Drag Race UK", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677f68847ccc8123a22b39", + "imdb_id": "tt0096545", + "name": "Birds of a Feather", + "type": "series", + "year": "1989–2020" + }, + { + "_id": "5c161165173739c9f4b33c47", + "imdb_id": "tt8435344", + "name": "ThunderCats Roar", + "type": "series", + "year": "2020" + }, + { + "_id": "5ac23acaa5989fb32186c6b6", + "imdb_id": "tt6882202", + "type": "series", + "name": "The Detail", + "year": "2018" + }, + { + "_id": "5c2248f6173739c9f46da940", + "imdb_id": "tt3588312", + "name": "The Comic Artist and Assistants", + "type": "series", + "year": "2014–" + }, + { + "_id": "5c0db445173739c9f40bd398", + "imdb_id": "tt0124228", + "name": "Astro Boy", + "type": "series", + "year": "1980–2004" + }, + { + "_id": "53677f23847ccc8123a1cf28", + "imdb_id": "tt0041038", + "name": "The Lone Ranger", + "type": "series", + "year": "1949–1957" + }, + { + "_id": "53677f12847ccc8123a19fb4", + "imdb_id": "tt0138967", + "name": "Hercules", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "53677f66847ccc8123a229e4", + "imdb_id": "tt3455408", + "name": "The Curse of Oak Island", + "type": "series", + "year": "2014–" + }, + { + "_id": "5abd8f79e0a43c01da2769a7", + "imdb_id": "tt5615700", + "type": "series", + "name": "Siren", + "year": "2018–2020" + }, + { + "_id": "6433e31964ec43ef98879466", + "imdb_id": "tt13622776", + "name": "Ahsoka", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c3ba9d0d582b25756dc9407", + "imdb_id": "tt0182632", + "name": "Seiju Sentai Gingaman", + "type": "series", + "year": "1998–1999" + }, + { + "_id": "5c309b7d173739c9f4dec668", + "imdb_id": "tt7535706", + "name": "Anime-Gataris", + "type": "series", + "year": "2017" + }, + { + "_id": "56b8dfe8f6b914c6c680fe9e", + "imdb_id": "tt2184186", + "name": "A League of Their Own", + "year": "2010–", + "type": "series" + }, + { + "_id": "551bcc56cc9eee85bb52e0cc", + "imdb_id": "tt2305660", + "name": "Ixion Saga DT", + "year": "2012–2013", + "type": "series" + }, + { + "_id": "5c3d2562d582b25756ab3416", + "imdb_id": "tt0050022", + "name": "The Gumby Show", + "type": "series", + "year": "1956–1969" + }, + { + "_id": "53677eff847ccc8123a15cda", + "imdb_id": "tt2372162", + "name": "Orange Is the New Black", + "type": "series", + "year": "2013–2019" + }, + { + "_id": "5c34c6b2173739c9f42a812d", + "imdb_id": "tt1718249", + "name": "BlackBoxTV", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677efc847ccc8123a1505b", + "imdb_id": "tt0088631", + "name": "Thundercats", + "type": "series", + "year": "1985–1989" + }, + { + "_id": "53677f3a847ccc8123a1efa2", + "imdb_id": "tt0050053", + "name": "The Real McCoys", + "type": "series", + "year": "1957–1963" + }, + { + "_id": "58401d39b0a40c25066dccef", + "imdb_id": "tt6112556", + "name": "Yuri!!! On Ice", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "642dbb3b64ec43ef98c039e6", + "imdb_id": "tt27329086", + "name": "Konosuba: An Explosion on This Wonderful World!", + "type": "series", + "year": "2023" + }, + { + "_id": "539c4866a8f27b1bb90afe67", + "imdb_id": "tt0086689", + "name": "A Country Practice", + "type": "series", + "year": "1981–1993" + }, + { + "_id": "5c0c3c26173739c9f467997e", + "imdb_id": "tt4917066", + "name": "Prison School", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "53677ef9847ccc8123a13d02", + "imdb_id": "tt0972412", + "name": "Private Practice", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "54fc0934711bd19c92ad499a", + "imdb_id": "tt0444953", + "name": "Kaleido Star", + "year": "2003–2004", + "type": "series" + }, + { + "_id": "5c0a0532173739c9f4686644", + "imdb_id": "tt4925000", + "name": "Descendants of the Sun", + "type": "series", + "year": "2016" + }, + { + "_id": "588b6ae11635517fbf56aa12", + "imdb_id": "tt0085050", + "name": "Mama's Family", + "type": "series", + "year": "1983–1990" + }, + { + "_id": "5c0d7d49173739c9f49b2824", + "imdb_id": "tt0058829", + "name": "Mister Roberts", + "type": "series", + "year": "1965–" + }, + { + "_id": "55075d8a711bd19c92addee1", + "imdb_id": "tt2250034", + "name": "Kokoro Connect", + "year": "2012", + "type": "series" + }, + { + "_id": "53677f07847ccc8123a18275", + "imdb_id": "tt0057773", + "name": "The Munsters", + "type": "series", + "year": "1964–1966" + }, + { + "_id": "5fa9107e542425334132c8be", + "imdb_id": "tt11273012", + "name": "Bruh", + "type": "series", + "year": "2019–" + }, + { + "_id": "5c0f1eeb173739c9f463089a", + "imdb_id": "tt1577461", + "name": "So You Think You Can Dance", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677f66847ccc8123a229f5", + "imdb_id": "tt2741950", + "name": "Enlisted", + "type": "series", + "year": "2014" + }, + { + "_id": "5c1ac922173739c9f42d0260", + "imdb_id": "tt7187044", + "name": "City on a Hill", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "610aa58264ec43ef9837a607", + "imdb_id": "tt10516496", + "name": "Chip 'N' Dale: Park Life", + "type": "series", + "year": "2021–" + }, + { + "_id": "55435a0cb0c9284285038c9c", + "imdb_id": "tt4009874", + "name": "Souten Kouro (Los Tres Reinos)", + "year": "2009–", + "type": "series" + }, + { + "_id": "55075f80711bd19c92ade17e", + "imdb_id": "tt1300170", + "name": "Xam'd: Lost Memories", + "year": "2008–", + "type": "series" + }, + { + "_id": "55075da7711bd19c92addffc", + "imdb_id": "tt3052798", + "name": "Packages from Planet X", + "year": "2013–2014", + "type": "series" + }, + { + "_id": "53677f17847ccc8123a1ab33", + "imdb_id": "tt3010520", + "name": "Turbo FAST", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677f7c847ccc8123a23f02", + "imdb_id": "tt2628232", + "name": "Penny Dreadful", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "53677f21847ccc8123a1cb0d", + "imdb_id": "tt0119189", + "name": "George Wallace", + "type": "series", + "year": "1997" + }, + { + "_id": "53677f19847ccc8123a1b34d", + "imdb_id": "tt0098948", + "name": "Wings", + "type": "series", + "year": "1990–1997" + }, + { + "_id": "5a4edf70543165dcd88c09a6", + "imdb_id": "tt7369770", + "type": "series", + "name": "Ellen's Game of Games", + "year": "2017–2021" + }, + { + "_id": "53677f19847ccc8123a1b367", + "imdb_id": "tt0182621", + "name": "The PJs", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "5c3a4c83d582b257561cef51", + "imdb_id": "tt0320053", + "name": "Life with Bonnie", + "type": "series", + "year": "2002–2004" + }, + { + "_id": "60c7e0fc64ec43ef9864fce1", + "imdb_id": "tt9257258", + "name": "Kevin Can F**k Himself", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677efd847ccc8123a1548d", + "imdb_id": "tt0278191", + "name": "Fear Factor", + "type": "series", + "year": "2001–2012" + }, + { + "_id": "53677f00847ccc8123a165bf", + "imdb_id": "tt1442552", + "name": "The Marriage Ref", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c252913173739c9f4ba592b", + "imdb_id": "tt0305051", + "name": "Kiteretsu Daihyakka", + "type": "series", + "year": "1988–1996" + }, + { + "_id": "5c170798173739c9f48ccf26", + "imdb_id": "tt3673480", + "name": "The Good Lord Bird", + "type": "series", + "year": "2020" + }, + { + "_id": "53677f08847ccc8123a184ee", + "imdb_id": "tt0044283", + "name": "My Little Margie", + "type": "series", + "year": "1952–1955" + }, + { + "_id": "5b90fde4173739c9f47cfb90", + "imdb_id": "tt0369081", + "name": "Ask This Old House", + "type": "series", + "year": "2002–" + }, + { + "_id": "551ad00bcc9eee85bb52dfa9", + "imdb_id": "tt1137419", + "name": "The Alan Titchmarsh Show", + "year": "2007–2014", + "type": "series" + }, + { + "_id": "53677f47847ccc8123a2014b", + "imdb_id": "tt0346314", + "name": "Ghost in the Shell: Stand Alone Complex", + "type": "series", + "year": "2002–2005" + }, + { + "_id": "53677f25847ccc8123a1d68a", + "imdb_id": "tt1739796", + "name": "My Bride Is a Mermaid", + "type": "series", + "year": "2007" + }, + { + "_id": "592ddcb01635517fbf56e8a0", + "imdb_id": "tt5014882", + "name": "The Durrells", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "53677eff847ccc8123a15dfd", + "imdb_id": "tt0052463", + "name": "The Detectives", + "type": "series", + "year": "1959–1962" + }, + { + "_id": "53677f57847ccc8123a217e3", + "imdb_id": "tt0115674", + "name": "BeetleBorgs", + "type": "series", + "year": "1996–1998" + }, + { + "_id": "53677f02847ccc8123a16cd9", + "imdb_id": "tt0203254", + "name": "Franklin", + "type": "series", + "year": "1997–2006" + }, + { + "_id": "626755e764ec43ef989fef86", + "imdb_id": "tt14192504", + "name": "We Own This City", + "type": "series", + "year": "2022" + }, + { + "_id": "53ac6496a8f27b1bb90b2fc7", + "imdb_id": "tt2084712", + "name": "Young & Hungry", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "55075d31711bd19c92addb83", + "imdb_id": "tt0132652", + "name": "Buffalo Bill, Jr.", + "year": "1955–1956", + "type": "series" + }, + { + "_id": "5c583dd3d582b25756134de1", + "imdb_id": "tt0928095", + "name": "Kiba", + "type": "series", + "year": "2006–2007" + }, + { + "_id": "55353f1bcc9eee85bb52e700", + "imdb_id": "tt1161684", + "name": "Rosario + Vampire", + "year": "2008", + "type": "series" + }, + { + "_id": "55197ffacc9eee85bb52dd20", + "imdb_id": "tt1821149", + "name": "#DUPE#", + "year": "2008", + "type": "series" + }, + { + "_id": "5c1bce49173739c9f4f194af", + "imdb_id": "tt5897818", + "name": "Days", + "type": "series", + "year": "2016" + }, + { + "_id": "5c5c61e2d582b25756a15462", + "imdb_id": "tt0101111", + "name": "Good Sports", + "type": "series", + "year": "1991–" + }, + { + "_id": "5b8e9330173739c9f47d6733", + "imdb_id": "tt5057054", + "name": "Tom Clancy's Jack Ryan", + "type": "series", + "year": "2018–2023" + }, + { + "_id": "619d0c7d64ec43ef983fc3d0", + "imdb_id": "tt15766736", + "name": "The Center Seat: 55 Years of Star Trek", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "5c1bb80c173739c9f4c66c58", + "imdb_id": "tt0101187", + "name": "The Royal Family", + "type": "series", + "year": "1991–1992" + }, + { + "_id": "5e3cfaa6c4ccb5dd9299e5b5", + "imdb_id": "tt9686380", + "name": "Indebted", + "type": "series", + "year": "2020" + }, + { + "_id": "5c0bef15173739c9f4c68dbc", + "imdb_id": "tt1312171", + "name": "The Umbrella Academy", + "type": "series", + "year": "2019–2024" + }, + { + "_id": "53677efd847ccc8123a15530", + "imdb_id": "tt0075488", + "name": "CHiPs", + "type": "series", + "year": "1977–1983" + }, + { + "_id": "542d1638a8f27b1bb90cf498", + "imdb_id": "tt0075473", + "name": "The All-New Super Friends Hour", + "type": "series", + "year": "1977–1978" + }, + { + "_id": "6296ced564ec43ef98a78c9a", + "imdb_id": "tt13475676", + "name": "Tom Swift", + "type": "series", + "year": "2022" + }, + { + "_id": "5c1442ac173739c9f4a64b37", + "imdb_id": "tt6905542", + "name": "The Dark Crystal: Age of Resistance", + "type": "series", + "year": "2019" + }, + { + "_id": "53677f60847ccc8123a22309", + "imdb_id": "tt0775407", + "name": "Wonder Pets!", + "type": "series", + "year": "2006–2016" + }, + { + "_id": "5c493c4ed582b257567380aa", + "imdb_id": "tt0066716", + "name": "The Smith Family", + "type": "series", + "year": "1971–1972" + }, + { + "_id": "5c60cabed582b25756b5a1be", + "imdb_id": "tt2388184", + "name": "Zyuden Sentai Kyoryuger", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "53677f02847ccc8123a16853", + "imdb_id": "tt1299729", + "name": "Delocated", + "type": "series", + "year": "2009–2013" + }, + { + "_id": "5c0c7b6d173739c9f4dad095", + "imdb_id": "tt5603356", + "name": "Ace Attorney", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "55912f26bf6c900d183846c3", + "imdb_id": "tt4677846", + "name": "Lost in Oz", + "year": "2015–2018", + "type": "series" + }, + { + "_id": "53677f4a847ccc8123a205c9", + "imdb_id": "tt0853174", + "name": "Gogoriki", + "type": "series", + "year": "2003–2012" + }, + { + "_id": "53677efd847ccc8123a15889", + "imdb_id": "tt1592254", + "name": "The Defenders", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5c09a793173739c9f4c8318a", + "imdb_id": "tt3644692", + "name": "Banshee Origins", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "6096df0364ec43ef98e3e099", + "imdb_id": "tt13851958", + "name": "Vivy: Fluorite Eye's Song", + "type": "series", + "year": "2021" + }, + { + "_id": "53677f74847ccc8123a2377d", + "imdb_id": "tt0127569", + "name": "Ghostbusters", + "type": "series", + "year": "1986–1987" + }, + { + "_id": "5834f3b3b0a40c25066d27c6", + "imdb_id": "tt6233538", + "name": "Roman Empire", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "53677efc847ccc8123a14f19", + "imdb_id": "tt1596786", + "name": "American Pickers", + "type": "series", + "year": "2010–" + }, + { + "_id": "5bbf2acd173739c9f4b74912", + "imdb_id": "tt7414406", + "name": "All American", + "type": "series", + "year": "2018–" + }, + { + "_id": "54fb5f34711bd19c92ad435d", + "imdb_id": "tt0816401", + "name": "The Replacements", + "year": "2006–2022", + "type": "series" + }, + { + "_id": "595803361635517fbf56e93d", + "imdb_id": "tt5936448", + "name": "Riviera", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "5c0cdc9e173739c9f457ca8c", + "imdb_id": "tt6256484", + "name": "While You Were Sleeping", + "type": "series", + "year": "2017" + }, + { + "_id": "6226108d64ec43ef986638ba", + "imdb_id": "tt14819828", + "name": "Business Proposal", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f1c847ccc8123a1bb13", + "imdb_id": "tt2177954", + "name": "Polar Bear's Café", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "6528b9f6bd36726cbb286505", + "imdb_id": "tt13911628", + "name": "Lessons in Chemistry", + "type": "series", + "year": "2023" + }, + { + "_id": "5d680182c4ccb5dd92ac0aad", + "imdb_id": "tt8107988", + "name": "Carole & Tuesday", + "type": "series", + "year": "2019" + }, + { + "_id": "53677efd847ccc8123a15896", + "imdb_id": "tt0080240", + "name": "Magnum, P.I.", + "type": "series", + "year": "1980–1988" + }, + { + "_id": "5c19bf45173739c9f43fdc0b", + "imdb_id": "tt4903514", + "name": "Inside the Factory", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677f18847ccc8123a1b081", + "imdb_id": "tt0075512", + "name": "Grange Hill", + "type": "series", + "year": "1978–2008" + }, + { + "_id": "658d01bfbd36726cbbc37a05", + "imdb_id": "tt3881914", + "name": "Blossoms Shanghai", + "type": "series", + "year": "2023–" + }, + { + "_id": "541463a1a8f27b1bb90c9987", + "imdb_id": "tt1745240", + "name": "Kimi ni Todoke: From Me to You", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "53677f4f847ccc8123a20d98", + "imdb_id": "tt1215996", + "name": "Blassreiter", + "type": "series", + "year": "2008" + }, + { + "_id": "615fb03764ec43ef98616c1a", + "imdb_id": "tt11379026", + "name": "Ghosts", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f0c847ccc8123a19371", + "imdb_id": "tt0054572", + "name": "Top Cat", + "type": "series", + "year": "1961–1962" + }, + { + "_id": "6118d71864ec43ef9881dfb1", + "imdb_id": "tt12779780", + "name": "Fena: Pirate Princess", + "type": "series", + "year": "2021" + }, + { + "_id": "53677f05847ccc8123a179fb", + "imdb_id": "tt1996607", + "name": "Dream High", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "53677f05847ccc8123a17985", + "imdb_id": "tt1190931", + "name": "American Greed", + "type": "series", + "year": "2007–2023" + }, + { + "_id": "6102ee7964ec43ef98f489a9", + "imdb_id": "tt13409388", + "name": "The Idaten Deities Know Only Peace", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f7b847ccc8123a23d3e", + "imdb_id": "tt0147772", + "name": "Here's Boomer", + "type": "series", + "year": "1980–1982" + }, + { + "_id": "63ba8c7464ec43ef98d3cd2f", + "imdb_id": "tt25809288", + "name": "The Reincarnation of the Strongest Exorcist in Another World", + "type": "series", + "year": "2023" + }, + { + "_id": "637b5aa164ec43ef9805810b", + "imdb_id": "tt18335752", + "name": "1923", + "type": "series", + "year": "2022–2023" + }, + { + "_id": "53677f2c847ccc8123a1e27f", + "imdb_id": "tt2433738", + "name": "Wentworth", + "type": "series", + "year": "2013–2021" + }, + { + "_id": "5aa7ceb453336c1ba8b1d7be", + "imdb_id": "tt6987788", + "type": "series", + "name": "Nailed It!", + "year": "2018–" + }, + { + "_id": "53677f0a847ccc8123a1871d", + "imdb_id": "tt0115378", + "name": "Superman: The Animated Series", + "type": "series", + "year": "1996–2000" + }, + { + "_id": "58cf9c791635517fbf56e636", + "imdb_id": "tt1984119", + "name": "Feud", + "type": "series", + "year": "2017–" + }, + { + "_id": "53677f07847ccc8123a17e4c", + "imdb_id": "tt0965404", + "name": "Bubble Guppies", + "type": "series", + "year": "2011–2023" + }, + { + "_id": "53677f4a847ccc8123a2044f", + "imdb_id": "tt0278876", + "name": "The Saddle Club", + "type": "series", + "year": "2001–2009" + }, + { + "_id": "59e07530067c465210c4381c", + "imdb_id": "tt5290382", + "type": "series", + "name": "Mindhunter", + "year": "2017–2019" + }, + { + "_id": "5c111f17173739c9f4dc7ef5", + "imdb_id": "tt8086718", + "name": "Grand Blue", + "type": "series", + "year": "2018" + }, + { + "_id": "5c28ca3d173739c9f4f7c484", + "imdb_id": "tt0991047", + "name": "Gun x Sword", + "type": "series", + "year": "2005" + }, + { + "_id": "6066ecbe5424253341069cce", + "imdb_id": "tt12677870", + "name": "Law & Order: Organized Crime", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c0b5539173739c9f4b752b9", + "imdb_id": "tt0200337", + "name": "Family Law", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5c19bf65173739c9f4401bf6", + "imdb_id": "tt8010544", + "name": "Persona 5: The Animation", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677f42847ccc8123a1fa4e", + "imdb_id": "tt0044263", + "name": "Four Star Playhouse", + "type": "series", + "year": "1952–1956" + }, + { + "_id": "53677f23847ccc8123a1cfde", + "imdb_id": "tt2022713", + "name": "Brickleberry", + "type": "series", + "year": "2012–2015" + }, + { + "_id": "53677ef9847ccc8123a138ce", + "imdb_id": "tt0248654", + "name": "Six Feet Under", + "type": "series", + "year": "2001–2005" + }, + { + "_id": "6263961c64ec43ef981d440f", + "imdb_id": "tt15527326", + "name": "The Creature Cases", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f04847ccc8123a173d3", + "imdb_id": "tt0058806", + "name": "Gidget", + "type": "series", + "year": "1965–1966" + }, + { + "_id": "53677f18847ccc8123a1b089", + "imdb_id": "tt0372650", + "name": "Cyborg 009", + "type": "series", + "year": "2001–2002" + }, + { + "_id": "53677efc847ccc8123a14fdf", + "imdb_id": "tt1591468", + "name": "Chaos", + "type": "series", + "year": "2011" + }, + { + "_id": "53677f00847ccc8123a16336", + "imdb_id": "tt1029248", + "name": "Moribito: Guardian of the Spirit", + "type": "series", + "year": "2007" + }, + { + "_id": "53677f35847ccc8123a1eb42", + "imdb_id": "tt0103559", + "name": "Street Sharks", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "5c2fe99a173739c9f4c205fe", + "imdb_id": "tt5724688", + "name": "Stolen Life", + "type": "series", + "year": "2016–" + }, + { + "_id": "608d0d4064ec43ef982f6c62", + "imdb_id": "tt14192040", + "name": "RuPaul's Drag Race Down Under", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677efd847ccc8123a15725", + "imdb_id": "tt0147746", + "name": "Batman Beyond", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "5c0b3544173739c9f48fdfca", + "imdb_id": "tt0066707", + "name": "Sabrina the Teenage Witch", + "type": "series", + "year": "1971–1974" + }, + { + "_id": "53677f72847ccc8123a23546", + "imdb_id": "tt0409637", + "name": "Washington Week", + "type": "series", + "year": "1967–" + }, + { + "_id": "55072f9c711bd19c92add931", + "imdb_id": "tt0111877", + "name": "Almost Perfect", + "year": "1995–1996", + "type": "series" + }, + { + "_id": "5c3a763dd582b2575636cc2e", + "imdb_id": "tt0042111", + "name": "The George Burns and Gracie Allen Show", + "type": "series", + "year": "1950–1958" + }, + { + "_id": "5c1f4513173739c9f408d02d", + "imdb_id": "tt4616700", + "name": "Ore Monogatari!!", + "type": "series", + "year": "2015" + }, + { + "_id": "5c0a90df173739c9f44d76aa", + "imdb_id": "tt5223426", + "name": "Food: Fact or Fiction?", + "type": "series", + "year": "2015–" + }, + { + "_id": "53677efc847ccc8123a15322", + "imdb_id": "tt0460637", + "name": "Everybody Hates Chris", + "type": "series", + "year": "2005–2024" + }, + { + "_id": "5672c5babb83c66498991c42", + "imdb_id": "tt4254242", + "name": "The Magicians", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "5a61ef23543165dcd87c3bd7", + "imdb_id": "tt5932548", + "type": "series", + "name": "Britannia", + "year": "2017–2021" + }, + { + "_id": "5c3d92bed582b25756dcdff0", + "imdb_id": "tt4219136", + "name": "THE IDOLM@STER CINDERELLA GIRLS", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677efd847ccc8123a159e7", + "imdb_id": "tt0063950", + "name": "Scooby Doo, Where Are You!", + "type": "series", + "year": "1969–1978" + }, + { + "_id": "5819ad5655f8aab460cfa87c", + "imdb_id": "tt0108755", + "name": "Duckman: Private Dick/Family Man", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677f74847ccc8123a2389b", + "imdb_id": "tt0065296", + "name": "The Goodies", + "type": "series", + "year": "1970–1982" + }, + { + "_id": "62aed4ed64ec43ef988dabee", + "imdb_id": "tt10011306", + "name": "Spriggan", + "type": "series", + "year": "2022" + }, + { + "_id": "5378cc70847ccc8123ad59b2", + "imdb_id": "tt0088500", + "name": "Count Duckula", + "type": "series", + "year": "1988–1993" + }, + { + "_id": "54d7b484e573cadcfa1fb288", + "imdb_id": "tt3488298", + "name": "American Crime", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "5a8ae9ce53336c1ba80f5241", + "imdb_id": "tt6317068", + "type": "series", + "name": "Final Space", + "year": "2018–2021" + }, + { + "_id": "5c1a41e3173739c9f41e5321", + "imdb_id": "tt8425308", + "name": "Magic for Humans", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "55075d6d711bd19c92addd0d", + "imdb_id": "tt2595486", + "name": "Love Live!: School Idol Project", + "year": "2013–2014", + "type": "series" + }, + { + "_id": "6433aad264ec43ef983f445f", + "imdb_id": "tt27404658", + "name": "The Aristocrat's Otherworldly Adventure: Serving Gods Who Go Too Far", + "type": "series", + "year": "2023" + }, + { + "_id": "53677f1a847ccc8123a1b6ee", + "imdb_id": "tt0142183", + "name": "Super Dimension Fortress Macross", + "type": "series", + "year": "1982–2002" + }, + { + "_id": "53677f05847ccc8123a17676", + "imdb_id": "tt0907702", + "name": "Wallander", + "type": "series", + "year": "2005–2013" + }, + { + "_id": "5c1e836a173739c9f4c736bb", + "imdb_id": "tt8310612", + "name": "The Other Two", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "5c0c5715173739c9f4a05212", + "imdb_id": "tt5637544", + "name": "Guidance", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "5c23bfc0173739c9f424a678", + "imdb_id": "tt0112193", + "name": "They Think It's All Over", + "type": "series", + "year": "1995–2011" + }, + { + "_id": "53677f4a847ccc8123a206be", + "imdb_id": "tt0094519", + "name": "The New Statesman", + "type": "series", + "year": "1987–1994" + }, + { + "_id": "607b6cd664ec43ef989e1461", + "imdb_id": "tt11945774", + "name": "Wahl Street", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677ef9847ccc8123a143be", + "imdb_id": "tt0090481", + "name": "Matlock", + "type": "series", + "year": "1986–1995" + }, + { + "_id": "5e9e7eda5424253341e6489b", + "imdb_id": "tt12057106", + "name": "Tower of God", + "type": "series", + "year": "2020" + }, + { + "_id": "53677f15847ccc8123a1a756", + "imdb_id": "tt1740718", + "name": "The Talk", + "type": "series", + "year": "2010–" + }, + { + "_id": "53677f5a847ccc8123a21b75", + "imdb_id": "tt1128052", + "name": "WordGirl", + "type": "series", + "year": "2007–2015" + }, + { + "_id": "53677f4a847ccc8123a206ab", + "imdb_id": "tt0047773", + "name": "Soldiers of Fortune", + "type": "series", + "year": "1955–1957" + }, + { + "_id": "5388b7bfa8f27b1bb90abf54", + "imdb_id": "tt2788780", + "name": "Undateable", + "type": "series", + "year": "2014–2016" + }, + { + "_id": "54fb5f50711bd19c92ad445a", + "imdb_id": "tt3062788", + "name": "Kate and Mim-Mim", + "year": "2014–", + "type": "series" + }, + { + "_id": "53677f57847ccc8123a21623", + "imdb_id": "tt0061280", + "name": "The Mothers-In-Law", + "type": "series", + "year": "1967–1969" + }, + { + "_id": "5c0a619f173739c9f4f53c0c", + "imdb_id": "tt6901486", + "name": "Seven Mortal Sins", + "type": "series", + "year": "2017" + }, + { + "_id": "53677f0c847ccc8123a1928a", + "imdb_id": "tt0083483", + "name": "St. Elsewhere", + "type": "series", + "year": "1982–1988" + }, + { + "_id": "57e09487d7e54929823e5b55", + "imdb_id": "tt5462720", + "type": "series", + "name": "Kevin Can Wait", + "year": "2016–2018" + }, + { + "_id": "5c037f30173739c9f402585f", + "imdb_id": "tt7645192", + "name": "Baby", + "type": "series", + "year": "2018–2020" + }, + { + "_id": "5c16c760173739c9f4212daa", + "imdb_id": "tt7005920", + "name": "Ready, Steady, Wiggle!", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "53677f54847ccc8123a213d1", + "imdb_id": "tt0111932", + "name": "Cybill", + "type": "series", + "year": "1995–1998" + }, + { + "_id": "5c206db4173739c9f42c3611", + "imdb_id": "tt0051283", + "name": "The Huckleberry Hound Show", + "type": "series", + "year": "1958–1962" + }, + { + "_id": "542d1638a8f27b1bb90cf4b4", + "imdb_id": "tt3640276", + "name": "The Brokenwood Mysteries", + "type": "series", + "year": "2014–" + }, + { + "_id": "53677f0a847ccc8123a1887f", + "imdb_id": "tt0052472", + "name": "Hawaiian Eye", + "type": "series", + "year": "1959–1963" + }, + { + "_id": "5c153e69173739c9f45272cd", + "imdb_id": "tt8236528", + "name": "Wok of Love", + "type": "series", + "year": "2018" + }, + { + "_id": "5c32bacd173739c9f4bd72da", + "imdb_id": "tt0353078", + "name": "The Monkey King", + "type": "series", + "year": "2002–" + }, + { + "_id": "633f29d464ec43ef98c138cb", + "imdb_id": "tt14367168", + "name": "Let the Right One In", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f40847ccc8123a1f543", + "imdb_id": "tt1723760", + "name": "Dallas", + "type": "series", + "year": "2012–2014" + }, + { + "_id": "53677f17847ccc8123a1b026", + "imdb_id": "tt0138956", + "name": "Beyond Belief: Fact or Fiction", + "type": "series", + "year": "1997–2024" + }, + { + "_id": "635678bd64ec43ef98ddf7a6", + "imdb_id": "tt16358384", + "name": "Tulsa King", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c11d797173739c9f4551f61", + "imdb_id": "tt8269398", + "name": "Come and Hug Me", + "type": "series", + "year": "2018" + }, + { + "_id": "53c6f7daa8f27b1bb90b80ed", + "imdb_id": "tt0115275", + "name": "Moesha", + "type": "series", + "year": "1996–2001" + }, + { + "_id": "53677ef9847ccc8123a13802", + "imdb_id": "tt1582350", + "name": "Episodes", + "type": "series", + "year": "2011–2017" + }, + { + "_id": "53677f04847ccc8123a17517", + "imdb_id": "tt0908454", + "name": "Gavin & Stacey", + "type": "series", + "year": "2007–2019" + }, + { + "_id": "5c0c43e0173739c9f4779b88", + "imdb_id": "tt0080199", + "name": "The Big Show", + "type": "series", + "year": "1980" + }, + { + "_id": "53677f17847ccc8123a1ae5b", + "imdb_id": "tt0061281", + "name": "Mr. Terrific", + "type": "series", + "year": "1966–1967" + }, + { + "_id": "53677f14847ccc8123a1a55b", + "imdb_id": "tt0081831", + "name": "Bergerac", + "type": "series", + "year": "1981–1991" + }, + { + "_id": "53677ef9847ccc8123a13c13", + "imdb_id": "tt1703925", + "name": "Wilfred", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "53677efa847ccc8123a148a2", + "imdb_id": "tt0112175", + "name": "Spider-Man: The Animated Series", + "type": "series", + "year": "1994–1998" + }, + { + "_id": "62ef55dd64ec43ef9854868d", + "imdb_id": "tt15303180", + "name": "Lang leve de liefde", + "type": "series", + "year": "2020–" + }, + { + "_id": "568fc965bb83c664989bf8d1", + "imdb_id": "tt4118584", + "name": "Shades of Blue", + "year": "2016–2018", + "type": "series" + }, + { + "_id": "53677f00847ccc8123a167a1", + "imdb_id": "tt0106115", + "name": "Rocko's Modern Life", + "type": "series", + "year": "1993–1996" + }, + { + "_id": "5c5a56add582b25756e49b52", + "imdb_id": "tt1132201", + "name": "Bokura no", + "type": "series", + "year": "2007" + }, + { + "_id": "53677f1f847ccc8123a1c493", + "imdb_id": "tt0085108", + "name": "We Got It Made", + "type": "series", + "year": "1983–1988" + }, + { + "_id": "53677f47847ccc8123a2016f", + "imdb_id": "tt0229889", + "name": "El Chavo del Ocho", + "type": "series", + "year": "1972–1983" + }, + { + "_id": "53677ef9847ccc8123a13c36", + "imdb_id": "tt0337792", + "name": "Wire in the Blood", + "type": "series", + "year": "2002–2008" + }, + { + "_id": "53677f5e847ccc8123a222e1", + "imdb_id": "tt1518542", + "name": "Sarabhai V/S Sarabhai", + "type": "series", + "year": "2004–2017" + }, + { + "_id": "59ca0bab1712e0f4ddef875f", + "imdb_id": "tt7305166", + "type": "series", + "name": "The Opposition with Jordan Klepper", + "year": "2017–2018" + }, + { + "_id": "53677f40847ccc8123a1f71a", + "imdb_id": "tt0050055", + "name": "The Restless Gun", + "type": "series", + "year": "1957–1959" + }, + { + "_id": "5c1c6da8173739c9f41c5a2f", + "imdb_id": "tt0374366", + "name": "Steve Harvey's Big Time Challenge", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "53677f2c847ccc8123a1e333", + "imdb_id": "tt2155025", + "name": "Please Like Me", + "type": "series", + "year": "2013–2016" + }, + { + "_id": "53677f29847ccc8123a1db40", + "imdb_id": "tt0108829", + "name": "Kommissar Rex", + "type": "series", + "year": "1994–2004" + }, + { + "_id": "55eefe62bf6c900d18416d94", + "imdb_id": "tt0108719", + "name": "Cardiac Arrest", + "year": "1994–1996", + "type": "series" + }, + { + "_id": "5507329e711bd19c92adda9b", + "imdb_id": "tt0202748", + "name": "Popular", + "year": "1999–2001", + "type": "series" + }, + { + "_id": "654632cbbd36726cbbdd8c01", + "imdb_id": "tt29366100", + "name": "Only for Love", + "type": "series", + "year": "2022–" + }, + { + "_id": "5c25f82c173739c9f40cc62e", + "imdb_id": "tt8372010", + "name": "Tsugumomo", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677f08847ccc8123a182fe", + "imdb_id": "tt0450357", + "name": "Wonder Showzen", + "type": "series", + "year": "2000–2007" + }, + { + "_id": "53677f08847ccc8123a18540", + "imdb_id": "tt0363328", + "name": "Drake & Josh", + "type": "series", + "year": "2004–2007" + }, + { + "_id": "622b5a2f64ec43ef981f39d2", + "imdb_id": "tt14432384", + "name": "Theodosia", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f00847ccc8123a163b1", + "imdb_id": "tt1685397", + "name": "Amagami SS", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "5503a5c4711bd19c92add623", + "imdb_id": "tt4354880", + "name": "Mr. Mercedes", + "year": "2017–2019", + "type": "series" + }, + { + "_id": "5a7ffb5b543165dcd86d63dc", + "imdb_id": "tt7369974", + "type": "series", + "name": "Step Up: High Water", + "year": "2018–2022" + }, + { + "_id": "5da69794c4ccb5dd92d36e05", + "imdb_id": "tt8289480", + "name": "Treadstone", + "type": "series", + "year": "2019" + }, + { + "_id": "5fbe747954242533417f160e", + "imdb_id": "tt11032396", + "name": "Saved by the Bell", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "554c85b816e3a4523a768a24", + "imdb_id": "tt4086030", + "name": "The Henry Ford Innovation Nation with Mo Rocca", + "year": "2014–", + "type": "series" + }, + { + "_id": "5c5dc9cbd582b257567b9905", + "imdb_id": "tt9615014", + "name": "Lego Masters", + "type": "series", + "year": "2020–" + }, + { + "_id": "5c32b5f2173739c9f4b78303", + "imdb_id": "tt8134186", + "name": "Devs", + "type": "series", + "year": "2020" + }, + { + "_id": "53677ef9847ccc8123a1420c", + "imdb_id": "tt1319598", + "name": "Meet the Browns", + "type": "series", + "year": "2009–2012" + }, + { + "_id": "5c291707173739c9f49170c0", + "imdb_id": "tt9458372", + "name": "Boogiepop and Others", + "type": "series", + "year": "2019" + }, + { + "_id": "5b49cd2b16f4806c2ac47c15", + "imdb_id": "tt5916218", + "type": "series", + "name": "Skylanders Academy", + "year": "2016–2018" + }, + { + "_id": "53677ef9847ccc8123a14363", + "imdb_id": "tt1112285", + "name": "Fear Itself", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "603dd0aa5424253341c8981f", + "imdb_id": "tt11640020", + "name": "Debris", + "type": "series", + "year": "2021" + }, + { + "_id": "654e010fbd36726cbb0ac369", + "imdb_id": "tt13623608", + "name": "The Curse", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c0a26e5173739c9f48ca2b3", + "imdb_id": "tt1074206", + "type": "series", + "name": "The Passage", + "year": "2019" + }, + { + "_id": "54fb899a711bd19c92ad483a", + "imdb_id": "tt0877507", + "name": "Buso Renkin", + "year": "2006–2007", + "type": "series" + }, + { + "_id": "5c17c1e7173739c9f4a539f1", + "imdb_id": "tt0108964", + "name": "Toen was geluk heel gewoon", + "type": "series", + "year": "1994–2009" + }, + { + "_id": "53677f17847ccc8123a1ac81", + "imdb_id": "tt0140644", + "name": "Space Battleship Yamato", + "type": "series", + "year": "1974–1975" + }, + { + "_id": "53677f4a847ccc8123a2066e", + "imdb_id": "tt0112196", + "name": "The Tick", + "type": "series", + "year": "1994–1997" + }, + { + "_id": "53677ef9847ccc8123a139aa", + "imdb_id": "tt0439100", + "name": "Weeds", + "type": "series", + "year": "2005–2012" + }, + { + "_id": "53677f15847ccc8123a1a6b9", + "imdb_id": "tt2560140", + "name": "Attack on Titan", + "type": "series", + "year": "2013–2023" + }, + { + "_id": "53677f5a847ccc8123a21bb3", + "imdb_id": "tt0280240", + "name": "The Big O", + "type": "series", + "year": "1999–2023" + }, + { + "_id": "54fb5f36711bd19c92ad4384", + "imdb_id": "tt0088507", + "name": "Dirty Pair", + "year": "1985–1988", + "type": "series" + }, + { + "_id": "54fb899a711bd19c92ad4837", + "imdb_id": "tt0185655", + "name": "Spaceketeers", + "year": "1978–1979", + "type": "series" + }, + { + "_id": "53677f2c847ccc8123a1e2df", + "imdb_id": "tt1494191", + "name": "The Untold History of the United States", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "53677ef9847ccc8123a13850", + "imdb_id": "tt1643266", + "name": "Ancient Aliens", + "type": "series", + "year": "2009–" + }, + { + "_id": "64bfd142bd36726cbbb78ef4", + "imdb_id": "tt21844490", + "name": "Dark Gathering", + "type": "series", + "year": "2023–" + }, + { + "_id": "589d216d1635517fbf56d91d", + "imdb_id": "tt5651762", + "name": "The Quad", + "type": "series", + "year": "2017–2018" + }, + { + "_id": "53677efd847ccc8123a15653", + "imdb_id": "tt0068049", + "name": "The Bob Newhart Show", + "type": "series", + "year": "1972–1978" + }, + { + "_id": "61630ae964ec43ef984ecdcd", + "imdb_id": "tt10635210", + "name": "Science Fell in Love, So I Tried to Prove It", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "53677ef9847ccc8123a1441c", + "imdb_id": "tt0475047", + "name": "Hotel Babylon", + "type": "series", + "year": "2006–2009" + }, + { + "_id": "54df8d6ce573cadcfa1fcf78", + "imdb_id": "tt3957196", + "name": "Yona of the Dawn", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "61de4d8364ec43ef98a58188", + "imdb_id": "tt13624900", + "name": "Naomi", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f1d847ccc8123a1bf0b", + "imdb_id": "tt0844203", + "name": "The One Show", + "type": "series", + "year": "2006–" + }, + { + "_id": "53677f0c847ccc8123a19175", + "imdb_id": "tt0094516", + "name": "My Secret Identity", + "type": "series", + "year": "1988–1991" + }, + { + "_id": "53677efa847ccc8123a14a2f", + "imdb_id": "tt1727434", + "name": "My Babysitter's a Vampire", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "60d964b964ec43ef980ffe62", + "imdb_id": "tt10199718", + "name": "Gold Diggers", + "type": "series", + "year": "2019–" + }, + { + "_id": "5bec7726173739c9f4624dbc", + "imdb_id": "tt7801780", + "name": "Origin", + "type": "series", + "year": "2018" + }, + { + "_id": "5c1b5ff5173739c9f4269ff6", + "imdb_id": "tt8199790", + "name": "Joe Pera Talks with You", + "type": "series", + "year": "2018–2021" + }, + { + "_id": "53677f23847ccc8123a1cf85", + "imdb_id": "tt2836308", + "name": "Adam Devine's House Party", + "type": "series", + "year": "2013–" + }, + { + "_id": "642874a864ec43ef988cba8e", + "imdb_id": "tt13911284", + "name": "Hell's Paradise: Jigokuraku", + "type": "series", + "year": "2023–" + }, + { + "_id": "536907e7847ccc8123acdcd7", + "imdb_id": "tt0139803", + "name": "Top of the Pops", + "type": "series", + "year": "1964–2022" + }, + { + "_id": "53677f12847ccc8123a19ecb", + "imdb_id": "tt0220880", + "name": "Courage the Cowardly Dog", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5c0db572173739c9f40d4aa6", + "imdb_id": "tt0098818", + "name": "Harry and the Hendersons", + "type": "series", + "year": "1991–1993" + }, + { + "_id": "5c601a59d582b25756b3bb23", + "imdb_id": "tt0069632", + "name": "Sigmund and the Sea Monsters", + "type": "series", + "year": "1973–1975" + }, + { + "_id": "551bcc58cc9eee85bb52e0cd", + "imdb_id": "tt2312036", + "name": "East Los High", + "year": "2013–2017", + "type": "series" + }, + { + "_id": "5f033fec5424253341e857c7", + "imdb_id": "tt12227418", + "name": "The God of High School", + "type": "series", + "year": "2020" + }, + { + "_id": "5c517344d582b25756201533", + "imdb_id": "tt0190897", + "name": "The All-New Popeye Hour", + "type": "series", + "year": "1978–1983" + }, + { + "_id": "54f466ac451edcfca9b1c576", + "imdb_id": "tt3516878", + "name": "Secrets and Lies", + "year": "2015–2016", + "type": "series" + }, + { + "_id": "5c1b07ed173739c9f4aba645", + "imdb_id": "tt5827092", + "name": "Macross Delta", + "type": "series", + "year": "2015–2016" + }, + { + "_id": "5c0b59d3173739c9f4bc9af3", + "imdb_id": "tt4046242", + "name": "Ai Tenchi Muyo!", + "type": "series", + "year": "2014" + }, + { + "_id": "53677efd847ccc8123a1547e", + "imdb_id": "tt0103466", + "name": "The Larry Sanders Show", + "type": "series", + "year": "1992–1998" + }, + { + "_id": "5c0c05ce173739c9f4f43989", + "imdb_id": "tt6157148", + "name": "Weightlifting Fairy Kim Bok-Joo", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "53677f1d847ccc8123a1be84", + "imdb_id": "tt0950721", + "name": "Back to You", + "type": "series", + "year": "2007–2008" + }, + { + "_id": "54cb9995e573cadcfa1f80a6", + "imdb_id": "tt3498622", + "name": "Fortitude", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "5c0a30dc173739c9f49d5318", + "imdb_id": "tt9059350", + "name": "Warrior Nun", + "type": "series", + "year": "2020–2022" + }, + { + "_id": "64313fb964ec43ef98f4ba6a", + "imdb_id": "tt14648592", + "name": "Magical Destroyers", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a137ab", + "imdb_id": "tt0840196", + "name": "Skins", + "type": "series", + "year": "2007–2013" + }, + { + "_id": "536907e6847ccc8123acdcce", + "imdb_id": "tt0205195", + "name": "Ladies Man", + "type": "series", + "year": "1999–2001" + }, + { + "_id": "6260f0b064ec43ef9844cf4d", + "imdb_id": "tt15791630", + "name": "The Kardashians", + "type": "series", + "year": "2022–" + }, + { + "_id": "53677f00847ccc8123a16501", + "imdb_id": "tt1842127", + "name": "Mortal Kombat: Legacy", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "53677f02847ccc8123a16d40", + "imdb_id": "tt0077064", + "name": "Prisoner", + "type": "series", + "year": "1979–1986" + }, + { + "_id": "5c119b62173739c9f4de0d70", + "imdb_id": "tt0075528", + "name": "Lou Grant", + "type": "series", + "year": "1977–1982" + }, + { + "_id": "5b1e9fff16f4806c2a295c8d", + "imdb_id": "tt7562112", + "type": "series", + "name": "Pose", + "year": "2018–2021" + }, + { + "_id": "5f0f08bc54242533419e3243", + "imdb_id": "tt9814116", + "name": "Brave New World", + "type": "series", + "year": "2020" + }, + { + "_id": "53677efa847ccc8123a14af1", + "imdb_id": "tt0103584", + "name": "X-Men: The Animated Series", + "type": "series", + "year": "1992–1997" + }, + { + "_id": "53677f66847ccc8123a229ab", + "imdb_id": "tt1675276", + "name": "Dan Vs.", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "53690806847ccc8123acdea0", + "imdb_id": "tt2127216", + "name": "Un-Go", + "type": "series", + "year": "2011" + }, + { + "_id": "53677f1d847ccc8123a1be14", + "imdb_id": "tt0118364", + "name": "Just Shoot Me!", + "type": "series", + "year": "1997–2003" + }, + { + "_id": "5e3cde70c4ccb5dd928c71aa", + "imdb_id": "tt10327412", + "name": "Tommy", + "type": "series", + "year": "2020" + }, + { + "_id": "53677f1b847ccc8123a1ba01", + "imdb_id": "tt2666270", + "name": "About a Boy", + "type": "series", + "year": "2014–2015" + }, + { + "_id": "53677f47847ccc8123a20181", + "imdb_id": "tt0050067", + "name": "The Thin Man", + "type": "series", + "year": "1957–1959" + }, + { + "_id": "5c277c8a173739c9f4bae84d", + "imdb_id": "tt5120600", + "name": "Danger & Eggs", + "type": "series", + "year": "2015–2017" + }, + { + "_id": "53677ef9847ccc8123a13cae", + "imdb_id": "tt0388595", + "name": "Extreme Makeover: Home Edition", + "type": "series", + "year": "2003–2020" + }, + { + "_id": "581246ced7e5492982414bcb", + "imdb_id": "tt3655448", + "name": "The Young Pope", + "type": "series", + "year": "2016" + }, + { + "_id": "5c143613173739c9f48ca042", + "imdb_id": "tt7056766", + "name": "Reunited Worlds", + "type": "series", + "year": "2017" + }, + { + "_id": "54fb8993711bd19c92ad4822", + "imdb_id": "tt0159883", + "name": "Patlabor: The TV Series", + "year": "1989–1990", + "type": "series" + }, + { + "_id": "612dc4b964ec43ef9806e79e", + "imdb_id": "tt12851524", + "name": "Only Murders in the Building", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f02847ccc8123a16bf6", + "imdb_id": "tt2654580", + "name": "Almost Human", + "type": "series", + "year": "2013–2014" + }, + { + "_id": "53677f71847ccc8123a234e8", + "imdb_id": "tt0324692", + "name": "Ant & Dec's Saturday Night Takeaway", + "type": "series", + "year": "2002–2023" + }, + { + "_id": "59c7a0eb1712e0f4dd3ca3b3", + "imdb_id": "tt6423364", + "type": "series", + "name": "Bad Blood", + "year": "2017–2018" + }, + { + "_id": "53677f08847ccc8123a182ef", + "imdb_id": "tt0235923", + "name": "Invader ZIM", + "type": "series", + "year": "2001–2006" + }, + { + "_id": "5c18e64c173739c9f48dfb97", + "imdb_id": "tt0417306", + "name": "CMT Crossroads", + "type": "series", + "year": "2002–" + }, + { + "_id": "53677efc847ccc8123a14fcd", + "imdb_id": "tt0238793", + "name": "Monarch of the Glen", + "type": "series", + "year": "2000–2005" + }, + { + "_id": "5c198d5b173739c9f4db45b4", + "imdb_id": "tt6562134", + "name": "VeggieTales in the City", + "type": "series", + "year": "2017" + }, + { + "_id": "55a648adbf6c900d183ad16c", + "imdb_id": "tt4731072", + "name": "Food Wars: Shokugeki no Soma", + "year": "2015–2020", + "type": "series" + }, + { + "_id": "5ef016445424253341d72e30", + "imdb_id": "tt2077823", + "name": "Perry Mason", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "5c1d4986173739c9f499861f", + "imdb_id": "tt0480499", + "name": "Team Galaxy", + "type": "series", + "year": "2006–2008" + }, + { + "_id": "5c0d7363173739c9f485ec8f", + "imdb_id": "tt1209393", + "name": "Vampire Knight", + "type": "series", + "year": "2008" + }, + { + "_id": "64c51881bd36726cbb3285b7", + "imdb_id": "tt11691774", + "name": "Only Murders in the Building", + "type": "series", + "year": "2021–" + }, + { + "_id": "5c1a8f6e173739c9f4b7b7f6", + "imdb_id": "tt0293994", + "name": "Zillion", + "type": "series", + "year": "1987" + }, + { + "_id": "53677ef9847ccc8123a13a86", + "imdb_id": "tt1297754", + "name": "Republic of Doyle", + "type": "series", + "year": "2010–2014" + }, + { + "_id": "5f548d0a542425334184b998", + "imdb_id": "tt10732104", + "name": "Power Book II: Ghost", + "type": "series", + "year": "2020–" + }, + { + "_id": "53677f09847ccc8123a185e1", + "imdb_id": "tt3443306", + "name": "The Qwaser of Stigmata II", + "type": "series", + "year": "2010–2011" + }, + { + "_id": "55075d8b711bd19c92addee2", + "imdb_id": "tt2250100", + "name": "The Ambition of Oda Nobuna", + "year": "2012–", + "type": "series" + }, + { + "_id": "5c1fa77c173739c9f4c70c8e", + "imdb_id": "tt0061294", + "name": "Shazzan", + "type": "series", + "year": "1967–1969" + }, + { + "_id": "5c4e6a36d582b257564a631c", + "imdb_id": "tt5363872", + "name": "Bajillion Dollar Propertie$", + "type": "series", + "year": "2016–2019" + }, + { + "_id": "5db1d4b1c4ccb5dd9278c022", + "imdb_id": "tt10752770", + "name": "Sistas", + "type": "series", + "year": "2019–" + }, + { + "_id": "5bf77c35173739c9f4a34c17", + "imdb_id": "tt6052530", + "name": "Quotidien", + "type": "series", + "year": "2016–" + }, + { + "_id": "53677f29847ccc8123a1de18", + "imdb_id": "tt2659152", + "name": "WWE Main Event", + "type": "series", + "year": "2012–" + }, + { + "_id": "5c152007173739c9f4119097", + "imdb_id": "tt7406334", + "name": "Black Monday", + "type": "series", + "year": "2019–2021" + }, + { + "_id": "5c60cab9d582b25756b59c1a", + "imdb_id": "tt0108880", + "name": "Ninja Sentai Kakuranger", + "type": "series", + "year": "1994–1995" + }, + { + "_id": "53677ef9847ccc8123a13cde", + "imdb_id": "tt0485301", + "name": "Torchwood", + "type": "series", + "year": "2006–2011" + }, + { + "_id": "5c52205bd582b257561d8a55", + "imdb_id": "tt9067020", + "name": "The I-Land", + "type": "series", + "year": "2019" + }, + { + "_id": "659e291fbd36726cbb9a8c21", + "imdb_id": "tt21088136", + "name": "Criminal Record", + "type": "series", + "year": "2024–" + }, + { + "_id": "5c30d477173739c9f450aaf3", + "imdb_id": "tt6283624", + "name": "Radio Star", + "type": "series", + "year": "2007–" + }, + { + "_id": "61ee0cfe64ec43ef9866f075", + "imdb_id": "tt11958610", + "name": "Trigger Point", + "type": "series", + "year": "2022–" + }, + { + "_id": "5887457a1635517fbf56a29d", + "imdb_id": "tt5339440", + "name": "One Day at a Time", + "type": "series", + "year": "2017–2020" + }, + { + "_id": "53677f40847ccc8123a1f5a7", + "imdb_id": "tt0218769", + "name": "I Am Weasel", + "type": "series", + "year": "1997–1999" + }, + { + "_id": "5c4d0f04d582b25756991874", + "imdb_id": "tt0387775", + "name": "Sakigake!! Cromartie Kôkô", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "62cd94c264ec43ef980ddedd", + "imdb_id": "tt18561422", + "name": "Vermeil in Gold: A Desperate Magician Barges Into the Magical World Alongside the Strongest Calamity", + "type": "series", + "year": "2022" + }, + { + "_id": "53677f54847ccc8123a2139e", + "imdb_id": "tt0052441", + "name": "The Alaskans", + "type": "series", + "year": "1959–1960" + }, + { + "_id": "5c45a8f6d582b2575698fabd", + "imdb_id": "tt8026448", + "name": "Tacoma FD", + "type": "series", + "year": "2019–" + }, + { + "_id": "5c11cdae173739c9f444fb8c", + "imdb_id": "tt5743796", + "name": "Warrior", + "type": "series", + "year": "2019–2023" + }, + { + "_id": "5bfae6a8173739c9f43fcc53", + "imdb_id": "tt5830254", + "name": "Das Boot", + "type": "series", + "year": "2018–" + }, + { + "_id": "53677f19847ccc8123a1b3ec", + "imdb_id": "tt2402207", + "name": "The Last Ship", + "type": "series", + "year": "2014–2018" + }, + { + "_id": "53677f5a847ccc8123a21c2c", + "imdb_id": "tt0247087", + "name": "The District", + "type": "series", + "year": "2000–2004" + }, + { + "_id": "606da77e54242533412bd9f0", + "imdb_id": "tt12439466", + "name": "Love Is in the Air", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "5c61b465d582b25756c962ae", + "imdb_id": "tt1227046", + "name": "Shadow Star Narutaru", + "type": "series", + "year": "2003–" + }, + { + "_id": "57df8232d7e54929823e4cc2", + "imdb_id": "tt0310416", + "name": "Australian Survivor", + "year": "2002–", + "type": "series" + }, + { + "_id": "5446aeeda8f27b1bb90d5ee5", + "imdb_id": "tt2294048", + "name": "Blast of Tempest", + "type": "series", + "year": "2012–2013" + }, + { + "_id": "5c19f679173739c9f48edf4d", + "imdb_id": "tt9421868", + "name": "Selena: The Series", + "type": "series", + "year": "2020–2021" + }, + { + "_id": "6340ed2864ec43ef982ee380", + "imdb_id": "tt16098700", + "name": "Fire Country", + "type": "series", + "year": "2022–" + }, + { + "_id": "64cfc2e6bd36726cbb47fdc0", + "imdb_id": "tt27729024", + "name": "100 Years of Warner Bros.", + "type": "series", + "year": "2023" + }, + { + "_id": "5fc1a64254242533413b5e44", + "imdb_id": "tt13218362", + "name": "Kongen befaler", + "type": "series", + "year": "2019–" + }, + { + "_id": "53677ef9847ccc8123a13795", + "imdb_id": "tt1798274", + "name": "The Lying Game", + "type": "series", + "year": "2011–2013" + }, + { + "_id": "607720f964ec43ef980e4903", + "imdb_id": "tt13049906", + "name": "The Saint's Magic Power Is Omnipotent", + "type": "series", + "year": "2021–" + }, + { + "_id": "6221a86e64ec43ef98b220fe", + "imdb_id": "tt16350094", + "name": "The Boys Presents: Diabolical", + "type": "series", + "year": "2022" + }, + { + "_id": "542ed14ca8f27b1bb90cfc52", + "imdb_id": "tt0213377", + "name": "Widget, the World Watcher", + "type": "series", + "year": "1990–" + }, + { + "_id": "5b8e9330173739c9f47d687d", + "imdb_id": "tt6487482", + "name": "Insatiable", + "type": "series", + "year": "2018–2019" + }, + { + "_id": "53677f05847ccc8123a179aa", + "imdb_id": "tt1548669", + "name": "Gravity", + "type": "series", + "year": "2010" + }, + { + "_id": "5c0c6575173739c9f4be2989", + "imdb_id": "tt1208358", + "name": "Blade of the Immortal", + "type": "series", + "year": "2008" + }, + { + "_id": "53677ef9847ccc8123a139d2", + "imdb_id": "tt1319900", + "name": "Ghost Adventures", + "type": "series", + "year": "2008–" + }, + { + "_id": "53677f02847ccc8123a16931", + "imdb_id": "tt0044231", + "name": "Adventures of Superman", + "type": "series", + "year": "1952–1958" + }, + { + "_id": "5c4b86c1d582b2575694da43", + "imdb_id": "tt0462653", + "name": "Xabungle", + "type": "series", + "year": "1982–1983" + }, + { + "_id": "5c09b541173739c9f4e44eec", + "imdb_id": "tt0406429", + "name": "Law & Order: Trial by Jury", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "55fa7ed4bf6c900d1841f473", + "imdb_id": "tt4474310", + "name": "The Player", + "year": "2015", + "type": "series" + }, + { + "_id": "53677f22847ccc8123a1ce68", + "imdb_id": "tt0053522", + "name": "The Famous Adventures of Mr. Magoo", + "type": "series", + "year": "1964–1965" + }, + { + "_id": "5c223749173739c9f4499a9c", + "imdb_id": "tt1394286", + "name": "Chrome Shelled Regios", + "type": "series", + "year": "2009" + }, + { + "_id": "53677f32847ccc8123a1e83c", + "imdb_id": "tt0366027", + "name": "I'm with Her", + "type": "series", + "year": "2003–2004" + }, + { + "_id": "53677f6d847ccc8123a231a3", + "imdb_id": "tt0086727", + "name": "The Henderson Kids", + "type": "series", + "year": "1985–1986" + }, + { + "_id": "53677f0f847ccc8123a19c42", + "imdb_id": "tt0988820", + "name": "The Inspector Lynley Mysteries", + "type": "series", + "year": "2001–2007" + }, + { + "_id": "53677efe847ccc8123a15bcd", + "imdb_id": "tt0057729", + "name": "The Addams Family", + "type": "series", + "year": "1964–1966" + }, + { + "_id": "5c280129173739c9f4c67efc", + "imdb_id": "tt0159855", + "name": "Voltes Five", + "type": "series", + "year": "1977–1978" + }, + { + "_id": "53677f02847ccc8123a16f10", + "imdb_id": "tt1158671", + "name": "Spice and Wolf", + "type": "series", + "year": "2008–2009" + }, + { + "_id": "5c11319f173739c9f4019f94", + "imdb_id": "tt0217910", + "name": "The Amanda Show", + "type": "series", + "year": "1999–2002" + }, + { + "_id": "5c267179173739c9f4fcf689", + "imdb_id": "tt0925436", + "name": "Idaten Jump", + "type": "series", + "year": "2005–2006" + }, + { + "_id": "640f111c64ec43ef98a8e309", + "imdb_id": "tt9794044", + "name": "Citadel", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677ef9847ccc8123a13b51", + "imdb_id": "tt1319636", + "name": "Dark Blue", + "type": "series", + "year": "2009–2010" + }, + { + "_id": "5c243d18173739c9f41f7d23", + "imdb_id": "tt1639471", + "name": "Arakawa Under the Bridge", + "type": "series", + "year": "2010" + }, + { + "_id": "5c5335b7d582b257568d904d", + "imdb_id": "tt0045411", + "name": "The Man Behind the Badge", + "type": "series", + "year": "1953–1955" + }, + { + "_id": "53677ef9847ccc8123a13d7c", + "imdb_id": "tt0463827", + "name": "Mock the Week", + "type": "series", + "year": "2005–2022" + }, + { + "_id": "656b94d9bd36726cbb5c37ce", + "imdb_id": "tt28348835", + "name": "Castaway Diva", + "type": "series", + "year": "2023–" + }, + { + "_id": "53677f4a847ccc8123a206a1", + "imdb_id": "tt0411003", + "name": "LAX", + "type": "series", + "year": "2004–2005" + }, + { + "_id": "53677efa847ccc8123a14763", + "imdb_id": "tt1492966", + "name": "Louie", + "type": "series", + "year": "2010–2015" + }, + { + "_id": "53677f6f847ccc8123a232e2", + "imdb_id": "tt2322158", + "name": "Crisis", + "type": "series", + "year": "2014" + }, + { + "_id": "5ff5b9b9542425334178ada9", + "imdb_id": "tt13273826", + "name": "The Uncanny Counter", + "type": "series", + "year": "2020–2023" + }, + { + "_id": "53677eff847ccc8123a160df", + "imdb_id": "tt0144069", + "name": "Street Fighter II: V", + "type": "series", + "year": "1995" + }, + { + "_id": "53677f72847ccc8123a23535", + "imdb_id": "tt3496994", + "name": "Saint George", + "type": "series", + "year": "2014" + }, + { + "_id": "53677f12847ccc8123a19eac", + "imdb_id": "tt3322312", + "name": "Daredevil", + "type": "series", + "year": "2015–2018" + }, + { + "_id": "5c0f2328173739c9f46b3c8e", + "imdb_id": "tt8434720", + "name": "A Love So Beautiful", + "type": "series", + "year": "2017" + }, + { + "_id": "55c4bfcbbf6c900d183cce55", + "imdb_id": "tt4680240", + "name": "Club de Cuervos", + "year": "2015–2019", + "type": "series" + }, + { + "_id": "5d970f2bc4ccb5dd92b1d1bb", + "imdb_id": "tt7826108", + "name": "Raising Dion", + "type": "series", + "year": "2019–2022" + }, + { + "_id": "53677f1f847ccc8123a1c583", + "imdb_id": "tt0398617", + "name": "Zoids: Fuzors", + "type": "series", + "year": "2003–2005" + }, + { + "_id": "60b1319564ec43ef9886c1c6", + "imdb_id": "tt13405062", + "name": "Back Arrow", + "type": "series", + "year": "2021" + }, + { + "_id": "53677f6f847ccc8123a232f0", + "imdb_id": "tt0165592", + "name": "Play for Today", + "type": "series", + "year": "1970–1984" + }, + { + "_id": "53677eff847ccc8123a15e3f", + "imdb_id": "tt0391666", + "name": "Morangos com Açúcar", + "type": "series", + "year": "2003–2012" + }, + { + "_id": "5c2f4b1b173739c9f47d32a7", + "imdb_id": "tt0081852", + "name": "Dr. Slump", + "type": "series", + "year": "1981–1986" + }, + { + "_id": "633ac17764ec43ef984143e2", + "imdb_id": "tt14932528", + "name": "Don't Hug Me I'm Scared", + "type": "series", + "year": "2022–" + }, + { + "_id": "54fdec2d711bd19c92adc454", + "imdb_id": "tt0985492", + "name": "Toward the Terra", + "year": "2007", + "type": "series" + }, + { + "_id": "53677f6d847ccc8123a23279", + "imdb_id": "tt2832756", + "name": "Love Child", + "type": "series", + "year": "2014–2017" + }, + { + "_id": "5a28ce05543165dcd8fa10ce", + "imdb_id": "tt2452242", + "type": "series", + "name": "Happy!", + "year": "2017–2019" + }, + { + "_id": "53677f1e847ccc8123a1c1e7", + "imdb_id": "tt0096531", + "name": "Alien Nation", + "type": "series", + "year": "1989–1990" + }, + { + "_id": "583c367cb0a40c25066d909f", + "imdb_id": "tt4659174", + "name": "Ice", + "type": "series", + "year": "2016–" + }, + { + "_id": "615dceeb64ec43ef98f26ff9", + "imdb_id": "tt13483212", + "name": "Banished from the Hero's Party, I Decided to Live a Quiet Life in the Countryside", + "type": "series", + "year": "2021–" + }, + { + "_id": "57fdd0a1d7e54929823ff76d", + "imdb_id": "tt4422756", + "name": "The Real O'Neals", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "5c2ba894173739c9f412e5a9", + "imdb_id": "tt6220550", + "name": "Hip Whip Girl: Keijo!!!!!!", + "type": "series", + "year": "2016–2017" + }, + { + "_id": "65299b4ebd36726cbb6b953e", + "imdb_id": "tt28774702", + "name": "The Kingdoms of Ruin", + "type": "series", + "year": "2023–" + }, + { + "_id": "5c251eb0173739c9f4a41061", + "imdb_id": "tt2374683", + "name": "Empresses in the Palace", + "type": "series", + "year": "2011–2012" + }, + { + "_id": "5c2bc2cc173739c9f44b39b4", + "imdb_id": "tt0111994", + "name": "Hang Time", + "type": "series", + "year": "1995–2000" + }, + { + "_id": "53677efa847ccc8123a145d2", + "imdb_id": "tt1149608", + "name": "Being Erica", + "type": "series", + "year": "2009–2011" + }, + { + "_id": "5c0c5f3c173739c9f4b14ebe", + "imdb_id": "tt0103463", + "name": "Dinosaur Squadron Zyuranger", + "type": "series", + "year": "1992–1993" + }, + { + "_id": "6097841c64ec43ef98d506c7", + "imdb_id": "tt13362302", + "name": "Shadows House", + "type": "series", + "year": "2021–2022" + }, + { + "_id": "53677ef9847ccc8123a13fe5", + "imdb_id": "tt1741256", + "name": "Suburgatory", + "type": "series", + "year": "2011–2014" + }, + { + "_id": "536907e9847ccc8123acdd3d", + "imdb_id": "tt0065317", + "name": "McCloud", + "type": "series", + "year": "1970–1977" + }, + { + "_id": "617241b264ec43ef9892f305", + "imdb_id": "tt9737326", + "name": "Invasion", + "type": "series", + "year": "2021–" + }, + { + "_id": "53677f0f847ccc8123a19871", + "imdb_id": "tt0203248", + "name": "Bad Girls", + "type": "series", + "year": "1999–2006" + }, + { + "_id": "53677efd847ccc8123a15695", + "imdb_id": "tt0273026", + "name": "Timewatch", + "type": "series", + "year": "1982–" + }, + { + "_id": "53677f4f847ccc8123a20d55", + "imdb_id": "tt0291672", + "name": "Time Squad", + "type": "series", + "year": "2001–2003" + } + ] +} \ No newline at end of file diff --git a/src/node/consumer/test/assets/flash-episode-list.json b/src/node/consumer/test/assets/flash-episode-list.json new file mode 100644 index 0000000..0b4878e --- /dev/null +++ b/src/node/consumer/test/assets/flash-episode-list.json @@ -0,0 +1,232 @@ +{ + "meta": { + "status": "Ended", + "videos": [ + { + "name": "Pilot", + "season": 1, + "number": 0, + "firstAired": "1990-09-20T00:00:00.000Z", + "rating": "6.6", + "id": "tt0098798:1:0", + "overview": "", + "imdb_id": "tt0099580" + }, + { + "name": "Out of Control", + "season": 1, + "number": 1, + "firstAired": "1990-09-26T00:00:00.000Z", + "rating": "6.8", + "id": "tt0098798:1:1", + "overview": "", + "imdb_id": "tt0579962" + }, + { + "name": "Watching the Detectives", + "season": 1, + "number": 2, + "firstAired": "1990-10-17T00:00:00.000Z", + "rating": "6.9", + "id": "tt0098798:1:2", + "overview": "", + "imdb_id": "tt0579971" + }, + { + "name": "Honor Among Thieves", + "season": 1, + "number": 3, + "firstAired": "1990-10-25T00:00:00.000Z", + "rating": "6.8", + "id": "tt0098798:1:3", + "overview": "", + "imdb_id": "tt0579961" + }, + { + "name": "Double Vision", + "season": 1, + "number": 4, + "firstAired": "1990-11-01T00:00:00.000Z", + "rating": "6.6", + "id": "tt0098798:1:4", + "overview": "", + "imdb_id": "tt0579957" + }, + { + "name": "Sins of the Father", + "season": 1, + "number": 5, + "firstAired": "1990-11-08T00:00:00.000Z", + "rating": "6.9", + "id": "tt0098798:1:5", + "overview": "", + "imdb_id": "tt0579965" + }, + { + "name": "Child's Play", + "season": 1, + "number": 6, + "firstAired": "1990-11-15T00:00:00.000Z", + "rating": "6.8", + "id": "tt0098798:1:6", + "overview": "", + "imdb_id": "tt0579955" + }, + { + "name": "Shroud of Death", + "season": 1, + "number": 7, + "firstAired": "1990-11-29T00:00:00.000Z", + "rating": "7.1", + "id": "tt0098798:1:7", + "overview": "", + "imdb_id": "tt0579963" + }, + { + "name": "Ghost in the Machine", + "season": 1, + "number": 8, + "firstAired": "1990-12-13T00:00:00.000Z", + "rating": "7.7", + "id": "tt0098798:1:8", + "overview": "", + "imdb_id": "tt0579959" + }, + { + "name": "Sight Unseen", + "season": 1, + "number": 9, + "firstAired": "1991-01-10T00:00:00.000Z", + "rating": "7", + "id": "tt0098798:1:9", + "overview": "", + "imdb_id": "tt0579964" + }, + { + "name": "Beat the Clock", + "season": 1, + "number": 10, + "firstAired": "1991-01-31T00:00:00.000Z", + "rating": "7", + "id": "tt0098798:1:10", + "overview": "", + "imdb_id": "tt0579953" + }, + { + "name": "The Trickster", + "season": 1, + "number": 11, + "firstAired": "1991-02-07T00:00:00.000Z", + "rating": "7.7", + "id": "tt0098798:1:11", + "overview": "", + "imdb_id": "tt0579969" + }, + { + "name": "Tina, Is That You?", + "season": 1, + "number": 12, + "firstAired": "1991-02-14T00:00:00.000Z", + "rating": "6.8", + "id": "tt0098798:1:12", + "overview": "", + "imdb_id": "tt0579967" + }, + { + "name": "Be My Baby", + "season": 1, + "number": 13, + "firstAired": "1991-02-20T00:00:00.000Z", + "rating": "6.5", + "id": "tt0098798:1:13", + "overview": "", + "imdb_id": "tt0579952" + }, + { + "name": "Fast Forward", + "season": 1, + "number": 14, + "firstAired": "1991-02-27T00:00:00.000Z", + "rating": "7.9", + "id": "tt0098798:1:14", + "overview": "", + "imdb_id": "tt0579958" + }, + { + "name": "Deadly Nightshade", + "season": 1, + "number": 15, + "firstAired": "1991-03-28T00:00:00.000Z", + "rating": "7.7", + "id": "tt0098798:1:15", + "overview": "", + "imdb_id": "tt0579966" + }, + { + "name": "Captain Cold", + "season": 1, + "number": 16, + "firstAired": "1991-04-05T00:00:00.000Z", + "rating": "7.7", + "id": "tt0098798:1:16", + "overview": "", + "imdb_id": "tt0579954" + }, + { + "name": "Twin Streaks", + "season": 1, + "number": 17, + "firstAired": "1991-04-12T00:00:00.000Z", + "rating": "7.1", + "id": "tt0098798:1:17", + "overview": "", + "imdb_id": "tt0579970" + }, + { + "name": "Done with Mirrors", + "season": 1, + "number": 18, + "firstAired": "1991-04-27T00:00:00.000Z", + "rating": "7.3", + "id": "tt0098798:1:18", + "overview": "", + "imdb_id": "tt0579956" + }, + { + "name": "Good Night, Central City", + "season": 1, + "number": 19, + "firstAired": "1991-05-04T00:00:00.000Z", + "rating": "7.1", + "id": "tt0098798:1:19", + "overview": "", + "imdb_id": "tt0579960" + }, + { + "name": "Alpha", + "season": 1, + "number": 20, + "firstAired": "1991-05-11T00:00:00.000Z", + "rating": "7.5", + "id": "tt0098798:1:20", + "overview": "", + "imdb_id": "tt0579951" + }, + { + "name": "Trial of the Trickster", + "season": 1, + "number": 21, + "firstAired": "1991-05-18T00:00:00.000Z", + "rating": "7.9", + "id": "tt0098798:1:21", + "overview": "", + "imdb_id": "tt0579968" + } + ], + "id": "tt0098798", + "behaviorHints": { + "defaultVideoId": null, + "hasScheduledVideos": false + } + } +} \ No newline at end of file diff --git a/src/node/consumer/test/assets/kitsu-naruto-full.json b/src/node/consumer/test/assets/kitsu-naruto-full.json new file mode 100644 index 0000000..61e2073 --- /dev/null +++ b/src/node/consumer/test/assets/kitsu-naruto-full.json @@ -0,0 +1,2491 @@ +{ + "meta": { + "id": "kitsu:11", + "kitsu_id": "11", + "type": "series", + "animeType": "TV", + "name": "Naruto", + "slug": "naruto", + "aliases": [ + "Naruto" + ], + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power" + ], + "logo": "https://assets.fanart.tv/fanart/tv/78857/hdtvlogo/naruto-50667b3780bf2.png", + "poster": "https://media.kitsu.io/anime/11/poster_image/medium-410cee5d114a5f70d69e795755e8348a.jpeg", + "background": "https://assets.fanart.tv/fanart/tv/78857/showbackground/naruto-53b827ea97f87.jpg", + "description": "Moments prior to Naruto Uzumaki's birth, a huge demon known as the Kyuubi, the Nine-Tailed Fox, attacked Konohagakure, the Hidden Leaf Village, and wreaked havoc. In order to put an end to the Kyuubi's rampage, the leader of the village, the Fourth Hokage, sacrificed his life and sealed the monstrous beast inside the newborn Naruto.\nNow, Naruto is a hyperactive and knuckle-headed ninja still living in Konohagakure. Shunned because of the Kyuubi inside him, Naruto struggles to find his place in the village, while his burning desire to become the Hokage of Konohagakure leads him not only to some great new friends, but also some deadly foes.\n[Written by MAL Rewrite]", + "releaseInfo": "2002-2007", + "year": "2002-2007", + "imdbRating": "8.0", + "userCount": 156026, + "status": "finished", + "runtime": "23 min", + "trailers": [ + { + "source": "j2hiC9BmJlQ", + "type": "Trailer" + } + ], + "videos": [ + { + "id": "kitsu:11:1", + "title": "Enter: Naruto Uzumaki!", + "released": "2002-10-03T00:00:00.000Z", + "season": 1, + "episode": 1, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/451/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 1 + }, + { + "id": "kitsu:11:2", + "title": "My Name is Konohamaru!", + "released": "2002-10-10T00:00:00.000Z", + "season": 1, + "episode": 2, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/452/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 2 + }, + { + "id": "kitsu:11:3", + "title": "Sasuke and Sakura: Friends or Foes?", + "released": "2002-10-17T00:00:00.000Z", + "season": 1, + "episode": 3, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/453/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 3 + }, + { + "id": "kitsu:11:4", + "title": "Pass or Fail: Survival Test", + "released": "2002-10-24T00:00:00.000Z", + "season": 1, + "episode": 4, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/454/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 4 + }, + { + "id": "kitsu:11:5", + "title": "You Failed! Kakashi's Final Decision", + "released": "2002-10-31T00:00:00.000Z", + "season": 1, + "episode": 5, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/455/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 5 + }, + { + "id": "kitsu:11:6", + "title": "A Dangerous Mission! Journey to the Land of Waves!", + "released": "2002-11-07T00:00:00.000Z", + "season": 1, + "episode": 6, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/456/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 6 + }, + { + "id": "kitsu:11:7", + "title": "The Assassin of the Mist!", + "released": "2002-11-14T00:00:00.000Z", + "season": 1, + "episode": 7, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/457/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 7 + }, + { + "id": "kitsu:11:8", + "title": "The Oath of Pain", + "released": "2002-11-21T00:00:00.000Z", + "season": 1, + "episode": 8, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/458/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 8 + }, + { + "id": "kitsu:11:9", + "title": "Kakashi: Sharingan Warrior", + "released": "2002-11-28T00:00:00.000Z", + "season": 1, + "episode": 9, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/459/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 9 + }, + { + "id": "kitsu:11:10", + "title": "The Forest of Chakra", + "released": "2002-12-05T00:00:00.000Z", + "season": 1, + "episode": 10, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/460/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 10 + }, + { + "id": "kitsu:11:11", + "title": "The Land Where a Hero Once Lived", + "released": "2002-12-12T00:00:00.000Z", + "season": 1, + "episode": 11, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/461/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 11 + }, + { + "id": "kitsu:11:12", + "title": "Battle on the Bridge! Zabuza Returns!!", + "released": "2002-12-19T00:00:00.000Z", + "season": 1, + "episode": 12, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/462/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 12 + }, + { + "id": "kitsu:11:13", + "title": "Haku's Secret Jutsu: Crystal Ice Mirrors", + "released": "2002-12-26T00:00:00.000Z", + "season": 1, + "episode": 13, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/463/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 13 + }, + { + "id": "kitsu:11:14", + "title": "The Number One Hyperactive, Knucklehead Ninja Joins the Fight!!", + "released": "2003-01-09T00:00:00.000Z", + "season": 1, + "episode": 14, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/464/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 14 + }, + { + "id": "kitsu:11:15", + "title": "Zero Visibility: The Sharingan Shatters", + "released": "2003-01-16T00:00:00.000Z", + "season": 1, + "episode": 15, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/465/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 15 + }, + { + "id": "kitsu:11:16", + "title": "The Broken Seal", + "released": "2003-01-23T00:00:00.000Z", + "season": 1, + "episode": 16, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/466/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 16 + }, + { + "id": "kitsu:11:17", + "title": "White Past: Hidden Ambition", + "released": "2003-01-30T00:00:00.000Z", + "season": 1, + "episode": 17, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/467/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 17 + }, + { + "id": "kitsu:11:18", + "title": "The Weapons Known as Shinobi", + "released": "2003-02-06T00:00:00.000Z", + "season": 1, + "episode": 18, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/468/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 18 + }, + { + "id": "kitsu:11:19", + "title": "The Demon in the Snow", + "released": "2003-02-13T00:00:00.000Z", + "season": 1, + "episode": 19, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/469/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 19 + }, + { + "id": "kitsu:11:20", + "title": "A New Chapter Begins: The Chunin Exam!", + "released": "2003-02-20T00:00:00.000Z", + "season": 1, + "episode": 20, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/470/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 20 + }, + { + "id": "kitsu:11:21", + "title": "Identify Yourself: Powerful New Rivals", + "released": "2003-02-27T00:00:00.000Z", + "season": 1, + "episode": 21, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/471/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 21 + }, + { + "id": "kitsu:11:22", + "title": "Chunin Challenge: Rock Lee vs. Sasuke!", + "released": "2003-03-06T00:00:00.000Z", + "season": 1, + "episode": 22, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/472/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 22 + }, + { + "id": "kitsu:11:23", + "title": "Genin Takedown! All Nine Rookies Face Off!", + "released": "2003-03-13T00:00:00.000Z", + "season": 1, + "episode": 23, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/473/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 23 + }, + { + "id": "kitsu:11:24", + "title": "Start Your Engines: The Chunin Exam Begins!", + "released": "2003-03-20T00:00:00.000Z", + "season": 1, + "episode": 24, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/474/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 24 + }, + { + "id": "kitsu:11:25", + "title": "The Tenth Question: All or Nothing!", + "released": "2003-03-27T00:00:00.000Z", + "season": 1, + "episode": 25, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/475/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 25 + }, + { + "id": "kitsu:11:26", + "title": "Special Report: Live from the Forest of Death!", + "released": "2003-04-02T00:00:00.000Z", + "season": 1, + "episode": 26, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/476/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 26 + }, + { + "id": "kitsu:11:27", + "title": "The Chunin Exam Stage 2: The Forest of Death", + "released": "2003-04-02T00:00:00.000Z", + "season": 1, + "episode": 27, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/477/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 27 + }, + { + "id": "kitsu:11:28", + "title": "Eat or be Eaten: Panic in the Forest", + "released": "2003-04-09T00:00:00.000Z", + "season": 1, + "episode": 28, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/478/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 28 + }, + { + "id": "kitsu:11:29", + "title": "Naruto's Counterattack: Never Give In!", + "released": "2003-04-16T00:00:00.000Z", + "season": 1, + "episode": 29, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/479/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 29 + }, + { + "id": "kitsu:11:30", + "title": "The Sharingan Revived: Dragon-Flame Jutsu!", + "released": "2003-04-23T00:00:00.000Z", + "season": 1, + "episode": 30, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/480/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 30 + }, + { + "id": "kitsu:11:31", + "title": "Bushy Brow's Pledge: Undying Love and Protection!", + "released": "2003-04-30T00:00:00.000Z", + "season": 1, + "episode": 31, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/481/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 31 + }, + { + "id": "kitsu:11:32", + "title": "Sakura Blossoms!", + "released": "2003-05-07T00:00:00.000Z", + "season": 1, + "episode": 32, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/482/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 32 + }, + { + "id": "kitsu:11:33", + "title": "Battle Formation: Ino-Shika-Cho!", + "released": "2003-05-14T00:00:00.000Z", + "season": 1, + "episode": 33, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/483/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 33 + }, + { + "id": "kitsu:11:34", + "title": "Akamaru Trembles: Gaara's Cruel Strength!", + "released": "2003-05-21T00:00:00.000Z", + "season": 1, + "episode": 34, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/484/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 34 + }, + { + "id": "kitsu:11:35", + "title": "The Scroll's Secret: No Peeking Allowed", + "released": "2003-05-28T00:00:00.000Z", + "season": 1, + "episode": 35, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/485/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 1, + "imdbEpisode": 35 + }, + { + "id": "kitsu:11:36", + "title": "Clone vs. Clone: Mine are Better than Yours!", + "released": "2003-06-04T00:00:00.000Z", + "season": 1, + "episode": 36, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172591/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 1 + }, + { + "id": "kitsu:11:37", + "title": "Surviving the Cut! The Rookie Nine Together Again!", + "released": "2003-06-11T00:00:00.000Z", + "season": 1, + "episode": 37, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172592/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 2 + }, + { + "id": "kitsu:11:38", + "title": "Narrowing the Field: Sudden Death Elimination!", + "released": "2003-06-18T00:00:00.000Z", + "season": 1, + "episode": 38, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172593/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 3 + }, + { + "id": "kitsu:11:39", + "title": "Bushy Brow's Jealousy: Lions Barrage Unleashed!", + "released": "2003-07-02T00:00:00.000Z", + "season": 1, + "episode": 39, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172594/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 4 + }, + { + "id": "kitsu:11:40", + "title": "Kakashi and Orochimaru: Face-to-Face!", + "released": "2003-07-09T00:00:00.000Z", + "season": 1, + "episode": 40, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172595/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 5 + }, + { + "id": "kitsu:11:41", + "title": "Kunoichi Rumble: The Rivals Get Serious!", + "released": "2003-07-16T00:00:00.000Z", + "season": 1, + "episode": 41, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172596/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 6 + }, + { + "id": "kitsu:11:42", + "title": "The Ultimate Battle: Cha!", + "released": "2003-07-23T00:00:00.000Z", + "season": 1, + "episode": 42, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172597/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 7 + }, + { + "id": "kitsu:11:43", + "title": "Killer Kunoichi and a Shaky Shikamaru", + "released": "2003-07-30T00:00:00.000Z", + "season": 1, + "episode": 43, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172598/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 8 + }, + { + "id": "kitsu:11:44", + "title": "Akamaru Unleashed! Who's Top Dog Now?", + "released": "2003-08-06T00:00:00.000Z", + "season": 1, + "episode": 44, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172599/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 9 + }, + { + "id": "kitsu:11:45", + "title": "Surprise Attack! Naruto's Secret Weapon!", + "released": "2003-08-20T00:00:00.000Z", + "season": 1, + "episode": 45, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172600/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 10 + }, + { + "id": "kitsu:11:46", + "title": "Byakugan Battle: Hinata Grows Bold!", + "released": "2003-08-20T00:00:00.000Z", + "season": 1, + "episode": 46, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172601/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 11 + }, + { + "id": "kitsu:11:47", + "title": "A Failure Stands Tall!", + "released": "2003-08-27T00:00:00.000Z", + "season": 1, + "episode": 47, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172602/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 12 + }, + { + "id": "kitsu:11:48", + "title": "Gaara vs. Rock Lee: The Power of Youth Explodes!", + "released": "2003-09-03T00:00:00.000Z", + "season": 1, + "episode": 48, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/172603/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 13 + }, + { + "id": "kitsu:11:49", + "title": "Lee's Hidden Strength: Forbidden Secret Jutsu!", + "released": "2003-09-10T00:00:00.000Z", + "season": 1, + "episode": 49, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/499/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 14 + }, + { + "id": "kitsu:11:50", + "title": "The Fifth Gate: A Splendid Ninja is Born", + "released": "2003-09-17T00:00:00.000Z", + "season": 1, + "episode": 50, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/500/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 15 + }, + { + "id": "kitsu:11:51", + "title": "A Shadow in Darkness: Danger Approaches Sasuke", + "released": "2003-09-24T00:00:00.000Z", + "season": 1, + "episode": 51, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/501/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 16 + }, + { + "id": "kitsu:11:52", + "title": "Ebisu Returns: Naruto's Toughest Training Yet!", + "released": "2003-10-01T00:00:00.000Z", + "season": 1, + "episode": 52, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/502/original.jpeg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 17 + }, + { + "id": "kitsu:11:53", + "title": "Long Time No See: Jiraiya Returns!", + "released": "2003-10-08T00:00:00.000Z", + "season": 1, + "episode": 53, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167771/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 18 + }, + { + "id": "kitsu:11:54", + "title": "The Summoning Jutsu: Wisdom of the Toad Sage!", + "released": "2003-10-15T00:00:00.000Z", + "season": 1, + "episode": 54, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167772/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 19 + }, + { + "id": "kitsu:11:55", + "title": "A Feeling of Yearning, A Flower Full of Hope", + "released": "2003-10-22T00:00:00.000Z", + "season": 1, + "episode": 55, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167773/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 20 + }, + { + "id": "kitsu:11:56", + "title": "Live or Die: Risk it All to Win it All!", + "released": "2003-10-29T00:00:00.000Z", + "season": 1, + "episode": 56, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167774/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 21 + }, + { + "id": "kitsu:11:57", + "title": "He Flies! He Jumps! He Lurks! Chief Toad Appears!", + "released": "2003-11-05T00:00:00.000Z", + "season": 1, + "episode": 57, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167775/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 22 + }, + { + "id": "kitsu:11:58", + "title": "Hospital Besieged: The Evil Hand Revealed!", + "released": "2003-11-12T00:00:00.000Z", + "season": 1, + "episode": 58, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167776/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 23 + }, + { + "id": "kitsu:11:59", + "title": "The Final Rounds: Rush to the Battle Arena!", + "released": "2003-11-19T00:00:00.000Z", + "season": 1, + "episode": 59, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167777/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 24 + }, + { + "id": "kitsu:11:60", + "title": "Byakugan vs. Shadow Clone", + "released": "2003-11-26T00:00:00.000Z", + "season": 1, + "episode": 60, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167778/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 25 + }, + { + "id": "kitsu:11:61", + "title": "Ultimate Defense: Zero Blind Spot!", + "released": "2003-12-03T00:00:00.000Z", + "season": 1, + "episode": 61, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167779/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 26 + }, + { + "id": "kitsu:11:62", + "title": "A Failure's True Power", + "released": "2003-12-10T00:00:00.000Z", + "season": 1, + "episode": 62, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167780/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 27 + }, + { + "id": "kitsu:11:63", + "title": "Hit it or Quit it: The Final Rounds Get Complicated!", + "released": "2003-12-17T00:00:00.000Z", + "season": 1, + "episode": 63, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167781/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 28 + }, + { + "id": "kitsu:11:64", + "title": "Zero Motivation: The Guy with Cloud Envy!", + "released": "2003-12-24T00:00:00.000Z", + "season": 1, + "episode": 64, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167782/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 29 + }, + { + "id": "kitsu:11:65", + "title": "Dancing Leaf, Squirming Sand", + "released": "2004-01-07T00:00:00.000Z", + "season": 1, + "episode": 65, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167783/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 30 + }, + { + "id": "kitsu:11:66", + "title": "Bushy Brow's Jutsu: Sasuke Style!", + "released": "2004-01-14T00:00:00.000Z", + "season": 1, + "episode": 66, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167784/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 31 + }, + { + "id": "kitsu:11:67", + "title": "Late for the Show, But Ready to Go! The Ultimate Secret Technique is Born!", + "released": "2004-01-14T00:00:00.000Z", + "season": 1, + "episode": 67, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167785/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 32 + }, + { + "id": "kitsu:11:68", + "title": "Zero Hour! The Destruction of the Hidden Leaf Village Begins!", + "released": "2004-01-28T00:00:00.000Z", + "season": 1, + "episode": 68, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167786/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 33 + }, + { + "id": "kitsu:11:69", + "title": "Village in Distress: A New A-Ranked Mission!", + "released": "2004-02-04T00:00:00.000Z", + "season": 1, + "episode": 69, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167787/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 34 + }, + { + "id": "kitsu:11:70", + "title": "A Shirker's Call to Action: A Layabout No More!", + "released": "2004-02-11T00:00:00.000Z", + "season": 1, + "episode": 70, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167788/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 35 + }, + { + "id": "kitsu:11:71", + "title": "An Unrivaled Match: Hokage Battle Royale!", + "released": "2004-02-18T00:00:00.000Z", + "season": 1, + "episode": 71, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167789/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 36 + }, + { + "id": "kitsu:11:72", + "title": "A Mistake from the Past: A Face Revealed!", + "released": "2004-02-25T00:00:00.000Z", + "season": 1, + "episode": 72, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167790/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 37 + }, + { + "id": "kitsu:11:73", + "title": "Forbidden Secret Technique: Reaper Death Seal!", + "released": "2004-03-03T00:00:00.000Z", + "season": 1, + "episode": 73, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167791/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 38 + }, + { + "id": "kitsu:11:74", + "title": "Astonishing Truth! Gaara's Identity Emerges!", + "released": "2004-03-10T00:00:00.000Z", + "season": 1, + "episode": 74, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167792/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 39 + }, + { + "id": "kitsu:11:75", + "title": "Sasuke's Decision: Pushed to the Edge!", + "released": "2004-03-17T00:00:00.000Z", + "season": 1, + "episode": 75, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167793/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 40 + }, + { + "id": "kitsu:11:76", + "title": "Assassin of the Moonlit Night", + "released": "2004-03-24T00:00:00.000Z", + "season": 1, + "episode": 76, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167794/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 41 + }, + { + "id": "kitsu:11:77", + "title": "Light vs. Dark: The Two Faces of Gaara", + "released": "2004-03-31T00:00:00.000Z", + "season": 1, + "episode": 77, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167795/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 42 + }, + { + "id": "kitsu:11:78", + "title": "Naruto's Ninja Handbook", + "released": "2004-04-07T00:00:00.000Z", + "season": 1, + "episode": 78, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167796/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 43 + }, + { + "id": "kitsu:11:79", + "title": "Beyond the Limit of Darkness and Light", + "released": "2004-04-14T00:00:00.000Z", + "season": 1, + "episode": 79, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167797/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 44 + }, + { + "id": "kitsu:11:80", + "title": "The Third Hokage, Forever...", + "released": "2004-04-21T00:00:00.000Z", + "season": 1, + "episode": 80, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167798/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 45 + }, + { + "id": "kitsu:11:81", + "title": "Return of the Morning Mist", + "released": "2004-04-28T00:00:00.000Z", + "season": 1, + "episode": 81, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167799/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 46 + }, + { + "id": "kitsu:11:82", + "title": "Eye to Eye: Sharingan vs. Sharingan!", + "released": "2004-05-05T00:00:00.000Z", + "season": 1, + "episode": 82, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167800/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 47 + }, + { + "id": "kitsu:11:83", + "title": "Jiraiya: Naruto's Potential Disaster!", + "released": "2004-05-12T00:00:00.000Z", + "season": 1, + "episode": 83, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167801/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 2, + "imdbEpisode": 48 + }, + { + "id": "kitsu:11:84", + "title": "Roar, Chidori! Brother vs. Brother!", + "released": "2004-05-19T00:00:00.000Z", + "season": 1, + "episode": 84, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167802/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 1 + }, + { + "id": "kitsu:11:85", + "title": "Hate Among the Uchihas: The Last of the Clan!", + "released": "2004-05-26T00:00:00.000Z", + "season": 1, + "episode": 85, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167803/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 2 + }, + { + "id": "kitsu:11:86", + "title": "A New Training Begins: I Will Be Strong!", + "released": "2004-06-02T00:00:00.000Z", + "season": 1, + "episode": 86, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167804/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 3 + }, + { + "id": "kitsu:11:87", + "title": "Keep on Training: Pop Goes the Water Balloon!", + "released": "2004-06-09T00:00:00.000Z", + "season": 1, + "episode": 87, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167805/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 4 + }, + { + "id": "kitsu:11:88", + "title": "Focal Point: The Mark of the Leaf", + "released": "2004-06-16T00:00:00.000Z", + "season": 1, + "episode": 88, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/486/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 5 + }, + { + "id": "kitsu:11:89", + "title": "An Impossible Choice: The Pain Within Tsunade's Heart", + "released": "2004-06-23T00:00:00.000Z", + "season": 1, + "episode": 89, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/487/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 6 + }, + { + "id": "kitsu:11:90", + "title": "Unforgivable! A Total Lack of Respect!", + "released": "2004-07-07T00:00:00.000Z", + "season": 1, + "episode": 90, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/488/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 7 + }, + { + "id": "kitsu:11:91", + "title": "Inheritence! The Necklace of Death!", + "released": "2004-07-14T00:00:00.000Z", + "season": 1, + "episode": 91, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/489/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 8 + }, + { + "id": "kitsu:11:92", + "title": "A Dubious Offer! Tsunade's Choice!", + "released": "2004-07-21T00:00:00.000Z", + "season": 1, + "episode": 92, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/490/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 9 + }, + { + "id": "kitsu:11:93", + "title": "Breakdown! The Deal is Off!", + "released": "2004-07-28T00:00:00.000Z", + "season": 1, + "episode": 93, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/491/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 10 + }, + { + "id": "kitsu:11:94", + "title": "Attack! Fury of the Rasengan!", + "released": "2004-08-04T00:00:00.000Z", + "season": 1, + "episode": 94, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/492/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 11 + }, + { + "id": "kitsu:11:95", + "title": "The Fifth Hokage! A Life on the Line!", + "released": "2004-08-11T00:00:00.000Z", + "season": 1, + "episode": 95, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/493/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 12 + }, + { + "id": "kitsu:11:96", + "title": "Deadlock! Sannin Showdown!", + "released": "2004-08-11T00:00:00.000Z", + "season": 1, + "episode": 96, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/494/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 13 + }, + { + "id": "kitsu:11:97", + "title": "Kidnapped! Naruto's Hot Spring Adventure!", + "released": "2004-08-18T00:00:00.000Z", + "season": 1, + "episode": 97, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/495/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 14 + }, + { + "id": "kitsu:11:98", + "title": "Tsunade's Warning: Ninja No More!", + "released": "2004-08-25T00:00:00.000Z", + "season": 1, + "episode": 98, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/496/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 15 + }, + { + "id": "kitsu:11:99", + "title": "The Will of Fire Still Burns!", + "released": "2004-09-01T00:00:00.000Z", + "season": 1, + "episode": 99, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/497/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 16 + }, + { + "id": "kitsu:11:100", + "title": "Sensei and Student: The Bond of the Shinobi", + "released": "2004-09-08T00:00:00.000Z", + "season": 1, + "episode": 100, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/498/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 17 + }, + { + "id": "kitsu:11:101", + "title": "Gotta See! Gotta Know! Kakashi-Sensei's True Face!", + "released": "2004-09-15T00:00:00.000Z", + "season": 1, + "episode": 101, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167807/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 18 + }, + { + "id": "kitsu:11:102", + "title": "Mission: Help an Old Friend in the Land of Tea", + "released": "2004-09-22T00:00:00.000Z", + "season": 1, + "episode": 102, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167808/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 19 + }, + { + "id": "kitsu:11:103", + "title": "The Race is on! Trouble on the High Seas!", + "released": "2004-09-29T00:00:00.000Z", + "season": 1, + "episode": 103, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167810/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 20 + }, + { + "id": "kitsu:11:104", + "title": "Run Idate Run! Nagi Island Awaits!", + "released": "2004-10-13T00:00:00.000Z", + "season": 1, + "episode": 104, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167811/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 21 + }, + { + "id": "kitsu:11:105", + "title": "A Fierce Battle of Rolling Thunder!", + "released": "2004-10-20T00:00:00.000Z", + "season": 1, + "episode": 105, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167813/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 22 + }, + { + "id": "kitsu:11:106", + "title": "The Last Leg: A Final Act of Desperation", + "released": "2004-10-27T00:00:00.000Z", + "season": 1, + "episode": 106, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167816/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 23 + }, + { + "id": "kitsu:11:107", + "title": "The Battle Begins: Naruto vs. Sasuke", + "released": "2004-11-03T00:00:00.000Z", + "season": 1, + "episode": 107, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167818/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 24 + }, + { + "id": "kitsu:11:108", + "title": "Bitter Rivals and Broken Bonds", + "released": "2004-11-10T00:00:00.000Z", + "season": 1, + "episode": 108, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167820/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 25 + }, + { + "id": "kitsu:11:109", + "title": "An Invitation from the Sound", + "released": "2004-11-17T00:00:00.000Z", + "season": 1, + "episode": 109, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167822/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 26 + }, + { + "id": "kitsu:11:110", + "title": "Formation! The Sasuke Retrieval Squad", + "released": "2004-11-24T00:00:00.000Z", + "season": 1, + "episode": 110, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167824/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 27 + }, + { + "id": "kitsu:11:111", + "title": "Sound vs. Leaf", + "released": "2004-11-24T00:00:00.000Z", + "season": 1, + "episode": 111, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167828/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 28 + }, + { + "id": "kitsu:11:112", + "title": "Squad Mutiny: Everything Falls Apart!", + "released": "2004-12-01T00:00:00.000Z", + "season": 1, + "episode": 112, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167830/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 29 + }, + { + "id": "kitsu:11:113", + "title": "Full Throttle Power! Choji, Ablaze!", + "released": "2004-12-08T00:00:00.000Z", + "season": 1, + "episode": 113, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167831/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 30 + }, + { + "id": "kitsu:11:114", + "title": "Good-bye Old Friend...! I'll Always Believe in You!", + "released": "2004-12-15T00:00:00.000Z", + "season": 1, + "episode": 114, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167835/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 31 + }, + { + "id": "kitsu:11:115", + "title": "Your Opponent Is Me!", + "released": "2004-12-22T00:00:00.000Z", + "season": 1, + "episode": 115, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167837/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 32 + }, + { + "id": "kitsu:11:116", + "title": "360 Degrees of Vision: The Byakugan's Blind Spot", + "released": "2005-01-05T00:00:00.000Z", + "season": 1, + "episode": 116, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167840/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 33 + }, + { + "id": "kitsu:11:117", + "title": "Losing is Not an Option!", + "released": "2005-01-05T00:00:00.000Z", + "season": 1, + "episode": 117, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167843/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 34 + }, + { + "id": "kitsu:11:118", + "title": "The Vessel Arrives Too Late", + "released": "2005-01-12T00:00:00.000Z", + "season": 1, + "episode": 118, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167848/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 35 + }, + { + "id": "kitsu:11:119", + "title": "Miscalculation: A New Enemy Appears!", + "released": "2005-01-19T00:00:00.000Z", + "season": 1, + "episode": 119, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167851/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 36 + }, + { + "id": "kitsu:11:120", + "title": "Roar and Howl! The Ultimate Tag Team", + "released": "2005-02-02T00:00:00.000Z", + "season": 1, + "episode": 120, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167854/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 37 + }, + { + "id": "kitsu:11:121", + "title": "To Each His Own Battle", + "released": "2005-02-09T00:00:00.000Z", + "season": 1, + "episode": 121, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167857/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 38 + }, + { + "id": "kitsu:11:122", + "title": "Fakeout: Shikamaru's Comeback!", + "released": "2005-02-16T00:00:00.000Z", + "season": 1, + "episode": 122, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167860/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 39 + }, + { + "id": "kitsu:11:123", + "title": "The Leaf's Handsome Devil!", + "released": "2005-02-23T00:00:00.000Z", + "season": 1, + "episode": 123, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167863/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 40 + }, + { + "id": "kitsu:11:124", + "title": "The Beast Within", + "released": "2005-03-02T00:00:00.000Z", + "season": 1, + "episode": 124, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167864/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 41 + }, + { + "id": "kitsu:11:125", + "title": "The Sand Shinobi: Allies of the Leaf", + "released": "2005-03-09T00:00:00.000Z", + "season": 1, + "episode": 125, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167866/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 42 + }, + { + "id": "kitsu:11:126", + "title": "Showdown: Gaara vs. Kimimaro!", + "released": "2005-03-16T00:00:00.000Z", + "season": 1, + "episode": 126, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167869/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 43 + }, + { + "id": "kitsu:11:127", + "title": "Vengeful Strike! The Bracken Dance", + "released": "2005-03-30T00:00:00.000Z", + "season": 1, + "episode": 127, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167872/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 44 + }, + { + "id": "kitsu:11:128", + "title": "A Cry on Deaf Ears", + "released": "2005-03-30T00:00:00.000Z", + "season": 1, + "episode": 128, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167875/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 45 + }, + { + "id": "kitsu:11:129", + "title": "Brothers: Distance Among the Uchiha", + "released": "2005-04-06T00:00:00.000Z", + "season": 1, + "episode": 129, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167878/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 46 + }, + { + "id": "kitsu:11:130", + "title": "Father and Son, the Broken Crest", + "released": "2005-04-13T00:00:00.000Z", + "season": 1, + "episode": 130, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167881/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 47 + }, + { + "id": "kitsu:11:131", + "title": "The Secrets of the Mangekyo Sharingan!", + "released": "2005-04-20T00:00:00.000Z", + "season": 1, + "episode": 131, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167885/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 3, + "imdbEpisode": 48 + }, + { + "id": "kitsu:11:132", + "title": "For a Friend", + "released": "2005-04-27T00:00:00.000Z", + "season": 1, + "episode": 132, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167886/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 1 + }, + { + "id": "kitsu:11:133", + "title": "A Plea From a Friend", + "released": "2005-05-04T00:00:00.000Z", + "season": 1, + "episode": 133, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167891/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 2 + }, + { + "id": "kitsu:11:134", + "title": "The End of Tears", + "released": "2005-05-11T00:00:00.000Z", + "season": 1, + "episode": 134, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167894/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 3 + }, + { + "id": "kitsu:11:135", + "title": "The Promise That Could Not Be Kept", + "released": "2005-05-18T00:00:00.000Z", + "season": 1, + "episode": 135, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167896/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 4 + }, + { + "id": "kitsu:11:136", + "title": "Deep Cover!? A Super S-Ranked Mission!", + "released": "2005-05-25T00:00:00.000Z", + "season": 1, + "episode": 136, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167898/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 5 + }, + { + "id": "kitsu:11:137", + "title": "A Town of Outlaws, the Shadow of the Fuma Clan", + "released": "2005-06-01T00:00:00.000Z", + "season": 1, + "episode": 137, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167900/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 6 + }, + { + "id": "kitsu:11:138", + "title": "Pure Betrayal, and a Fleeting Plea!", + "released": "2005-06-08T00:00:00.000Z", + "season": 1, + "episode": 138, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167901/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 7 + }, + { + "id": "kitsu:11:139", + "title": "Pure Terror! The House of Orochimaru", + "released": "2005-06-15T00:00:00.000Z", + "season": 1, + "episode": 139, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167903/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 8 + }, + { + "id": "kitsu:11:140", + "title": "Two Heartbeats: Kabuto's Trap", + "released": "2005-06-22T00:00:00.000Z", + "season": 1, + "episode": 140, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167905/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 9 + }, + { + "id": "kitsu:11:141", + "title": "Sakura's Determination", + "released": "2005-06-29T00:00:00.000Z", + "season": 1, + "episode": 141, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167906/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 10 + }, + { + "id": "kitsu:11:142", + "title": "The Three Villains from the Maximum Security Prison", + "released": "2005-07-06T00:00:00.000Z", + "season": 1, + "episode": 142, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167908/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 11 + }, + { + "id": "kitsu:11:143", + "title": "Tonton! I'm Counting on You!", + "released": "2005-07-13T00:00:00.000Z", + "season": 1, + "episode": 143, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167910/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 12 + }, + { + "id": "kitsu:11:144", + "title": "A New Squad! Two People and a Dog?!", + "released": "2005-07-20T00:00:00.000Z", + "season": 1, + "episode": 144, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167912/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 13 + }, + { + "id": "kitsu:11:145", + "title": "A New Formation: Ino-Shika-Cho!", + "released": "2005-07-27T00:00:00.000Z", + "season": 1, + "episode": 145, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167914/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 14 + }, + { + "id": "kitsu:11:146", + "title": "Orochimaru's Shadow", + "released": "2005-08-10T00:00:00.000Z", + "season": 1, + "episode": 146, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167915/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 15 + }, + { + "id": "kitsu:11:147", + "title": "A Clash of Fate: You Can't Bring Me Down", + "released": "2005-08-17T00:00:00.000Z", + "season": 1, + "episode": 147, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167918/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 16 + }, + { + "id": "kitsu:11:148", + "title": "Search for the Rare Bikochu Beetle", + "released": "2005-08-17T00:00:00.000Z", + "season": 1, + "episode": 148, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167920/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 17 + }, + { + "id": "kitsu:11:149", + "title": "What's the Difference? Don't All Insects Look Alike?", + "released": "2005-08-24T00:00:00.000Z", + "season": 1, + "episode": 149, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167921/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 18 + }, + { + "id": "kitsu:11:150", + "title": "A Battle of Bugs: The Deceivers and the Deceived", + "released": "2005-08-31T00:00:00.000Z", + "season": 1, + "episode": 150, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167923/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 19 + }, + { + "id": "kitsu:11:151", + "title": "Blaze Away Byakugan: This Is My Ninja Way", + "released": "2005-09-14T00:00:00.000Z", + "season": 1, + "episode": 151, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167924/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 20 + }, + { + "id": "kitsu:11:152", + "title": "Funeral March for the Living", + "released": "2005-09-21T00:00:00.000Z", + "season": 1, + "episode": 152, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167926/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 21 + }, + { + "id": "kitsu:11:153", + "title": "A Lesson Learned: The Iron Fist of Love", + "released": "2005-09-28T00:00:00.000Z", + "season": 1, + "episode": 153, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167928/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 22 + }, + { + "id": "kitsu:11:154", + "title": "The Enemy of the Byakugan", + "released": "2005-10-05T00:00:00.000Z", + "season": 1, + "episode": 154, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167930/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 23 + }, + { + "id": "kitsu:11:155", + "title": "The Dark Creeping Clouds", + "released": "2005-10-12T00:00:00.000Z", + "season": 1, + "episode": 155, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167931/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 24 + }, + { + "id": "kitsu:11:156", + "title": "Raiga's Counterattack", + "released": "2005-10-19T00:00:00.000Z", + "season": 1, + "episode": 156, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167933/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 25 + }, + { + "id": "kitsu:11:157", + "title": "Run! The Curry of Life", + "released": "2005-10-26T00:00:00.000Z", + "season": 1, + "episode": 157, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167934/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 26 + }, + { + "id": "kitsu:11:158", + "title": "Follow My Lead! The Great Survival Challenge", + "released": "2005-11-02T00:00:00.000Z", + "season": 1, + "episode": 158, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167936/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 27 + }, + { + "id": "kitsu:11:159", + "title": "Bounty Hunter from the Wilderness", + "released": "2005-11-09T00:00:00.000Z", + "season": 1, + "episode": 159, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167939/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 28 + }, + { + "id": "kitsu:11:160", + "title": "Hunt or Be Hunted?! Showdown at the O.K. Temple!", + "released": "2005-11-16T00:00:00.000Z", + "season": 1, + "episode": 160, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167942/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 29 + }, + { + "id": "kitsu:11:161", + "title": "The Appearance of Strange Visitors", + "released": "2005-11-23T00:00:00.000Z", + "season": 1, + "episode": 161, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167943/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 30 + }, + { + "id": "kitsu:11:162", + "title": "The Cursed Warrior", + "released": "2005-11-30T00:00:00.000Z", + "season": 1, + "episode": 162, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167944/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 31 + }, + { + "id": "kitsu:11:163", + "title": "The Tactician's Intent", + "released": "2005-12-07T00:00:00.000Z", + "season": 1, + "episode": 163, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167945/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 32 + }, + { + "id": "kitsu:11:164", + "title": "Too Late for Help", + "released": "2005-12-14T00:00:00.000Z", + "season": 1, + "episode": 164, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167946/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 33 + }, + { + "id": "kitsu:11:165", + "title": "The Death of Naruto", + "released": "2005-12-21T00:00:00.000Z", + "season": 1, + "episode": 165, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167947/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 34 + }, + { + "id": "kitsu:11:166", + "title": "When Time Stands Still", + "released": "2006-01-04T00:00:00.000Z", + "season": 1, + "episode": 166, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167948/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 35 + }, + { + "id": "kitsu:11:167", + "title": "When Egrets Flap Their Wings", + "released": "2006-01-04T00:00:00.000Z", + "season": 1, + "episode": 167, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167949/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 36 + }, + { + "id": "kitsu:11:168", + "title": "Mix It, Stretch It, Boil It Up! Burn, Copper Pot, Burn!", + "released": "2006-01-18T00:00:00.000Z", + "season": 1, + "episode": 168, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167950/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 37 + }, + { + "id": "kitsu:11:169", + "title": "Remembrance: The Lost Page", + "released": "2006-01-25T00:00:00.000Z", + "season": 1, + "episode": 169, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167951/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 38 + }, + { + "id": "kitsu:11:170", + "title": "The Closed Door", + "released": "2006-02-01T00:00:00.000Z", + "season": 1, + "episode": 170, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167952/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 39 + }, + { + "id": "kitsu:11:171", + "title": "Infiltration: The Set-Up!", + "released": "2006-02-08T00:00:00.000Z", + "season": 1, + "episode": 171, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167953/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 40 + }, + { + "id": "kitsu:11:172", + "title": "Despair: A Fractured Heart", + "released": "2006-02-15T00:00:00.000Z", + "season": 1, + "episode": 172, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167954/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 41 + }, + { + "id": "kitsu:11:173", + "title": "The Battle at Sea: The Power Unleashed!", + "released": "2006-02-22T00:00:00.000Z", + "season": 1, + "episode": 173, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167955/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 42 + }, + { + "id": "kitsu:11:174", + "title": "Impossible! Celebrity Ninja Art - Money Style Jutsu!", + "released": "2006-03-01T00:00:00.000Z", + "season": 1, + "episode": 174, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167956/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 43 + }, + { + "id": "kitsu:11:175", + "title": "The Treasure Hunt is On!", + "released": "2006-03-08T00:00:00.000Z", + "season": 1, + "episode": 175, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167957/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 44 + }, + { + "id": "kitsu:11:176", + "title": "Run, Dodge, Zigzag! Chase or Be Chased!", + "released": "2006-03-15T00:00:00.000Z", + "season": 1, + "episode": 176, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167958/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 45 + }, + { + "id": "kitsu:11:177", + "title": "Please, Mr. Postman!", + "released": "2006-03-22T00:00:00.000Z", + "season": 1, + "episode": 177, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167959/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 46 + }, + { + "id": "kitsu:11:178", + "title": "Encounter! The Boy with a Star's Name", + "released": "2006-03-29T00:00:00.000Z", + "season": 1, + "episode": 178, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167960/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 47 + }, + { + "id": "kitsu:11:179", + "title": "The Remembered Lullaby", + "released": "2006-04-05T00:00:00.000Z", + "season": 1, + "episode": 179, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167961/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 4, + "imdbEpisode": 48 + }, + { + "id": "kitsu:11:180", + "title": "Hidden Jutsu: The Price of The Ninja Art: Kujaku", + "released": "2006-04-12T00:00:00.000Z", + "season": 1, + "episode": 180, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167962/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 1 + }, + { + "id": "kitsu:11:181", + "title": "Hoshikage, The Buried Truth", + "released": "2006-04-19T00:00:00.000Z", + "season": 1, + "episode": 181, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167963/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 2 + }, + { + "id": "kitsu:11:182", + "title": "Reunion, The Remaining time", + "released": "2006-04-26T00:00:00.000Z", + "season": 1, + "episode": 182, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167964/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 3 + }, + { + "id": "kitsu:11:183", + "title": "The Star's Radiance", + "released": "2006-05-03T00:00:00.000Z", + "season": 1, + "episode": 183, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167965/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 4 + }, + { + "id": "kitsu:11:184", + "title": "Kiba's Long Day!", + "released": "2006-05-10T00:00:00.000Z", + "season": 1, + "episode": 184, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167966/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 5 + }, + { + "id": "kitsu:11:185", + "title": "A Legend from the Hidden Leaf: The Onbaa!", + "released": "2006-05-17T00:00:00.000Z", + "season": 1, + "episode": 185, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167967/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 6 + }, + { + "id": "kitsu:11:186", + "title": "Laughing Shino", + "released": "2006-05-24T00:00:00.000Z", + "season": 1, + "episode": 186, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167968/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 7 + }, + { + "id": "kitsu:11:187", + "title": "Open for Business! The Leaf Moving Service", + "released": "2006-05-31T00:00:00.000Z", + "season": 1, + "episode": 187, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167969/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 8 + }, + { + "id": "kitsu:11:188", + "title": "Mystery of the Targeted Merchants", + "released": "2006-06-07T00:00:00.000Z", + "season": 1, + "episode": 188, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167970/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 9 + }, + { + "id": "kitsu:11:189", + "title": "A Limitless Supply of Ninja Tools", + "released": "2006-06-14T00:00:00.000Z", + "season": 1, + "episode": 189, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167971/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 10 + }, + { + "id": "kitsu:11:190", + "title": "The Byakugan Sees the Blind Spot", + "released": "2006-06-21T00:00:00.000Z", + "season": 1, + "episode": 190, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167972/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 11 + }, + { + "id": "kitsu:11:191", + "title": "Forecast: Death! Cloudy with Chance of Sun", + "released": "2006-06-28T00:00:00.000Z", + "season": 1, + "episode": 191, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167973/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 12 + }, + { + "id": "kitsu:11:192", + "title": "Ino Screams! Chubby Paradise!", + "released": "2006-07-05T00:00:00.000Z", + "season": 1, + "episode": 192, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167975/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 13 + }, + { + "id": "kitsu:11:193", + "title": "Viva Dojo Challenge! Youth Is All About Passion!", + "released": "2006-07-12T00:00:00.000Z", + "season": 1, + "episode": 193, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167976/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 14 + }, + { + "id": "kitsu:11:194", + "title": "The Mysterious Curse of the Haunted Castle", + "released": "2006-07-19T00:00:00.000Z", + "season": 1, + "episode": 194, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167977/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 15 + }, + { + "id": "kitsu:11:195", + "title": "The Third Super-Beast!", + "released": "2006-07-26T00:00:00.000Z", + "season": 1, + "episode": 195, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167978/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 16 + }, + { + "id": "kitsu:11:196", + "title": "Hot-Blooded Confrontation: Student vs. Sensei", + "released": "2006-08-09T00:00:00.000Z", + "season": 1, + "episode": 196, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167979/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 17 + }, + { + "id": "kitsu:11:197", + "title": "Crisis! The Hidden Leaf 11 Gather!", + "released": "2006-08-16T00:00:00.000Z", + "season": 1, + "episode": 197, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167980/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 18 + }, + { + "id": "kitsu:11:198", + "title": "The ANBU Gives Up? Naruto's Recollection", + "released": "2006-08-23T00:00:00.000Z", + "season": 1, + "episode": 198, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167981/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 19 + }, + { + "id": "kitsu:11:199", + "title": "The Missed Target", + "released": "2006-08-30T00:00:00.000Z", + "season": 1, + "episode": 199, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167982/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 20 + }, + { + "id": "kitsu:11:200", + "title": "The Powerful Helper", + "released": "2006-09-13T00:00:00.000Z", + "season": 1, + "episode": 200, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167983/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 21 + }, + { + "id": "kitsu:11:201", + "title": "Multiple Traps! Countdown to Destruction", + "released": "2006-09-20T00:00:00.000Z", + "season": 1, + "episode": 201, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167984/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 22 + }, + { + "id": "kitsu:11:202", + "title": "The Top 5 Ninja Battles", + "released": "2006-09-27T00:00:00.000Z", + "season": 1, + "episode": 202, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167985/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 23 + }, + { + "id": "kitsu:11:203", + "title": "Kurenai's Decision, Squad 8 Left Behind", + "released": "2006-10-05T00:00:00.000Z", + "season": 1, + "episode": 203, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167986/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 24 + }, + { + "id": "kitsu:11:204", + "title": "Yakumo's Sealed Ability", + "released": "2006-10-05T00:00:00.000Z", + "season": 1, + "episode": 204, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167987/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 25 + }, + { + "id": "kitsu:11:205", + "title": "Kurenai's Top-Secret Mission: The Promise With the Third Hokage", + "released": "2006-10-05T00:00:00.000Z", + "season": 1, + "episode": 205, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167988/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 26 + }, + { + "id": "kitsu:11:206", + "title": "Genjutsu or Reality?", + "released": "2006-10-19T00:00:00.000Z", + "season": 1, + "episode": 206, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167989/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 27 + }, + { + "id": "kitsu:11:207", + "title": "The Supposed Sealed Ability", + "released": "2006-10-26T00:00:00.000Z", + "season": 1, + "episode": 207, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167990/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 28 + }, + { + "id": "kitsu:11:208", + "title": "The Weight of the Prized Artifact!", + "released": "2006-11-02T00:00:00.000Z", + "season": 1, + "episode": 208, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167991/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 29 + }, + { + "id": "kitsu:11:209", + "title": "The Enemy: Ninja Dropouts", + "released": "2006-11-09T00:00:00.000Z", + "season": 1, + "episode": 209, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167992/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 30 + }, + { + "id": "kitsu:11:210", + "title": "The Bewildering Forest", + "released": "2006-11-16T00:00:00.000Z", + "season": 1, + "episode": 210, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167993/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 31 + }, + { + "id": "kitsu:11:211", + "title": "Memory of Flames", + "released": "2006-11-30T00:00:00.000Z", + "season": 1, + "episode": 211, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167994/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 32 + }, + { + "id": "kitsu:11:212", + "title": "To Each His Own Path", + "released": "2006-12-07T00:00:00.000Z", + "season": 1, + "episode": 212, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167995/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 33 + }, + { + "id": "kitsu:11:213", + "title": "Vanished Memories", + "released": "2006-12-14T00:00:00.000Z", + "season": 1, + "episode": 213, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167996/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 34 + }, + { + "id": "kitsu:11:214", + "title": "Bringing Back Reality", + "released": "2006-12-21T00:00:00.000Z", + "season": 1, + "episode": 214, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167997/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 35 + }, + { + "id": "kitsu:11:215", + "title": "A Past to Be Erased", + "released": "2006-12-21T00:00:00.000Z", + "season": 1, + "episode": 215, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167998/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 36 + }, + { + "id": "kitsu:11:216", + "title": "The Targeted Shukaku", + "released": "2007-01-11T00:00:00.000Z", + "season": 1, + "episode": 216, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/167999/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 37 + }, + { + "id": "kitsu:11:217", + "title": "Sand Alliance With The Leaf Shinobi", + "released": "2007-01-18T00:00:00.000Z", + "season": 1, + "episode": 217, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/168000/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 38 + }, + { + "id": "kitsu:11:218", + "title": "The Counterattack!", + "released": "2007-01-25T00:00:00.000Z", + "season": 1, + "episode": 218, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/168001/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 39 + }, + { + "id": "kitsu:11:219", + "title": "The Ultimate Weapon Reborn", + "released": "2007-02-01T00:00:00.000Z", + "season": 1, + "episode": 219, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/168002/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 40 + }, + { + "id": "kitsu:11:220", + "title": "Departure", + "released": "2007-02-08T00:00:00.000Z", + "season": 1, + "episode": 220, + "thumbnail": "https://media.kitsu.io/episodes/thumbnails/168003/original.jpg", + "imdb_id": "tt0409591", + "imdbSeason": 5, + "imdbEpisode": 41 + } + ], + "links": [ + { + "name": "8.0", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto" + }, + { + "name": "Sequel: Naruto: Shippuuden", + "category": "Franchise", + "url": "stremio:///detail/series/kitsu:1555" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ], + "imdb_id": "tt0409591" + }, + "cacheMaxAge": 43200 +} \ No newline at end of file diff --git a/src/node/consumer/test/assets/name-to-imdb-flash.json b/src/node/consumer/test/assets/name-to-imdb-flash.json new file mode 100644 index 0000000..73a7dd7 --- /dev/null +++ b/src/node/consumer/test/assets/name-to-imdb-flash.json @@ -0,0 +1,111 @@ +{ + "d": [ + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BMTQ2MTc0MTAtN2VlYi00N2ZkLTlhNmUtMjcyZDg0YzNiYjEyXkEyXkFqcGdeQXVyMzU3MTc5OTE@._V1_.jpg", + 680, + 1000 + ], + "id": "tt0098798", + "l": "The Flash", + "q": "TV series", + "qid": "tvSeries", + "s": "John Wesley Shipp, Amanda Pays", + "y": 1990, + "yr": "1990-1991" + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BMGU2OGMyNzUtM2Q5NS00ZTdhLThmNjItODRiZDQ5MGMzZGNmXkEyXkFqcGdeQXVyMjQzMzQzODY@._V1_.jpg", + 766, + 1023 + ], + "id": "tt0100678", + "l": "Stan the Flasher", + "q": "feature", + "qid": "movie", + "s": "Claude Berri, Aurore Clément", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BMDlmNTQ3NzctMGUzYi00MjEyLWIzNmUtNjhjYzZlMDQ5OTE3XkEyXkFqcGdeQXVyMzY4ODk0Nw@@._V1_.jpg", + 800, + 600 + ], + "id": "tt27750546", + "l": "The Flash: Video News Release", + "q": "TV special", + "qid": "tvSpecial", + "s": "John Wesley Shipp, Amanda Pays", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BMjViZmVlMmUtNzljNS00NjhjLTk5ODMtNTZiZWRlOWRkMWU5XkEyXkFqcGdeQXVyMDA1NzM3OA@@._V1_.jpg", + 1500, + 2000 + ], + "id": "tt8408320", + "l": "Shenzhen Flash", + "q": "short", + "qid": "short", + "s": "", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BODU4YmIxYzItYTdjYy00NmQ3LWJkYmQtM2UwZGZjNjZhMjYwXkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_.jpg", + 1991, + 2931 + ], + "id": "tt0097365", + "l": "Flesh Gordon Meets the Cosmic Cheerleaders", + "q": "feature", + "qid": "movie", + "s": "Vince Murdocco, Robyn Kelly", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BYjMwMjgwNjAtZjllYi00Y2QyLWI2MzUtOGIwMDJjNWQ3YjQxL2ltYWdlL2ltYWdlXkEyXkFqcGdeQXVyNjg3MTAzODM@._V1_.jpg", + 3183, + 2015 + ], + "id": "tt2356508", + "l": "Arrow Flash", + "q": "video game", + "qid": "videoGame", + "s": "Action, Sci-Fi", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BNTZkNzU2MzEtNzUwMS00NTFmLTgxY2EtZTk1ZTI3NDUzN2M1XkEyXkFqcGdeQXVyMTgwMDI4MTc@._V1_.jpg", + 299, + 230 + ], + "id": "tt0444569", + "l": "Clash!", + "q": "TV series", + "qid": "tvSeries", + "s": "Billy Kimball, Dave Levin", + "y": 1990 + }, + { + "i": [ + "https://m.media-amazon.com/images/M/MV5BNGNkZTYwNTYtNTc2Mi00ODFjLTg3MjctNTRiMGQwMDc4MjBkXkEyXkFqcGdeQXVyMzU0NzkwMDg@._V1_.jpg", + 1152, + 1548 + ], + "id": "tt0099584", + "l": "Of Flesh and Blood", + "q": "feature", + "qid": "movie", + "s": "Breon, Dick Bangham", + "y": 1990 + } + ], + "q": "the_flash%201990", + "v": 1 +} \ No newline at end of file diff --git a/src/node/consumer/test/assets/test-cinemata-theflash.json b/src/node/consumer/test/assets/test-cinemata-theflash.json new file mode 100644 index 0000000..c2791b4 --- /dev/null +++ b/src/node/consumer/test/assets/test-cinemata-theflash.json @@ -0,0 +1,373 @@ +{ + "meta": { + "awards": "Nominated for 2 Primetime Emmys. 4 nominations total", + "cast": [ + "John Wesley Shipp", + "Amanda Pays", + "Alex Désert" + ], + "country": "United States", + "description": "A police forensic scientist, Barry Allen, battles crimes as the super-fast superhero \"The Flash.\"", + "director": null, + "dvdRelease": "2011-01-25T00:00:00.000Z", + "genre": [ + "Action", + "Crime", + "Fantasy" + ], + "imdbRating": "7.1", + "imdb_id": "tt0098798", + "name": "The Flash", + "popularity": 0.987, + "poster": "https://images.metahub.space/poster/small/tt0098798/img", + "released": "1990-09-20T00:00:00.000Z", + "runtime": "2 min", + "status": "Ended", + "tvdb_id": "78650", + "type": "series", + "writer": [ + "Danny Bilson", + "Paul De Meo" + ], + "year": "1990–1991", + "popularities": { + "moviedb": 57.842, + "trakt": 2, + "stremio": 0.987, + "stremio_lib": 0 + }, + "background": "https://images.metahub.space/background/medium/tt0098798/img", + "logo": "https://images.metahub.space/logo/medium/tt0098798/img", + "moviedb_id": 236, + "slug": "series/the-flash-0098798", + "id": "tt0098798", + "genres": [ + "Action", + "Crime", + "Fantasy" + ], + "releaseInfo": "1990–1991", + "videos": [ + { + "name": "Pilot", + "season": 1, + "number": 1, + "firstAired": "1990-09-20T00:00:00.000Z", + "tvdb_id": 335168, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/1/w780.jpg", + "id": "tt0098798:1:1", + "released": "1990-09-20T00:00:00.000Z", + "episode": 1 + }, + { + "name": "Out of Control", + "season": 1, + "number": 2, + "firstAired": "1990-09-27T00:00:00.000Z", + "tvdb_id": 291041, + "rating": "7.5", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/2/w780.jpg", + "id": "tt0098798:1:2", + "released": "1990-09-27T00:00:00.000Z", + "episode": 2 + }, + { + "name": "Watching the Detectives", + "season": 1, + "number": 3, + "firstAired": "1990-10-18T00:00:00.000Z", + "tvdb_id": 291042, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/3/w780.jpg", + "id": "tt0098798:1:3", + "released": "1990-10-18T00:00:00.000Z", + "episode": 3 + }, + { + "name": "Honor Among Thieves", + "season": 1, + "number": 4, + "firstAired": "1990-10-25T00:00:00.000Z", + "tvdb_id": 291043, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/4/w780.jpg", + "id": "tt0098798:1:4", + "released": "1990-10-25T00:00:00.000Z", + "episode": 4 + }, + { + "name": "Double Vision", + "season": 1, + "number": 5, + "firstAired": "1990-11-01T00:00:00.000Z", + "tvdb_id": 291044, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/5/w780.jpg", + "id": "tt0098798:1:5", + "released": "1990-11-01T00:00:00.000Z", + "episode": 5 + }, + { + "name": "Sins of the Father", + "season": 1, + "number": 6, + "firstAired": "1990-11-08T00:00:00.000Z", + "tvdb_id": 291045, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/6/w780.jpg", + "id": "tt0098798:1:6", + "released": "1990-11-08T00:00:00.000Z", + "episode": 6 + }, + { + "name": "Child's Play", + "season": 1, + "number": 7, + "firstAired": "1990-11-15T00:00:00.000Z", + "tvdb_id": 291046, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/7/w780.jpg", + "id": "tt0098798:1:7", + "released": "1990-11-15T00:00:00.000Z", + "episode": 7 + }, + { + "name": "Shroud of Death", + "season": 1, + "number": 8, + "firstAired": "1990-11-29T00:00:00.000Z", + "tvdb_id": 291047, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/8/w780.jpg", + "id": "tt0098798:1:8", + "released": "1990-11-29T00:00:00.000Z", + "episode": 8 + }, + { + "name": "Ghost in the Machine", + "season": 1, + "number": 9, + "firstAired": "1990-12-13T00:00:00.000Z", + "tvdb_id": 291048, + "rating": "7.5", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/9/w780.jpg", + "id": "tt0098798:1:9", + "released": "1990-12-13T00:00:00.000Z", + "episode": 9 + }, + { + "name": "Sight Unseen", + "season": 1, + "number": 10, + "firstAired": "1991-01-10T00:00:00.000Z", + "tvdb_id": 291049, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/10/w780.jpg", + "id": "tt0098798:1:10", + "released": "1991-01-10T00:00:00.000Z", + "episode": 10 + }, + { + "name": "Beat the Clock", + "season": 1, + "number": 11, + "firstAired": "1991-01-31T00:00:00.000Z", + "tvdb_id": 291050, + "rating": "6.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/11/w780.jpg", + "id": "tt0098798:1:11", + "released": "1991-01-31T00:00:00.000Z", + "episode": 11 + }, + { + "name": "The Trickster", + "season": 1, + "number": 12, + "firstAired": "1991-02-07T00:00:00.000Z", + "tvdb_id": 291051, + "rating": "7.5", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/12/w780.jpg", + "id": "tt0098798:1:12", + "released": "1991-02-07T00:00:00.000Z", + "episode": 12 + }, + { + "name": "Tina, Is That You?", + "season": 1, + "number": 13, + "firstAired": "1991-02-14T00:00:00.000Z", + "tvdb_id": 291052, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/13/w780.jpg", + "id": "tt0098798:1:13", + "released": "1991-02-14T00:00:00.000Z", + "episode": 13 + }, + { + "name": "Be My Baby", + "season": 1, + "number": 14, + "firstAired": "1991-02-21T00:00:00.000Z", + "tvdb_id": 291053, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/14/w780.jpg", + "id": "tt0098798:1:14", + "released": "1991-02-21T00:00:00.000Z", + "episode": 14 + }, + { + "name": "Fast Forward", + "season": 1, + "number": 15, + "firstAired": "1991-02-27T00:00:00.000Z", + "tvdb_id": 291054, + "rating": "6.5", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/15/w780.jpg", + "id": "tt0098798:1:15", + "released": "1991-02-27T00:00:00.000Z", + "episode": 15 + }, + { + "name": "Deadly Nightshade", + "season": 1, + "number": 16, + "firstAired": "1991-03-30T00:00:00.000Z", + "tvdb_id": 291055, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/16/w780.jpg", + "id": "tt0098798:1:16", + "released": "1991-03-30T00:00:00.000Z", + "episode": 16 + }, + { + "name": "Captain Cold", + "season": 1, + "number": 17, + "firstAired": "1991-04-06T00:00:00.000Z", + "tvdb_id": 291056, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/17/w780.jpg", + "id": "tt0098798:1:17", + "released": "1991-04-06T00:00:00.000Z", + "episode": 17 + }, + { + "name": "Twin Streaks", + "season": 1, + "number": 18, + "firstAired": "1991-04-13T00:00:00.000Z", + "tvdb_id": 291057, + "rating": "6.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/18/w780.jpg", + "id": "tt0098798:1:18", + "released": "1991-04-13T00:00:00.000Z", + "episode": 18 + }, + { + "name": "Done with Mirrors", + "season": 1, + "number": 19, + "firstAired": "1991-04-27T00:00:00.000Z", + "tvdb_id": 291058, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/19/w780.jpg", + "id": "tt0098798:1:19", + "released": "1991-04-27T00:00:00.000Z", + "episode": 19 + }, + { + "name": "Good Night, Central City", + "season": 1, + "number": 20, + "firstAired": "1991-05-04T00:00:00.000Z", + "tvdb_id": 291059, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/20/w780.jpg", + "id": "tt0098798:1:20", + "released": "1991-05-04T00:00:00.000Z", + "episode": 20 + }, + { + "name": "Alpha", + "season": 1, + "number": 21, + "firstAired": "1991-05-11T00:00:00.000Z", + "tvdb_id": 291060, + "rating": "7.0", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/21/w780.jpg", + "id": "tt0098798:1:21", + "released": "1991-05-11T00:00:00.000Z", + "episode": 21 + }, + { + "name": "The Trial of the Trickster", + "season": 1, + "number": 22, + "firstAired": "1991-05-18T00:00:00.000Z", + "tvdb_id": 291061, + "rating": "7.5", + "thumbnail": "https://episodes.metahub.space/tt0098798/1/22/w780.jpg", + "id": "tt0098798:1:22", + "released": "1991-05-18T00:00:00.000Z", + "episode": 22 + } + ], + "links": [ + { + "name": "7.1", + "category": "imdb", + "url": "https://imdb.com/title/tt0098798" + }, + { + "name": "The Flash", + "category": "share", + "url": "https://www.strem.io/s/series/the-flash-0098798" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fv3-cinemeta.strem.io%2Fmanifest.json/series/top?genre=Action" + }, + { + "name": "Crime", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fv3-cinemeta.strem.io%2Fmanifest.json/series/top?genre=Crime" + }, + { + "name": "Fantasy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fv3-cinemeta.strem.io%2Fmanifest.json/series/top?genre=Fantasy" + }, + { + "name": "John Wesley Shipp", + "category": "Cast", + "url": "stremio:///search?search=John%20Wesley%20Shipp" + }, + { + "name": "Amanda Pays", + "category": "Cast", + "url": "stremio:///search?search=Amanda%20Pays" + }, + { + "name": "Alex Désert", + "category": "Cast", + "url": "stremio:///search?search=Alex%20D%C3%A9sert" + }, + { + "name": "Danny Bilson", + "category": "Writers", + "url": "stremio:///search?search=Danny%20Bilson" + }, + { + "name": "Paul De Meo", + "category": "Writers", + "url": "stremio:///search?search=Paul%20De%20Meo" + } + ], + "behaviorHints": { + "defaultVideoId": null, + "hasScheduledVideos": true + } + } +} \ No newline at end of file diff --git a/src/node/consumer/test/assets/test-kitsu-search-id-naruto.json b/src/node/consumer/test/assets/test-kitsu-search-id-naruto.json new file mode 100644 index 0000000..1ff7631 --- /dev/null +++ b/src/node/consumer/test/assets/test-kitsu-search-id-naruto.json @@ -0,0 +1,1060 @@ +{ + "metas": [ + { + "id": "kitsu:11", + "type": "series", + "animeType": "TV", + "name": "Naruto", + "aliases": [ + "Naruto" + ], + "description": "Moments prior to Naruto Uzumaki's birth, a huge demon known as the Kyuubi, the Nine-Tailed Fox, attacked Konohagakure, the Hidden Leaf Village, and wreaked havoc. In order to put an end to the Kyuubi's rampage, the leader of the village, the Fourth Hokage, sacrificed his life and sealed the monstrous beast inside the newborn Naruto.\nNow, Naruto is a hyperactive and knuckle-headed ninja still living in Konohagakure. Shunned because of the Kyuubi inside him, Naruto struggles to find his place in the village, while his burning desire to become the Hokage of Konohagakure leads him not only to some great new friends, but also some deadly foes.\n[Written by MAL Rewrite]", + "releaseInfo": "2002-2007", + "runtime": "23 min", + "imdbRating": "8.0", + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power" + ], + "logo": "https://assets.fanart.tv/fanart/tv/78857/hdtvlogo/naruto-50667b3780bf2.png", + "poster": "https://media.kitsu.io/anime/11/poster_image/medium-410cee5d114a5f70d69e795755e8348a.jpeg", + "background": "https://assets.fanart.tv/fanart/tv/78857/showbackground/naruto-53b827ea97f87.jpg", + "trailers": [ + { + "source": "j2hiC9BmJlQ", + "type": "Trailer" + } + ], + "links": [ + { + "name": "8.0", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:1555", + "type": "series", + "animeType": "TV", + "name": "Naruto: Shippuuden", + "aliases": [ + "Naruto: Shippuden", + "Naruto: Shippuuden", + "Naruto Hurricane Chronicles" + ], + "description": "It has been two and a half years since Naruto Uzumaki left Konohagakure, the Hidden Leaf Village, for intense training following events which fueled his desire to be stronger. Now Akatsuki, the mysterious organization of elite rogue ninja, is closing in on their grand plan which may threaten the safety of the entire shinobi world.\n\nAlthough Naruto is older and sinister events loom on the horizon, he has changed little in personality—still rambunctious and childish—though he is now far more confident and possesses an even greater determination to protect his friends and home. Come whatever may, Naruto will carry on with the fight for what is important to him, even at the expense of his own body, in the continuation of the saga about the boy who wishes to become Hokage.\n\n(Source: MAL Rewrite)", + "releaseInfo": "2007-2017", + "runtime": "23 min", + "imdbRating": "8.4", + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power", + "Adventure" + ], + "logo": "https://assets.fanart.tv/fanart/tv/79824/hdtvlogo/naruto-shippuuden-540cc2d768e14.png", + "poster": "https://media.kitsu.io/anime/poster_images/1555/medium.jpg", + "background": "https://assets.fanart.tv/fanart/tv/79824/showbackground/naruto-shippuuden-53d6e20630860.jpg", + "trailers": [ + { + "source": "1dy2zPPrKD0", + "type": "Trailer" + } + ], + "links": [ + { + "name": "8.4", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + } + ] + }, + { + "id": "kitsu:46581", + "type": "series", + "animeType": "special", + "name": "ROAD OF NARUTO", + "aliases": [ + "ROAD OF NARUTO", + "NARUTO - ナルト - 20 周年記念", + "NARUTO 20 Shuunenkinen", + "Naruto 20th Anniversary PV" + ], + "description": "A special animation to commemorate the 20th anniversary of the NARUTO anime.", + "releaseInfo": "2022", + "runtime": "10 min", + "imdbRating": "8.3", + "genres": [], + "poster": "https://media.kitsu.io/anime/46581/poster_image/medium-9ecc4e4e91f2e6b0012115e33104ba28.jpeg", + "background": "https://media.kitsu.io/anime/46581/cover_image/777c9d609b0fe4da063651a7b6c60708.jpg", + "trailers": [ + { + "source": "yKELA1qBAKA", + "type": "Trailer" + } + ], + "links": [ + { + "name": "8.3", + "category": "imdb", + "url": "https://kitsu.io/anime/road-of-naruto" + } + ] + }, + { + "id": "kitsu:549", + "type": "series", + "animeType": "special", + "name": "Naruto: Takigakure no Shitou - Ore ga Eiyuu Dattebayo!", + "aliases": [ + "Naruto: The Lost Story - Mission: Protect the Waterfall Village", + "Naruto: Takigakure no Shitou - Ore ga Eiyuu Dattebayo!", + "Battle at Hidden Falls. I am the Hero!", + "Naruto OVA 2", + "Naruto: Jump Festa 2004" + ], + "description": "A routine rank-C mission turned into a full-blown battle as the Hidden Fall village is attacked by enemy ninjas. Now Naruto, Sasuke and Sakura must help the leader of the Hidden Fall, Shibuki, protect his village and show him what being a hero is all about.\n(Source: ANN)", + "releaseInfo": "2003", + "runtime": "40 min", + "imdbRating": "6.6", + "genres": [ + "Action", + "Adventure", + "Comedy", + "Super Power" + ], + "poster": "https://media.kitsu.io/anime/poster_images/549/medium.jpg", + "background": "https://media.kitsu.io/anime/cover_images/549/original.jpg", + "trailers": [], + "links": [ + { + "name": "6.6", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-takigakure-no-shitou-ore-ga-eiyuu-dattebayo" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:7008", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Shippuuden Movie 6 - Road to Ninja", + "aliases": [ + "Road to Ninja: Naruto the Movie", + "Naruto: Shippuuden Movie 6 - Road to Ninja", + "Naruto Movie 9" + ], + "description": "Ten years ago, a gigantic demon beast known as the Nine-Tailed Demon Fox was released from its jinchuuriki by an unknown shinobi wearing a mask. The village of Konohagakure was close to destruction by the attack of the Nine-Tails, but the village was saved by its leader. Minato Namikaze and his wife Kushina Uzumaki—who was the jinchuuriki at the time of the attack—sealed away the demon inside their new born son: Naruto Uzumaki. However, this act of saving the village cost them their lives and they left the future of the ninja world to Naruto.\nWith the demon fox sealed away, things continued as normal. However, the peace of the village would not last long, for Pain, Konan, Itachi Uchiha, Kisame Hoshigaki, Sasori, Deidara, Hidan and Kakuzu—members of a dreaded shinobi group called the Akatsuki—attacked Konohagakure. Naruto narrowly manages to launch a counter-attack but why have these shinobi appeared when all of them were meant to have died? The mystery remains, but the shinobi are praised by heir families for completing such a dangerous mission. However, one of them who has never known the faces of his parents, Naruto, cannot help but feel lonely. At that exact time, suddenly, the masked man makes his appearance in Konoha. Naruto and his allies are both attacked by the man's mysterious new doujutsu.\n(Source: Naruto Wikia)", + "releaseInfo": "2012", + "runtime": "109 min", + "imdbRating": "7.8", + "genres": [ + "Action", + "Adventure", + "Martial Arts", + "Super Power" + ], + "logo": "https://assets.fanart.tv/fanart/movies/118406/hdmovielogo/naruto-shippuden-movie-6-road-to-ninja-51888cf79d03d.png", + "poster": "https://media.kitsu.io/anime/poster_images/7008/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt2290828/img", + "trailers": [ + { + "source": "TDpYU8OmD-k", + "type": "Trailer" + } + ], + "links": [ + { + "name": "7.8", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-movie-6-road-to-ninja" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:2036", + "type": "series", + "animeType": "special", + "name": "Naruto: Dai Katsugeki!! Yuki Hime Shinobu Houjou Dattebayo! Special: Konoha Annual Sports Festival", + "aliases": [ + "Hidden Leaf Village Grand Sports Festival", + "Naruto: Dai Katsugeki!! Yuki Hime Shinobu Houjou Dattebayo! Special: Konoha Annual Sports Festival", + "Gekijouban Naruto: Dai Katsugeki! Yuki Hime Ninpouchou Datte ba yo! - S1 Konoha Annual Sports Festival", + "Konoha no Sato no Daiun Douaki" + ], + "description": "The genin of Kohona are having a sports day filled with races, obstacle courses and of course the relay and the prize is a paid vacation for the winner. Unfortunately Naruto and his stomach are getting him into trouble again.\nNaruto really needs to go to the toilet but he has to wait for the line to the restroom is so long even the Akatsuki and Kabuto are in line! After the group race he runs to the toilet to find it closed for cleaning but then he tries to go to into the ladies room but Hinata pops by and tries to tell Naruto something but is interrupted by the speaker and then off to the obstacle course.\nNaruto needs to drink a whole liter of milk in this critical state. After that he sees some portable toilets, but they are wrecked by Choji's Human Boulder. Naruto tries to beat them up but Ino comes and drags him back. Finally the relay; Sakura passed it to Sasuke but on Naruto's turn the baton Sasuke was holding poked his butt. Out of desperation Naruto wins and finishes the race. He runs off to find a toilet but Shikamaru stops him. They cheer for him on the track but Naruto can't hold it anymore and let's it ALL go on the field with everyone standing around him. \n", + "releaseInfo": "2004", + "runtime": "11 min", + "imdbRating": "6.6", + "genres": [ + "Action", + "Comedy", + "Fantasy", + "Martial Arts", + "Sports" + ], + "poster": "https://media.kitsu.io/anime/poster_images/2036/medium.jpg", + "background": "https://media.kitsu.io/anime/cover_images/2036/original.jpg", + "trailers": [], + "links": [ + { + "name": "6.6", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-dai-katsugeki-yuki-hime-shinobu-houjou-dattebayo-special-konoha-annual-sports-festival" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Fantasy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Fantasy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Sports", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Sports" + } + ] + }, + { + "id": "kitsu:2245", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Shippuuden Movie 1", + "aliases": [ + "Naruto: Shippuden the Movie", + "Naruto: Shippuuden Movie 1", + "Naruto Shippuuden Movie", + "Naruto Movie 4", + "Gekijouban Naruto Shippuuden" + ], + "description": "Demons that once almost destroyed the world, are revived by someone. To prevent the world from being destroyed, the demon has to be sealed and the only one who can do it is the shrine maiden Shion from the country of demons, who has two powers; one is sealing demons and the other is predicting the deaths of humans. This time Naruto's mission is to guard Shion, but she predicts Naruto's death. The only way to escape it, is to get away from Shion, which would leave her unguarded, then the demon, whose only goal is to kill Shion will do so, thus meaning the end of the world. Naruto decides to challenge this \"prediction of death,\" but fails to prove Shion's prediction wrong and supposedly dies in vain.\n(Source: Wikipedia)", + "releaseInfo": "2007", + "runtime": "94 min", + "imdbRating": "7.3", + "genres": [ + "Action", + "Adventure", + "Comedy", + "Fantasy" + ], + "logo": "https://assets.fanart.tv/fanart/movies/20982/hdmovielogo/-naruto-----5bedd3e81eabf.png", + "poster": "https://media.kitsu.io/anime/poster_images/2245/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt0988982/img", + "trailers": [], + "links": [ + { + "name": "7.3", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-movie-1" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Fantasy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Fantasy" + } + ] + }, + { + "id": "kitsu:3606", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Shippuuden Movie 2 - Kizuna", + "aliases": [ + "Naruto: Shippuden the Movie 2 -Bonds-", + "Naruto: Shippuuden Movie 2 - Kizuna", + "Naruto Movie 5", + "Naruto Shippuuden Movie 2", + "Naruto Shippuuden: Bonds" + ], + "description": "A mysterious group of ninjas makes a surprise attack on the Konohagakure, which takes great damage. The nightmare of another Shinobi World War could become a reality. Sasuke, who left Konoha to kill his brother, Itachi, appears for the second time in front of Naruto at an unknown location to prevent it from coming to fruition.\n(Source: Wikipedia)", + "releaseInfo": "2008", + "runtime": "93 min", + "imdbRating": "7.2", + "genres": [ + "Action", + "Martial Arts", + "Supernatural" + ], + "logo": "https://assets.fanart.tv/fanart/movies/17581/hdmovielogo/naruto-shippuden-the-movie-bonds-5bec1ee26ec2c.png", + "poster": "https://media.kitsu.io/anime/poster_images/3606/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt1160524/img", + "trailers": [ + { + "source": "OkI3ZCEbx_E", + "type": "Trailer" + } + ], + "links": [ + { + "name": "7.2", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-movie-2-kizuna" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Supernatural", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Supernatural" + } + ] + }, + { + "id": "kitsu:6861", + "type": "series", + "animeType": "TV", + "name": "Naruto SD: Rock Lee no Seishun Full-Power Ninden", + "aliases": [ + "NARUTO Spin-Off: Rock Lee & His Ninja Pals", + "Naruto SD: Rock Lee no Seishun Full-Power Ninden" + ], + "description": "Welcome to the Hidden Leaf Village. The village where Uzumaki Naruto, star of the TV show \"Naruto\" makes his home. Every day, countless powerful ninjas carry out missions and train to hone their skills. Our main character is one of these powerful ninjas...but it's not Naruto! It's the ninja who can't use ninjutsu, Rock Lee! In spite of his handicap, Lee has big dreams. He works hard every day to perfect his hand-to-hand combat skills and become a splendid ninja! And to achieve his dream, he puts in more effort than anyone else. Under the hot-blooded tutelage of his teacher Guy, he works alongside his teammates Tenten and Neji. Watch the Beautiful Green Beast Rock Lee train, go on missions, and have all sorts of adventures! \n(Source: Crunchyroll) ", + "releaseInfo": "2012-2013", + "runtime": "24 min", + "imdbRating": "6.7", + "genres": [ + "Action", + "Comedy", + "Parody" + ], + "logo": "https://assets.fanart.tv/fanart/tv/257837/hdtvlogo/rock-lee--his-ninja-pals-61ffa96d3a159.png", + "poster": "https://media.kitsu.io/anime/poster_images/6861/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt2301807/img", + "trailers": [ + { + "source": "vAuU88KX8EA", + "type": "Trailer" + } + ], + "links": [ + { + "name": "6.7", + "category": "imdb", + "url": "https://kitsu.io/anime/rock-lee-no-seishun-full-power-ninden" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Parody", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Parody" + } + ] + }, + { + "id": "kitsu:3484", + "type": "series", + "animeType": "special", + "name": "Naruto Shippuuden: Shippuu! \"Konoha Gakuen\" Den", + "aliases": [ + "Naruto Shippuden: Konoha Gakuen - Special", + "Naruto Shippuuden: Shippuu! \"Konoha Gakuen\" Den", + "NARUTO Shippu Konoha Gakuen Den Special", + "Konoha High" + ], + "description": "Naruto school special.\nNaruto is a new cool student and when he meets Sasuke they start fighting.", + "releaseInfo": "2008", + "runtime": "8 min", + "imdbRating": "6.9", + "genres": [ + "Comedy" + ], + "poster": "https://media.kitsu.io/anime/poster_images/3484/medium.jpg", + "background": "https://media.kitsu.io/anime/cover_images/3484/original.jpg", + "trailers": [], + "links": [ + { + "name": "6.9", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-konoha-gakuen-special" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + } + ] + }, + { + "id": "kitsu:1941", + "type": "movie", + "animeType": "movie", + "name": "Naruto Movie 3: Dai Koufun! Mikazuki Jima no Animaru Panikku Dattebayo!", + "aliases": [ + "Naruto the Movie 3: Guardians of the Crescent Moon Kingdom", + "Naruto Movie 3: Dai Koufun! Mikazuki Jima no Animaru Panikku Dattebayo!", + "Naruto Movie Volume 3", + "Naruto: Gekijouban Naruto: Dai Koufun! Mikazuki-jima no Animal Panic Datte ba yo!" + ], + "description": "Naruto, Kakashi, Sakura, and Lee are sent to protect a prince during his trip around the world and see that he returns safely to his home in the Moon Country. The Moon Country happens to be really rich and as such the Prince tends to buy anything his heart desires, during his travels the Prince would come across a circus group that features a rare Sabre-toothed tiger that he just had to have. So he purchased the entire group. Suddenly a mission to protect just the spoiled prince that hardly listened to anything said, turns in to a mission to look after animals and a prince that doesn't listen to what they say, and in the end somehow get them all back safely to their home country. All the while there are three mysterious Ninja wielding some frightening jutsu waiting for them. Why are they attacking them? What do they want with Team Kakashi!?!\n(Source: NarutoFan)", + "releaseInfo": "2006", + "runtime": "94 min", + "imdbRating": "6.7", + "genres": [ + "Action", + "Adventure" + ], + "logo": "https://assets.fanart.tv/fanart/movies/18861/hdmovielogo/naruto-the-movie-guardians-of-the-crescent-moon-kingdom-5bedb85d66f02.png", + "poster": "https://media.kitsu.io/anime/poster_images/1941/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt1071815/img", + "trailers": [], + "links": [ + { + "name": "6.7", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-movie-3-dai-koufun-mikazuki-jima-no-animaru-panikku-dattebayo" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + } + ] + }, + { + "id": "kitsu:13051", + "type": "series", + "animeType": "TV", + "name": "Boruto: Naruto Next Generations", + "aliases": [ + "Boruto: Naruto Next Generations" + ], + "description": "Naruto was a young shinobi with an incorrigible knack for mischief. He achieved his dream to become the greatest ninja in the village and his face sits atop the Hokage monument. But this is not his story... A new generation of ninja are ready to take the stage, led by Naruto's own son, Boruto!\n\n(Source: VIZ Media)", + "releaseInfo": "2017-2023", + "runtime": "23 min", + "imdbRating": "6.4", + "genres": [ + "Adventure", + "Martial Arts", + "Super Power", + "Action" + ], + "logo": "https://assets.fanart.tv/fanart/tv/321285/hdtvlogo/boruto-naruto-next-generations-58e5152372f97.png", + "poster": "https://media.kitsu.io/anime/13051/poster_image/medium-16da0c0699ed8ccb42f8832a35791a00.jpeg", + "background": "https://assets.fanart.tv/fanart/tv/321285/showbackground/boruto-naruto-next-generations-5cc9deee6417c.jpg", + "trailers": [ + { + "source": "p3acMxaM7-g", + "type": "Trailer" + } + ], + "links": [ + { + "name": "6.4", + "category": "imdb", + "url": "https://kitsu.io/anime/boruto-naruto-next-generations" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + } + ] + }, + { + "id": "kitsu:833", + "type": "movie", + "animeType": "movie", + "name": "Naruto Movie 2: Dai Gekitotsu! Maboroshi no Chiteiiseki Dattebayo!", + "aliases": [ + "Naruto the Movie 2: Legend of the Stone of Gelel", + "Naruto Movie 2: Dai Gekitotsu! Maboroshi no Chiteiiseki Dattebayo!", + "Naruto THE Movie vol.2", + "Naruto Movie 2", + "Gekijouban Naruto" + ], + "description": "Naruto, Shikamaru, and Sakura are executing their mission of delivering a lost pet to a certain village. However, right in the midst of things, troops led by the mysterious knight, Temujin, attack them. In the violent battle, the three become separated. Temujin challenges Naruto to a fight and at the end of the fierce battle, both fall together from a high cliff. Furthermore, Shikamaru, having been left behind, beholds a giant moving fortress as it appears before his very eyes. In order to get a grasp on the situation, he infiltrates the fortress by himself, however once there he witnesses a frightening sight... \n(Source: ANN)", + "releaseInfo": "2005", + "runtime": "96 min", + "imdbRating": "6.7", + "genres": [ + "Adventure", + "Comedy", + "Drama", + "Fantasy", + "Supernatural" + ], + "logo": "https://assets.fanart.tv/fanart/movies/16910/hdmovielogo/naruto-the-movie-2-legend-of-the-stone-of-gelel-5bedb846070cd.png", + "poster": "https://media.kitsu.io/anime/poster_images/833/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt0791188/img", + "trailers": [], + "links": [ + { + "name": "6.7", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-movie-2-daigekitotsu-maboroshi-no-chiteiiseki-dattebayo" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Drama", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Drama" + }, + { + "name": "Fantasy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Fantasy" + }, + { + "name": "Supernatural", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Supernatural" + } + ] + }, + { + "id": "kitsu:5266", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Shippuuden Movie 4 - The Lost Tower", + "aliases": [ + "Naruto: Shippuuden Movie 4 - The Lost Tower", + "Naruto Movie 7", + "Gekijouban Naruto Shippuuden: The Lost Tower" + ], + "description": "Assigned on a mission to capture Mukade, a missing-nin, Naruto Uzumaki sets out for the once glorious historic ruins of \"Ouran\", where he pursues and corners the rogue ninja. Mukade's goal is revealed to be a dormant leyline within the ruins; he unleashes the power of the leyline, causing a light to envelop Naruto, sending him into the past, 20 years before the series began. When Naruto awakens, he comes into contact with the Fourth Hokage, Minato Namikaze.\n(Source: Wikipedia) ", + "releaseInfo": "2010", + "runtime": "85 min", + "imdbRating": "7.4", + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power" + ], + "logo": "https://assets.fanart.tv/fanart/movies/50723/hdmovielogo/naruto-shippuden-the-movie-the-lost-tower-520653a7df7ae.png", + "poster": "https://media.kitsu.io/anime/poster_images/5266/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt1703048/img", + "trailers": [ + { + "source": "q4C4CZT8NTM", + "type": "Trailer" + } + ], + "links": [ + { + "name": "7.4", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-movie-4-the-lost-tower" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:4520", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Shippuuden Movie 3 - Hi no Ishi wo Tsugu Mono", + "aliases": [ + "Naruto Shippuden the Movie: Will of Fire", + "Naruto: Shippuuden Movie 3 - Hi no Ishi wo Tsugu Mono", + "Naruto Shippuuden: Gekijouban Naruto Shippuuden: Hi no Ishi o Tsugu Mono", + "Naruto Shippuuden Movie 3", + "Naruto Movie 6", + "Naruto Shippuuden 3: Inheritors of Will of Fire" + ], + "description": "Ninjas with bloodline limits begin disappearing in all the countries and blame points toward the fire nation. By Tsunade's order, Kakashi is sacrificed to prevent an all out war. After inheriting charms left by Kakashi, Naruto fights through friends and foes to prevent his death while changing the minds of those who've inherited the will of fire.\n(Source: ANN)", + "releaseInfo": "2009", + "runtime": "95 min", + "imdbRating": "7.3", + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power" + ], + "logo": "https://assets.fanart.tv/fanart/movies/36728/hdmovielogo/naruto-shippuden-the-movie-inheritors-of-the-will-of-fire-5beeac1a1b9a3.png", + "poster": "https://media.kitsu.io/anime/poster_images/4520/medium.jpg", + "background": "https://assets.fanart.tv/fanart/movies/36728/moviebackground/naruto-shippuden-the-movie-inheritors-of-the-will-of-fire-61eb010493d50.jpg", + "trailers": [ + { + "source": "dJ12XeF6S2Y", + "type": "Trailer" + } + ], + "links": [ + { + "name": "7.3", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-shippuden-movie-3-hi-no-ishi-wo-tsugu-mono" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:7543", + "type": "movie", + "animeType": "movie", + "name": "The Last: Naruto the Movie", + "aliases": [ + "The Last: Naruto the Movie", + "Naruto Movie 10: Naruto the Movie: The Last,Naruto: Shippuuden Movie 7 - The Last", + "Naruto Movie 10: Naruto the Movie: The Last", + "Naruto: Shippuuden Movie 7 - The Last" + ], + "description": "The moon is beginning to fall, and at the rate it's going, it is doomed to fall on the Earth. The countdown for the survival of the planet begins. Among the havoc, Hinata's younger sister Hanabi is captured by the mysterious enemy, Toneri Ootsutsuki. Naruto must overcome great danger on a mission to save Hanabi and the world along with Hinata, Sai, Shikamaru, and Sakura is their final story. \"The final story is a first love.\"\n\n(Source: Anime News Network)", + "releaseInfo": "2014", + "runtime": "112 min", + "imdbRating": "8.0", + "genres": [ + "Action", + "Martial Arts", + "Super Power", + "Romance" + ], + "logo": "https://assets.fanart.tv/fanart/movies/317442/hdmovielogo/the-last-naruto-the-movie-553cbe16d6e54.png", + "poster": "https://media.kitsu.io/anime/7543/poster_image/medium-bb44bd1650f32d1c947e07eb073eb5e8.jpeg", + "background": "https://assets.fanart.tv/fanart/movies/317442/moviebackground/the-last-naruto-the-movie-56d5e9bdf1fa6.jpg", + "trailers": [ + { + "source": "tA3yE4_t6SY", + "type": "Trailer" + } + ], + "links": [ + { + "name": "8.0", + "category": "imdb", + "url": "https://kitsu.io/anime/the-last-naruto-the-movie" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + }, + { + "name": "Romance", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Romance" + } + ] + }, + { + "id": "kitsu:11771", + "type": "series", + "animeType": "special", + "name": "Boruto: Naruto the Movie - Naruto ga Hokage ni Natta Hi", + "aliases": [ + "Boruto: Naruto the Movie - Naruto ga Hokage ni Natta Hi", + "Boruto: Naruto the Movie - The Day Naruto Became the Hokage" + ], + "description": "Bundled with the limited edition of Blu-ray/DVD of Boruto: Naruto the Movie.", + "releaseInfo": "2016", + "runtime": "10 min", + "imdbRating": "7.5", + "genres": [ + "Action", + "Comedy", + "Martial Arts", + "Super Power" + ], + "poster": "https://media.kitsu.io/anime/poster_images/11771/medium.jpg", + "background": "https://media.kitsu.io/anime/cover_images/11771/original.jpg", + "trailers": [], + "links": [ + { + "name": "7.5", + "category": "imdb", + "url": "https://kitsu.io/anime/boruto-naruto-the-movie-naruto-ga-hokage-ni-natta-hi" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:405", + "type": "movie", + "animeType": "movie", + "name": "Naruto the Movie: Ninja Clash in the Land of Snow", + "aliases": [ + "Naruto the Movie: Ninja Clash in the Land of Snow", + "Naruto Movie 1: Dai Katsugeki!! Yuki Hime Shinobu Houjou Dattebayo!", + "Naruto: Daikatsugeki! Yukihime Ninpocho Dattebayo!", + "Naruto: It's the Snow Princess' Ninja Art Book!" + ], + "description": "A land forever covered in ice... A princess missing for ten years... And one high-spirited ninja named Naruto! \nNaruto and the rest of Squad 7 take on a new mission: bring popular movie star Yukie Fujikaze to the Land of Snow, where they're filming the final scenes of her latest movie. Trouble is, she's even more headstrong than Naruto, and she doesn't want to go! Her reluctance may be connected to what else lies in wait for them--three rogue Snow ninja and a tyrannical ruler seeking the key to a mysterious treasure...\n(Source: VIZ Media)", + "releaseInfo": "2004", + "runtime": "82 min", + "imdbRating": "6.9", + "genres": [ + "Adventure", + "Comedy", + "Drama", + "Historical", + "Supernatural" + ], + "logo": "https://assets.fanart.tv/fanart/movies/16907/hdmovielogo/naruto-the-movie-ninja-clash-in-the-land-of-snow-5bedc89654867.png", + "poster": "https://media.kitsu.io/anime/poster_images/405/medium.jpg", + "background": "https://images.metahub.space/background/medium/tt0476680/img", + "trailers": [], + "links": [ + { + "name": "6.9", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-the-movie-ninja-clash-in-the-land-of-snow" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Drama", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Drama" + }, + { + "name": "Historical", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Historical" + }, + { + "name": "Supernatural", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Supernatural" + } + ] + }, + { + "id": "kitsu:6292", + "type": "movie", + "animeType": "movie", + "name": "Naruto: Honoo no Chuunin Shiken! Naruto vs. Konohamaru!!", + "aliases": [ + "Chunin Exam on Fire! and Naruto vs. Konohamaru!", + "Naruto: Honoo no Chuunin Shiken! Naruto vs. Konohamaru!!" + ], + "description": "Naruto faces off against his old pupil Konohamaru in a tournament during the chuunin entrance exams.", + "releaseInfo": "2011", + "runtime": "14 min", + "imdbRating": "7.1", + "genres": [ + "Action", + "Adventure", + "Martial Arts", + "Super Power" + ], + "poster": "https://media.kitsu.io/anime/6292/poster_image/medium-5aaa86a422ce294f2551e3387ca4edc9.jpeg", + "background": "https://media.kitsu.io/anime/cover_images/6292/original.jpg", + "trailers": [], + "links": [ + { + "name": "7.1", + "category": "imdb", + "url": "https://kitsu.io/anime/naruto-honoo-no-chuunin-shiken-naruto-vs-konohamaru" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Adventure", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Adventure" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + } + ] + }, + { + "id": "kitsu:10089", + "type": "movie", + "animeType": "movie", + "name": "Boruto: Naruto the Movie", + "aliases": [ + "Boruto: Naruto the Movie", + "Gekijouban Naruto (2015)" + ], + "description": "Boruto Uzumaki has inherited the mischievous spirit and endless energy from his famous father, the 7th Hokage, Naruto. As he enters his Chunin exams, a harsh decision made by Naruto angers Boruto, causing their personalities to clash, awakening a fierce ambition within the young shinobi to surpass his father with his own skills and techniques. But in order to do so, he will need the help of none other than Uchiha Sasuke, Naruto's lifelong rival and childhood friend. Although Boruto has convinced himself that he has what it takes to surpass the 7th Hokage, he soon discovers that the road ahead is not nearly as simple as the young shinobi has envisioned.Boruto: Naruto the Movie opens the doors for a new generation of shinobi to put their abilities to the test, as they face a mysterious enemy and hope to restore peace to Konoha, and the hardships within their own families. The 7th Hokage certainly has an impressive battle history behind him, but on this occasion, he will need the strong teamwork of old friends and new talents in order to win.", + "releaseInfo": "2015", + "runtime": "95 min", + "imdbRating": "7.6", + "genres": [ + "Action", + "Comedy", + "Super Power", + "Martial Arts" + ], + "logo": "https://assets.fanart.tv/fanart/movies/347201/hdmovielogo/boruto-naruto-the-movie-56069e1a3f13f.png", + "poster": "https://media.kitsu.io/anime/10089/poster_image/medium-08ef5392ff25db376a86b040d242296d.jpeg", + "background": "https://images.metahub.space/background/medium/tt4618398/img", + "trailers": [ + { + "source": "Cvdv2GGnn0A", + "type": "Trailer" + } + ], + "links": [ + { + "name": "7.6", + "category": "imdb", + "url": "https://kitsu.io/anime/boruto-naruto-the-movie" + }, + { + "name": "Action", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Action" + }, + { + "name": "Comedy", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Comedy" + }, + { + "name": "Super Power", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Super Power" + }, + { + "name": "Martial Arts", + "category": "Genres", + "url": "stremio:///discover/https%3A%2F%2Fanime-kitsu.strem.fun%2Fmanifest.json/anime/kitsu-anime-popular?genre=Martial Arts" + } + ] + } + ], + "cacheMaxAge": 43200 +} \ No newline at end of file diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/cache_service.test.ts index 3e258b1..79acdf2 100644 --- a/src/node/consumer/test/cache_service.test.ts +++ b/src/node/consumer/test/cache_service.test.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; // required -import { ILoggingService } from '@interfaces/logging_service'; -import { CacheService, CacheMethod } from '@services/cache_service'; +import {ILoggingService} from '@interfaces/logging_service'; +import {CacheMethod, CacheService} from '@services/cache_service'; jest.mock('@services/configuration_service', () => { return { @@ -12,7 +12,7 @@ jest.mock('@services/configuration_service', () => { MONGO_INITDB_ROOT_USERNAME: 'mongo', MONGO_INITDB_ROOT_PASSWORD: 'mongo', NO_CACHE: false, - COLLECTION_NAME: 'knightcrawler_consumer_collection', + COLLECTION_NAME: 'knightcrawler_consumer_collection', }, } } @@ -43,8 +43,8 @@ jest.mock('@tirke/node-cache-manager-mongodb', () => { describe('CacheService Tests', () => { let cacheService: CacheService, - loggingService: ILoggingService, - cacheMethod: CacheMethod; + loggingService: ILoggingService, + cacheMethod: CacheMethod; beforeEach(() => { process.env.LOG_LEVEL = 'debug'; @@ -100,7 +100,7 @@ describe('CacheService Tests', () => { cacheMethod = jest.fn().mockRejectedValue(new Error('Test error')); await expect(cacheService.cacheTrackers(cacheMethod)).rejects.toThrow('Test error'); }); - + it('should handle when cache is disabled', async () => { jest.mock('@services/configuration_service', () => { return { diff --git a/src/node/consumer/test/configuration_service.test.ts b/src/node/consumer/test/configuration_service.test.ts index fc21c39..c751564 100644 --- a/src/node/consumer/test/configuration_service.test.ts +++ b/src/node/consumer/test/configuration_service.test.ts @@ -26,13 +26,13 @@ describe('Configuration Tests', () => { process.env.IMDB_INTERVAL_MS = '1000'; process.env.JOB_CONCURRENCY = '1'; process.env.JOBS_ENABLED = 'true'; - + // shitty hack cause jest caches modules and resetModules isnt working - ({ configurationService } = await import("@services/configuration_service")); + ({configurationService} = await import("@services/configuration_service")); }); - + it('should populate cacheConfig correctly', () => { - const { cacheConfig } = configurationService; + const {cacheConfig} = configurationService; expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); expect(cacheConfig.MONGODB_PORT).toBe('27017'); expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); @@ -44,7 +44,7 @@ describe('Configuration Tests', () => { }); it('should populate databaseConfig correctly', () => { - const { databaseConfig } = configurationService; + const {databaseConfig} = configurationService; expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); expect(databaseConfig.POSTGRES_PORT).toBe(5432); expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); @@ -55,33 +55,33 @@ describe('Configuration Tests', () => { }); it('should populate jobConfig correctly', () => { - const { jobConfig } = configurationService; + const {jobConfig} = configurationService; expect(jobConfig.JOB_CONCURRENCY).toBe(1); expect(jobConfig.JOBS_ENABLED).toBe(true); }); it('should populate metadataConfig correctly', () => { - const { metadataConfig } = configurationService; + const {metadataConfig} = configurationService; expect(metadataConfig.IMDB_CONCURRENT).toBe(1); expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); }); it('should populate rabbitConfig correctly', () => { - const { rabbitConfig } = configurationService; + const {rabbitConfig} = configurationService; expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); }); it('should populate torrentConfig correctly', () => { - const { torrentConfig } = configurationService; + const {torrentConfig} = configurationService; expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); expect(torrentConfig.TIMEOUT).toBe(30000); }); it('should populate trackerConfig correctly', () => { - const { trackerConfig } = configurationService; + const {trackerConfig} = configurationService; expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); expect(trackerConfig.UDP_ENABLED).toBe(false); }); - + }); \ No newline at end of file diff --git a/src/node/consumer/test/logging_service.test.ts b/src/node/consumer/test/logging_service.test.ts index 08ffc41..6dff068 100644 --- a/src/node/consumer/test/logging_service.test.ts +++ b/src/node/consumer/test/logging_service.test.ts @@ -1,5 +1,5 @@ import "reflect-metadata"; // required -import { LoggingService } from '@services/logging_service'; +import {LoggingService} from '@services/logging_service'; jest.mock('pino', () => { const actualPino = jest.requireActual('pino'); @@ -14,7 +14,7 @@ jest.mock('pino', () => { }; }); -describe('LoggingService', () => { +describe('LoggingService Tests', () => { let service: LoggingService, mockLogger: any; @@ -24,22 +24,22 @@ describe('LoggingService', () => { }); it('should log info', () => { - service.info('test message', { key: 'value' }); - expect(mockLogger.info).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + service.info('test message', {key: 'value'}); + expect(mockLogger.info).toHaveBeenCalledWith('test message', [{key: 'value'}]); }); it('should log error', () => { - service.error('test message', { key: 'value' }); - expect(mockLogger.error).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + service.error('test message', {key: 'value'}); + expect(mockLogger.error).toHaveBeenCalledWith('test message', [{key: 'value'}]); }); it('should log debug', () => { - service.debug('test message', { key: 'value' }); - expect(mockLogger.debug).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + service.debug('test message', {key: 'value'}); + expect(mockLogger.debug).toHaveBeenCalledWith('test message', [{key: 'value'}]); }); it('should log warn', () => { - service.warn('test message', { key: 'value' }); - expect(mockLogger.warn).toHaveBeenCalledWith('test message', [{ key: 'value' }]); + service.warn('test message', {key: 'value'}); + expect(mockLogger.warn).toHaveBeenCalledWith('test message', [{key: 'value'}]); }) }); \ No newline at end of file diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/metadata_service.test.ts new file mode 100644 index 0000000..9a786bc --- /dev/null +++ b/src/node/consumer/test/metadata_service.test.ts @@ -0,0 +1,91 @@ +import "reflect-metadata"; // required +import {ICacheService} from "@interfaces/cache_service"; +import {IMetadataResponse} from "@interfaces/metadata_response"; +import {MetadataService} from "@services/metadata_service"; +import {setupServer} from "msw/node"; +import * as responses from "./mock-responses/metadata_mock_responses"; + +jest.mock('@services/cache_service', () => { + return { + cacheWrapImdbId: jest.fn().mockImplementation(async (key, fn) => await fn()), + cacheWrapKitsuId: jest.fn().mockImplementation(async (key, fn) => await fn()), + cacheWrapMetadata: jest.fn().mockImplementation(async (key, fn) => await fn()), + } +}) + +const server = setupServer( + responses.cinemetaQueryResponse, + responses.cinemetaFlashMetadataSearchTestResponse, + responses.kitsuNarutoIdSearchTestResponse, + responses.kitsuNarutoMetaDataSearchTestResponse, + responses.nameToImdbTheFlash, + responses.checkIfImdbEpisode); + +beforeAll(() => server.listen()) +beforeEach(() => { + jest.spyOn(Date, 'now').mockImplementation(() => 1234567890); +}) +afterEach(() => () => { + server.resetHandlers() + jest.spyOn(Date, 'now').mockRestore(); +}) +afterAll(() => server.close()) + +describe('MetadataService Tests', () => { + let metadataService: MetadataService, + mockCacheService: ICacheService; + + beforeEach(() => { + mockCacheService = jest.requireMock('@services/cache_service'); + metadataService = new MetadataService(mockCacheService); + }); + + it("should get kitsu id", async () => { + const result = await metadataService.getKitsuId({ + title: 'Naruto', + year: 2002, + season: 1 + }); + expect(mockCacheService.cacheWrapKitsuId).toHaveBeenCalledWith('naruto 2002 S1', expect.any(Function)); + expect(result).not.toBeNull(); + expect(result).toEqual('11'); + }); + + it("should get kitsu metadata", async () => { + const result = await metadataService.getMetadata({ + id: 'kitsu:11', + type: 'series' + }); + + expect(mockCacheService.cacheWrapMetadata).toHaveBeenCalledWith('kitsu:11', expect.any(Function)); + expect(result).not.toBeNull(); + + const body = result as IMetadataResponse; + expect(body.videos).not.toBeNull(); + expect(body.videos.length).toBe(220); + }); + + it("should get imdb metadata", async () => { + const result = await metadataService.getMetadata({ + id: 'tt0098798', + type: 'series' + }); + + expect(mockCacheService.cacheWrapMetadata).toHaveBeenCalledWith('tt0098798', expect.any(Function)); + expect(result).not.toBeNull(); + + const body = result as IMetadataResponse; + expect(body.videos).not.toBeNull(); + expect(body.videos.length).toBe(22); + }); + + it("should check if imdb id is an episode", async () => { + const result = await metadataService.isEpisodeImdbId('tt0579968'); + expect(result).toBe(true); + }); + + it("should escape title", () => { + const result = metadataService.escapeTitle('Naruto: Shippuden'); + expect(result).toEqual('naruto shippuden'); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/mock-responses/metadata_mock_responses.ts b/src/node/consumer/test/mock-responses/metadata_mock_responses.ts new file mode 100644 index 0000000..1b4b18d --- /dev/null +++ b/src/node/consumer/test/mock-responses/metadata_mock_responses.ts @@ -0,0 +1,40 @@ +import {http, HttpResponse} from "msw"; +import cinemetaQuery from "../assets/cinemeta-query-response.json"; +import cinemetaFlashFull from "../assets/flash-episode-list.json"; +import kitsuNarutoFull from "../assets/kitsu-naruto-full.json"; +import imdbTheFlash from "../assets/name-to-imdb-flash.json"; +import kitsuNarutoSearchId from "../assets/test-kitsu-search-id-naruto.json"; + +const kitsuNarutoIdSearchTestResponse = http.get('https://anime-kitsu.strem.fun/catalog/series/kitsu-anime-list/search=naruto%202002%20S1.json', () => { + return HttpResponse.json(kitsuNarutoSearchId); +}); + +const kitsuNarutoMetaDataSearchTestResponse = http.get('https://anime-kitsu.strem.fun/meta/Series/kitsu:11.json', () => { + return HttpResponse.json(kitsuNarutoFull); +}); + +const nameToImdbTheFlash = http.get('https://sg.media-imdb.com/suggests/t/the%20flash%201990.json', () => { + const jsonpResponse = `/**/imdb$the_flash%201990(${JSON.stringify(imdbTheFlash)});`; + return HttpResponse.json(jsonpResponse); +}); + +const cinemetaQueryResponse = http.get('https://cinemeta.strem.io/stremioget/stremio/v1/q.json', () => { + return HttpResponse.json(cinemetaQuery); +}); + +const cinemetaFlashMetadataSearchTestResponse = http.get('https://v3-cinemeta.strem.io/meta/imdb/tt0098798.json', () => { + return HttpResponse.json(cinemetaFlashFull); +}); + +const checkIfImdbEpisode = http.get('https://www.imdb.com/title/tt0579968/', () => { + return HttpResponse.text(''); +}); + +export { + kitsuNarutoIdSearchTestResponse, + kitsuNarutoMetaDataSearchTestResponse, + nameToImdbTheFlash, + cinemetaQueryResponse, + cinemetaFlashMetadataSearchTestResponse, + checkIfImdbEpisode +} \ No newline at end of file diff --git a/src/node/consumer/test/mock-responses/trackers_mock_responses.ts b/src/node/consumer/test/mock-responses/trackers_mock_responses.ts new file mode 100644 index 0000000..ca4d68a --- /dev/null +++ b/src/node/consumer/test/mock-responses/trackers_mock_responses.ts @@ -0,0 +1,5 @@ +import {http, HttpResponse} from "msw"; + +export const trackerTestResponse = http.get('https://ngosang.github.io/trackerslist/trackers_all.txt', () => { + return HttpResponse.text('http://tracker1.com\nhttp://tracker2.com') +}); \ No newline at end of file diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts index 0b551d6..ec4c2ea 100644 --- a/src/node/consumer/test/process_torrent_job.test.ts +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -1,8 +1,8 @@ import "reflect-metadata"; // required -import { ILoggingService } from '@interfaces/logging_service'; -import { ITorrentProcessingService } from '@interfaces/torrent_processing_service'; -import { ProcessTorrentsJob } from '@jobs/process_torrents_job'; -import { configurationService } from '@services/configuration_service'; +import {ILoggingService} from '@interfaces/logging_service'; +import {ITorrentProcessingService} from '@interfaces/torrent_processing_service'; +import {ProcessTorrentsJob} from '@jobs/process_torrents_job'; +import {configurationService} from '@services/configuration_service'; import client, {ConsumeMessage} from 'amqplib'; jest.mock('@services/configuration_service', () => { @@ -48,7 +48,7 @@ jest.mock('@services/torrent_processing_service', () => { }) describe('ProcessTorrentsJob Tests', () => { - let processTorrentsJob: ProcessTorrentsJob, + let processTorrentsJob: ProcessTorrentsJob, loggingService: ILoggingService, torrentProcessingService: ITorrentProcessingService; @@ -60,7 +60,7 @@ describe('ProcessTorrentsJob Tests', () => { afterEach(() => { jest.clearAllMocks() - }) + }) describe('listenToQueue', () => { test('should connect to the rabbitmq server and create a channel', async () => { @@ -79,7 +79,7 @@ describe('ProcessTorrentsJob Tests', () => { test('should process messages from the queue', async () => { const mockMessage = { - content: Buffer.from(JSON.stringify({ + content: Buffer.from(JSON.stringify({ message: { name: 'test_name', source: 'test_source', @@ -90,7 +90,7 @@ describe('ProcessTorrentsJob Tests', () => { leechers: 0, imdb: 'test_imdb', processed: false, - } + } })), } as ConsumeMessage; diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/torrent_download_service.test.ts index 7b19925..ef13ca6 100644 --- a/src/node/consumer/test/torrent_download_service.test.ts +++ b/src/node/consumer/test/torrent_download_service.test.ts @@ -1,7 +1,7 @@ import "reflect-metadata"; // required -import { ILoggingService } from '@interfaces/logging_service'; +import {ILoggingService} from '@interfaces/logging_service'; import {IParsedTorrent} from "@interfaces/parsed_torrent"; -import { TorrentDownloadService } from '@services/torrent_download_service'; +import {TorrentDownloadService} from '@services/torrent_download_service'; import torrentStream from 'torrent-stream'; jest.mock('@services/logging_service', () => { @@ -22,7 +22,7 @@ jest.mock('torrent-stream', () => { describe('TorrentDownloadService', () => { let torrentDownloadService: TorrentDownloadService, - mockLoggingService: ILoggingService; + mockLoggingService: ILoggingService; beforeEach(() => { mockLoggingService = jest.requireMock('@services/logging_service'); @@ -42,7 +42,7 @@ describe('TorrentDownloadService', () => { uploadDate: new Date(), seeders: 100, torrentId: 'torrent1', - fileCollection: { }, + fileCollection: {}, title: 'Test Movie', year: 2020, season: 1, @@ -58,7 +58,7 @@ describe('TorrentDownloadService', () => { container: 'mp4', unrated: false, }; - + const mockFiles = [ { name: 'file1.mp4', @@ -134,7 +134,7 @@ describe('TorrentDownloadService', () => { fileId: file.fileIndex, })), }); - + expect(torrentStream).toHaveBeenCalledWith(expect.any(String), expect.any(Object)); expect(mockLoggingService.debug).toHaveBeenCalledWith(`Adding torrent with infoHash ${mockTorrent.infoHash} to torrent engine...`); }); diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/tracker_service.test.ts index e233479..3fe9981 100644 --- a/src/node/consumer/test/tracker_service.test.ts +++ b/src/node/consumer/test/tracker_service.test.ts @@ -1,15 +1,11 @@ import "reflect-metadata"; // required -import { ICacheService } from '@interfaces/cache_service'; -import { ILoggingService } from '@interfaces/logging_service'; -import { TrackerService } from '@services/tracker_service'; -import { http, HttpResponse } from 'msw' -import { setupServer } from 'msw/node'; +import {ICacheService} from '@interfaces/cache_service'; +import {ILoggingService} from '@interfaces/logging_service'; +import {TrackerService} from '@services/tracker_service'; +import {setupServer} from 'msw/node'; +import * as responses from "./mock-responses/trackers_mock_responses"; -const server = setupServer( - http.get('https://ngosang.github.io/trackerslist/trackers_all.txt', ({ request, params, cookies }) => { - return HttpResponse.text('http://tracker1.com\nhttp://tracker2.com') - }), -) +const server = setupServer(responses.trackerTestResponse); jest.mock('@services/logging_service', () => { return { @@ -38,8 +34,8 @@ afterAll(() => server.close()) describe('TrackerService', () => { let trackerService: TrackerService, - mockCacheService: ICacheService, - mockLoggingService: ILoggingService; + mockCacheService: ICacheService, + mockLoggingService: ILoggingService; beforeEach(() => { mockCacheService = jest.requireMock('@services/cache_service'); @@ -54,6 +50,6 @@ describe('TrackerService', () => { expect(result).toEqual(mockTrackers); expect(mockLoggingService.info).toHaveBeenCalledWith(`Trackers updated at 1234567890: ${mockTrackers.length} trackers`); - + }); }); \ No newline at end of file diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index e3f3dd3..d85609d 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -2,8 +2,12 @@ "compileOnSave": false, "compilerOptions": { "target": "ESNext", - "lib": ["ESNext"], - "typeRoots": ["node_modules/@types"], + "lib": [ + "ESNext" + ], + "typeRoots": [ + "node_modules/@types" + ], "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, @@ -21,16 +25,37 @@ "importHelpers": true, "baseUrl": "src", "paths": { - "@/*": ["*"], - "@enums/*": ["lib/enums/*"], - "@repository/*": ["lib/repository/*"], - "@interfaces/*": ["lib/interfaces/*"], - "@models/*": ["lib/models/*"], - "@services/*": ["lib/services/*"], - "@helpers/*": ["lib/helpers/*"], - "@jobs/*": ["lib/jobs/*"] + "@/*": [ + "*" + ], + "@enums/*": [ + "lib/enums/*" + ], + "@repository/*": [ + "lib/repository/*" + ], + "@interfaces/*": [ + "lib/interfaces/*" + ], + "@models/*": [ + "lib/models/*" + ], + "@services/*": [ + "lib/services/*" + ], + "@helpers/*": [ + "lib/helpers/*" + ], + "@jobs/*": [ + "lib/jobs/*" + ] } }, - "include": ["src", "test"], - "exclude": ["node_modules"] + "include": [ + "src", + "test" + ], + "exclude": [ + "node_modules" + ] } \ No newline at end of file From 001d10fac9434df8afe589edb1f2de2821511f0a Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 18:08:24 +0000 Subject: [PATCH 43/55] dont like where i put assets - moved them closer to the mock response methods that use them --- .../assets/cinemeta-query-response.json | 0 .../assets/flash-episode-list.json | 0 .../{ => mock-responses}/assets/kitsu-naruto-full.json | 0 .../assets/name-to-imdb-flash.json | 0 .../assets/test-cinemata-theflash.json | 0 .../assets/test-kitsu-search-id-naruto.json | 0 .../test/mock-responses/metadata_mock_responses.ts | 10 +++++----- 7 files changed, 5 insertions(+), 5 deletions(-) rename src/node/consumer/test/{ => mock-responses}/assets/cinemeta-query-response.json (100%) rename src/node/consumer/test/{ => mock-responses}/assets/flash-episode-list.json (100%) rename src/node/consumer/test/{ => mock-responses}/assets/kitsu-naruto-full.json (100%) rename src/node/consumer/test/{ => mock-responses}/assets/name-to-imdb-flash.json (100%) rename src/node/consumer/test/{ => mock-responses}/assets/test-cinemata-theflash.json (100%) rename src/node/consumer/test/{ => mock-responses}/assets/test-kitsu-search-id-naruto.json (100%) diff --git a/src/node/consumer/test/assets/cinemeta-query-response.json b/src/node/consumer/test/mock-responses/assets/cinemeta-query-response.json similarity index 100% rename from src/node/consumer/test/assets/cinemeta-query-response.json rename to src/node/consumer/test/mock-responses/assets/cinemeta-query-response.json diff --git a/src/node/consumer/test/assets/flash-episode-list.json b/src/node/consumer/test/mock-responses/assets/flash-episode-list.json similarity index 100% rename from src/node/consumer/test/assets/flash-episode-list.json rename to src/node/consumer/test/mock-responses/assets/flash-episode-list.json diff --git a/src/node/consumer/test/assets/kitsu-naruto-full.json b/src/node/consumer/test/mock-responses/assets/kitsu-naruto-full.json similarity index 100% rename from src/node/consumer/test/assets/kitsu-naruto-full.json rename to src/node/consumer/test/mock-responses/assets/kitsu-naruto-full.json diff --git a/src/node/consumer/test/assets/name-to-imdb-flash.json b/src/node/consumer/test/mock-responses/assets/name-to-imdb-flash.json similarity index 100% rename from src/node/consumer/test/assets/name-to-imdb-flash.json rename to src/node/consumer/test/mock-responses/assets/name-to-imdb-flash.json diff --git a/src/node/consumer/test/assets/test-cinemata-theflash.json b/src/node/consumer/test/mock-responses/assets/test-cinemata-theflash.json similarity index 100% rename from src/node/consumer/test/assets/test-cinemata-theflash.json rename to src/node/consumer/test/mock-responses/assets/test-cinemata-theflash.json diff --git a/src/node/consumer/test/assets/test-kitsu-search-id-naruto.json b/src/node/consumer/test/mock-responses/assets/test-kitsu-search-id-naruto.json similarity index 100% rename from src/node/consumer/test/assets/test-kitsu-search-id-naruto.json rename to src/node/consumer/test/mock-responses/assets/test-kitsu-search-id-naruto.json diff --git a/src/node/consumer/test/mock-responses/metadata_mock_responses.ts b/src/node/consumer/test/mock-responses/metadata_mock_responses.ts index 1b4b18d..01eba04 100644 --- a/src/node/consumer/test/mock-responses/metadata_mock_responses.ts +++ b/src/node/consumer/test/mock-responses/metadata_mock_responses.ts @@ -1,9 +1,9 @@ import {http, HttpResponse} from "msw"; -import cinemetaQuery from "../assets/cinemeta-query-response.json"; -import cinemetaFlashFull from "../assets/flash-episode-list.json"; -import kitsuNarutoFull from "../assets/kitsu-naruto-full.json"; -import imdbTheFlash from "../assets/name-to-imdb-flash.json"; -import kitsuNarutoSearchId from "../assets/test-kitsu-search-id-naruto.json"; +import cinemetaQuery from "./assets/cinemeta-query-response.json"; +import cinemetaFlashFull from "./assets/flash-episode-list.json"; +import kitsuNarutoFull from "./assets/kitsu-naruto-full.json"; +import imdbTheFlash from "./assets/name-to-imdb-flash.json"; +import kitsuNarutoSearchId from "./assets/test-kitsu-search-id-naruto.json"; const kitsuNarutoIdSearchTestResponse = http.get('https://anime-kitsu.strem.fun/catalog/series/kitsu-anime-list/search=naruto%202002%20S1.json', () => { return HttpResponse.json(kitsuNarutoSearchId); From fe8b7a096ddc0081c0b53d78622e9a45e7a05136 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 21:16:48 +0000 Subject: [PATCH 44/55] few more metadata tests and a single torrent entry service test for now --- .../src/lib/services/metadata_service.ts | 152 ++++++++++-------- .../consumer/test/metadata_service.test.ts | 30 +++- .../test/torrent_entries_service.test.ts | 109 +++++++++++++ 3 files changed, 218 insertions(+), 73 deletions(-) create mode 100644 src/node/consumer/test/torrent_entries_service.test.ts diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index 0faeb4d..f986f34 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -15,7 +15,7 @@ import nameToImdb from 'name-to-imdb'; const CINEMETA_URL = 'https://v3-cinemeta.strem.io'; const KITSU_URL = 'https://anime-kitsu.strem.fun'; -const TIMEOUT = 20000; +const TIMEOUT = 60000; @injectable() export class MetadataService implements IMetadataService { @@ -33,7 +33,7 @@ export class MetadataService implements IMetadataService { const query = encodeURIComponent(key); return this.cacheService.cacheWrapKitsuId(key, - () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, {timeout: 60000}) + () => axios.get(`${KITSU_URL}/catalog/series/kitsu-anime-list/search=${query}.json`, {timeout: TIMEOUT}) .then((response) => { const body = response.data as IKitsuCatalogJsonResponse; if (body && body.metas && body.metas.length) { @@ -75,14 +75,14 @@ export class MetadataService implements IMetadataService { return this.cacheService.cacheWrapMetadata(key.toString(), () => { switch (isImdbId) { case true: - return this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/imdb/${key}.json`); + return this.requestMetadata(`${CINEMETA_URL}/meta/imdb/${key}.json`, this.handleCinemetaResponse); default: - return this.requestKitsuMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`) + return this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`, this.handleKitsuResponse) }}) .catch(() => { // try different type in case there was a mismatch const otherType = metaType === TorrentType.Movie ? TorrentType.Series : TorrentType.Movie; - return this.requestCinemetaMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`) + return this.requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`, this.handleCinemetaResponse) }) .catch((error) => { throw new Error(`failed metadata query ${key} due: ${error.message}`); @@ -90,12 +90,16 @@ export class MetadataService implements IMetadataService { }; public isEpisodeImdbId = async (imdbId: string | undefined): Promise => { - if (!imdbId) { + if (!imdbId || !imdbId.toString().match(/^tt\d+$/)) { + return false; + } + + try { + const response = await axios.get(`https://www.imdb.com/title/${imdbId}/`, {timeout: TIMEOUT}); + return response.data.includes('video.episode'); + } catch (error) { return false; } - return axios.get(`https://www.imdb.com/title/${imdbId}/`, {timeout: 10000}) - .then(response => !!(response.data && response.data.includes('video.episode'))) - .catch(() => false); }; public escapeTitle = (title: string): string => title.toLowerCase() @@ -108,72 +112,78 @@ export class MetadataService implements IMetadataService { .replace(/\s{2,}/, ' ') // replace multiple spaces .trim(); - private requestKitsuMetadata = async (url: string): Promise => { - const response = await axios.get(url, {timeout: TIMEOUT}); - const body = response.data; - return this.handleKitsuResponse(body as IKitsuJsonResponse); + private requestMetadata = async (url: string, handler: (body: unknown) => IMetadataResponse): Promise => { + try { + const response = await axios.get(url, { timeout: TIMEOUT }); + const body = response.data; + return handler(body); + } catch (error) { + throw new Error(`HTTP error! status: ${error.response?.status}`); + } }; - private requestCinemetaMetadata = async (url: string): Promise => { - const response = await axios.get(url, {timeout: TIMEOUT}); - const body = response.data; - return this.handleCinemetaResponse(body as ICinemetaJsonResponse); + private handleCinemetaResponse = (response: unknown): IMetadataResponse => { + const body = response as ICinemetaJsonResponse + + return ({ + imdbId: parseInt(body.meta?.id || '0'), + type: body.meta?.type, + title: body.meta?.name, + year: parseInt(body.meta?.year || '0'), + country: body.meta?.country, + genres: body.meta?.genres, + status: body.meta?.status, + videos: body.meta?.videos + ? body.meta.videos.map(video => ({ + name: video.name, + season: video.season, + episode: video.episode, + imdbSeason: video.season, + imdbEpisode: video.episode, + })) + : [], + episodeCount: body.meta?.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta?.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }); }; - private handleCinemetaResponse = (body: ICinemetaJsonResponse): IMetadataResponse => ({ - imdbId: parseInt(body.meta?.id || '0'), - type: body.meta?.type, - title: body.meta?.name, - year: parseInt(body.meta?.year || '0'), - country: body.meta?.country, - genres: body.meta?.genres, - status: body.meta?.status, - videos: body.meta?.videos - ? body.meta.videos.map(video => ({ - name: video.name, - season: video.season, - episode: video.episode, - imdbSeason: video.season, - imdbEpisode: video.episode, - })) - : [], - episodeCount: body.meta?.videos - ? this.getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta?.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }); - - private handleKitsuResponse = (body: IKitsuJsonResponse): IMetadataResponse => ({ - kitsuId: parseInt(body.meta?.kitsu_id || '0'), - type: body.meta?.type, - title: body.meta?.name, - year: parseInt(body.meta?.year || '0'), - country: body.meta?.country, - genres: body.meta?.genres, - status: body.meta?.status, - videos: body.meta?.videos - ? body.meta?.videos.map(video => ({ - name: video.title, - season: video.season, - episode: video.episode, - kitsuId: video.id, - kitsuEpisode: video.episode, - released: video.released, - })) - : [], - episodeCount: body.meta?.videos - ? this.getEpisodeCount(body.meta.videos) - : [], - totalCount: body.meta?.videos - ? body.meta.videos.filter( - entry => entry.season !== 0 && entry.episode !== 0 - ).length - : 0, - }); + private handleKitsuResponse = (response: unknown): IMetadataResponse => { + const body = response as IKitsuJsonResponse; + + return ({ + kitsuId: parseInt(body.meta?.kitsu_id || '0'), + type: body.meta?.type, + title: body.meta?.name, + year: parseInt(body.meta?.year || '0'), + country: body.meta?.country, + genres: body.meta?.genres, + status: body.meta?.status, + videos: body.meta?.videos + ? body.meta?.videos.map(video => ({ + name: video.title, + season: video.season, + episode: video.episode, + kitsuId: video.id, + kitsuEpisode: video.episode, + released: video.released, + })) + : [], + episodeCount: body.meta?.videos + ? this.getEpisodeCount(body.meta.videos) + : [], + totalCount: body.meta?.videos + ? body.meta.videos.filter( + entry => entry.season !== 0 && entry.episode !== 0 + ).length + : 0, + }); + }; private getEpisodeCount = (videos: ICommonVideoMetadata[]): number[] => Object.values( diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/metadata_service.test.ts index 9a786bc..64a88d2 100644 --- a/src/node/consumer/test/metadata_service.test.ts +++ b/src/node/consumer/test/metadata_service.test.ts @@ -79,12 +79,38 @@ describe('MetadataService Tests', () => { expect(body.videos.length).toBe(22); }); - it("should check if imdb id is an episode", async () => { + it("should get imdb id the flash 2014", async () => { + const result = await metadataService.getImdbId({ + title: 'The Flash', + year: 2014, + type: 'series' + }); + expect(mockCacheService.cacheWrapImdbId).toHaveBeenCalledWith('the flash_2014_series', expect.any(Function)); + expect(result).not.toBeNull(); + expect(result).toEqual('tt3107288'); + }); + + it("should return false if imdb id is not provided", async () => { + const result = await metadataService.isEpisodeImdbId(undefined); + expect(result).toBe(false); + }); + + it("should return false if kitsu id is provided", async () => { + const result = await metadataService.isEpisodeImdbId("kitsu:11"); + expect(result).toBe(false); + }); + + it("should escape title naruto, with year", () => { + const result = metadataService.escapeTitle('Naruto: Shippuden | 2002'); + expect(result).toEqual('naruto shippuden 2002'); + }); + + it("should check if imdb id is an episode: the flash 1990", async () => { const result = await metadataService.isEpisodeImdbId('tt0579968'); expect(result).toBe(true); }); - it("should escape title", () => { + it("should escape title naruto, no year", () => { const result = metadataService.escapeTitle('Naruto: Shippuden'); expect(result).toEqual('naruto shippuden'); }); diff --git a/src/node/consumer/test/torrent_entries_service.test.ts b/src/node/consumer/test/torrent_entries_service.test.ts new file mode 100644 index 0000000..604aa36 --- /dev/null +++ b/src/node/consumer/test/torrent_entries_service.test.ts @@ -0,0 +1,109 @@ +import "reflect-metadata"; // required +import {TorrentType} from "@enums/torrent_types"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {ITorrentFileService} from "@interfaces/torrent_file_service"; +import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {TorrentEntriesService} from "@services/torrent_entries_service"; + + + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + warn: jest.fn(), + } +}) + +jest.mock('@services/torrent_file_service', () => { + return { + parseTorrentFiles: jest.fn(), + } +}) + +jest.mock('@services/metadata_service', () => { + return { + getImdbId: jest.fn(), + } +}) + +jest.mock('@services/torrent_subtitle_service', () => { + return { + assignSubtitles: jest.fn(), + } +}) + +jest.mock('@repository/database_repository', () => { + return { + createTorrent: jest.fn().mockResolvedValue(undefined), + createFile: jest.fn().mockResolvedValue(undefined), + } +}) + +describe('TorrentEntriesService Tests', () => { + let torrentEntriesService: TorrentEntriesService, + mockLoggingService: ILoggingService, + mockFileService: ITorrentFileService, + mockMetadataService: IMetadataService, + mockSubtitleService: ITorrentSubtitleService, + mockDatabaseRepository: IDatabaseRepository; + + beforeEach(() => { + mockFileService = jest.requireMock('@services/torrent_file_service'); + mockMetadataService = jest.requireMock('@services/metadata_service'); + mockSubtitleService = jest.requireMock('@services/torrent_subtitle_service'); + mockLoggingService = jest.requireMock('@services/logging_service'); + mockDatabaseRepository = jest.requireMock('@repository/database_repository'); + torrentEntriesService = new TorrentEntriesService(mockMetadataService, mockLoggingService, mockFileService , mockSubtitleService, mockDatabaseRepository); + }); + + it('should create a torrent entry', async () => { + const torrent : IParsedTorrent = { + title: 'Test title', + provider: 'Test provider', + infoHash: 'Test infoHash', + type: TorrentType.Movie, + }; + + const fileCollection : ITorrentFileCollection = { + videos: [{ + fileIndex: 0, + title: 'Test video', + size: 123456, + imdbId: 'tt1234567', + }], + contents: [], + subtitles: [], + }; + + const fileCollectionWithSubtitles : ITorrentFileCollection = { + ...fileCollection, + subtitles: [ { + fileId: 0, + title: 'Test subtitle', + fileIndex: 0, + path: 'Test path', + infoHash: 'Test infoHash', + }], + }; + + (mockMetadataService.getImdbId as jest.Mock).mockResolvedValue('tt1234567'); + (mockFileService.parseTorrentFiles as jest.Mock).mockResolvedValue(fileCollection); + (mockSubtitleService.assignSubtitles as jest.Mock).mockResolvedValue(fileCollectionWithSubtitles); + (mockDatabaseRepository.createTorrent as jest.Mock).mockResolvedValue(torrent); + + await torrentEntriesService.createTorrentEntry(torrent); + + expect(mockMetadataService.getImdbId).toHaveBeenCalledWith({ title: 'Test title', year: undefined, type: TorrentType.Movie }); + expect(mockFileService.parseTorrentFiles).toHaveBeenCalledWith(torrent); + expect(mockFileService.parseTorrentFiles).toHaveReturnedWith(Promise.resolve(fileCollection)); + expect(mockSubtitleService.assignSubtitles).toHaveBeenCalledWith(fileCollection); + expect(mockSubtitleService.assignSubtitles).toHaveReturnedWith(Promise.resolve(fileCollectionWithSubtitles)); + expect(mockDatabaseRepository.createTorrent).toHaveBeenCalledWith(expect.objectContaining(torrent)); + }); +}); \ No newline at end of file From c2ada8344e4ae98c08bec2b2708d646b2d474d00 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Thu, 8 Feb 2024 21:18:56 +0000 Subject: [PATCH 45/55] fix lint fix command --- src/node/consumer/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index ecf0674..09fa964 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -8,7 +8,7 @@ "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", "start": "node --trace-deprecation dist/main.cjs", "lint": "eslint ./src --ext .ts,.js", - "lint-fix": "npm run lint --fix", + "lint-fix": "npm run lint -- --fix", "test": "jest", "test:watch": "jest --watch" }, From 36864e4db164b35a4ebdcc4925e555b96f9cf57a Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Fri, 9 Feb 2024 14:59:27 +0000 Subject: [PATCH 46/55] tests to ensure entries are created --- .../lib/interfaces/torrent_entries_service.ts | 4 +- .../lib/services/torrent_entries_service.ts | 17 +- src/node/consumer/test/cache_service.test.ts | 1 + .../consumer/test/logging_service.test.ts | 1 + .../consumer/test/metadata_service.test.ts | 1 + .../consumer/test/process_torrent_job.test.ts | 1 + .../test/torrent_download_service.test.ts | 1 + .../test/torrent_entries_service.test.ts | 249 +++++++++++++++++- .../consumer/test/tracker_service.test.ts | 1 + 9 files changed, 260 insertions(+), 16 deletions(-) diff --git a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts index f05268a..032be9b 100644 --- a/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/interfaces/torrent_entries_service.ts @@ -1,12 +1,12 @@ import {IParsedTorrent} from "@interfaces/parsed_torrent"; -import {ITorrentAttributes} from "@repository/interfaces/torrent_attributes"; +import {ITorrentAttributes, ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; import {SkipTorrent} from "@repository/models/skipTorrent"; import {Torrent} from "@repository/models/torrent"; export interface ITorrentEntriesService { createTorrentEntry(torrent: IParsedTorrent, overwrite: boolean): Promise; - createSkipTorrentEntry(torrent: Torrent): Promise<[SkipTorrent, boolean | null]>; + createSkipTorrentEntry(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]>; getStoredTorrentEntry(torrent: Torrent): Promise; diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 17124d5..2bea7f1 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -110,7 +110,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); }; - public createSkipTorrentEntry: (torrent: Torrent) => Promise<[SkipTorrent, boolean | null]> = async (torrent: Torrent) => this.repository.createSkipTorrent(torrent.dataValues); + public createSkipTorrentEntry: (torrent: ITorrentCreationAttributes) => Promise<[SkipTorrent, boolean | null]> = async (torrent: ITorrentCreationAttributes) => this.repository.createSkipTorrent(torrent); public getStoredTorrentEntry = async (torrent: Torrent): Promise => this.repository.getSkipTorrent(torrent.infoHash) .catch(() => this.repository.getTorrent(torrent.dataValues)) @@ -173,8 +173,6 @@ export class TorrentEntriesService implements ITorrentEntriesService { return {}; }); - this.assignMetaIds(fileCollection, imdbId, kitsuId); - if (!fileCollection.contents || !fileCollection.contents.length) { return; } @@ -206,10 +204,13 @@ export class TorrentEntriesService implements ITorrentEntriesService { } return Promise.resolve(); }) - .then(() => PromiseHelpers.sequence(fileCollection.videos!.map(video => (): Promise => { - const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; - return this.repository.createFile(newVideo) - }))) + .then(() => { + const promises = fileCollection.videos!.map(video => { + const newVideo: IFileCreationAttributes = {...video, infoHash: video.infoHash, title: video.title}; + return this.repository.createFile(newVideo); + }); + return Promise.all(promises); + }) .then(() => this.logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) .catch(error => this.logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); }; @@ -248,7 +249,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { }; private assignMetaIds = (fileCollection: ITorrentFileCollection, imdbId: string | undefined, kitsuId: number): ITorrentFileCollection => { - if (fileCollection.videos && fileCollection.videos.length) { + if (fileCollection && fileCollection.videos && fileCollection.videos.length) { fileCollection.videos.forEach(video => { video.imdbId = imdbId || ''; video.kitsuId = kitsuId || 0; diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/cache_service.test.ts index 79acdf2..d32bb9a 100644 --- a/src/node/consumer/test/cache_service.test.ts +++ b/src/node/consumer/test/cache_service.test.ts @@ -47,6 +47,7 @@ describe('CacheService Tests', () => { cacheMethod: CacheMethod; beforeEach(() => { + jest.clearAllMocks(); process.env.LOG_LEVEL = 'debug'; loggingService = jest.requireMock('@services/logging_service'); cacheMethod = jest.fn().mockResolvedValue({}); diff --git a/src/node/consumer/test/logging_service.test.ts b/src/node/consumer/test/logging_service.test.ts index 6dff068..975d45e 100644 --- a/src/node/consumer/test/logging_service.test.ts +++ b/src/node/consumer/test/logging_service.test.ts @@ -19,6 +19,7 @@ describe('LoggingService Tests', () => { mockLogger: any; beforeEach(() => { + jest.clearAllMocks(); service = new LoggingService(); mockLogger = (service as any).logger; }); diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/metadata_service.test.ts index 64a88d2..3fa868a 100644 --- a/src/node/consumer/test/metadata_service.test.ts +++ b/src/node/consumer/test/metadata_service.test.ts @@ -23,6 +23,7 @@ const server = setupServer( beforeAll(() => server.listen()) beforeEach(() => { + jest.clearAllMocks(); jest.spyOn(Date, 'now').mockImplementation(() => 1234567890); }) afterEach(() => () => { diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts index ec4c2ea..0eac22b 100644 --- a/src/node/consumer/test/process_torrent_job.test.ts +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -53,6 +53,7 @@ describe('ProcessTorrentsJob Tests', () => { torrentProcessingService: ITorrentProcessingService; beforeEach(() => { + jest.clearAllMocks(); loggingService = jest.requireMock('@services/logging_service'); torrentProcessingService = jest.requireMock('@services/torrent_processing_service'); processTorrentsJob = new ProcessTorrentsJob(torrentProcessingService, loggingService); diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/torrent_download_service.test.ts index ef13ca6..f513d88 100644 --- a/src/node/consumer/test/torrent_download_service.test.ts +++ b/src/node/consumer/test/torrent_download_service.test.ts @@ -25,6 +25,7 @@ describe('TorrentDownloadService', () => { mockLoggingService: ILoggingService; beforeEach(() => { + jest.clearAllMocks(); mockLoggingService = jest.requireMock('@services/logging_service'); torrentDownloadService = new TorrentDownloadService(mockLoggingService); }); diff --git a/src/node/consumer/test/torrent_entries_service.test.ts b/src/node/consumer/test/torrent_entries_service.test.ts index 604aa36..50d0188 100644 --- a/src/node/consumer/test/torrent_entries_service.test.ts +++ b/src/node/consumer/test/torrent_entries_service.test.ts @@ -7,10 +7,11 @@ import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; import {ITorrentFileService} from "@interfaces/torrent_file_service"; import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {IFileAttributes} from "@repository/interfaces/file_attributes"; +import {ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; +import {Torrent} from "@repository/models/torrent"; import {TorrentEntriesService} from "@services/torrent_entries_service"; - - jest.mock('@services/logging_service', () => { return { error: jest.fn(), @@ -22,19 +23,21 @@ jest.mock('@services/logging_service', () => { jest.mock('@services/torrent_file_service', () => { return { - parseTorrentFiles: jest.fn(), + parseTorrentFiles: jest.fn().mockResolvedValue(undefined), + isPackTorrent: jest.fn().mockResolvedValue(undefined), } }) jest.mock('@services/metadata_service', () => { return { - getImdbId: jest.fn(), + getImdbId: jest.fn().mockResolvedValue(undefined), + getKitsuId: jest.fn().mockResolvedValue(undefined), } }) jest.mock('@services/torrent_subtitle_service', () => { return { - assignSubtitles: jest.fn(), + assignSubtitles: jest.fn().mockResolvedValue(undefined), } }) @@ -42,6 +45,11 @@ jest.mock('@repository/database_repository', () => { return { createTorrent: jest.fn().mockResolvedValue(undefined), createFile: jest.fn().mockResolvedValue(undefined), + createSkipTorrent: jest.fn().mockResolvedValue(undefined), + getSkipTorrent: jest.fn().mockResolvedValue(undefined), + getTorrent: jest.fn().mockResolvedValue(undefined), + setTorrentSeeders: jest.fn().mockResolvedValue(undefined), + getFiles: jest.fn().mockResolvedValue(undefined), } }) @@ -54,12 +62,14 @@ describe('TorrentEntriesService Tests', () => { mockDatabaseRepository: IDatabaseRepository; beforeEach(() => { + jest.clearAllMocks(); + mockFileService = jest.requireMock('@services/torrent_file_service'); mockMetadataService = jest.requireMock('@services/metadata_service'); mockSubtitleService = jest.requireMock('@services/torrent_subtitle_service'); mockLoggingService = jest.requireMock('@services/logging_service'); mockDatabaseRepository = jest.requireMock('@repository/database_repository'); - torrentEntriesService = new TorrentEntriesService(mockMetadataService, mockLoggingService, mockFileService , mockSubtitleService, mockDatabaseRepository); + torrentEntriesService = new TorrentEntriesService(mockMetadataService, mockLoggingService, mockFileService , mockSubtitleService, mockDatabaseRepository); }); it('should create a torrent entry', async () => { @@ -106,4 +116,231 @@ describe('TorrentEntriesService Tests', () => { expect(mockSubtitleService.assignSubtitles).toHaveReturnedWith(Promise.resolve(fileCollectionWithSubtitles)); expect(mockDatabaseRepository.createTorrent).toHaveBeenCalledWith(expect.objectContaining(torrent)); }); + + it('should assign imdbId correctly', async () => { + const torrent : IParsedTorrent = { + title: 'Test title', + provider: 'Test provider', + infoHash: 'Test infoHash', + type: TorrentType.Movie, + }; + + const fileCollection : ITorrentFileCollection = { + videos: [{ + fileIndex: 0, + title: 'Test video', + size: 123456, + imdbId: 'tt1234567', + }], + contents: [], + subtitles: [], + }; + + const fileCollectionWithSubtitles : ITorrentFileCollection = { + ...fileCollection, + subtitles: [ { + fileId: 0, + title: 'Test subtitle', + fileIndex: 0, + path: 'Test path', + infoHash: 'Test infoHash', + }], + }; + + (mockMetadataService.getImdbId as jest.Mock).mockResolvedValue('tt1234567'); + (mockFileService.parseTorrentFiles as jest.Mock).mockResolvedValue(fileCollection); + (mockSubtitleService.assignSubtitles as jest.Mock).mockResolvedValue(fileCollectionWithSubtitles); + (mockDatabaseRepository.createTorrent as jest.Mock).mockResolvedValue(torrent); + + await torrentEntriesService.createTorrentEntry(torrent); + + expect(torrent.imdbId).toEqual('tt1234567'); + expect(torrent.kitsuId).toEqual(undefined); + }); + + it('should assign kitsuId correctly', async () => { + const torrent : IParsedTorrent = { + title: 'Test title', + provider: 'Test provider', + infoHash: 'Test infoHash', + type: TorrentType.Anime, + }; + + const fileCollection : ITorrentFileCollection = { + videos: [{ + fileIndex: 0, + title: 'Test video', + size: 123456, + kitsuId: 11 + }], + contents: [], + subtitles: [], + }; + + const fileCollectionWithSubtitles : ITorrentFileCollection = { + ...fileCollection, + subtitles: [ { + fileId: 0, + title: 'Test subtitle', + fileIndex: 0, + path: 'Test path', + infoHash: 'Test infoHash', + }], + }; + + (mockMetadataService.getKitsuId as jest.Mock).mockResolvedValue(11); + (mockFileService.parseTorrentFiles as jest.Mock).mockResolvedValue(fileCollection); + (mockSubtitleService.assignSubtitles as jest.Mock).mockResolvedValue(fileCollectionWithSubtitles); + (mockDatabaseRepository.createTorrent as jest.Mock).mockResolvedValue(torrent); + + await torrentEntriesService.createTorrentEntry(torrent); + + expect(torrent.imdbId).toEqual(undefined); + expect(torrent.kitsuId).toEqual(11); + }); + + it('should create a skip torrent entry', async () => { + const torrent: ITorrentCreationAttributes = { + infoHash: 'Test infoHash', + provider: 'Test provider', + title: 'Test title', + type: TorrentType.Movie, + }; + + (mockDatabaseRepository.createSkipTorrent as jest.Mock).mockResolvedValue([torrent, null]); + + const result = await torrentEntriesService.createSkipTorrentEntry(torrent); + + expect(mockDatabaseRepository.createSkipTorrent).toHaveBeenCalledWith(torrent); + expect(result).toEqual([torrent, null]); + }); + + it('should get stored torrent entry', async () => { + const torrent = { + infoHash: 'Test infoHash', + provider: 'Test provider', + title: 'Test title', + type: TorrentType.Movie, + dataValues: { + infoHash: 'Test infoHash', + provider: 'Test provider', + title: 'Test title', + type: TorrentType.Movie, + } + } as Torrent; + + (mockDatabaseRepository.getSkipTorrent as jest.Mock).mockRejectedValue(undefined); + (mockDatabaseRepository.getTorrent as jest.Mock).mockResolvedValue(torrent); + + const result = await torrentEntriesService.getStoredTorrentEntry(torrent); + + expect(mockDatabaseRepository.getSkipTorrent).toHaveBeenCalledWith(torrent.infoHash); + expect(mockDatabaseRepository.getTorrent).toHaveBeenCalledWith(torrent.dataValues); + expect(result).toEqual(torrent); + }); + + it('should check and update torrent', async () => { + const torrent : IParsedTorrent = { + title: 'Test title', + provider: 'Test provider', + infoHash: 'Test infoHash', + type: TorrentType.Movie, + seeders: 1, + }; + + const files : IFileAttributes[] = [{ + infoHash: 'Test infoHash', + fileIndex: 0, + title: 'Test title', + path: 'Test path', + size: 123456, + },{ + infoHash: 'Test infoHash 2', + fileIndex: 1, + title: 'Test title 2', + path: 'Test path 2', + size: 234567, + }]; + + const torrentInstance = { + ...torrent, + dataValues:{ ...torrent}, + save: jest.fn().mockResolvedValue(torrent), + }; + + const filesInstance = { + ...files, + dataValues:{ ...files}, + save: jest.fn().mockResolvedValue(files), + }; + + const seedersResponse = [1]; + + (mockDatabaseRepository.getTorrent as jest.Mock).mockResolvedValue(torrentInstance); + + (mockDatabaseRepository.setTorrentSeeders as jest.Mock).mockResolvedValue(seedersResponse); + (mockDatabaseRepository.getFiles as jest.Mock).mockResolvedValue(filesInstance) + + const result = await torrentEntriesService.checkAndUpdateTorrent(torrent); + + expect(mockDatabaseRepository.getTorrent).toHaveBeenCalledWith({ + infoHash: torrent.infoHash, + provider: torrent.provider + }); + + expect(mockDatabaseRepository.getFiles).toHaveBeenCalledWith(torrent.infoHash); + expect(mockDatabaseRepository.setTorrentSeeders).toHaveBeenCalledWith(torrentInstance.dataValues, 1); + expect(result).toEqual(true); + }); + + it('should create torrent contents', async () => { + const torrent = { + infoHash: 'Test infoHash', + provider: 'Test provider', + title: 'Test title', + type: TorrentType.Movie, + dataValues: { + infoHash: 'Test infoHash', + provider: 'Test provider', + title: 'Test title', + type: TorrentType.Movie, + } + } as Torrent; + + const fileCollection : ITorrentFileCollection = { + videos: [{ + id: 1, + title: 'Test video', + size: 123456, + imdbId: 'tt1234567', + infoHash: 'Test infoHash', + }], + contents: [], + subtitles: [], + }; + + const fileCollectionWithContents : ITorrentFileCollection = { + ...fileCollection, + contents: [{ + size: 123456, + fileIndex: 0, + path: 'Test path', + infoHash: 'Test infoHash', + }], + }; + + (mockDatabaseRepository.getFiles as jest.Mock).mockResolvedValue(fileCollection.videos); + (mockFileService.parseTorrentFiles as jest.Mock).mockResolvedValue(fileCollectionWithContents); + (mockSubtitleService.assignSubtitles as jest.Mock).mockResolvedValue(fileCollectionWithContents); + (mockDatabaseRepository.createFile as jest.Mock).mockResolvedValue(Promise.resolve()); + (mockDatabaseRepository.createTorrent as jest.Mock).mockResolvedValue(torrent); + + await torrentEntriesService.createTorrentContents(torrent); + + const newTorrentFiles = await (mockDatabaseRepository.createTorrent as jest.Mock).mock.calls[0][0].files; + + newTorrentFiles.forEach(file => { + expect(mockDatabaseRepository.createFile).toHaveBeenCalledWith(file); + }); + }); }); \ No newline at end of file diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/tracker_service.test.ts index 3fe9981..71b7353 100644 --- a/src/node/consumer/test/tracker_service.test.ts +++ b/src/node/consumer/test/tracker_service.test.ts @@ -24,6 +24,7 @@ jest.mock('@services/cache_service', () => { beforeAll(() => server.listen()) beforeEach(() => { + jest.clearAllMocks(); jest.spyOn(Date, 'now').mockImplementation(() => 1234567890); }) afterEach(() => () => { From 740b75f1068017aaf16e8f586181189842e43e71 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Fri, 9 Feb 2024 15:32:02 +0000 Subject: [PATCH 47/55] add assign subtitles tests, and fix subtitles service --- .../lib/services/torrent_subtitle_service.ts | 32 ++++-- .../test/torrent_subtitle_service.test.ts | 102 ++++++++++++++++++ 2 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 src/node/consumer/test/torrent_subtitle_service.test.ts diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index dccede4..be2641c 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -10,8 +10,14 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { public assignSubtitles = (fileCollection: ITorrentFileCollection): ITorrentFileCollection => { if (fileCollection.videos && fileCollection.videos.length && fileCollection.subtitles && fileCollection.subtitles.length) { if (fileCollection.videos.length === 1) { - fileCollection.videos[0].subtitles = fileCollection.subtitles; - return {...fileCollection, subtitles: []}; + const matchingSubtitles = fileCollection.subtitles.filter(subtitle => + this.mostProbableSubtitleVideos(subtitle, [fileCollection.videos[0]]).length > 0 + ); + fileCollection.videos[0].subtitles = matchingSubtitles; + const nonMatchingSubtitles = fileCollection.subtitles.filter(subtitle => + !matchingSubtitles.includes(subtitle) + ); + return {...fileCollection, subtitles: nonMatchingSubtitles}; } const parsedVideos = fileCollection.videos.map(video => this.parseVideo(video)); @@ -32,12 +38,11 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { private parseVideo = (video: IFileAttributes): IFileAttributes => { const fileName = video.title?.split('/')?.pop()?.replace(/\.(\w{2,4})$/, '') || ''; const folderName = video.title?.replace(/\/?[^/]+$/, '') || ''; - return { - videoFile: video, + return Object.assign(video, { fileName: fileName, folderName: folderName, ...this.parseFilename(video.title.toString() || '') - }; + }); } private mostProbableSubtitleVideos = (subtitle: ISubtitleAttributes, parsedVideos: IFileAttributes[]): IFileAttributes[] => { @@ -48,13 +53,15 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return byFileName.map(v => v); } const byTitleSeasonEpisode = parsedVideos.filter(video => video.title === parsedSub.title - && this.arrayEquals(video.seasons || [], parsedSub.seasons || []) - && this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); + && parsedSub.seasons && parsedSub.episodes + && this.arrayEquals(video.seasons || [], parsedSub.seasons) + && this.arrayEquals(video.episodes || [], parsedSub.episodes)); if (this.singleVideoFile(byTitleSeasonEpisode)) { return byTitleSeasonEpisode.map(v => v); } - const bySeasonEpisode = parsedVideos.filter(video => this.arrayEquals(video.seasons || [], parsedSub.seasons || []) - && this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); + const bySeasonEpisode = parsedVideos.filter(video => parsedSub.seasons && parsedSub.episodes + && this.arrayEquals(video.seasons || [], parsedSub.seasons) + && this.arrayEquals(video.episodes || [], parsedSub.episodes)); if (this.singleVideoFile(bySeasonEpisode)) { return bySeasonEpisode.map(v => v); } @@ -62,10 +69,15 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { if (this.singleVideoFile(byTitle)) { return byTitle.map(v => v); } - const byEpisode = parsedVideos.filter(video => this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); + const byEpisode = parsedVideos.filter(video => parsedSub.episodes + && this.arrayEquals(video.episodes || [], parsedSub.episodes || [])); if (this.singleVideoFile(byEpisode)) { return byEpisode.map(v => v); } + const byInfoHash = parsedVideos.filter(video => video.infoHash === subtitle.infoHash); + if (this.singleVideoFile(byInfoHash)) { + return byInfoHash.map(v => v); + } return []; } diff --git a/src/node/consumer/test/torrent_subtitle_service.test.ts b/src/node/consumer/test/torrent_subtitle_service.test.ts new file mode 100644 index 0000000..d4c097d --- /dev/null +++ b/src/node/consumer/test/torrent_subtitle_service.test.ts @@ -0,0 +1,102 @@ +import "reflect-metadata"; // required +import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; +import {TorrentSubtitleService} from "@services/torrent_subtitle_service"; + +describe('TrrentSubtitleService tests', () => { + let torrentSubtitleService: TorrentSubtitleService; + + beforeEach(() => { + jest.clearAllMocks(); + torrentSubtitleService = new TorrentSubtitleService(); + }); + + it('should assign subtitles to a single video', () => { + const fileCollection: ITorrentFileCollection = { + videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + contents: [], + subtitles: [{ title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result.videos[0].subtitles).toEqual(fileCollection.subtitles); + expect(result.subtitles).toEqual([]); + }); + + it('should not assign subtitles if there are no videos', () => { + const fileCollection: ITorrentFileCollection = { + videos: [], + contents: [], + subtitles: [{ title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result).toEqual(fileCollection); + }); + + it('should not assign subtitles if there are no subtitles', () => { + const fileCollection: ITorrentFileCollection = { + videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + contents: [], + subtitles: [], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result).toEqual(fileCollection); + }); + + it('should assign subtitles to multiple videos', () => { + const fileCollection: ITorrentFileCollection = { + videos: [ + { title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }, + { title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' } + ], + contents: [], + subtitles: [ + { title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }, + { title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash' } + ], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result.videos[0].subtitles).toEqual([fileCollection.subtitles[0]]); + expect(result.videos[1].subtitles).toEqual([fileCollection.subtitles[1]]); + expect(result.subtitles).toEqual([]); + }); + + it('should not assign subtitles if there are no matching videos', () => { + const fileCollection: ITorrentFileCollection = { + videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + contents: [], + subtitles: [{ title: 'Non-matching subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Non-matching infoHash' }], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result.videos[0].subtitles).toEqual([]); + expect(result.subtitles).toEqual([fileCollection.subtitles[0]]); + }); + + it('should assign subtitles to the most probable videos based on filename, title, season, and episode', () => { + const fileCollection: ITorrentFileCollection = { + videos: [ + { title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }, + { title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' } + ], + contents: [], + subtitles: [ + { title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }, + { title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash' } + ], + }; + + const result = torrentSubtitleService.assignSubtitles(fileCollection); + + expect(result.videos[0].subtitles).toEqual([fileCollection.subtitles[0]]); + expect(result.videos[1].subtitles).toEqual([fileCollection.subtitles[1]]); + expect(result.subtitles).toEqual([]); + }); +}); \ No newline at end of file From e04f2d01a4fc9c0ed09bf22c73c2d67b5fb51a40 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Fri, 9 Feb 2024 16:18:00 +0000 Subject: [PATCH 48/55] Start of some file service tests. final service that needed to be tested We need a lot more tests in this - its the main processor for the consumer really --- .../src/lib/services/torrent_file_service.ts | 8 +- .../test/torrent_file_service.test.ts | 216 ++++++++++++++++++ .../test/torrent_subtitle_service.test.ts | 2 +- 3 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/node/consumer/test/torrent_file_service.test.ts diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index 5d40160..f8ab06d 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -46,6 +46,10 @@ export class TorrentFileService implements ITorrentFileService { return Promise.reject(new Error('Torrent title is missing')); } + if (!torrent.infoHash) { + return Promise.reject(new Error('Torrent infoHash is missing')); + } + const parsedTorrentName = parse(torrent.title); const query: IMetaDataQuery = { id: torrent.kitsuId || torrent.imdbId, @@ -115,7 +119,7 @@ export class TorrentFileService implements ITorrentFileService { const parsedVideos = filteredVideos.map(video => ({ infoHash: torrent.infoHash, fileIndex: video.fileIndex, - title: video.path || video.title || video.fileName || '', + title: video.title || video.path || video.fileName || '', size: video.size || torrent.size, imdbId: torrent.imdbId?.toString() || metadata && metadata.imdbId?.toString(), kitsuId: parseInt(torrent.kitsuId?.toString() || metadata && metadata.kitsuId?.toString() || '0') @@ -129,7 +133,7 @@ export class TorrentFileService implements ITorrentFileService { .then(videos => videos.map((video: IFileAttributes) => ({ infoHash: torrent.infoHash, fileIndex: video.fileIndex, - title: video.path || video.title, + title: video.title || video.path, size: video.size, imdbId: video.imdbId, }))); diff --git a/src/node/consumer/test/torrent_file_service.test.ts b/src/node/consumer/test/torrent_file_service.test.ts new file mode 100644 index 0000000..292e079 --- /dev/null +++ b/src/node/consumer/test/torrent_file_service.test.ts @@ -0,0 +1,216 @@ +import "reflect-metadata"; // required +import {TorrentType} from "@enums/torrent_types"; +import {ILoggingService} from "@interfaces/logging_service"; +import {IMetadataService} from "@interfaces/metadata_service"; +import {IParsedTorrent} from "@interfaces/parsed_torrent"; +import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; +import {TorrentFileService} from "@services/torrent_file_service"; + +jest.mock('@services/logging_service', () => { + return { + error: jest.fn(), + info: jest.fn(), + debug: jest.fn(), + } +}) + +jest.mock('@services/torrent_download_service', () => { + return { + getTorrentFiles: jest.fn().mockImplementation(() => Promise.resolve({ + contents: [], + videos: [], + subtitles: [], + })), + }; +}); + +jest.mock('@services/metadata_service', () => { + return { + getMetadata: jest.fn().mockImplementation(() => Promise.resolve(undefined)), + } +}); + +describe('TorrentFileService tests', () => { + let torrentFileService: TorrentFileService, + mockLoggingService: ILoggingService, + mockDownloadService: ITorrentDownloadService, + mockMetadataService: IMetadataService; + + beforeEach(() => { + jest.clearAllMocks(); + mockLoggingService = jest.requireMock('@services/logging_service'); + mockDownloadService = jest.requireMock('@services/torrent_download_service'); + mockMetadataService = jest.requireMock('@services/metadata_service'); + torrentFileService = new TorrentFileService(mockMetadataService, mockDownloadService, mockLoggingService); + }); + + + it('should parse torrent files correctly', () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Movie, + infoHash: '1234567890abcdef', + }; + + const result = torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toBeInstanceOf(Promise); + + result.then(res => { + expect(res).toHaveProperty('videos'); + expect(res).toHaveProperty('subtitles'); + expect(res).toHaveProperty('contents'); + }); + }); + + it('should reject when torrent has no title', async () => { + const mockTorrent: IParsedTorrent = { + kitsuId: 123, + type: TorrentType.Movie, + infoHash: '1234567890abcdef', + }; + + await expect(torrentFileService.parseTorrentFiles(mockTorrent)).rejects.toThrow('Torrent title is missing'); + }); + + it('should handle torrent with no kitsuId', async () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + type: TorrentType.Movie, + infoHash: '1234567890abcdef', + }; + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); + + it('should handle torrent of type Series', async () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Series, + infoHash: '1234567890abcdef', + }; + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); + + it('should reject when torrent has no infoHash', async () => { + const mockTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Movie, + } as IParsedTorrent; + + await expect(torrentFileService.parseTorrentFiles(mockTorrent)).rejects.toThrow('Torrent infoHash is missing'); + }); + + it('should handle torrent with no type', async () => { + const mockTorrent = { + title: 'test', + kitsuId: 123, + infoHash: '1234567890abcdef', + } as IParsedTorrent; + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); + + it('should handle torrent of type Anime', async () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Anime, + infoHash: '1234567890abcdef', + }; + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); + + it('should handle torrent with a single video', async () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Movie, + infoHash: '1234567890abcdef', + }; + + (mockDownloadService.getTorrentFiles as jest.Mock).mockImplementation(() => Promise.resolve({ + contents: [], + videos: [{ + title: 'video1', + path: 'path/to/video1', + size: 123456789, + fileIndex: 0, + }], + subtitles: [], + })); + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result.videos).toHaveLength(1); + expect(result.videos[0]).toHaveProperty('title', 'video1'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); + + it('should handle torrent with multiple videos', async () => { + const mockTorrent: IParsedTorrent = { + title: 'test', + kitsuId: 123, + type: TorrentType.Movie, + infoHash: '1234567890abcdef', + }; + + (mockDownloadService.getTorrentFiles as jest.Mock).mockImplementation(() => Promise.resolve({ + contents: [], + videos: [ + { + title: 'video1', + path: 'path/to/video1', + size: 123456789, + fileIndex: 0, + }, + { + title: 'video2', + path: 'path/to/video2', + size: 123456789, + fileIndex: 1, + }, + { + title: 'video3', + path: 'path/to/video3', + size: 123456789, + fileIndex: 2, + } + ], + subtitles: [], + })); + + const result = await torrentFileService.parseTorrentFiles(mockTorrent); + + expect(result).toHaveProperty('videos'); + expect(result.videos).toHaveLength(3); + expect(result.videos[0]).toHaveProperty('title', 'video1'); + expect(result.videos[1]).toHaveProperty('title', 'video2'); + expect(result.videos[2]).toHaveProperty('title', 'video3'); + expect(result).toHaveProperty('subtitles'); + expect(result).toHaveProperty('contents'); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/torrent_subtitle_service.test.ts b/src/node/consumer/test/torrent_subtitle_service.test.ts index d4c097d..5eff584 100644 --- a/src/node/consumer/test/torrent_subtitle_service.test.ts +++ b/src/node/consumer/test/torrent_subtitle_service.test.ts @@ -2,7 +2,7 @@ import "reflect-metadata"; // required import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; import {TorrentSubtitleService} from "@services/torrent_subtitle_service"; -describe('TrrentSubtitleService tests', () => { +describe('TorrentSubtitleService tests', () => { let torrentSubtitleService: TorrentSubtitleService; beforeEach(() => { From 360bc2097092711b70c2258292207536ff575273 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Sat, 10 Feb 2024 00:15:20 +0000 Subject: [PATCH 49/55] Comment resolution --- .gitignore | 3 +- src/node/consumer/.eslintignore | 4 +- src/node/consumer/.nvmrc | 1 - src/node/consumer/Dockerfile | 2 +- src/node/consumer/{esbuild.js => esbuild.ts} | 26 ++-- src/node/consumer/jest.config.cjs | 11 -- src/node/consumer/jest.config.ts | 14 ++ src/node/consumer/package.json | 4 +- .../src/lib/helpers/boolean_helpers.ts | 2 +- .../src/lib/interfaces/composition_root.ts | 3 - .../src/lib/interfaces/season_episode_map.ts | 7 - .../src/lib/jobs/process_torrents_job.ts | 15 +- .../src/lib/models/composition_root.ts | 27 ---- .../src/lib/repository/database_repository.ts | 137 +++++++++++------- .../src/lib/repository/models/skipTorrent.ts | 1 - .../src/lib/services/cache_service.ts | 36 ++--- .../src/lib/services/configuration_service.ts | 2 +- .../src/lib/services/logging_service.ts | 1 - .../src/lib/services/metadata_service.ts | 82 +++++------ .../lib/services/torrent_download_service.ts | 16 +- .../lib/services/torrent_entries_service.ts | 52 +++---- .../src/lib/services/torrent_file_service.ts | 54 ++----- .../services/torrent_processing_service.ts | 23 +-- .../lib/services/torrent_subtitle_service.ts | 6 +- .../src/lib/services/tracker_service.ts | 17 +-- src/node/consumer/src/main.ts | 6 +- .../consumer/src/setup/composition_root.ts | 22 +++ .../{lib/models => setup}/inversify_config.ts | 5 +- .../src/{lib/models => setup}/ioc_types.ts | 0 src/node/consumer/test/cache_service.test.ts | 10 +- .../consumer/test/metadata_service.test.ts | 11 +- .../consumer/test/process_torrent_job.test.ts | 9 +- .../test/torrent_download_service.test.ts | 8 +- .../test/torrent_entries_service.test.ts | 72 +++++---- .../test/torrent_file_service.test.ts | 13 +- .../test/torrent_subtitle_service.test.ts | 28 ++-- .../consumer/test/tracker_service.test.ts | 10 +- src/node/consumer/tsconfig.json | 3 + 38 files changed, 377 insertions(+), 366 deletions(-) delete mode 100644 src/node/consumer/.nvmrc rename src/node/consumer/{esbuild.js => esbuild.ts} (64%) delete mode 100644 src/node/consumer/jest.config.cjs create mode 100644 src/node/consumer/jest.config.ts delete mode 100644 src/node/consumer/src/lib/interfaces/composition_root.ts delete mode 100644 src/node/consumer/src/lib/interfaces/season_episode_map.ts delete mode 100644 src/node/consumer/src/lib/models/composition_root.ts create mode 100644 src/node/consumer/src/setup/composition_root.ts rename src/node/consumer/src/{lib/models => setup}/inversify_config.ts (94%) rename src/node/consumer/src/{lib/models => setup}/ioc_types.ts (100%) diff --git a/.gitignore b/.gitignore index 6a0132e..6a4f0ab 100644 --- a/.gitignore +++ b/.gitignore @@ -403,5 +403,4 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml -dist/ -**/localdev.compose.yml \ No newline at end of file +dist/ \ No newline at end of file diff --git a/src/node/consumer/.eslintignore b/src/node/consumer/.eslintignore index 7773828..0f6ba20 100644 --- a/src/node/consumer/.eslintignore +++ b/src/node/consumer/.eslintignore @@ -1 +1,3 @@ -dist/ \ No newline at end of file +dist/ +esbuild.ts +jest.config.ts \ No newline at end of file diff --git a/src/node/consumer/.nvmrc b/src/node/consumer/.nvmrc deleted file mode 100644 index 016efd8..0000000 --- a/src/node/consumer/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v20.10.0 \ No newline at end of file diff --git a/src/node/consumer/Dockerfile b/src/node/consumer/Dockerfile index 9474653..b869f14 100644 --- a/src/node/consumer/Dockerfile +++ b/src/node/consumer/Dockerfile @@ -8,7 +8,7 @@ COPY package*.json ./ RUN npm install COPY . . RUN npm run build -RUN npm install --omit=dev +RUN npm prune --omit=dev FROM node:lts-buster-slim diff --git a/src/node/consumer/esbuild.js b/src/node/consumer/esbuild.ts similarity index 64% rename from src/node/consumer/esbuild.js rename to src/node/consumer/esbuild.ts index 17393df..4584dd5 100644 --- a/src/node/consumer/esbuild.js +++ b/src/node/consumer/esbuild.ts @@ -1,14 +1,22 @@ -import {build} from "esbuild"; -import {readFileSync, rmSync} from "fs"; +import { build } from "esbuild"; +import { readFileSync, rmSync } from "fs"; -const {devDependencies} = JSON.parse(readFileSync("./package.json", "utf8")); +interface DevDependencies { + [key: string]: string; +} + +interface PackageJson { + devDependencies?: DevDependencies; +} + +const { devDependencies } = JSON.parse(readFileSync("./package.json", "utf8")) as PackageJson; const start = Date.now(); try { const outdir = "dist"; - rmSync(outdir, {recursive: true, force: true}); + rmSync(outdir, { recursive: true, force: true }); build({ bundle: true, @@ -27,8 +35,8 @@ try { plugins: [ { name: "populate-import-meta", - setup: ({onLoad}) => { - onLoad({filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`)}, args => { + setup: ({ onLoad }) => { + onLoad({ filter: new RegExp(`${import.meta.dirname}/src/.*.(js|ts)$`) }, args => { const contents = readFileSync(args.path, "utf8"); const transformedContents = contents @@ -36,19 +44,15 @@ try { .replace(/import\.meta\.filename/g, "__filename") .replace(/import\.meta\.dirname/g, "__dirname"); - return {contents: transformedContents, loader: "default"}; + return { contents: transformedContents, loader: "default" }; }); }, } ], }).then(() => { - // biome-ignore lint/style/useTemplate: - // eslint-disable-next-line no-undef console.log("⚡ " + "\x1b[32m" + `Done in ${Date.now() - start}ms`); }); } catch (e) { - // eslint-disable-next-line no-undef console.log(e); - // eslint-disable-next-line no-undef process.exit(1); } \ No newline at end of file diff --git a/src/node/consumer/jest.config.cjs b/src/node/consumer/jest.config.cjs deleted file mode 100644 index 8611f31..0000000 --- a/src/node/consumer/jest.config.cjs +++ /dev/null @@ -1,11 +0,0 @@ -const {pathsToModuleNameMapper} = require('ts-jest'); -const {compilerOptions} = require('./tsconfig.json'); - -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {prefix: '/src/'}), - modulePaths: [ - '' - ], -}; \ No newline at end of file diff --git a/src/node/consumer/jest.config.ts b/src/node/consumer/jest.config.ts new file mode 100644 index 0000000..426cc27 --- /dev/null +++ b/src/node/consumer/jest.config.ts @@ -0,0 +1,14 @@ +import { pathsToModuleNameMapper } from 'ts-jest'; +import { compilerOptions } from './tsconfig.json'; + +export default { + preset: 'ts-jest', + testEnvironment: 'node', + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/src/' }), + modulePaths: [ + '' + ], + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, +}; \ No newline at end of file diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index 09fa964..e6e5a13 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -4,9 +4,9 @@ "type": "module", "scripts": { "clean": "rm -rf dist", - "build": "node esbuild.js", + "build": "tsx esbuild.ts", "dev": "tsx watch --ignore node_modules src/main.ts | pino-pretty", - "start": "node --trace-deprecation dist/main.cjs", + "start": "node dist/main.cjs", "lint": "eslint ./src --ext .ts,.js", "lint-fix": "npm run lint -- --fix", "test": "jest", diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index 79c68a0..1216bbe 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,5 +1,5 @@ export const BooleanHelpers = { - parseBool: function (value: string | number | undefined, defaultValue: boolean): boolean { + parseBool: (value: string | number | undefined, defaultValue: boolean): boolean => { switch (typeof value) { case 'string': return parseStringToBool(value, defaultValue); diff --git a/src/node/consumer/src/lib/interfaces/composition_root.ts b/src/node/consumer/src/lib/interfaces/composition_root.ts deleted file mode 100644 index b584625..0000000 --- a/src/node/consumer/src/lib/interfaces/composition_root.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface ICompositionalRoot { - start(): Promise; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/interfaces/season_episode_map.ts b/src/node/consumer/src/lib/interfaces/season_episode_map.ts deleted file mode 100644 index 5fae99b..0000000 --- a/src/node/consumer/src/lib/interfaces/season_episode_map.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {ICommonVideoMetadata} from "@interfaces/common_video_metadata"; - -export interface ISeasonEpisodeMap { - [season: number]: { - [episode: number]: ICommonVideoMetadata; - } -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/jobs/process_torrents_job.ts b/src/node/consumer/src/lib/jobs/process_torrents_job.ts index 6af4966..b010407 100644 --- a/src/node/consumer/src/lib/jobs/process_torrents_job.ts +++ b/src/node/consumer/src/lib/jobs/process_torrents_job.ts @@ -2,26 +2,21 @@ import {ILoggingService} from "@interfaces/logging_service"; import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; import {ITorrentProcessingService} from "@interfaces/torrent_processing_service"; -import {IocTypes} from "@models/ioc_types"; import {IIngestedTorrentAttributes} from "@repository/interfaces/ingested_torrent_attributes"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import client, {Channel, Connection, ConsumeMessage, Options} from 'amqplib' import {inject, injectable} from "inversify"; @injectable() export class ProcessTorrentsJob implements IProcessTorrentsJob { + @inject(IocTypes.ITorrentProcessingService) torrentProcessingService: ITorrentProcessingService; + @inject(IocTypes.ILoggingService) logger: ILoggingService; + private readonly assertQueueOptions: Options.AssertQueue = {durable: true}; private readonly consumeQueueOptions: Options.Consume = {noAck: false}; - private torrentProcessingService: ITorrentProcessingService; - private logger: ILoggingService; - constructor(@inject(IocTypes.ITorrentProcessingService) torrentProcessingService: ITorrentProcessingService, - @inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.torrentProcessingService = torrentProcessingService; - this.logger = logger; - } - - public listenToQueue = async (): Promise => { + async listenToQueue(): Promise { if (!configurationService.jobConfig.JOBS_ENABLED) { return; } diff --git a/src/node/consumer/src/lib/models/composition_root.ts b/src/node/consumer/src/lib/models/composition_root.ts deleted file mode 100644 index 7270cd4..0000000 --- a/src/node/consumer/src/lib/models/composition_root.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {ICompositionalRoot} from "@interfaces/composition_root"; -import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; -import {ITrackerService} from "@interfaces/tracker_service"; -import {IocTypes} from "@models/ioc_types"; -import {IDatabaseRepository} from "@repository/interfaces/database_repository"; -import {inject, injectable} from "inversify"; - -@injectable() -export class CompositionalRoot implements ICompositionalRoot { - private trackerService: ITrackerService; - private databaseRepository: IDatabaseRepository; - private processTorrentsJob: IProcessTorrentsJob; - - constructor(@inject(IocTypes.ITrackerService) trackerService: ITrackerService, - @inject(IocTypes.IDatabaseRepository) databaseRepository: IDatabaseRepository, - @inject(IocTypes.IProcessTorrentsJob) processTorrentsJob: IProcessTorrentsJob) { - this.trackerService = trackerService; - this.databaseRepository = databaseRepository; - this.processTorrentsJob = processTorrentsJob; - } - - start = async (): Promise => { - await this.trackerService.getTrackers(); - await this.databaseRepository.connect(); - await this.processTorrentsJob.listenToQueue(); - }; -} \ No newline at end of file diff --git a/src/node/consumer/src/lib/repository/database_repository.ts b/src/node/consumer/src/lib/repository/database_repository.ts index 0a1a657..3152ece 100644 --- a/src/node/consumer/src/lib/repository/database_repository.ts +++ b/src/node/consumer/src/lib/repository/database_repository.ts @@ -1,6 +1,5 @@ import {PromiseHelpers} from '@helpers/promises_helpers'; import {ILoggingService} from "@interfaces/logging_service"; -import {IocTypes} from "@models/ioc_types"; import {IContentCreationAttributes} from "@repository/interfaces/content_attributes"; import {IDatabaseRepository} from "@repository/interfaces/database_repository"; import {IFileAttributes, IFileCreationAttributes} from "@repository/interfaces/file_attributes"; @@ -15,6 +14,7 @@ import {SkipTorrent} from "@repository/models/skipTorrent"; import {Subtitle} from "@repository/models/subtitle"; import {Torrent} from "@repository/models/torrent"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import {inject, injectable} from "inversify"; import moment from 'moment'; import {literal, Op, WhereOptions} from "sequelize"; @@ -22,6 +22,8 @@ import {Model, Sequelize} from 'sequelize-typescript'; @injectable() export class DatabaseRepository implements IDatabaseRepository { + @inject(IocTypes.ILoggingService) logger: ILoggingService; + private readonly database: Sequelize; private models = [ @@ -34,14 +36,11 @@ export class DatabaseRepository implements IDatabaseRepository { IngestedTorrent, IngestedPage]; - private logger: ILoggingService; - - constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.logger = logger; + constructor() { this.database = this.createDatabase(); } - public connect = async (): Promise => { + async connect(): Promise { try { await this.database.sync({alter: configurationService.databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS}); } catch (error) { @@ -49,42 +48,50 @@ export class DatabaseRepository implements IDatabaseRepository { this.logger.error('Failed syncing database'); process.exit(1); } - }; + } - public getProvider = async (provider: Provider): Promise => { + async getProvider(provider: Provider): Promise { try { const [result] = await Provider.findOrCreate({where: {name: {[Op.eq]: provider.name}}, defaults: provider}); return result; } catch { return provider as Provider; } - }; + } - public getTorrent = async (torrent: ITorrentAttributes): Promise => { + async getTorrent(torrent: ITorrentAttributes): Promise { const where = torrent.infoHash ? {infoHash: torrent.infoHash} : {provider: torrent.provider, torrentId: torrent.torrentId}; return await Torrent.findOne({where}); - }; + } - public getTorrentsBasedOnTitle = async (titleQuery: string, type: string): Promise => this.getTorrentsBasedOnQuery({ - title: {[Op.regexp]: `${titleQuery}`}, - type - }); + async getTorrentsBasedOnTitle(titleQuery: string, type: string): Promise { + return this.getTorrentsBasedOnQuery({ + title: {[Op.regexp]: `${titleQuery}`}, + type + }); + } - public getTorrentsBasedOnQuery = async (where: WhereOptions): Promise => await Torrent.findAll({where}); + async getTorrentsBasedOnQuery(where: WhereOptions): Promise { + return await Torrent.findAll({where}); + } - public getFilesBasedOnQuery = async (where: WhereOptions): Promise => await File.findAll({where}); + async getFilesBasedOnQuery(where: WhereOptions): Promise { + return await File.findAll({where}); + } - public getTorrentsWithoutSize = async (): Promise => await Torrent.findAll({ - where: literal( - 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), - order: [ - ['seeders', 'DESC'] - ] - }); + async getTorrentsWithoutSize(): Promise { + return await Torrent.findAll({ + where: literal( + 'exists (select 1 from files where files."infoHash" = torrent."infoHash" and files.size = 300000000)'), + order: [ + ['seeders', 'DESC'] + ] + }); + } - public getUpdateSeedersTorrents = async (limit = 50): Promise => { + async getUpdateSeedersTorrents(limit = 50): Promise { const until = moment().subtract(7, 'days').format('YYYY-MM-DD'); return await Torrent.findAll({ where: literal(`torrent."updatedAt" < '${until}'`), @@ -94,9 +101,9 @@ export class DatabaseRepository implements IDatabaseRepository { ['updatedAt', 'ASC'] ] }); - }; + } - public getUpdateSeedersNewTorrents = async (limit = 50): Promise => { + async getUpdateSeedersNewTorrents(limit = 50): Promise { const lastUpdate = moment().subtract(12, 'hours').format('YYYY-MM-DD'); const createdAfter = moment().subtract(4, 'days').format('YYYY-MM-DD'); return await Torrent.findAll({ @@ -107,15 +114,17 @@ export class DatabaseRepository implements IDatabaseRepository { ['updatedAt', 'ASC'] ] }); - }; + } - public getNoContentsTorrents = async (): Promise => await Torrent.findAll({ - where: {opened: false, seeders: {[Op.gte]: 1}}, - limit: 500, - order: literal('random()') - }); + async getNoContentsTorrents(): Promise { + return await Torrent.findAll({ + where: {opened: false, seeders: {[Op.gte]: 1}}, + limit: 500, + order: literal('random()') + }); + } - public createTorrent = async (torrent: ITorrentCreationAttributes): Promise => { + async createTorrent(torrent: ITorrentCreationAttributes): Promise { try { await Torrent.upsert(torrent); await this.createContents(torrent.infoHash, torrent.contents); @@ -124,9 +133,9 @@ export class DatabaseRepository implements IDatabaseRepository { this.logger.error(`Failed to create torrent: ${torrent.infoHash}`); this.logger.debug("Error: ", error); } - }; + } - public setTorrentSeeders = async (torrent: ITorrentAttributes, seeders: number): Promise<[number]> => { + async setTorrentSeeders(torrent: ITorrentAttributes, seeders: number): Promise<[number]> { const where = torrent.infoHash ? {infoHash: torrent.infoHash} : {provider: torrent.provider, torrentId: torrent.torrentId}; @@ -135,11 +144,13 @@ export class DatabaseRepository implements IDatabaseRepository { {seeders: seeders}, {where: where} ); - }; + } - public deleteTorrent = async (infoHash: string): Promise => await Torrent.destroy({where: {infoHash: infoHash}}); + async deleteTorrent(infoHash: string): Promise { + return await Torrent.destroy({where: {infoHash: infoHash}}); + } - public createFile = async (file: IFileCreationAttributes): Promise => { + async createFile(file: IFileCreationAttributes): Promise { try { const operatingFile = File.build(file); if (operatingFile.id) { @@ -162,22 +173,28 @@ export class DatabaseRepository implements IDatabaseRepository { this.logger.error(`Failed to create file: ${file.infoHash}`); this.logger.debug("Error: ", error); } - }; + } - public getFiles = async (infoHash: string): Promise => File.findAll({where: {infoHash: infoHash}}); + async getFiles(infoHash: string): Promise { + return File.findAll({where: {infoHash: infoHash}}); + } - public getFilesBasedOnTitle = async (titleQuery: string): Promise => File.findAll({where: {title: {[Op.regexp]: `${titleQuery}`}}}); + async getFilesBasedOnTitle(titleQuery: string): Promise { + return File.findAll({where: {title: {[Op.regexp]: `${titleQuery}`}}}); + } - public deleteFile = async (id: number): Promise => File.destroy({where: {id: id}}); + async deleteFile(id: number): Promise { + return File.destroy({where: {id: id}}); + } - public createSubtitles = async (infoHash: string, subtitles: ISubtitleCreationAttributes[] | undefined): Promise[]> => { + async createSubtitles(infoHash: string, subtitles: ISubtitleCreationAttributes[] | undefined): Promise[]> { if (subtitles && subtitles.length) { return Subtitle.bulkCreate(subtitles.map(subtitle => ({...subtitle, infoHash: infoHash, title: subtitle.path}))); } return Promise.resolve(); - }; + } - public upsertSubtitles = async (file: File, subtitles: ISubtitleCreationAttributes[] | undefined): Promise => { + async upsertSubtitles(file: File, subtitles: ISubtitleCreationAttributes[] | undefined): Promise { if (file.id && subtitles && subtitles.length) { await PromiseHelpers.sequence(subtitles .map(subtitle => { @@ -195,30 +212,38 @@ export class DatabaseRepository implements IDatabaseRepository { } })); } - }; + } - public getSubtitles = async (infoHash: string): Promise => Subtitle.findAll({where: {infoHash: infoHash}}); + async getSubtitles(infoHash: string): Promise { + return Subtitle.findAll({where: {infoHash: infoHash}}); + } - public getUnassignedSubtitles = async (): Promise => Subtitle.findAll({where: {fileId: null}}); + async getUnassignedSubtitles(): Promise { + return Subtitle.findAll({where: {fileId: null}}); + } - public createContents = async (infoHash: string, contents: IContentCreationAttributes[] | undefined): Promise => { + async createContents(infoHash: string, contents: IContentCreationAttributes[] | undefined): Promise { if (contents && contents.length) { await Content.bulkCreate(contents.map(content => ({...content, infoHash})), {ignoreDuplicates: true}); await Torrent.update({opened: true}, {where: {infoHash: infoHash}, silent: true}); } - }; + } - public getContents = async (infoHash: string): Promise => Content.findAll({where: {infoHash: infoHash}}); + async getContents(infoHash: string): Promise { + return Content.findAll({where: {infoHash: infoHash}}); + } - public getSkipTorrent = async (infoHash: string): Promise => { + async getSkipTorrent(infoHash: string): Promise { const result = await SkipTorrent.findByPk(infoHash); if (!result) { throw new Error(`torrent not found: ${infoHash}`); } return result.dataValues as SkipTorrent; - }; + } - public createSkipTorrent = async (torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]> => SkipTorrent.upsert({infoHash: torrent.infoHash}); + async createSkipTorrent(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]> { + return SkipTorrent.upsert({infoHash: torrent.infoHash}); + } private createDatabase = (): Sequelize => { const newDatabase = new Sequelize( @@ -232,4 +257,4 @@ export class DatabaseRepository implements IDatabaseRepository { return newDatabase; }; -} +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/repository/models/skipTorrent.ts b/src/node/consumer/src/lib/repository/models/skipTorrent.ts index b280004..9022126 100644 --- a/src/node/consumer/src/lib/repository/models/skipTorrent.ts +++ b/src/node/consumer/src/lib/repository/models/skipTorrent.ts @@ -1,7 +1,6 @@ import {ISkipTorrentAttributes, ISkipTorrentCreationAttributes} from "@repository/interfaces/skip_torrent_attributes"; import {Column, DataType, Model, Table} from 'sequelize-typescript'; - @Table({modelName: 'skip_torrent', timestamps: false}) export class SkipTorrent extends Model { diff --git a/src/node/consumer/src/lib/services/cache_service.ts b/src/node/consumer/src/lib/services/cache_service.ts index 761784a..015a995 100644 --- a/src/node/consumer/src/lib/services/cache_service.ts +++ b/src/node/consumer/src/lib/services/cache_service.ts @@ -2,8 +2,8 @@ import {CacheType} from "@enums/cache_types"; import {ICacheOptions} from "@interfaces/cache_options"; import {ICacheService} from "@interfaces/cache_service"; import {ILoggingService} from "@interfaces/logging_service"; -import {IocTypes} from "@models/ioc_types"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import {mongoDbStore} from '@tirke/node-cache-manager-mongodb' import {Cache, createCache, MemoryCache, memoryStore} from 'cache-manager'; import {inject, injectable} from "inversify"; @@ -23,12 +23,12 @@ export type CacheMethod = () => any; @injectable() export class CacheService implements ICacheService { - private logger: ILoggingService; + @inject(IocTypes.ILoggingService) private logger: ILoggingService; + private readonly memoryCache: MemoryCache | undefined; private readonly remoteCache: Cache | MemoryCache | undefined; - constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.logger = logger; + constructor() { if (configurationService.cacheConfig.NO_CACHE) { this.logger.info('Cache is disabled'); return; @@ -38,17 +38,21 @@ export class CacheService implements ICacheService { this.remoteCache = this.initiateRemoteCache(); } - public cacheWrapImdbId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); + cacheWrapImdbId(key: string, method: CacheMethod): Promise { + return this.cacheWrap(CacheType.MongoDb, `${IMDB_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); + } - public cacheWrapKitsuId = (key: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); + cacheWrapKitsuId(key: string, method: CacheMethod): Promise { + return this.cacheWrap(CacheType.MongoDb, `${KITSU_ID_PREFIX}:${key}`, method, {ttl: GLOBAL_TTL}); + } - public cacheWrapMetadata = (id: string, method: CacheMethod): Promise => - this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, {ttl: MEMORY_TTL}); + cacheWrapMetadata(id: string, method: CacheMethod): Promise { + return this.cacheWrap(CacheType.Memory, `${METADATA_PREFIX}:${id}`, method, {ttl: MEMORY_TTL}); + } - public cacheTrackers = (method: CacheMethod): Promise => - this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, {ttl: TRACKERS_TTL}); + cacheTrackers(method: CacheMethod): Promise { + return this.cacheWrap(CacheType.Memory, `${TRACKERS_KEY_PREFIX}`, method, {ttl: TRACKERS_TTL}); + } private initiateMemoryCache = (): MemoryCache => createCache(memoryStore(), { @@ -91,8 +95,7 @@ export class CacheService implements ICacheService { } } - private cacheWrap = async ( - cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { + private cacheWrap = async (cacheType: CacheType, key: string, method: CacheMethod, options: ICacheOptions): Promise => { const cache = this.getCacheType(cacheType); if (configurationService.cacheConfig.NO_CACHE || !cache) { @@ -104,6 +107,5 @@ export class CacheService implements ICacheService { this.logger.debug(`Cache options: ${JSON.stringify(options)}`); return cache.wrap(key, method, options.ttl); - } -} - + }; +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/configuration_service.ts b/src/node/consumer/src/lib/services/configuration_service.ts index 7545d56..39cf00d 100644 --- a/src/node/consumer/src/lib/services/configuration_service.ts +++ b/src/node/consumer/src/lib/services/configuration_service.ts @@ -14,4 +14,4 @@ export const configurationService = { metadataConfig: metadataConfig, trackerConfig: trackerConfig, torrentConfig: torrentConfig -}; +}; \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/logging_service.ts b/src/node/consumer/src/lib/services/logging_service.ts index 3eef3b8..5b2837d 100644 --- a/src/node/consumer/src/lib/services/logging_service.ts +++ b/src/node/consumer/src/lib/services/logging_service.ts @@ -29,5 +29,4 @@ export class LoggingService implements ILoggingService { this.logger.warn(message, args); }; } - /* eslint-enable @typescript-eslint/no-explicit-any */ \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/metadata_service.ts b/src/node/consumer/src/lib/services/metadata_service.ts index f986f34..3dfeb1d 100644 --- a/src/node/consumer/src/lib/services/metadata_service.ts +++ b/src/node/consumer/src/lib/services/metadata_service.ts @@ -7,7 +7,7 @@ import {IKitsuJsonResponse} from "@interfaces/kitsu_metadata"; import {IMetaDataQuery} from "@interfaces/metadata_query"; import {IMetadataResponse} from "@interfaces/metadata_response"; import {IMetadataService} from "@interfaces/metadata_service"; -import {IocTypes} from "@models/ioc_types"; +import {IocTypes} from "@setup/ioc_types"; import axios from 'axios'; import {ResultTypes, search} from 'google-sr'; import {inject, injectable} from "inversify"; @@ -19,13 +19,9 @@ const TIMEOUT = 60000; @injectable() export class MetadataService implements IMetadataService { - private cacheService: ICacheService; + @inject(IocTypes.ICacheService) private cacheService: ICacheService; - constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService) { - this.cacheService = cacheService; - } - - public getKitsuId = async (info: IMetaDataQuery): Promise => { + async getKitsuId(info: IMetaDataQuery): Promise { const title = this.escapeTitle(info.title!.replace(/\s\|\s.*/, '')); const year = info.year ? ` ${info.year}` : ''; const season = info.season || 0 > 1 ? ` S${info.season}` : ''; @@ -42,9 +38,9 @@ export class MetadataService implements IMetadataService { throw new Error('No search results'); } })); - }; + } - public getImdbId = async (info: IMetaDataQuery): Promise => { + async getImdbId(info: IMetaDataQuery): Promise { const name = this.escapeTitle(info.title!); const year = info.year || (info.date && info.date.slice(0, 4)); const key = `${name}_${year || 'NA'}_${info.type}`; @@ -61,9 +57,9 @@ export class MetadataService implements IMetadataService { const imdbIdFallback = await this.getIMDbIdFromGoogle(googleQuery); return imdbIdFallback && 'tt' + imdbIdFallback.toString().replace(/tt0*([1-9][0-9]*)$/, '$1').padStart(7, '0'); } - }; + } - public getMetadata = (query: IMetaDataQuery): Promise => { + async getMetadata(query: IMetaDataQuery): Promise { if (!query.id) { return Promise.reject("no valid id provided"); } @@ -71,25 +67,28 @@ export class MetadataService implements IMetadataService { const key = Number.isInteger(query.id) || query.id.toString().match(/^\d+$/) ? `kitsu:${query.id}` : query.id; const metaType = query.type === TorrentType.Movie ? TorrentType.Movie : TorrentType.Series; const isImdbId = Boolean(key.toString().match(/^tt\d+$/)); - - return this.cacheService.cacheWrapMetadata(key.toString(), () => { - switch (isImdbId) { - case true: - return this.requestMetadata(`${CINEMETA_URL}/meta/imdb/${key}.json`, this.handleCinemetaResponse); - default: - return this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`, this.handleKitsuResponse) - }}) - .catch(() => { + + try { + try { + return await this.cacheService.cacheWrapMetadata(key.toString(), () => { + switch (isImdbId) { + case true: + return this.requestMetadata(`${CINEMETA_URL}/meta/imdb/${key}.json`, this.handleCinemetaResponse); + default: + return this.requestMetadata(`${KITSU_URL}/meta/${metaType}/${key}.json`, this.handleKitsuResponse) + } + }); + } catch (e) { // try different type in case there was a mismatch const otherType = metaType === TorrentType.Movie ? TorrentType.Series : TorrentType.Movie; return this.requestMetadata(`${CINEMETA_URL}/meta/${otherType}/${key}.json`, this.handleCinemetaResponse) - }) - .catch((error) => { - throw new Error(`failed metadata query ${key} due: ${error.message}`); - }); - }; + } + } catch (error) { + throw new Error(`failed metadata query ${key} due: ${error.message}`); + } + } - public isEpisodeImdbId = async (imdbId: string | undefined): Promise => { + async isEpisodeImdbId(imdbId: string | undefined): Promise { if (!imdbId || !imdbId.toString().match(/^tt\d+$/)) { return false; } @@ -100,21 +99,23 @@ export class MetadataService implements IMetadataService { } catch (error) { return false; } - }; + } - public escapeTitle = (title: string): string => title.toLowerCase() - .normalize('NFKD') // normalize non-ASCII characters - .replace(/[\u0300-\u036F]/g, '') - .replace(/&/g, 'and') - .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces - .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars - .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering - .replace(/\s{2,}/, ' ') // replace multiple spaces - .trim(); + escapeTitle(title: string): string { + return title.toLowerCase() + .normalize('NFKD') // normalize non-ASCII characters + .replace(/[\u0300-\u036F]/g, '') + .replace(/&/g, 'and') + .replace(/[;, ~./]+/g, ' ') // replace dots, commas or underscores with spaces + .replace(/[^\w \-()×+#@!'\u0400-\u04ff]+/g, '') // remove all non-alphanumeric chars + .replace(/^\d{1,2}[.#\s]+(?=(?:\d+[.\s]*)?[\u0400-\u04ff])/i, '') // remove russian movie numbering + .replace(/\s{2,}/, ' ') // replace multiple spaces + .trim(); + } private requestMetadata = async (url: string, handler: (body: unknown) => IMetadataResponse): Promise => { try { - const response = await axios.get(url, { timeout: TIMEOUT }); + const response = await axios.get(url, {timeout: TIMEOUT}); const body = response.data; return handler(body); } catch (error) { @@ -124,7 +125,7 @@ export class MetadataService implements IMetadataService { private handleCinemetaResponse = (response: unknown): IMetadataResponse => { const body = response as ICinemetaJsonResponse - + return ({ imdbId: parseInt(body.meta?.id || '0'), type: body.meta?.type, @@ -155,7 +156,7 @@ export class MetadataService implements IMetadataService { private handleKitsuResponse = (response: unknown): IMetadataResponse => { const body = response as IKitsuJsonResponse; - + return ({ kitsuId: parseInt(body.meta?.kitsu_id || '0'), type: body.meta?.type, @@ -230,5 +231,4 @@ export class MetadataService implements IMetadataService { throw new Error('Failed to find IMDb ID from Google search'); } }; -} - +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_download_service.ts b/src/node/consumer/src/lib/services/torrent_download_service.ts index 79bfb63..46aa9f5 100644 --- a/src/node/consumer/src/lib/services/torrent_download_service.ts +++ b/src/node/consumer/src/lib/services/torrent_download_service.ts @@ -3,11 +3,11 @@ import {ILoggingService} from "@interfaces/logging_service"; import {IParsedTorrent} from "@interfaces/parsed_torrent"; import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; -import {IocTypes} from "@models/ioc_types"; import {IContentAttributes} from "@repository/interfaces/content_attributes"; import {IFileAttributes} from "@repository/interfaces/file_attributes"; import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import {inject, injectable} from "inversify"; import {encode} from 'magnet-uri'; import {parse} from "parse-torrent-title"; @@ -25,7 +25,8 @@ interface ITorrentFile { @injectable() export class TorrentDownloadService implements ITorrentDownloadService { - private logger: ILoggingService; + @inject(IocTypes.ILoggingService) private logger: ILoggingService; + private engineOptions: TorrentEngineOptions = { connections: configurationService.torrentConfig.MAX_CONNECTIONS_PER_TORRENT, uploads: 0, @@ -34,11 +35,7 @@ export class TorrentDownloadService implements ITorrentDownloadService { tracker: true, }; - constructor(@inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.logger = logger; - } - - public getTorrentFiles = async (torrent: IParsedTorrent, timeout: number = 30000): Promise => { + async getTorrentFiles(torrent: IParsedTorrent, timeout: number = 30000): Promise { const torrentFiles: ITorrentFile[] = await this.filesFromTorrentStream(torrent, timeout); const videos = this.filterVideos(torrent, torrentFiles); @@ -50,7 +47,7 @@ export class TorrentDownloadService implements ITorrentDownloadService { videos: videos, subtitles: subtitles, }; - }; + } private filesFromTorrentStream = async (torrent: IParsedTorrent, timeout: number): Promise => { if (!torrent.infoHash) { @@ -164,5 +161,4 @@ export class TorrentDownloadService implements ITorrentDownloadService { path: file.path, size: file.length, }); -} - +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_entries_service.ts b/src/node/consumer/src/lib/services/torrent_entries_service.ts index 2bea7f1..681b55b 100644 --- a/src/node/consumer/src/lib/services/torrent_entries_service.ts +++ b/src/node/consumer/src/lib/services/torrent_entries_service.ts @@ -8,7 +8,6 @@ import {ITorrentEntriesService} from "@interfaces/torrent_entries_service"; import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; import {ITorrentFileService} from "@interfaces/torrent_file_service"; import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; -import {IocTypes} from "@models/ioc_types"; import {IDatabaseRepository} from "@repository/interfaces/database_repository"; import {IFileCreationAttributes} from "@repository/interfaces/file_attributes"; import {ISubtitleAttributes} from "@repository/interfaces/subtitle_attributes"; @@ -17,30 +16,19 @@ import {File} from "@repository/models/file"; import {SkipTorrent} from "@repository/models/skipTorrent"; import {Subtitle} from "@repository/models/subtitle"; import {Torrent} from "@repository/models/torrent"; +import {IocTypes} from "@setup/ioc_types"; import {inject, injectable} from "inversify"; import {parse} from 'parse-torrent-title'; @injectable() export class TorrentEntriesService implements ITorrentEntriesService { - private metadataService: IMetadataService; - private logger: ILoggingService; - private fileService: ITorrentFileService; - private subtitleService: ITorrentSubtitleService; - private repository: IDatabaseRepository; + @inject(IocTypes.IMetadataService) private metadataService: IMetadataService; + @inject(IocTypes.ILoggingService) private logger: ILoggingService; + @inject(IocTypes.ITorrentFileService) private fileService: ITorrentFileService; + @inject(IocTypes.ITorrentSubtitleService) private subtitleService: ITorrentSubtitleService; + @inject(IocTypes.IDatabaseRepository) private repository: IDatabaseRepository; - constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, - @inject(IocTypes.ILoggingService) logger: ILoggingService, - @inject(IocTypes.ITorrentFileService) fileService: ITorrentFileService, - @inject(IocTypes.ITorrentSubtitleService) torrentSubtitleService: ITorrentSubtitleService, - @inject(IocTypes.IDatabaseRepository) repository: IDatabaseRepository) { - this.metadataService = metadataService; - this.logger = logger; - this.fileService = fileService; - this.subtitleService = torrentSubtitleService; - this.repository = repository; - } - - public createTorrentEntry = async (torrent: IParsedTorrent, overwrite = false): Promise => { + async createTorrentEntry(torrent: IParsedTorrent, overwrite = false): Promise { if (!torrent.title) { this.logger.warn(`No title found for ${torrent.provider} [${torrent.infoHash}]`); return; @@ -108,15 +96,19 @@ export class TorrentEntriesService implements ITorrentEntriesService { return this.repository.createFile(newVideo) }))) .then(() => this.logger.info(`Created ${torrent.provider} entry for [${torrent.infoHash}] ${torrent.title}`)); - }; + } - public createSkipTorrentEntry: (torrent: ITorrentCreationAttributes) => Promise<[SkipTorrent, boolean | null]> = async (torrent: ITorrentCreationAttributes) => this.repository.createSkipTorrent(torrent); + async createSkipTorrentEntry(torrent: ITorrentCreationAttributes): Promise<[SkipTorrent, boolean | null]> { + return this.repository.createSkipTorrent(torrent); + } - public getStoredTorrentEntry = async (torrent: Torrent): Promise => this.repository.getSkipTorrent(torrent.infoHash) - .catch(() => this.repository.getTorrent(torrent.dataValues)) - .catch(() => undefined); + async getStoredTorrentEntry(torrent: Torrent): Promise { + return this.repository.getSkipTorrent(torrent.infoHash) + .catch(() => this.repository.getTorrent(torrent.dataValues)) + .catch(() => undefined); + } - public checkAndUpdateTorrent = async (torrent: IParsedTorrent): Promise => { + async checkAndUpdateTorrent(torrent: IParsedTorrent): Promise { const query: ITorrentAttributes = { infoHash: torrent.infoHash, provider: torrent.provider, @@ -146,9 +138,9 @@ export class TorrentEntriesService implements ITorrentEntriesService { .then(() => this.updateTorrentSeeders(existingTorrent.dataValues)) .then(() => Promise.resolve(true)) .catch(() => Promise.reject(false)); - }; + } - public createTorrentContents = async (torrent: Torrent): Promise => { + async createTorrentContents(torrent: Torrent): Promise { if (torrent.opened) { return; } @@ -213,9 +205,9 @@ export class TorrentEntriesService implements ITorrentEntriesService { }) .then(() => this.logger.info(`Created contents for ${torrent.provider} [${torrent.infoHash}] ${torrent.title}`)) .catch(error => this.logger.error(`Failed saving contents for [${torrent.infoHash}] ${torrent.title}`, error)); - }; + } - public updateTorrentSeeders = async (torrent: ITorrentAttributes): Promise<[number]> => { + async updateTorrentSeeders(torrent: ITorrentAttributes): Promise<[number]> { if (!(torrent.infoHash || (torrent.provider && torrent.torrentId)) || !Number.isInteger(torrent.seeders)) { return [0]; } @@ -231,7 +223,7 @@ export class TorrentEntriesService implements ITorrentEntriesService { this.logger.warn('Failed updating seeders:', error); return [0]; }); - }; + } private assignKitsuId = async (kitsuQuery: IMetaDataQuery, torrent: IParsedTorrent): Promise => { await this.metadataService.getKitsuId(kitsuQuery) diff --git a/src/node/consumer/src/lib/services/torrent_file_service.ts b/src/node/consumer/src/lib/services/torrent_file_service.ts index f8ab06d..60efe4d 100644 --- a/src/node/consumer/src/lib/services/torrent_file_service.ts +++ b/src/node/consumer/src/lib/services/torrent_file_service.ts @@ -7,14 +7,13 @@ import {IMetaDataQuery} from "@interfaces/metadata_query"; import {IMetadataResponse} from "@interfaces/metadata_response"; import {IMetadataService} from "@interfaces/metadata_service"; import {IParsedTorrent} from "@interfaces/parsed_torrent"; -import {ISeasonEpisodeMap} from "@interfaces/season_episode_map"; import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; import {ITorrentFileService} from "@interfaces/torrent_file_service"; -import {IocTypes} from "@models/ioc_types"; import {IContentAttributes} from "@repository/interfaces/content_attributes"; import {IFileAttributes} from "@repository/interfaces/file_attributes"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import Bottleneck from 'bottleneck'; import {inject, injectable} from "inversify"; import moment from 'moment'; @@ -23,25 +22,20 @@ import {parse} from 'parse-torrent-title'; const MIN_SIZE: number = 5 * 1024 * 1024; // 5 MB const MULTIPLE_FILES_SIZE = 4 * 1024 * 1024 * 1024; // 4 GB +type SeasonEpisodeMap = Record>; + @injectable() export class TorrentFileService implements ITorrentFileService { - private metadataService: IMetadataService; - private torrentDownloadService: ITorrentDownloadService; - private logger: ILoggingService; + @inject(IocTypes.IMetadataService) metadataService: IMetadataService; + @inject(IocTypes.ITorrentDownloadService) torrentDownloadService: ITorrentDownloadService; + @inject(IocTypes.ILoggingService) logger: ILoggingService; + private readonly imdb_limiter: Bottleneck = new Bottleneck({ maxConcurrent: configurationService.metadataConfig.IMDB_CONCURRENT, minTime: configurationService.metadataConfig.IMDB_INTERVAL_MS }); - constructor(@inject(IocTypes.IMetadataService) metadataService: IMetadataService, - @inject(IocTypes.ITorrentDownloadService) torrentDownloadService: ITorrentDownloadService, - @inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.metadataService = metadataService; - this.torrentDownloadService = torrentDownloadService; - this.logger = logger; - } - - public parseTorrentFiles = async (torrent: IParsedTorrent): Promise => { + async parseTorrentFiles(torrent: IParsedTorrent): Promise { if (!torrent.title) { return Promise.reject(new Error('Torrent title is missing')); } @@ -74,9 +68,9 @@ export class TorrentFileService implements ITorrentFileService { } return this.parseSeriesFiles(torrent, metadata) - }; + } - public isPackTorrent = (torrent: IParsedTorrent): boolean => { + isPackTorrent(torrent: IParsedTorrent): boolean { if (torrent.isPack) { return true; } @@ -96,7 +90,7 @@ export class TorrentFileService implements ITorrentFileService { const hasSingleEpisode: boolean = Boolean(Number.isInteger(parsedInfo.episode) || (!parsedInfo.episodes && parsedInfo.date)); return hasMultipleEpisodes && !hasSingleEpisode; - }; + } private parseSeriesVideos = (torrent: IParsedTorrent, videos: IFileAttributes[]): IFileAttributes[] => { const parsedTorrentName = parse(torrent.title!); @@ -482,7 +476,7 @@ export class TorrentFileService implements ITorrentFileService { const seriesMapping = metadata.videos .filter(video => video.season !== undefined && Number.isInteger(video.season) && video.episode !== undefined && Number.isInteger(video.episode)) - .reduce((map, video) => { + .reduce((map, video) => { if (video.season !== undefined && video.episode !== undefined) { const episodeMap = map[video.season] || {}; episodeMap[video.episode] = video; @@ -736,26 +730,4 @@ export class TorrentFileService implements ITorrentFileService { private div100 = (episode: number): number => (episode / 100 >> 0); private mod100 = (episode: number): number => episode % 100; -} - - - - - - - - - - - - - - - - - - - - - - +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_processing_service.ts b/src/node/consumer/src/lib/services/torrent_processing_service.ts index e62990c..a68ac03 100644 --- a/src/node/consumer/src/lib/services/torrent_processing_service.ts +++ b/src/node/consumer/src/lib/services/torrent_processing_service.ts @@ -4,25 +4,17 @@ import {IParsedTorrent} from "@interfaces/parsed_torrent"; import {ITorrentEntriesService} from "@interfaces/torrent_entries_service"; import {ITorrentProcessingService} from "@interfaces/torrent_processing_service"; import {ITrackerService} from "@interfaces/tracker_service"; -import {IocTypes} from "@models/ioc_types"; import {IIngestedTorrentAttributes} from "@repository/interfaces/ingested_torrent_attributes"; +import {IocTypes} from "@setup/ioc_types"; import {inject, injectable} from "inversify"; @injectable() export class TorrentProcessingService implements ITorrentProcessingService { - private torrentEntriesService: ITorrentEntriesService; - private logger: ILoggingService; - private trackerService: ITrackerService; + @inject(IocTypes.ITorrentEntriesService) torrentEntriesService: ITorrentEntriesService; + @inject(IocTypes.ILoggingService) logger: ILoggingService; + @inject(IocTypes.ITrackerService) trackerService: ITrackerService; - constructor(@inject(IocTypes.ITorrentEntriesService) torrentEntriesService: ITorrentEntriesService, - @inject(IocTypes.ILoggingService) logger: ILoggingService, - @inject(IocTypes.ITrackerService) trackerService: ITrackerService) { - this.torrentEntriesService = torrentEntriesService; - this.logger = logger; - this.trackerService = trackerService; - } - - public processTorrentRecord = async (torrent: IIngestedTorrentAttributes): Promise => { + async processTorrentRecord(torrent: IIngestedTorrentAttributes): Promise { const {category} = torrent; const type = category === 'tv' ? TorrentType.Series : TorrentType.Movie; const torrentInfo: IParsedTorrent = await this.parseTorrent(torrent, type); @@ -34,7 +26,7 @@ export class TorrentProcessingService implements ITorrentProcessingService { } return this.torrentEntriesService.createTorrentEntry(torrentInfo, false); - }; + } private assignTorrentTrackers = async (): Promise => { const trackers = await this.trackerService.getTrackers(); @@ -64,5 +56,4 @@ export class TorrentProcessingService implements ITorrentProcessingService { return torrent.imdb; }; -} - +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts index be2641c..5a678a9 100644 --- a/src/node/consumer/src/lib/services/torrent_subtitle_service.ts +++ b/src/node/consumer/src/lib/services/torrent_subtitle_service.ts @@ -7,7 +7,7 @@ import {parse} from 'parse-torrent-title'; @injectable() export class TorrentSubtitleService implements ITorrentSubtitleService { - public assignSubtitles = (fileCollection: ITorrentFileCollection): ITorrentFileCollection => { + assignSubtitles(fileCollection: ITorrentFileCollection): ITorrentFileCollection { if (fileCollection.videos && fileCollection.videos.length && fileCollection.subtitles && fileCollection.subtitles.length) { if (fileCollection.videos.length === 1) { const matchingSubtitles = fileCollection.subtitles.filter(subtitle => @@ -33,7 +33,7 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { return {...fileCollection, subtitles: unassignedSubs}; } return fileCollection; - }; + } private parseVideo = (video: IFileAttributes): IFileAttributes => { const fileName = video.title?.split('/')?.pop()?.replace(/\.(\w{2,4})$/, '') || ''; @@ -104,4 +104,4 @@ export class TorrentSubtitleService implements ITorrentSubtitleService { if (!array1 || !array2) return array1 === array2; return array1.length === array2.length && array1.every((value, index) => value === array2[index]) } -} +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/services/tracker_service.ts b/src/node/consumer/src/lib/services/tracker_service.ts index 11f2ad1..f1c9ed4 100644 --- a/src/node/consumer/src/lib/services/tracker_service.ts +++ b/src/node/consumer/src/lib/services/tracker_service.ts @@ -1,24 +1,20 @@ import {ICacheService} from "@interfaces/cache_service"; import {ILoggingService} from "@interfaces/logging_service"; import {ITrackerService} from "@interfaces/tracker_service"; -import {IocTypes} from "@models/ioc_types"; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import axios, {AxiosResponse} from 'axios'; import {inject, injectable} from "inversify"; @injectable() export class TrackerService implements ITrackerService { - private cacheService: ICacheService; - private logger: ILoggingService; + @inject(IocTypes.ICacheService) cacheService: ICacheService; + @inject(IocTypes.ILoggingService) logger: ILoggingService; - constructor(@inject(IocTypes.ICacheService) cacheService: ICacheService, - @inject(IocTypes.ILoggingService) logger: ILoggingService) { - this.cacheService = cacheService; - this.logger = logger; + async getTrackers(): Promise { + return this.cacheService.cacheTrackers(this.downloadTrackers); } - public getTrackers = async (): Promise => this.cacheService.cacheTrackers(this.downloadTrackers); - private downloadTrackers = async (): Promise => { const response: AxiosResponse = await axios.get(configurationService.trackerConfig.TRACKERS_URL); const trackersListText: string = response.data; @@ -37,5 +33,4 @@ export class TrackerService implements ITrackerService { return urlTrackers; }; -} - +} \ No newline at end of file diff --git a/src/node/consumer/src/main.ts b/src/node/consumer/src/main.ts index 22466a7..7a5afeb 100644 --- a/src/node/consumer/src/main.ts +++ b/src/node/consumer/src/main.ts @@ -1,7 +1,7 @@ import "reflect-metadata"; // required -import {ICompositionalRoot} from "@interfaces/composition_root"; -import {serviceContainer} from "@models/inversify_config"; -import {IocTypes} from "@models/ioc_types"; +import {ICompositionalRoot} from "@setup/composition_root"; +import {serviceContainer} from "@setup/inversify_config"; +import {IocTypes} from "@setup/ioc_types"; (async (): Promise => { const compositionalRoot = serviceContainer.get(IocTypes.ICompositionalRoot); diff --git a/src/node/consumer/src/setup/composition_root.ts b/src/node/consumer/src/setup/composition_root.ts new file mode 100644 index 0000000..ce28aa0 --- /dev/null +++ b/src/node/consumer/src/setup/composition_root.ts @@ -0,0 +1,22 @@ +import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; +import {ITrackerService} from "@interfaces/tracker_service"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {IocTypes} from "@setup/ioc_types"; +import {inject, injectable} from "inversify"; + +export interface ICompositionalRoot { + start(): Promise; +} + +@injectable() +export class CompositionalRoot implements ICompositionalRoot { + @inject(IocTypes.ITrackerService) trackerService: ITrackerService; + @inject(IocTypes.IDatabaseRepository) databaseRepository: IDatabaseRepository; + @inject(IocTypes.IProcessTorrentsJob) processTorrentsJob: IProcessTorrentsJob; + + async start(): Promise { + await this.trackerService.getTrackers(); + await this.databaseRepository.connect(); + await this.processTorrentsJob.listenToQueue(); + } +} \ No newline at end of file diff --git a/src/node/consumer/src/lib/models/inversify_config.ts b/src/node/consumer/src/setup/inversify_config.ts similarity index 94% rename from src/node/consumer/src/lib/models/inversify_config.ts rename to src/node/consumer/src/setup/inversify_config.ts index 2dcbc8c..796bacd 100644 --- a/src/node/consumer/src/lib/models/inversify_config.ts +++ b/src/node/consumer/src/setup/inversify_config.ts @@ -1,5 +1,4 @@ import {ICacheService} from "@interfaces/cache_service"; -import {ICompositionalRoot} from "@interfaces/composition_root"; import {ILoggingService} from "@interfaces/logging_service"; import {IMetadataService} from "@interfaces/metadata_service"; import {IProcessTorrentsJob} from "@interfaces/process_torrents_job"; @@ -10,8 +9,6 @@ import {ITorrentProcessingService} from "@interfaces/torrent_processing_service" import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; import {ITrackerService} from "@interfaces/tracker_service"; import {ProcessTorrentsJob} from "@jobs/process_torrents_job"; -import {CompositionalRoot} from "@models/composition_root"; -import {IocTypes} from "@models/ioc_types"; import {DatabaseRepository} from "@repository/database_repository"; import {IDatabaseRepository} from "@repository/interfaces/database_repository"; import {CacheService} from "@services/cache_service"; @@ -23,6 +20,8 @@ import {TorrentFileService} from "@services/torrent_file_service"; import {TorrentProcessingService} from "@services/torrent_processing_service"; import {TorrentSubtitleService} from "@services/torrent_subtitle_service"; import {TrackerService} from "@services/tracker_service"; +import {ICompositionalRoot, CompositionalRoot} from "@setup/composition_root"; +import {IocTypes} from "@setup/ioc_types"; import {Container} from "inversify"; const serviceContainer = new Container(); diff --git a/src/node/consumer/src/lib/models/ioc_types.ts b/src/node/consumer/src/setup/ioc_types.ts similarity index 100% rename from src/node/consumer/src/lib/models/ioc_types.ts rename to src/node/consumer/src/setup/ioc_types.ts diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/cache_service.test.ts index d32bb9a..6a5e8b6 100644 --- a/src/node/consumer/test/cache_service.test.ts +++ b/src/node/consumer/test/cache_service.test.ts @@ -1,6 +1,8 @@ import "reflect-metadata"; // required import {ILoggingService} from '@interfaces/logging_service'; import {CacheMethod, CacheService} from '@services/cache_service'; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; jest.mock('@services/configuration_service', () => { return { @@ -49,9 +51,12 @@ describe('CacheService Tests', () => { beforeEach(() => { jest.clearAllMocks(); process.env.LOG_LEVEL = 'debug'; - loggingService = jest.requireMock('@services/logging_service'); cacheMethod = jest.fn().mockResolvedValue({}); - cacheService = new CacheService(loggingService); + loggingService = jest.requireMock('@services/logging_service'); + const container = new Container(); + container.bind(CacheService).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(loggingService); + cacheService = container.get(CacheService); }); afterEach(() => { @@ -113,7 +118,6 @@ describe('CacheService Tests', () => { } }); - cacheService = new CacheService(loggingService); const result = await cacheService.cacheWrapImdbId('testKey', cacheMethod); expect(result).toBeDefined(); }); diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/metadata_service.test.ts index 3fa868a..9184d4c 100644 --- a/src/node/consumer/test/metadata_service.test.ts +++ b/src/node/consumer/test/metadata_service.test.ts @@ -2,6 +2,8 @@ import "reflect-metadata"; // required import {ICacheService} from "@interfaces/cache_service"; import {IMetadataResponse} from "@interfaces/metadata_response"; import {MetadataService} from "@services/metadata_service"; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; import {setupServer} from "msw/node"; import * as responses from "./mock-responses/metadata_mock_responses"; @@ -38,7 +40,10 @@ describe('MetadataService Tests', () => { beforeEach(() => { mockCacheService = jest.requireMock('@services/cache_service'); - metadataService = new MetadataService(mockCacheService); + const container = new Container(); + container.bind(MetadataService).toSelf(); + container.bind(IocTypes.ICacheService).toConstantValue(mockCacheService); + metadataService = container.get(MetadataService); }); it("should get kitsu id", async () => { @@ -57,10 +62,10 @@ describe('MetadataService Tests', () => { id: 'kitsu:11', type: 'series' }); - + expect(mockCacheService.cacheWrapMetadata).toHaveBeenCalledWith('kitsu:11', expect.any(Function)); expect(result).not.toBeNull(); - + const body = result as IMetadataResponse; expect(body.videos).not.toBeNull(); expect(body.videos.length).toBe(220); diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/process_torrent_job.test.ts index 0eac22b..9abcfba 100644 --- a/src/node/consumer/test/process_torrent_job.test.ts +++ b/src/node/consumer/test/process_torrent_job.test.ts @@ -3,7 +3,9 @@ import {ILoggingService} from '@interfaces/logging_service'; import {ITorrentProcessingService} from '@interfaces/torrent_processing_service'; import {ProcessTorrentsJob} from '@jobs/process_torrents_job'; import {configurationService} from '@services/configuration_service'; +import {IocTypes} from "@setup/ioc_types"; import client, {ConsumeMessage} from 'amqplib'; +import {Container} from "inversify"; jest.mock('@services/configuration_service', () => { return { @@ -56,7 +58,12 @@ describe('ProcessTorrentsJob Tests', () => { jest.clearAllMocks(); loggingService = jest.requireMock('@services/logging_service'); torrentProcessingService = jest.requireMock('@services/torrent_processing_service'); - processTorrentsJob = new ProcessTorrentsJob(torrentProcessingService, loggingService); + + const container = new Container(); + container.bind(ProcessTorrentsJob).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(loggingService); + container.bind(IocTypes.ITorrentProcessingService).toConstantValue(torrentProcessingService); + processTorrentsJob = container.get(ProcessTorrentsJob); }); afterEach(() => { diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/torrent_download_service.test.ts index f513d88..1a1619e 100644 --- a/src/node/consumer/test/torrent_download_service.test.ts +++ b/src/node/consumer/test/torrent_download_service.test.ts @@ -2,6 +2,8 @@ import "reflect-metadata"; // required import {ILoggingService} from '@interfaces/logging_service'; import {IParsedTorrent} from "@interfaces/parsed_torrent"; import {TorrentDownloadService} from '@services/torrent_download_service'; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; import torrentStream from 'torrent-stream'; jest.mock('@services/logging_service', () => { @@ -27,7 +29,11 @@ describe('TorrentDownloadService', () => { beforeEach(() => { jest.clearAllMocks(); mockLoggingService = jest.requireMock('@services/logging_service'); - torrentDownloadService = new TorrentDownloadService(mockLoggingService); + + const container = new Container(); + container.bind(TorrentDownloadService).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(mockLoggingService); + torrentDownloadService = container.get(TorrentDownloadService); }); it('should get torrent files', async () => { diff --git a/src/node/consumer/test/torrent_entries_service.test.ts b/src/node/consumer/test/torrent_entries_service.test.ts index 50d0188..48dca8b 100644 --- a/src/node/consumer/test/torrent_entries_service.test.ts +++ b/src/node/consumer/test/torrent_entries_service.test.ts @@ -6,11 +6,13 @@ import {IParsedTorrent} from "@interfaces/parsed_torrent"; import {ITorrentFileCollection} from "@interfaces/torrent_file_collection"; import {ITorrentFileService} from "@interfaces/torrent_file_service"; import {ITorrentSubtitleService} from "@interfaces/torrent_subtitle_service"; -import {IDatabaseRepository} from "@repository/interfaces/database_repository"; +import {IDatabaseRepository} from "@repository/interfaces/database_repository"; import {IFileAttributes} from "@repository/interfaces/file_attributes"; import {ITorrentCreationAttributes} from "@repository/interfaces/torrent_attributes"; import {Torrent} from "@repository/models/torrent"; import {TorrentEntriesService} from "@services/torrent_entries_service"; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; jest.mock('@services/logging_service', () => { return { @@ -63,24 +65,32 @@ describe('TorrentEntriesService Tests', () => { beforeEach(() => { jest.clearAllMocks(); - + mockFileService = jest.requireMock('@services/torrent_file_service'); mockMetadataService = jest.requireMock('@services/metadata_service'); mockSubtitleService = jest.requireMock('@services/torrent_subtitle_service'); mockLoggingService = jest.requireMock('@services/logging_service'); mockDatabaseRepository = jest.requireMock('@repository/database_repository'); - torrentEntriesService = new TorrentEntriesService(mockMetadataService, mockLoggingService, mockFileService , mockSubtitleService, mockDatabaseRepository); + + const container = new Container(); + container.bind(TorrentEntriesService).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(mockLoggingService); + container.bind(IocTypes.ITorrentFileService).toConstantValue(mockFileService); + container.bind(IocTypes.ITorrentSubtitleService).toConstantValue(mockSubtitleService); + container.bind(IocTypes.IDatabaseRepository).toConstantValue(mockDatabaseRepository); + container.bind(IocTypes.IMetadataService).toConstantValue(mockMetadataService); + torrentEntriesService = container.get(TorrentEntriesService); }); it('should create a torrent entry', async () => { - const torrent : IParsedTorrent = { + const torrent: IParsedTorrent = { title: 'Test title', provider: 'Test provider', infoHash: 'Test infoHash', type: TorrentType.Movie, }; - const fileCollection : ITorrentFileCollection = { + const fileCollection: ITorrentFileCollection = { videos: [{ fileIndex: 0, title: 'Test video', @@ -91,9 +101,9 @@ describe('TorrentEntriesService Tests', () => { subtitles: [], }; - const fileCollectionWithSubtitles : ITorrentFileCollection = { + const fileCollectionWithSubtitles: ITorrentFileCollection = { ...fileCollection, - subtitles: [ { + subtitles: [{ fileId: 0, title: 'Test subtitle', fileIndex: 0, @@ -109,7 +119,11 @@ describe('TorrentEntriesService Tests', () => { await torrentEntriesService.createTorrentEntry(torrent); - expect(mockMetadataService.getImdbId).toHaveBeenCalledWith({ title: 'Test title', year: undefined, type: TorrentType.Movie }); + expect(mockMetadataService.getImdbId).toHaveBeenCalledWith({ + title: 'Test title', + year: undefined, + type: TorrentType.Movie + }); expect(mockFileService.parseTorrentFiles).toHaveBeenCalledWith(torrent); expect(mockFileService.parseTorrentFiles).toHaveReturnedWith(Promise.resolve(fileCollection)); expect(mockSubtitleService.assignSubtitles).toHaveBeenCalledWith(fileCollection); @@ -118,14 +132,14 @@ describe('TorrentEntriesService Tests', () => { }); it('should assign imdbId correctly', async () => { - const torrent : IParsedTorrent = { + const torrent: IParsedTorrent = { title: 'Test title', provider: 'Test provider', infoHash: 'Test infoHash', type: TorrentType.Movie, }; - const fileCollection : ITorrentFileCollection = { + const fileCollection: ITorrentFileCollection = { videos: [{ fileIndex: 0, title: 'Test video', @@ -136,9 +150,9 @@ describe('TorrentEntriesService Tests', () => { subtitles: [], }; - const fileCollectionWithSubtitles : ITorrentFileCollection = { + const fileCollectionWithSubtitles: ITorrentFileCollection = { ...fileCollection, - subtitles: [ { + subtitles: [{ fileId: 0, title: 'Test subtitle', fileIndex: 0, @@ -159,14 +173,14 @@ describe('TorrentEntriesService Tests', () => { }); it('should assign kitsuId correctly', async () => { - const torrent : IParsedTorrent = { + const torrent: IParsedTorrent = { title: 'Test title', provider: 'Test provider', infoHash: 'Test infoHash', type: TorrentType.Anime, }; - const fileCollection : ITorrentFileCollection = { + const fileCollection: ITorrentFileCollection = { videos: [{ fileIndex: 0, title: 'Test video', @@ -177,9 +191,9 @@ describe('TorrentEntriesService Tests', () => { subtitles: [], }; - const fileCollectionWithSubtitles : ITorrentFileCollection = { + const fileCollectionWithSubtitles: ITorrentFileCollection = { ...fileCollection, - subtitles: [ { + subtitles: [{ fileId: 0, title: 'Test subtitle', fileIndex: 0, @@ -208,9 +222,9 @@ describe('TorrentEntriesService Tests', () => { }; (mockDatabaseRepository.createSkipTorrent as jest.Mock).mockResolvedValue([torrent, null]); - + const result = await torrentEntriesService.createSkipTorrentEntry(torrent); - + expect(mockDatabaseRepository.createSkipTorrent).toHaveBeenCalledWith(torrent); expect(result).toEqual([torrent, null]); }); @@ -240,7 +254,7 @@ describe('TorrentEntriesService Tests', () => { }); it('should check and update torrent', async () => { - const torrent : IParsedTorrent = { + const torrent: IParsedTorrent = { title: 'Test title', provider: 'Test provider', infoHash: 'Test infoHash', @@ -248,13 +262,13 @@ describe('TorrentEntriesService Tests', () => { seeders: 1, }; - const files : IFileAttributes[] = [{ + const files: IFileAttributes[] = [{ infoHash: 'Test infoHash', fileIndex: 0, title: 'Test title', path: 'Test path', - size: 123456, - },{ + size: 123456, + }, { infoHash: 'Test infoHash 2', fileIndex: 1, title: 'Test title 2', @@ -264,16 +278,16 @@ describe('TorrentEntriesService Tests', () => { const torrentInstance = { ...torrent, - dataValues:{ ...torrent}, + dataValues: {...torrent}, save: jest.fn().mockResolvedValue(torrent), }; const filesInstance = { ...files, - dataValues:{ ...files}, + dataValues: {...files}, save: jest.fn().mockResolvedValue(files), }; - + const seedersResponse = [1]; (mockDatabaseRepository.getTorrent as jest.Mock).mockResolvedValue(torrentInstance); @@ -284,10 +298,10 @@ describe('TorrentEntriesService Tests', () => { const result = await torrentEntriesService.checkAndUpdateTorrent(torrent); expect(mockDatabaseRepository.getTorrent).toHaveBeenCalledWith({ - infoHash: torrent.infoHash, + infoHash: torrent.infoHash, provider: torrent.provider }); - + expect(mockDatabaseRepository.getFiles).toHaveBeenCalledWith(torrent.infoHash); expect(mockDatabaseRepository.setTorrentSeeders).toHaveBeenCalledWith(torrentInstance.dataValues, 1); expect(result).toEqual(true); @@ -307,7 +321,7 @@ describe('TorrentEntriesService Tests', () => { } } as Torrent; - const fileCollection : ITorrentFileCollection = { + const fileCollection: ITorrentFileCollection = { videos: [{ id: 1, title: 'Test video', @@ -319,7 +333,7 @@ describe('TorrentEntriesService Tests', () => { subtitles: [], }; - const fileCollectionWithContents : ITorrentFileCollection = { + const fileCollectionWithContents: ITorrentFileCollection = { ...fileCollection, contents: [{ size: 123456, diff --git a/src/node/consumer/test/torrent_file_service.test.ts b/src/node/consumer/test/torrent_file_service.test.ts index 292e079..f30ae00 100644 --- a/src/node/consumer/test/torrent_file_service.test.ts +++ b/src/node/consumer/test/torrent_file_service.test.ts @@ -5,6 +5,8 @@ import {IMetadataService} from "@interfaces/metadata_service"; import {IParsedTorrent} from "@interfaces/parsed_torrent"; import {ITorrentDownloadService} from "@interfaces/torrent_download_service"; import {TorrentFileService} from "@services/torrent_file_service"; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; jest.mock('@services/logging_service', () => { return { @@ -38,10 +40,17 @@ describe('TorrentFileService tests', () => { beforeEach(() => { jest.clearAllMocks(); + mockLoggingService = jest.requireMock('@services/logging_service'); mockDownloadService = jest.requireMock('@services/torrent_download_service'); mockMetadataService = jest.requireMock('@services/metadata_service'); - torrentFileService = new TorrentFileService(mockMetadataService, mockDownloadService, mockLoggingService); + + const container = new Container(); + container.bind(TorrentFileService).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(mockLoggingService); + container.bind(IocTypes.IMetadataService).toConstantValue(mockMetadataService); + container.bind(IocTypes.ITorrentDownloadService).toConstantValue(mockDownloadService); + torrentFileService = container.get(TorrentFileService); }); @@ -56,7 +65,7 @@ describe('TorrentFileService tests', () => { const result = torrentFileService.parseTorrentFiles(mockTorrent); expect(result).toBeInstanceOf(Promise); - + result.then(res => { expect(res).toHaveProperty('videos'); expect(res).toHaveProperty('subtitles'); diff --git a/src/node/consumer/test/torrent_subtitle_service.test.ts b/src/node/consumer/test/torrent_subtitle_service.test.ts index 5eff584..71b6dd9 100644 --- a/src/node/consumer/test/torrent_subtitle_service.test.ts +++ b/src/node/consumer/test/torrent_subtitle_service.test.ts @@ -12,9 +12,9 @@ describe('TorrentSubtitleService tests', () => { it('should assign subtitles to a single video', () => { const fileCollection: ITorrentFileCollection = { - videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + videos: [{title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'}], contents: [], - subtitles: [{ title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }], + subtitles: [{title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash'}], }; const result = torrentSubtitleService.assignSubtitles(fileCollection); @@ -27,7 +27,7 @@ describe('TorrentSubtitleService tests', () => { const fileCollection: ITorrentFileCollection = { videos: [], contents: [], - subtitles: [{ title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }], + subtitles: [{title: 'Test subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash'}], }; const result = torrentSubtitleService.assignSubtitles(fileCollection); @@ -37,7 +37,7 @@ describe('TorrentSubtitleService tests', () => { it('should not assign subtitles if there are no subtitles', () => { const fileCollection: ITorrentFileCollection = { - videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + videos: [{title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'}], contents: [], subtitles: [], }; @@ -50,13 +50,13 @@ describe('TorrentSubtitleService tests', () => { it('should assign subtitles to multiple videos', () => { const fileCollection: ITorrentFileCollection = { videos: [ - { title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }, - { title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' } + {title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'}, + {title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'} ], contents: [], subtitles: [ - { title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }, - { title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash' } + {title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash'}, + {title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash'} ], }; @@ -69,9 +69,9 @@ describe('TorrentSubtitleService tests', () => { it('should not assign subtitles if there are no matching videos', () => { const fileCollection: ITorrentFileCollection = { - videos: [{ title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }], + videos: [{title: 'Test video', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'}], contents: [], - subtitles: [{ title: 'Non-matching subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Non-matching infoHash' }], + subtitles: [{title: 'Non-matching subtitle', fileIndex: 0, path: 'Test path', infoHash: 'Non-matching infoHash'}], }; const result = torrentSubtitleService.assignSubtitles(fileCollection); @@ -83,13 +83,13 @@ describe('TorrentSubtitleService tests', () => { it('should assign subtitles to the most probable videos based on filename, title, season, and episode', () => { const fileCollection: ITorrentFileCollection = { videos: [ - { title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' }, - { title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash' } + {title: 'Test video S01E01', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'}, + {title: 'Test video S01E02', size: 123456, imdbId: 'tt1234567', infoHash: 'Test infoHash'} ], contents: [], subtitles: [ - { title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash' }, - { title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash' } + {title: 'Test subtitle S01E01', fileIndex: 0, path: 'Test path', infoHash: 'Test infoHash'}, + {title: 'Test subtitle S01E02', fileIndex: 1, path: 'Test path', infoHash: 'Test infoHash'} ], }; diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/tracker_service.test.ts index 71b7353..065c7c1 100644 --- a/src/node/consumer/test/tracker_service.test.ts +++ b/src/node/consumer/test/tracker_service.test.ts @@ -2,6 +2,8 @@ import "reflect-metadata"; // required import {ICacheService} from '@interfaces/cache_service'; import {ILoggingService} from '@interfaces/logging_service'; import {TrackerService} from '@services/tracker_service'; +import {IocTypes} from "@setup/ioc_types"; +import {Container} from "inversify"; import {setupServer} from 'msw/node'; import * as responses from "./mock-responses/trackers_mock_responses"; @@ -21,7 +23,6 @@ jest.mock('@services/cache_service', () => { } }) - beforeAll(() => server.listen()) beforeEach(() => { jest.clearAllMocks(); @@ -41,7 +42,12 @@ describe('TrackerService', () => { beforeEach(() => { mockCacheService = jest.requireMock('@services/cache_service'); mockLoggingService = jest.requireMock('@services/logging_service'); - trackerService = new TrackerService(mockCacheService, mockLoggingService); + + const container = new Container(); + container.bind(TrackerService).toSelf(); + container.bind(IocTypes.ILoggingService).toConstantValue(mockLoggingService); + container.bind(IocTypes.ICacheService).toConstantValue(mockCacheService); + trackerService = container.get(TrackerService); }); it('should get trackers', async () => { diff --git a/src/node/consumer/tsconfig.json b/src/node/consumer/tsconfig.json index d85609d..f1b203c 100644 --- a/src/node/consumer/tsconfig.json +++ b/src/node/consumer/tsconfig.json @@ -48,6 +48,9 @@ ], "@jobs/*": [ "lib/jobs/*" + ], + "@setup/*": [ + "setup/*" ] } }, From 29a619c528229f2c2378bfa75c75c8de16862f88 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Sat, 10 Feb 2024 00:21:23 +0000 Subject: [PATCH 50/55] Didn't mean to remove this. Latest stable lts --- src/node/consumer/.nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/node/consumer/.nvmrc diff --git a/src/node/consumer/.nvmrc b/src/node/consumer/.nvmrc new file mode 100644 index 0000000..016efd8 --- /dev/null +++ b/src/node/consumer/.nvmrc @@ -0,0 +1 @@ +v20.10.0 \ No newline at end of file From 189128bbc1126a6aa71cdf1cd7af562c5fa93661 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Sat, 10 Feb 2024 10:56:35 +0000 Subject: [PATCH 51/55] Fix boolean helpers - also add tests for all helpers, and expand config tests to test values for booleans --- .../src/lib/helpers/boolean_helpers.ts | 48 ++---- .../test/configuration_service.test.ts | 87 ----------- .../test/helpers/boolean_helpers.test.ts | 35 +++++ .../test/helpers/extension_helpers.test.ts | 33 +++++ .../test/helpers/promise_helpers.test.ts | 55 +++++++ .../test/{ => services}/cache_service.test.ts | 0 .../services/configuration_service.test.ts | 139 ++++++++++++++++++ .../{ => services}/logging_service.test.ts | 0 .../{ => services}/metadata_service.test.ts | 2 +- .../process_torrent_job.test.ts | 0 .../torrent_download_service.test.ts | 0 .../torrent_entries_service.test.ts | 0 .../torrent_file_service.test.ts | 0 .../torrent_subtitle_service.test.ts | 0 .../{ => services}/tracker_service.test.ts | 2 +- 15 files changed, 278 insertions(+), 123 deletions(-) delete mode 100644 src/node/consumer/test/configuration_service.test.ts create mode 100644 src/node/consumer/test/helpers/boolean_helpers.test.ts create mode 100644 src/node/consumer/test/helpers/extension_helpers.test.ts create mode 100644 src/node/consumer/test/helpers/promise_helpers.test.ts rename src/node/consumer/test/{ => services}/cache_service.test.ts (100%) create mode 100644 src/node/consumer/test/services/configuration_service.test.ts rename src/node/consumer/test/{ => services}/logging_service.test.ts (100%) rename src/node/consumer/test/{ => services}/metadata_service.test.ts (98%) rename src/node/consumer/test/{ => services}/process_torrent_job.test.ts (100%) rename src/node/consumer/test/{ => services}/torrent_download_service.test.ts (100%) rename src/node/consumer/test/{ => services}/torrent_entries_service.test.ts (100%) rename src/node/consumer/test/{ => services}/torrent_file_service.test.ts (100%) rename src/node/consumer/test/{ => services}/torrent_subtitle_service.test.ts (100%) rename src/node/consumer/test/{ => services}/tracker_service.test.ts (96%) diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index 1216bbe..a1c79dd 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,40 +1,20 @@ export const BooleanHelpers = { - parseBool: (value: string | number | undefined, defaultValue: boolean): boolean => { - switch (typeof value) { - case 'string': - return parseStringToBool(value, defaultValue); - case 'boolean': - return value; - case 'number': - return parseNumberToBool(value, defaultValue); + parseBool: (value: string | undefined, defaultValue: boolean): boolean => { + if (value === undefined) { + return defaultValue; + } + + switch (value.trim().toLowerCase()) { + case 'true': + case 'yes': + case '1': + return true; + case 'false': + case 'no': + case '0': + return false; default: return defaultValue; } } -} - -const parseStringToBool = (input: string, defaultVal: boolean): boolean => { - switch (input.toLowerCase().trim()) { - case 'true': - case 'yes': - case '1': - return true; - case 'false': - case 'no': - case '0': - return false; - default: - return defaultVal - } -} - -const parseNumberToBool = (input: number, defaultVal: boolean): boolean => { - switch (input) { - case 1: - return true; - case 0: - return false; - default: - return defaultVal; - } } \ No newline at end of file diff --git a/src/node/consumer/test/configuration_service.test.ts b/src/node/consumer/test/configuration_service.test.ts deleted file mode 100644 index c751564..0000000 --- a/src/node/consumer/test/configuration_service.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import "reflect-metadata"; // required - -describe('Configuration Tests', () => { - let configurationService; - beforeAll(async () => { - process.env.MONGODB_HOST = 'test_mongodb'; - process.env.MONGODB_PORT = '27017'; - process.env.MONGODB_DB = 'knightcrawler'; - process.env.MONGO_INITDB_ROOT_USERNAME = 'mongo'; - process.env.MONGO_INITDB_ROOT_PASSWORD = 'mongo'; - process.env.NO_CACHE = 'false'; - process.env.MONGODB_COLLECTION = 'knightcrawler_consumer_collection'; - process.env.POSTGRES_HOST = 'postgres'; - process.env.POSTGRES_PORT = '5432'; - process.env.POSTGRES_DB = 'knightcrawler'; - process.env.POSTGRES_USER = 'postgres'; - process.env.POSTGRES_PASSWORD = 'postgres'; - process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'false'; - process.env.TRACKERS_URL = 'https://ngosang.github.io/trackerslist/trackers_all.txt'; - process.env.UDP_TRACKERS_ENABLED = 'false'; - process.env.MAX_CONNECTIONS_PER_TORRENT = '20'; - process.env.TORRENT_TIMEOUT = '30000'; - process.env.RABBIT_URI = 'amqp://localhost'; - process.env.QUEUE_NAME = 'test-queue'; - process.env.IMDB_CONCURRENT = '1'; - process.env.IMDB_INTERVAL_MS = '1000'; - process.env.JOB_CONCURRENCY = '1'; - process.env.JOBS_ENABLED = 'true'; - - // shitty hack cause jest caches modules and resetModules isnt working - ({configurationService} = await import("@services/configuration_service")); - }); - - it('should populate cacheConfig correctly', () => { - const {cacheConfig} = configurationService; - expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); - expect(cacheConfig.MONGODB_PORT).toBe('27017'); - expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); - expect(cacheConfig.MONGO_INITDB_ROOT_USERNAME).toBe('mongo'); - expect(cacheConfig.MONGO_INITDB_ROOT_PASSWORD).toBe('mongo'); - expect(cacheConfig.NO_CACHE).toBe(false); - expect(cacheConfig.COLLECTION_NAME).toBe('knightcrawler_consumer_collection'); - expect(cacheConfig.MONGO_URI).toBe('mongodb://mongo:mongo@test_mongodb:27017/knightcrawler?authSource=admin'); - }); - - it('should populate databaseConfig correctly', () => { - const {databaseConfig} = configurationService; - expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); - expect(databaseConfig.POSTGRES_PORT).toBe(5432); - expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); - expect(databaseConfig.POSTGRES_USER).toBe('postgres'); - expect(databaseConfig.POSTGRES_PASSWORD).toBe('postgres'); - expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); - expect(databaseConfig.POSTGRES_URI).toBe('postgres://postgres:postgres@postgres:5432/knightcrawler'); - }); - - it('should populate jobConfig correctly', () => { - const {jobConfig} = configurationService; - expect(jobConfig.JOB_CONCURRENCY).toBe(1); - expect(jobConfig.JOBS_ENABLED).toBe(true); - }); - - it('should populate metadataConfig correctly', () => { - const {metadataConfig} = configurationService; - expect(metadataConfig.IMDB_CONCURRENT).toBe(1); - expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); - }); - - it('should populate rabbitConfig correctly', () => { - const {rabbitConfig} = configurationService; - expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); - expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); - }); - - it('should populate torrentConfig correctly', () => { - const {torrentConfig} = configurationService; - expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); - expect(torrentConfig.TIMEOUT).toBe(30000); - }); - - it('should populate trackerConfig correctly', () => { - const {trackerConfig} = configurationService; - expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); - expect(trackerConfig.UDP_ENABLED).toBe(false); - }); - -}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/boolean_helpers.test.ts b/src/node/consumer/test/helpers/boolean_helpers.test.ts new file mode 100644 index 0000000..32e285c --- /dev/null +++ b/src/node/consumer/test/helpers/boolean_helpers.test.ts @@ -0,0 +1,35 @@ +import { BooleanHelpers } from '@helpers/boolean_helpers'; + +describe('BooleanHelpers.parseBool', () => { + it('should return true when value is "true"', () => { + expect(BooleanHelpers.parseBool('true', false)).toBe(true); + }); + + it('should return true when value is "1"', () => { + expect(BooleanHelpers.parseBool('1', false)).toBe(true); + }); + + it('should return true when value is "yes"', () => { + expect(BooleanHelpers.parseBool('yes', false)).toBe(true); + }); + + it('should return false when value is "false"', () => { + expect(BooleanHelpers.parseBool('false', true)).toBe(false); + }); + + it('should return false when value is "0"', () => { + expect(BooleanHelpers.parseBool('0', true)).toBe(false); + }); + + it('should return false when value is "no"', () => { + expect(BooleanHelpers.parseBool('no', true)).toBe(false); + }); + + it('should return default value when value is undefined', () => { + expect(BooleanHelpers.parseBool(undefined, true)).toBe(true); + }); + + it('should return default value when value is not "true", "1", "yes", "false", "0", or "no"', () => { + expect(BooleanHelpers.parseBool('random', true)).toBe(true); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/extension_helpers.test.ts b/src/node/consumer/test/helpers/extension_helpers.test.ts new file mode 100644 index 0000000..ad92d8d --- /dev/null +++ b/src/node/consumer/test/helpers/extension_helpers.test.ts @@ -0,0 +1,33 @@ +import { ExtensionHelpers } from '@helpers/extension_helpers'; + +describe('ExtensionHelpers', () => { + describe('isVideo', () => { + it('should return true when file extension is a video extension', () => { + expect(ExtensionHelpers.isVideo('file.mp4')).toBe(true); + }); + + it('should return false when file extension is not a video extension', () => { + expect(ExtensionHelpers.isVideo('file.txt')).toBe(false); + }); + }); + + describe('isSubtitle', () => { + it('should return true when file extension is a subtitle extension', () => { + expect(ExtensionHelpers.isSubtitle('file.srt')).toBe(true); + }); + + it('should return false when file extension is not a subtitle extension', () => { + expect(ExtensionHelpers.isSubtitle('file.txt')).toBe(false); + }); + }); + + describe('isDisk', () => { + it('should return true when file extension is a disk extension', () => { + expect(ExtensionHelpers.isDisk('file.iso')).toBe(true); + }); + + it('should return false when file extension is not a disk extension', () => { + expect(ExtensionHelpers.isDisk('file.txt')).toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/promise_helpers.test.ts b/src/node/consumer/test/helpers/promise_helpers.test.ts new file mode 100644 index 0000000..d265177 --- /dev/null +++ b/src/node/consumer/test/helpers/promise_helpers.test.ts @@ -0,0 +1,55 @@ +import { PromiseHelpers } from '@helpers/promises_helpers'; + +describe('PromiseHelpers', () => { + beforeAll(() => { + jest.useFakeTimers({timerLimit: 5000}); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + describe('sequence', () => { + it('should resolve promises in sequence', async () => { + const promises = [() => Promise.resolve(1), () => Promise.resolve(2), () => Promise.resolve(3)]; + const result = await PromiseHelpers.sequence(promises); + expect(result).toEqual([1, 2, 3]); + }); + }); + + describe('first', () => { + it('should resolve the first fulfilled promise', async () => { + const promises = [Promise.reject('error'), Promise.resolve('success'), Promise.resolve('success2')]; + const result = await PromiseHelpers.first(promises); + expect(result).toBe('success'); + }); + }); + + describe('delay', () => { + it('should delay execution', async () => { + const startTime = Date.now(); + const delayPromise = PromiseHelpers.delay(1000); + jest.runAllTimers(); + await delayPromise; + const endTime = Date.now(); + expect(endTime - startTime).toBeGreaterThanOrEqual(1000); + }, 30000); + }); + + describe('timeout', () => { + it('should reject promise after timeout', async () => { + const promise = new Promise((resolve) => setTimeout(resolve, 2000)); + const timeoutPromise = PromiseHelpers.timeout(1000, promise); + jest.advanceTimersByTime(1000); + await expect(timeoutPromise).rejects.toBe('Timed out'); + }, 20000); + }); + + describe('mostCommonValue', () => { + it('should return the most common value in an array', () => { + const array = [1, 2, 2, 3, 3, 3]; + const result = PromiseHelpers.mostCommonValue(array); + expect(result).toBe(3); + }); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/services/cache_service.test.ts similarity index 100% rename from src/node/consumer/test/cache_service.test.ts rename to src/node/consumer/test/services/cache_service.test.ts diff --git a/src/node/consumer/test/services/configuration_service.test.ts b/src/node/consumer/test/services/configuration_service.test.ts new file mode 100644 index 0000000..a82cea5 --- /dev/null +++ b/src/node/consumer/test/services/configuration_service.test.ts @@ -0,0 +1,139 @@ +import "reflect-metadata"; // required + +describe('Configuration Tests', () => { + beforeEach(() => { + jest.resetModules(); + }); + it('should populate cacheConfig correctly', async () => { + process.env.MONGODB_HOST = 'test_mongodb'; + process.env.MONGODB_PORT = '27017'; + process.env.MONGODB_DB = 'knightcrawler'; + process.env.MONGO_INITDB_ROOT_USERNAME = 'mongo'; + process.env.MONGO_INITDB_ROOT_PASSWORD = 'mongo'; + process.env.NO_CACHE = 'false'; + process.env.MONGODB_COLLECTION = 'knightcrawler_consumer_collection'; + const {configurationService} = await import("@services/configuration_service"); + const {cacheConfig} = configurationService; + expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); + expect(cacheConfig.MONGODB_PORT).toBe('27017'); + expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); + expect(cacheConfig.MONGO_INITDB_ROOT_USERNAME).toBe('mongo'); + expect(cacheConfig.MONGO_INITDB_ROOT_PASSWORD).toBe('mongo'); + expect(cacheConfig.NO_CACHE).toBe(false); + expect(cacheConfig.COLLECTION_NAME).toBe('knightcrawler_consumer_collection'); + expect(cacheConfig.MONGO_URI).toBe('mongodb://mongo:mongo@test_mongodb:27017/knightcrawler?authSource=admin'); + }); + + it('should populate databaseConfig correctly', async() => { + process.env.POSTGRES_HOST = 'postgres'; + process.env.POSTGRES_PORT = '5432'; + process.env.POSTGRES_DB = 'knightcrawler'; + process.env.POSTGRES_USER = 'postgres'; + process.env.POSTGRES_PASSWORD = 'postgres'; + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'false'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); + expect(databaseConfig.POSTGRES_PORT).toBe(5432); + expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); + expect(databaseConfig.POSTGRES_USER).toBe('postgres'); + expect(databaseConfig.POSTGRES_PASSWORD).toBe('postgres'); + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + expect(databaseConfig.POSTGRES_URI).toBe('postgres://postgres:postgres@postgres:5432/knightcrawler'); + }); + + it('should process boolean when true as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'true'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when 1 as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = '1'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when yes as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'yes'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when uppercase TRUE as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'TRUE'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when uppercase FALSE as false for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'FALSE'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should process boolean when no as false for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'no'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should process boolean when no as 0 for migrations', async () => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = '0'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should populate jobConfig correctly', async() => { + process.env.JOB_CONCURRENCY = '1'; + process.env.JOBS_ENABLED = 'true'; + const {configurationService} = await import("@services/configuration_service"); + const {jobConfig} = configurationService; + expect(jobConfig.JOB_CONCURRENCY).toBe(1); + expect(jobConfig.JOBS_ENABLED).toBe(true); + }); + + it('should populate metadataConfig correctly', async() => { + process.env.IMDB_CONCURRENT = '1'; + process.env.IMDB_INTERVAL_MS = '1000'; + const {configurationService} = await import("@services/configuration_service"); + const {metadataConfig} = configurationService; + expect(metadataConfig.IMDB_CONCURRENT).toBe(1); + expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); + }); + + it('should populate rabbitConfig correctly', async () => { + process.env.RABBIT_URI = 'amqp://localhost'; + process.env.QUEUE_NAME = 'test-queue'; + const {configurationService} = await import("@services/configuration_service"); + const {rabbitConfig} = configurationService; + expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); + expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); + }); + + it('should populate torrentConfig correctly', async () => { + process.env.MAX_CONNECTIONS_PER_TORRENT = '20'; + process.env.TORRENT_TIMEOUT = '30000'; + const {configurationService} = await import("@services/configuration_service"); + const {torrentConfig} = configurationService; + expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); + expect(torrentConfig.TIMEOUT).toBe(30000); + }); + + it('should populate trackerConfig correctly', async () => { + process.env.TRACKERS_URL = 'https://ngosang.github.io/trackerslist/trackers_all.txt'; + process.env.UDP_TRACKERS_ENABLED = 'false'; + const {configurationService} = await import("@services/configuration_service"); + const {trackerConfig} = configurationService; + expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); + expect(trackerConfig.UDP_ENABLED).toBe(false); + }); + +}); \ No newline at end of file diff --git a/src/node/consumer/test/logging_service.test.ts b/src/node/consumer/test/services/logging_service.test.ts similarity index 100% rename from src/node/consumer/test/logging_service.test.ts rename to src/node/consumer/test/services/logging_service.test.ts diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/services/metadata_service.test.ts similarity index 98% rename from src/node/consumer/test/metadata_service.test.ts rename to src/node/consumer/test/services/metadata_service.test.ts index 9184d4c..0b94220 100644 --- a/src/node/consumer/test/metadata_service.test.ts +++ b/src/node/consumer/test/services/metadata_service.test.ts @@ -5,7 +5,7 @@ import {MetadataService} from "@services/metadata_service"; import {IocTypes} from "@setup/ioc_types"; import {Container} from "inversify"; import {setupServer} from "msw/node"; -import * as responses from "./mock-responses/metadata_mock_responses"; +import * as responses from "../mock-responses/metadata_mock_responses"; jest.mock('@services/cache_service', () => { return { diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/services/process_torrent_job.test.ts similarity index 100% rename from src/node/consumer/test/process_torrent_job.test.ts rename to src/node/consumer/test/services/process_torrent_job.test.ts diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/services/torrent_download_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_download_service.test.ts rename to src/node/consumer/test/services/torrent_download_service.test.ts diff --git a/src/node/consumer/test/torrent_entries_service.test.ts b/src/node/consumer/test/services/torrent_entries_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_entries_service.test.ts rename to src/node/consumer/test/services/torrent_entries_service.test.ts diff --git a/src/node/consumer/test/torrent_file_service.test.ts b/src/node/consumer/test/services/torrent_file_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_file_service.test.ts rename to src/node/consumer/test/services/torrent_file_service.test.ts diff --git a/src/node/consumer/test/torrent_subtitle_service.test.ts b/src/node/consumer/test/services/torrent_subtitle_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_subtitle_service.test.ts rename to src/node/consumer/test/services/torrent_subtitle_service.test.ts diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/services/tracker_service.test.ts similarity index 96% rename from src/node/consumer/test/tracker_service.test.ts rename to src/node/consumer/test/services/tracker_service.test.ts index 065c7c1..4427817 100644 --- a/src/node/consumer/test/tracker_service.test.ts +++ b/src/node/consumer/test/services/tracker_service.test.ts @@ -5,7 +5,7 @@ import {TrackerService} from '@services/tracker_service'; import {IocTypes} from "@setup/ioc_types"; import {Container} from "inversify"; import {setupServer} from 'msw/node'; -import * as responses from "./mock-responses/trackers_mock_responses"; +import * as responses from "../mock-responses/trackers_mock_responses"; const server = setupServer(responses.trackerTestResponse); From d76ac286a15de29c0eec28559400ef2993039c18 Mon Sep 17 00:00:00 2001 From: iPromKnight <156901906+iPromKnight@users.noreply.github.com> Date: Sun, 11 Feb 2024 21:50:59 +0000 Subject: [PATCH 52/55] Update src/node/consumer/esbuild.ts Co-authored-by: Sleeyax --- src/node/consumer/esbuild.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/node/consumer/esbuild.ts b/src/node/consumer/esbuild.ts index 4584dd5..9c06bbc 100644 --- a/src/node/consumer/esbuild.ts +++ b/src/node/consumer/esbuild.ts @@ -1,9 +1,7 @@ import { build } from "esbuild"; import { readFileSync, rmSync } from "fs"; -interface DevDependencies { - [key: string]: string; -} +type DevDependencies = Record interface PackageJson { devDependencies?: DevDependencies; From 0428b3a83c485c41100aadc0e7020015e7cd14a4 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 12 Feb 2024 08:46:43 +0000 Subject: [PATCH 53/55] remove node-gyp --- src/node/consumer/package-lock.json | 846 +--------------------------- src/node/consumer/package.json | 1 - 2 files changed, 8 insertions(+), 839 deletions(-) diff --git a/src/node/consumer/package-lock.json b/src/node/consumer/package-lock.json index 8c8ea5c..41b4c50 100644 --- a/src/node/consumer/package-lock.json +++ b/src/node/consumer/package-lock.json @@ -44,7 +44,6 @@ "eslint-plugin-import-helpers": "^1.3.1", "jest": "^29.7.0", "msw": "^2.1.7", - "node-gyp": "^10.0.1", "pino-pretty": "^10.3.1", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", @@ -1293,102 +1292,6 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1892,34 +1795,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", - "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/@open-draft/deferred-promise": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", @@ -1942,16 +1817,6 @@ "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", "dev": true }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2422,15 +2287,6 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2477,31 +2333,6 @@ "resolved": "https://registry.npmjs.org/addr-to-ip-port/-/addr-to-ip-port-1.5.4.tgz", "integrity": "sha512-ByxmJgv8vjmDcl3IDToxL2yrWFrRtFpZAToY0f46XFXl8zS081t7El5MXIodwm7RC6DhHBRoOSMLFSPKCtHukg==" }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3259,51 +3090,6 @@ "node": ">=4" } }, - "node_modules/cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/cache-manager": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.4.0.tgz", @@ -3473,15 +3259,6 @@ "node": ">= 6" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/chrome-dgram": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/chrome-dgram/-/chrome-dgram-3.0.6.tgz", @@ -3556,15 +3333,6 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4031,12 +3799,6 @@ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/electron-to-chromium": { "version": "1.4.661", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.661.tgz", @@ -4066,6 +3828,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -4075,6 +3838,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -4102,21 +3866,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4705,12 +4454,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -4935,34 +4678,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -5011,18 +4726,6 @@ "rimraf": "bin.js" } }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5446,38 +5149,6 @@ "entities": "^4.4.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5575,15 +5246,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -5655,7 +5317,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "devOptional": true + "optional": true, + "peer": true }, "node_modules/ip-set": { "version": "1.0.2", @@ -5827,12 +5490,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -6070,24 +5727,6 @@ "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -6924,28 +6563,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "dev": true, - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -7047,153 +6664,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -7390,15 +6860,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -7437,76 +6898,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/node-gyp/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7519,21 +6910,6 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, - "node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "dev": true, - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7779,21 +7155,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -7948,22 +7309,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", @@ -8531,15 +7876,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -8566,19 +7902,6 @@ "node": ">=16" } }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -8853,15 +8176,6 @@ "node": ">=8" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", @@ -9427,7 +8741,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "devOptional": true, + "optional": true, + "peer": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -9437,7 +8752,8 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -9447,20 +8763,6 @@ "npm": ">= 3.0.0" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/sonic-boom": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", @@ -9515,18 +8817,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -9595,21 +8885,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/string.prototype.trim": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", @@ -9676,19 +8951,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -9743,56 +9005,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -10700,30 +9912,6 @@ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -10931,24 +10119,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/src/node/consumer/package.json b/src/node/consumer/package.json index e6e5a13..d144b5e 100644 --- a/src/node/consumer/package.json +++ b/src/node/consumer/package.json @@ -49,7 +49,6 @@ "eslint-plugin-import-helpers": "^1.3.1", "jest": "^29.7.0", "msw": "^2.1.7", - "node-gyp": "^10.0.1", "pino-pretty": "^10.3.1", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", From 40e126757293aefce7c36ff3382b21ab06fee493 Mon Sep 17 00:00:00 2001 From: iPromKnight Date: Mon, 12 Feb 2024 08:52:00 +0000 Subject: [PATCH 54/55] tested - we dont need this --- src/node/consumer/esbuild.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/node/consumer/esbuild.ts b/src/node/consumer/esbuild.ts index 9c06bbc..c483f01 100644 --- a/src/node/consumer/esbuild.ts +++ b/src/node/consumer/esbuild.ts @@ -1,14 +1,6 @@ import { build } from "esbuild"; import { readFileSync, rmSync } from "fs"; -type DevDependencies = Record - -interface PackageJson { - devDependencies?: DevDependencies; -} - -const { devDependencies } = JSON.parse(readFileSync("./package.json", "utf8")) as PackageJson; - const start = Date.now(); try { @@ -21,7 +13,6 @@ try { entryPoints: [ "./src/main.ts", ], - external: [...(devDependencies && Object.keys(devDependencies))], keepNames: true, minify: true, outbase: "./src", From 0925c2fb519ee4077fa111a0c667cc5b89f24a50 Mon Sep 17 00:00:00 2001 From: iPromKnight <156901906+iPromKnight@users.noreply.github.com> Date: Tue, 13 Feb 2024 19:51:49 +0000 Subject: [PATCH 55/55] Cleanup boolean helpers --- src/node/consumer/src/lib/helpers/boolean_helpers.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index a1c79dd..93819f6 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,10 +1,8 @@ export const BooleanHelpers = { parseBool: (value: string | undefined, defaultValue: boolean): boolean => { - if (value === undefined) { - return defaultValue; - } - - switch (value.trim().toLowerCase()) { + switch (value?.trim().toLowerCase()) { + case undefined: + return defaultValue; case 'true': case 'yes': case '1': @@ -14,7 +12,7 @@ export const BooleanHelpers = { case '0': return false; default: - return defaultValue; + throw new Error(`Invalid boolean value: '${value}'. Allowed values are 'true', 'false', 'yes', 'no', '1', or '0'.`); } } } \ No newline at end of file