Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
586 changes: 293 additions & 293 deletions .yarn/releases/yarn-4.13.0.cjs → .yarn/releases/yarn-4.15.0.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ enableGlobalCache: false

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.13.0.cjs
yarnPath: .yarn/releases/yarn-4.15.0.cjs
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ Watches for changes to TypeScript files and compiles them to JavaScript (use `ya
#### `yarn dev`
Runs the development server and restarts it when any file is changed

#### `yarn dev:cron`
Runs the cron job feature using ts-node

#### `yarn start`
Runs the server

Expand Down
3 changes: 1 addition & 2 deletions ecosystem.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ module.exports = {
apps: [
{
name: 'API',
script: 'node_modules/.bin/ts-node',
args: '--transpileOnly --files ./src/app.ts',
script: './src/app.ts',
env: { NODE_ENV: 'production', VERBOSE: 'false' },
env_verbose: { NODE_ENV: 'production', VERBOSE: 'true' },
instances: 0,
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"node": "24",
"yarn": ">=1.22.10"
},
"type": "module",
"scripts": {
"dev": "DEBUG=\"*universalmediaserver-api:server\" nodemon",
"start": "ts-node --files src/app.ts",
"start": "node src/app.ts",
"start:prod": "pm2 start ecosystem.config.js --update-env",
"start:prod:verbose": "pm2 start ecosystem.config.js --env verbose",
"reload:prod": "pm2 reload ecosystem.config.js",
Expand All @@ -31,12 +32,11 @@
"koa-qs": "3.0.0",
"koa-router": "14.0.0",
"lodash": "4.18.1",
"mongoose": "^9.0.2",
"mongoose": "^9.6.3",
"moviedb-promise": "4.0.8",
"object-mapper": "6.2.0",
"pm2": "^6.0.13",
"ts-node": "^10.9.2",
"typescript": "5.9"
"typescript": "^6.0.3"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
Expand All @@ -54,5 +54,5 @@
"ts-jest": "29.4.11",
"typescript-eslint": "^8.6.0"
},
"packageManager": "yarn@4.13.0"
"packageManager": "yarn@4.15.0"
}
12 changes: 6 additions & 6 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@
import bodyParser from 'koa-bodyparser';
import helmet from "koa-helmet";
import * as mongoose from 'mongoose';
import { ParameterizedContext } from 'koa';
import type { ParameterizedContext } from 'koa';
import koaQs from 'koa-qs';

Check failure on line 6 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Could not find a declaration file for module 'koa-qs'. '/home/runner/work/api/api/node_modules/koa-qs/index.js' implicitly has an 'any' type.

Check failure on line 6 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Could not find a declaration file for module 'koa-qs'. '/home/runner/work/api/api/node_modules/koa-qs/index.js' implicitly has an 'any' type.
import Debug from 'debug';

Check failure on line 7 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Could not find a declaration file for module 'debug'. '/home/runner/work/api/api/node_modules/debug/src/index.js' implicitly has an 'any' type.

Check failure on line 7 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Could not find a declaration file for module 'debug'. '/home/runner/work/api/api/node_modules/debug/src/index.js' implicitly has an 'any' type.
import * as fs from 'fs';
import * as http from 'http';
import * as https from 'https';

const debug = Debug('universalmediaserver-api:server');
import indexRouter from './routes/index';
import mediaRouter from './routes/media';
import deprecatedMediaRouter from './routes/deprecated/media';
import { DeprecationError, ExternalAPIError, IMDbIDNotFoundError, MediaNotFoundError, RateLimitError, ValidationError } from './helpers/customErrors';
import indexRouter from './routes/index.ts';
import mediaRouter from './routes/media.ts';
import deprecatedMediaRouter from './routes/deprecated/media.ts';
import { DeprecationError, ExternalAPIError, IMDbIDNotFoundError, MediaNotFoundError, RateLimitError, ValidationError } from './helpers/customErrors.ts';

const app = new Koa();

koaQs(app, 'first');

import connect from './models/connection';
import connect from './models/connection.ts';

const db: string = process.env.MONGO_URL;

Check failure on line 24 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Type 'string | undefined' is not assignable to type 'string'.

Check failure on line 24 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

Type 'string | undefined' is not assignable to type 'string'.
export const PORT: string = process.env.PORT || '3000';
const bypassMongo: boolean = Boolean(process.env.BYPASS_MONGO) || false;
if (process.env.NODE_ENV !== 'test') {
Expand All @@ -46,10 +46,10 @@
if (err instanceof RateLimitError) {
ctx.status = 429;
}
ctx.status = ctx.status || err.status || 500;

Check failure on line 49 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 49 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
ctx.body = { 'error': err.message };

Check failure on line 50 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 50 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
if (process.env.NODE_ENV !== 'production') {
ctx.body.stack = err.stack;

Check failure on line 52 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 52 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
}
if (
process.env.NODE_ENV !== 'test' &&
Expand All @@ -60,10 +60,10 @@
!(err instanceof ExternalAPIError) &&
// Stop logging errors for the deprecated routes getBySanitizedTitle and getBySanitizedTitleV2
!(
err.stack &&

Check failure on line 63 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 63 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
(
err.stack.includes('getBySanitizedTitle') ||

Check failure on line 65 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 65 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
err.stack.includes('controllers/deprecated')

Check failure on line 66 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.

Check failure on line 66 in src/app.ts

View workflow job for this annotation

GitHub Actions / build

'err' is of type 'unknown'.
)
)
)
Expand Down
5 changes: 3 additions & 2 deletions src/controllers/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import TMDBConfiguration, { TMDBConfigurationInterface } from '../models/TMDBConfiguration';
import { tmdb } from '../services/tmdb-api';
import TMDBConfiguration from '../models/TMDBConfiguration.ts';
import type { TMDBConfigurationInterface } from '../models/TMDBConfiguration.ts';
import { tmdb } from '../services/tmdb-api.ts';

let configuration: Partial<TMDBConfigurationInterface>;
let configurationExpiryDate: Date;
Expand Down
17 changes: 10 additions & 7 deletions src/controllers/deprecated/media.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import _ from 'lodash';

import { MediaNotFoundError, ValidationError } from '../../helpers/customErrors';
import FailedLookups, { FailedLookupsInterface } from '../../models/FailedLookups';
import MediaMetadata, { MediaMetadataInterface } from '../../models/MediaMetadata';
import SeriesMetadata, { SeriesMetadataInterface } from '../../models/SeriesMetadata';
import * as externalAPIHelper from '../../services/external-api-helper';
import * as deprecatedExternalAPIHelper from '../../services/deprecated/external-api-helper';
import { addSearchMatchByIMDbID } from '../media';
import { MediaNotFoundError, ValidationError } from '../../helpers/customErrors.ts';
import type { FailedLookupsInterface } from '../../models/FailedLookups.ts';
import type { MediaMetadataInterface } from '../../models/MediaMetadata.ts';
import type { SeriesMetadataInterface } from '../../models/SeriesMetadata.ts';
import FailedLookups from '../../models/FailedLookups.ts';
import MediaMetadata from '../../models/MediaMetadata.ts';
import SeriesMetadata from '../../models/SeriesMetadata.ts';
import * as externalAPIHelper from '../../services/external-api-helper.ts';
import * as deprecatedExternalAPIHelper from '../../services/deprecated/external-api-helper.ts';
import { addSearchMatchByIMDbID } from '../media.ts';

/**
* Since this is deprecated, it will only return a result that has been created
Expand Down
21 changes: 12 additions & 9 deletions src/controllers/media.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import _ from 'lodash';

import { DeprecationError, MediaNotFoundError, RateLimitError, ValidationError } from '../helpers/customErrors';
import { CollectionMetadataInterface } from '../models/CollectionMetadata';
import FailedLookups, { FailedLookupsInterface } from '../models/FailedLookups';
import LocalizeMetadata, { LocalizeMetadataInterface } from '../models/LocalizeMetadata';
import MediaMetadata, { MediaMetadataInterface } from '../models/MediaMetadata';
import { SeasonMetadataInterface } from '../models/SeasonMetadata';
import { SeriesMetadataInterface } from '../models/SeriesMetadata';
import * as externalAPIHelper from '../services/external-api-helper';
import { traceLog } from '../helpers/logging';
import { DeprecationError, MediaNotFoundError, RateLimitError, ValidationError } from '../helpers/customErrors.ts';
import type { CollectionMetadataInterface } from '../models/CollectionMetadata.ts';
import type { FailedLookupsInterface } from '../models/FailedLookups.ts';
import type { LocalizeMetadataInterface } from '../models/LocalizeMetadata.ts';
import type { MediaMetadataInterface } from '../models/MediaMetadata.ts';
import FailedLookups from '../models/FailedLookups.ts';
import LocalizeMetadata from '../models/LocalizeMetadata.ts';
import MediaMetadata from '../models/MediaMetadata.ts';
import type { SeasonMetadataInterface } from '../models/SeasonMetadata.ts';
import type { SeriesMetadataInterface } from '../models/SeriesMetadata.ts';
import * as externalAPIHelper from '../services/external-api-helper.ts';
import { traceLog } from '../helpers/logging.ts';

const THIRTY_DAYS_IN_MILLISECONDS = 24 * 60 * 60 * 30 * 1000;

Expand Down
3 changes: 2 additions & 1 deletion src/models/CollectionMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mongoose, { Schema, InferSchemaType } from 'mongoose';
import mongoose, { Schema } from 'mongoose';
import type { InferSchemaType } from 'mongoose';

const CollectionMetadataSchema: Schema = new Schema({
images: { type: Array },
Expand Down
3 changes: 2 additions & 1 deletion src/models/LocalizeMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mongoose, { Schema, InferSchemaType } from 'mongoose';
import mongoose, { Schema } from 'mongoose';
import type { InferSchemaType } from 'mongoose';

const LocalizeMetadataSchema = new Schema({
episodeNumber: { index: true, type: Number },
Expand Down
3 changes: 1 addition & 2 deletions src/models/MediaMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as mongoose from 'mongoose';
import { Schema } from 'mongoose';
import { CreditsResponse, EpisodeCreditsResponse, EpisodeExternalIdsResponse, EpisodeImagesResponse, MovieExternalIdsResponse, MovieImagesResponse } from 'moviedb-promise/dist/request-types';
import { ProductionCompany, ProductionCountry, SpokenLanguage } from 'moviedb-promise/dist/types';
import type { CreditsResponse, EpisodeCreditsResponse, EpisodeExternalIdsResponse, EpisodeImagesResponse, MovieExternalIdsResponse, MovieImagesResponse, ProductionCompany, ProductionCountry, SpokenLanguage } from 'moviedb-promise';

export interface MediaMetadataInterface {
actors?: Array<string>;
Expand Down
3 changes: 2 additions & 1 deletion src/models/SeasonMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mongoose, { Schema, InferSchemaType } from 'mongoose';
import mongoose, { Schema } from 'mongoose';
import type { InferSchemaType } from 'mongoose';

const castSubdocument = new Schema({
adult: { type: Boolean },
Expand Down
3 changes: 1 addition & 2 deletions src/models/SeriesMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as mongoose from 'mongoose';
import { Schema, Model } from 'mongoose';
import { Network, SimplePerson, SimpleSeason, TvImagesResponse, TvExternalIdsResponse, CreditsResponse } from 'moviedb-promise/dist/request-types';
import { ProductionCompany, ProductionCountry, SpokenLanguage } from 'moviedb-promise/dist/types';
import type { Network, ProductionCompany, ProductionCountry, SpokenLanguage, SimplePerson, SimpleSeason, TvImagesResponse, TvExternalIdsResponse, CreditsResponse } from 'moviedb-promise';

export interface SeriesMetadataInterface {
actors?: Array<string>;
Expand Down
3 changes: 2 additions & 1 deletion src/models/TMDBConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mongoose, { InferSchemaType, Schema } from 'mongoose';
import mongoose, { Schema } from 'mongoose';
import type { InferSchemaType } from 'mongoose';

const THREE_DAYS_IN_SECONDS = 259200;

Expand Down
6 changes: 3 additions & 3 deletions src/routes/deprecated/media.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Router from 'koa-router';
import * as DeprecatedMediaController from '../../controllers/deprecated/media';
import { subversions } from '../../helpers/subversioning';
import { DeprecationError } from '../../helpers/customErrors';
import * as DeprecatedMediaController from '../../controllers/deprecated/media.ts';
import { subversions } from '../../helpers/subversioning.ts';
import { DeprecationError } from '../../helpers/customErrors.ts';

const router = new Router({ prefix: '/api/media' });

Expand Down
4 changes: 2 additions & 2 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Router from 'koa-router';
import * as v8 from 'v8';

import { getConfiguration } from '../controllers/configuration';
import { subversions } from '../helpers/subversioning';
import { getConfiguration } from '../controllers/configuration.ts';
import { subversions } from '../helpers/subversioning.ts';

const { SYSTEM_ADMIN_KEY, NODE_APP_INSTANCE } = process.env!;

Expand Down
4 changes: 2 additions & 2 deletions src/routes/media.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Router from 'koa-router';

import * as MediaController from '../controllers/media';
import { subversions } from '../helpers/subversioning';
import * as MediaController from '../controllers/media.ts';
import { subversions } from '../helpers/subversioning.ts';

const router = new Router({ prefix: '/api/media' });

Expand Down
6 changes: 3 additions & 3 deletions src/services/deprecated/external-api-helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import _ from 'lodash';

import { getTMDBImageBaseURL } from '../../controllers/configuration';
import { MediaMetadataInterface } from '../../models/MediaMetadata';
import { SeriesMetadataInterface } from '../../models/SeriesMetadata';
import { getTMDBImageBaseURL } from '../../controllers/configuration.ts';
import type { MediaMetadataInterface } from '../../models/MediaMetadata.ts';
import type { SeriesMetadataInterface } from '../../models/SeriesMetadata.ts';

/*
* If the incoming metadata contains a poster image within the images
Expand Down
34 changes: 21 additions & 13 deletions src/services/external-api-helper.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { jaroWinkler } from '@skyra/jaro-winkler';
import episodeParser from 'episode-parser';
import _ from 'lodash';
import { FlattenMaps } from 'mongoose';
import { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest, SimpleEpisode, TvExternalIdsResponse, TvResult } from 'moviedb-promise/dist/request-types';

import { tmdb } from './tmdb-api';
import { ValidationError } from '../helpers/customErrors';
import { traceLog } from '../helpers/logging';
import CollectionMetadata, { CollectionMetadataInterface } from '../models/CollectionMetadata';
import FailedLookups, { FailedLookupsInterface } from '../models/FailedLookups';
import LocalizeMetadata, { LocalizeMetadataInterface } from '../models/LocalizeMetadata';
import MediaMetadata, { MediaMetadataInterface } from '../models/MediaMetadata';
import SeasonMetadata, { SeasonMetadataInterface } from '../models/SeasonMetadata';
import SeriesMetadata, { SeriesMetadataInterface } from '../models/SeriesMetadata';
import { mapper } from '../utils/data-mapper';
import type { FlattenMaps } from 'mongoose';
import type { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest, SimpleEpisode, TvExternalIdsResponse, TvResult } from 'moviedb-promise';

import { tmdb } from './tmdb-api.ts';
import { ValidationError } from '../helpers/customErrors.ts';
import { traceLog } from '../helpers/logging.ts';
import CollectionMetadata from '../models/CollectionMetadata.ts';
import FailedLookups from '../models/FailedLookups.ts';
import LocalizeMetadata from '../models/LocalizeMetadata.ts';
import MediaMetadata from '../models/MediaMetadata.ts';
import SeasonMetadata from '../models/SeasonMetadata.ts';
import SeriesMetadata from '../models/SeriesMetadata.ts';

import type { CollectionMetadataInterface } from '../models/CollectionMetadata.ts';
import type { FailedLookupsInterface } from '../models/FailedLookups.ts';
import type { LocalizeMetadataInterface } from '../models/LocalizeMetadata.ts';
import type { MediaMetadataInterface } from '../models/MediaMetadata.ts';
import type { SeasonMetadataInterface } from '../models/SeasonMetadata.ts';
import type { SeriesMetadataInterface } from '../models/SeriesMetadata.ts';

import { mapper } from '../utils/data-mapper.ts';

const getSeriesTMDBIDFromTMDBAPI = async(imdbID?: string, seriesTitle?: string, language?: string, year?: number): Promise<number> => {
if (imdbID) {
Expand Down
4 changes: 2 additions & 2 deletions src/services/tmdb-api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash';
import { MovieDb } from 'moviedb-promise';
import { CollectionInfoResponse, CollectionRequest, ConfigurationResponse, Episode, EpisodeRequest, FindRequest, FindResponse, IdAppendToResponseRequest, MovieResultsResponse, SearchMovieRequest, SearchTvRequest, ShowResponse, TvResultsResponse, TvSeasonRequest, TvSeasonResponse } from 'moviedb-promise/dist/request-types';
import { ExternalAPIError, RateLimitError } from '../helpers/customErrors';
import type { CollectionInfoResponse, CollectionRequest, ConfigurationResponse, Episode, EpisodeRequest, FindRequest, FindResponse, IdAppendToResponseRequest, MovieResultsResponse, SearchMovieRequest, SearchTvRequest, ShowResponse, TvResultsResponse, TvSeasonRequest, TvSeasonResponse } from 'moviedb-promise';
import { ExternalAPIError, RateLimitError } from '../helpers/customErrors.ts';

if (process.env.NODE_ENV === 'production' && !process.env.TMDB_API_KEY) {
throw new Error('TMDB_API_KEY not set');
Expand Down
12 changes: 6 additions & 6 deletions src/utils/data-mapper.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import _ from 'lodash';
import { CollectionInfoResponse, CreditsResponse, EpisodeCreditsResponse, Genre } from 'moviedb-promise';
import type { CollectionInfoResponse, CreditsResponse, EpisodeCreditsResponse, Genre } from 'moviedb-promise';
import * as objectMapper from 'object-mapper';

import { CollectionMetadataInterface } from '../models/CollectionMetadata';
import { LocalizeMetadataInterface } from '../models/LocalizeMetadata';
import { MediaMetadataInterface } from '../models/MediaMetadata';
import { SeasonMetadataInterface } from '../models/SeasonMetadata';
import { SeriesMetadataInterface } from '../models/SeriesMetadata';
import type { CollectionMetadataInterface } from '../models/CollectionMetadata.ts';
import type { LocalizeMetadataInterface } from '../models/LocalizeMetadata.ts';
import type { MediaMetadataInterface } from '../models/MediaMetadata.ts';
import type { SeasonMetadataInterface } from '../models/SeasonMetadata.ts';
import type { SeriesMetadataInterface } from '../models/SeriesMetadata.ts';

const tmdbEpisodeMap = {
'air_date': [
Expand Down
12 changes: 8 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true
"target": "es2025",
"module": "node20",
"moduleResolution": "node16",
"esModuleInterop": true,
"allowImportingTsExtensions": true,
"strict": true,
"rewriteRelativeImportExtensions": true,
"verbatimModuleSyntax": true
},
"files": [
"./src/interfaces.d.ts"
Expand Down
Loading
Loading