implemented basic OMDB integration

main
Inga 🏳‍🌈 11 months ago
parent 1e92edeae4
commit 449d95109e
  1. 1
      .eslintrc.js
  2. 52
      package-lock.json
  3. 3
      package.json
  4. 37
      src/integration/movies/omdb.spec.ts
  5. 26
      src/integration/movies/omdb.ts

@ -14,7 +14,6 @@ module.exports = {
root: true, root: true,
env: { env: {
node: true, node: true,
jest: true,
}, },
ignorePatterns: ['.eslintrc.js'], ignorePatterns: ['.eslintrc.js'],
rules: { rules: {

52
package-lock.json generated

@ -12,6 +12,8 @@
"@nestjs/common": "^10.0.0", "@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"node-fetch": "^2.7.0",
"p-queue": "^6.6.2",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1" "rxjs": "^7.8.1"
}, },
@ -23,6 +25,7 @@
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/jest": "^29.5.2", "@types/jest": "^29.5.2",
"@types/node": "^20.3.1", "@types/node": "^20.3.1",
"@types/node-fetch": "^2.6.9",
"@types/supertest": "^2.0.12", "@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
@ -2044,6 +2047,16 @@
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"node_modules/@types/node-fetch": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz",
"integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==",
"dev": true,
"dependencies": {
"@types/node": "*",
"form-data": "^4.0.0"
}
},
"node_modules/@types/qs": { "node_modules/@types/qs": {
"version": "6.9.10", "version": "6.9.10",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz",
@ -4173,6 +4186,11 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/events": { "node_modules/events": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@ -6659,6 +6677,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"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==",
"engines": {
"node": ">=4"
}
},
"node_modules/p-limit": { "node_modules/p-limit": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@ -6689,6 +6715,32 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/p-queue": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
"integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
"dependencies": {
"eventemitter3": "^4.0.4",
"p-timeout": "^3.2.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-timeout": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
"dependencies": {
"p-finally": "^1.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/p-try": { "node_modules/p-try": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",

@ -23,6 +23,8 @@
"@nestjs/common": "^10.0.0", "@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"node-fetch": "^2.7.0",
"p-queue": "^6.6.2",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1" "rxjs": "^7.8.1"
}, },
@ -34,6 +36,7 @@
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/jest": "^29.5.2", "@types/jest": "^29.5.2",
"@types/node": "^20.3.1", "@types/node": "^20.3.1",
"@types/node-fetch": "^2.6.9",
"@types/supertest": "^2.0.12", "@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",

@ -0,0 +1,37 @@
import { describe, it, expect } from '@jest/globals';
import { createOmdbClient } from './omdb';
describe('createOmdbClient', () => {
const client = createOmdbClient('68fd98ab');
it('returns some data for the sample movie id', async () => {
const result = await client.getMovieMetadata('tt11873472');
expect(result).toMatchObject({
'Actors': 'Cheryl Isheja, Elvis Ngabo, Diogène Ntarindwa',
'Awards': expect.any(String),
'BoxOffice': expect.any(String),
'Country': 'Rwanda, France, Canada, United Kingdom, United States',
'DVD': expect.any(String),
'Director': 'Anisia Uzeyman, Saul Williams',
'Genre': 'Musical, Sci-Fi',
'Language': 'Kinyarwanda, Kirundi, Swahili, French, English',
'Metascore': expect.stringMatching(/^\d+$/),
'Plot': expect.any(String),
'Poster': expect.stringMatching(/^http/),
'Production': expect.any(String),
'Rated': expect.any(String),
'Ratings': expect.any(Array),
'Released': '10 May 2023',
'Response': 'True',
'Runtime': '105 min',
'Title': 'Neptune Frost',
'Type': 'movie',
'Website': expect.any(String),
'Writer': 'Saul Williams',
'Year': '2021',
'imdbID': 'tt11873472',
'imdbRating': expect.stringMatching(/^\d?\d(\.\d)?$/),
'imdbVotes': expect.stringMatching(/^\d+$/),
});
}, 10_000);
});

@ -0,0 +1,26 @@
import fetch from 'node-fetch';
import PQueue from 'p-queue';
export const createOmdbClient = (apiKey: string) => {
// Rate limit (according to readme, it's 10k per day;
// here we set it 1 per second, should be enough for the demo app goal)
const queue = new PQueue({
interval: 1000,
intervalCap: 1,
timeout: 2000,
throwOnTimeout: true,
});
return {
getMovieMetadata: async (movieId: string) =>
queue.add(async () => {
const url = new URL('https://www.omdbapi.com/');
url.searchParams.append('i', movieId);
url.searchParams.append('apikey', apiKey);
url.searchParams.append('plot', 'full');
const response = await fetch(url);
const body = (await response.json()) as unknown;
return body;
}),
};
};
Loading…
Cancel
Save