Small Nest.js-based project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

121 lines
3.9 KiB

import { NormalizedOmdbData } from '../types';
import { RawOmdbData } from './types';
const identity = <T>(value: T) => value;
const stringToArray = (value: string) => value.split(', ');
const stringToNumber = (value: string) => parseInt(value, 10);
const stringToDuration = (value: string) => {
const match = /^(?<time>\d+)\smin$/.exec(value);
if (!match) {
throw new Error(`Cannot parse duration: "${value}"`);
}
// Both `groups` and `groups['time']` are guaranteed to be defined because of regex definition, but TS doesn't know that.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return stringToNumber(match.groups!['time']!);
};
const omdbRatingsToNormalizedRatings = (ratings: RawOmdbData['Ratings']) =>
ratings.map(({ Source, Value }) => ({ source: Source, value: Value }));
const createRequiredField = <TKey extends keyof NormalizedOmdbData, TRawValue>(
key: TKey,
value: TRawValue,
transformer: (value: TRawValue) => NormalizedOmdbData[TKey],
) => {
if (value === undefined) {
throw new Error(`Value for ${key} is not defined`);
}
if (value === 'N/A') {
throw new Error(`Value for ${key} is "N/A"`);
}
return {
[key]: transformer(value),
} as Record<TKey, NormalizedOmdbData[TKey]>;
};
const createOptionalField = <TKey extends keyof NormalizedOmdbData, TRawValue>(
key: TKey,
value: TRawValue,
transformer: (
value: Exclude<TRawValue, undefined>,
) => NormalizedOmdbData[TKey],
) => {
if (value === undefined || value === 'N/A') {
return undefined;
}
return createRequiredField(
key,
value as Exclude<TRawValue, undefined>,
transformer,
);
};
export const normalizeRawOmdbData = (
rawOmdbData: RawOmdbData,
): NormalizedOmdbData => {
const {
Actors,
Awards,
BoxOffice,
Country,
DVD,
Director,
Genre,
Language: _language,
Metascore: _metascore,
Plot,
Poster,
Production: _production,
Rated,
Ratings,
Released,
Runtime,
Title,
Type,
Website,
Writer,
Year,
imdbID,
imdbRating: _imdbRating,
imdbVotes: _imdbVotes,
totalSeasons,
...rest
} = rawOmdbData;
const restKeys = Object.keys(rest);
if (restKeys.length) {
throw new Error(
`Unexpected fields in OMDB response: ${restKeys.join(', ')}`,
);
}
return {
...createRequiredField('actors', Actors, stringToArray),
...createRequiredField('awards', Awards, identity),
...createOptionalField('boxOffice', BoxOffice, identity),
...createOptionalField('contentRating', Rated, identity),
...createRequiredField('description', Plot, identity),
...createOptionalField('directors', Director, stringToArray),
...createRequiredField('duration', Runtime, stringToDuration),
...createOptionalField('dvdReleaseDate', DVD, identity),
...createRequiredField('genres', Genre, stringToArray),
...createRequiredField('imdbId', imdbID, identity),
...createRequiredField('posterUrl', Poster, identity),
...createRequiredField('productionCountries', Country, stringToArray),
...createRequiredField('productionYear', Year, stringToNumber),
...createRequiredField(
'ratings',
Ratings,
omdbRatingsToNormalizedRatings,
),
...createRequiredField('releaseDate', Released, identity),
...createRequiredField('title', Title, identity),
...createOptionalField('totalSeasons', totalSeasons, stringToNumber),
...createRequiredField('type', Type, identity),
...createOptionalField('website', Website, identity),
...createRequiredField('writers', Writer, stringToArray),
};
};