From 8f882596f020b789f411eb499d72ad88e57453e9 Mon Sep 17 00:00:00 2001 From: Chuck MANCHUCK Reeves Date: Mon, 14 Aug 2023 15:10:25 +0000 Subject: [PATCH] feat: media package --- jest.config.ts | 5 + packages/media/README.md | 71 ++++ .../media/__tests__/__dataSets__/delete.ts | 10 + packages/media/__tests__/__dataSets__/get.ts | 361 ++++++++++++++++++ .../media/__tests__/__dataSets__/index.ts | 18 + packages/media/__tests__/__dataSets__/put.ts | 43 +++ packages/media/__tests__/common.ts | 1 + packages/media/__tests__/media.test.ts | 82 ++++ packages/media/__tests__/private.test.key | 28 ++ packages/media/lib/index.ts | 2 + packages/media/lib/media.ts | 69 ++++ packages/media/lib/types/Responses/index.ts | 2 + .../lib/types/Responses/mediaItemResponse.ts | 16 + .../types/Responses/mediaItemResponsePage.ts | 18 + packages/media/lib/types/index.ts | 3 + packages/media/lib/types/mediaItem.ts | 18 + packages/media/lib/types/mediaParameters.ts | 7 + packages/media/package.json | 33 ++ 18 files changed, 787 insertions(+) create mode 100644 packages/media/README.md create mode 100644 packages/media/__tests__/__dataSets__/delete.ts create mode 100644 packages/media/__tests__/__dataSets__/get.ts create mode 100644 packages/media/__tests__/__dataSets__/index.ts create mode 100644 packages/media/__tests__/__dataSets__/put.ts create mode 100644 packages/media/__tests__/common.ts create mode 100644 packages/media/__tests__/media.test.ts create mode 100644 packages/media/__tests__/private.test.key create mode 100644 packages/media/lib/index.ts create mode 100644 packages/media/lib/media.ts create mode 100644 packages/media/lib/types/Responses/index.ts create mode 100644 packages/media/lib/types/Responses/mediaItemResponse.ts create mode 100644 packages/media/lib/types/Responses/mediaItemResponsePage.ts create mode 100644 packages/media/lib/types/index.ts create mode 100644 packages/media/lib/types/mediaItem.ts create mode 100644 packages/media/lib/types/mediaParameters.ts create mode 100644 packages/media/package.json diff --git a/jest.config.ts b/jest.config.ts index 6474a42a..fab6a513 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -32,6 +32,11 @@ const config: Config.InitialOptions = { testMatch: ['/packages/jwt/__tests__/**/*.test.ts'], coveragePathIgnorePatterns: ['node_modules', '__tests__'], }, + { + displayName: 'MEDIA', + testMatch: ['/packages/media/__tests__/**/*.test.ts'], + coveragePathIgnorePatterns: ['node_modules', '__tests__'], + }, { displayName: 'MESSAGES', testMatch: ['/packages/messages/__tests__/**/*.test.ts'], diff --git a/packages/media/README.md b/packages/media/README.md new file mode 100644 index 00000000..ba5519d3 --- /dev/null +++ b/packages/media/README.md @@ -0,0 +1,71 @@ +# Vonage Media SDK for Node.js + +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/vonage/vonage-node-sdk/ci.yml?branch=3.x) [![Codecov](https://img.shields.io/codecov/c/github/vonage/vonage-node-sdk?label=Codecov&logo=codecov&style=flat-square)](https://codecov.io/gh/Vonage/vonage-server-sdk) ![Latest Release](https://img.shields.io/npm/v/@vonage/media?label=%40vonage%2Fmedia&style=flat-square) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg?style=flat-square)](../../CODE_OF_CONDUCT.md) [![License](https://img.shields.io/npm/l/@vonage/accounts?label=License&style=flat-square)][license] + + +Vonage + +This is the Vonage Media SDK for Node.js for use with [Vonage APIs](https://www.vonage.com/). To use it you will need a Vonage account. Sign up [for free at vonage.com][signup]. + +For full API documentation refer to [developer.vonage.com](https://developer.vonage.com/). + +- [Installation](#installation) +- [Usage](#usage) +- [Promises](#promises) +- [Testing](#testing) + +## Installation + +### With NPM + +```bash +npm install @vonage/media +``` + +### With Yarn + +```bash +yarn add @vonage/media +``` + +## Usage + +Unlike the other SDK's this package is not included in the [Vonage Server SDK for Node.js](https://github.com/vonage/vonage-node-sdk) + +```js +const { Auth } = require('@vonage/auth') +const { Media } = require('@vonage/media') + +const credentials = new Auth({ + applicationId: APP_ID, + privateKey: PRIAVTE_KEY, +}) +const options = {} +const mediaClient = new Media(credentials, options) +``` + +Where `credentials` is any option from [`@vonage/auth`](https://github.com/Vonage/vonage-node-sdk/blob/3.x/packages/auth/README.md#options), and `options` is any option from [`@vonage/server-client`](https://github.com/Vonage/vonage-node-sdk/blob/3.x/packages/server-client/README.md#options) + +## Promises + +Most methods that interact with the Vonage API uses Promises. You can either resolve these yourself, or use `await` to wait for a response. + +```js +const resp = await mediaClient.listMediaItem() + +mediaClient + .listMedia() + .then((resp) => console.log(resp)) + .catch((err) => console.error(err)) +``` + +## Testing + +Run: + +```bash +npm run test +``` + +[signup]: https://dashboard.nexmo.com/sign-up?utm_source=DEV_REL&utm_medium=github&utm_campaign=node-server-sdk +[license]: ../../LICENSE.txt diff --git a/packages/media/__tests__/__dataSets__/delete.ts b/packages/media/__tests__/__dataSets__/delete.ts new file mode 100644 index 00000000..283ff8ff --- /dev/null +++ b/packages/media/__tests__/__dataSets__/delete.ts @@ -0,0 +1,10 @@ +export default [ + { + label: 'delete media item', + requests: [['/v3/media/00000000-0000-0000-0000-000000000000', 'DELETE']], + responses: [[204]], + clientMethod: 'deleteMediaItem', + parameters: ['00000000-0000-0000-0000-000000000000'], + expected: undefined, + }, +]; diff --git a/packages/media/__tests__/__dataSets__/get.ts b/packages/media/__tests__/__dataSets__/get.ts new file mode 100644 index 00000000..92487a45 --- /dev/null +++ b/packages/media/__tests__/__dataSets__/get.ts @@ -0,0 +1,361 @@ +import { + MediaItem, + MediaItemResponse, + MediaItemPageResponse, + MediaParameters, +} from '../../lib/types'; + +export default [ + { + label: 'get media item', + requests: [['/v3/media/00000000-0000-0000-0000-000000000000/info', 'GET']], + responses: [ + [ + 200, + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + ], + clientMethod: 'getMediaItem', + parameters: ['00000000-0000-0000-0000-000000000000'], + expected: { + id: '00000000-0000-0000-0000-000000000000', + originalFileName: 'test.wav', + mimeType: 'audio/vnd.wave', + accountId: 'my_account', + storeId: 's3', + maxDownloadsAllowed: 0, + timesDownloaded: 0, + etag: '00000000000000000000000000000000', + mediaSize: 1234567, + timeCreated: '2020-01-01T14:00:00.000Z', + timeLastUpdated: '2020-01-01T14:00:00.000Z', + public: false, + metadataPrimary: null, + metadataSecondary: null, + } as MediaItem, + }, + { + label: 'get one page of media items', + requests: [['/v3/media?', 'GET']], + responses: [ + [ + 200, + { + page_size: 20, + page_index: 0, + _links: { + self: { + href: `/v3/media?page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_size=20&order=descending`, + }, + }, + count: 1, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + } as MediaItemPageResponse, + ], + ], + clientMethod: 'getMediaPage', + parameters: [], + expected: { + page_size: 20, + page_index: 0, + _links: { + self: { + href: `/v3/media?page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_size=20&order=descending`, + }, + }, + count: 1, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + }, + }, + { + label: 'get page of data with query parameters', + requests: [ + [ + `/v3/media?order=descending&page_index=42&page_size=10&start_time=2020-01-01T14:00:00.000Z&end_time=2020-01-01T14:00:00.000Z`, + 'GET', + ], + ], + responses: [ + [ + 200, + { + page_size: 20, + page_index: 0, + _links: { + self: { + href: `/v3/media?page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_size=20&order=descending`, + }, + }, + count: 1, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + } as MediaItemPageResponse, + ], + ], + clientMethod: 'getMediaPage', + parameters: [ + { + order: 'descending', + pageIndex: 42, + pageSize: 10, + startTime: '2020-01-01T14:00:00.000Z', + endTime: '2020-01-01T14:00:00.000Z', + } as MediaParameters, + ], + expected: { + page_size: 20, + page_index: 0, + _links: { + self: { + href: `/v3/media?page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_size=20&order=descending`, + }, + }, + count: 1, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + }, + }, + { + label: 'get multiple pages using generator', + requests: [ + ['/v3/media?page_index=0', 'GET'], + [`/v3/media?page_index=1`, 'GET'], + ], + responses: [ + [ + 200, + { + page_size: 20, + page_index: 0, + _links: { + self: { + href: `/v3/media?page_index=0&page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_index=0&page_size=20&order=descending`, + }, + next: { + href: `/v3/media?page_index=1&page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_index=1&page_size=20&order=descending`, + }, + }, + count: 2, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000000', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + } as MediaItemPageResponse, + ], + [ + 200, + { + page_size: 20, + page_index: 1, + _links: { + self: { + href: `/v3/media?page_index=0&page_size=20&order=descending`, + }, + first: { + href: `/v3/media?page_index=0&page_size=20&order=descending`, + }, + prev: { + href: `/v3/media?page_index=0&page_size=20&order=descending`, + }, + last: { + href: `/v3/media?page_index=1&page_size=20&order=descending`, + }, + }, + count: 2, + _embedded: { + media: [ + { + id: '00000000-0000-0000-0000-000000000001', + original_file_name: 'test.wav', + mime_type: 'audio/vnd.wave', + account_id: 'my_account', + store_id: 's3', + max_downloads_allowed: 0, + times_downloaded: 0, + etag: '00000000000000000000000000000000', + media_size: 1234567, + time_created: '2020-01-01T14:00:00.000Z', + time_last_updated: '2020-01-01T14:00:00.000Z', + public: false, + metadata_primary: null, + metadata_secondary: null, + } as MediaItemResponse, + ], + }, + } as MediaItemPageResponse, + ], + ], + clientMethod: 'listAllMediaItems', + parameters: [], + generator: true, + expected: [ + { + id: '00000000-0000-0000-0000-000000000000', + originalFileName: 'test.wav', + mimeType: 'audio/vnd.wave', + accountId: 'my_account', + storeId: 's3', + maxDownloadsAllowed: 0, + timesDownloaded: 0, + etag: '00000000000000000000000000000000', + mediaSize: 1234567, + timeCreated: '2020-01-01T14:00:00.000Z', + timeLastUpdated: '2020-01-01T14:00:00.000Z', + public: false, + metadataPrimary: null, + metadataSecondary: null, + }, + { + id: '00000000-0000-0000-0000-000000000001', + originalFileName: 'test.wav', + mimeType: 'audio/vnd.wave', + accountId: 'my_account', + storeId: 's3', + maxDownloadsAllowed: 0, + timesDownloaded: 0, + etag: '00000000000000000000000000000000', + mediaSize: 1234567, + timeCreated: '2020-01-01T14:00:00.000Z', + timeLastUpdated: '2020-01-01T14:00:00.000Z', + public: false, + metadataPrimary: null, + metadataSecondary: null, + }, + ], + }, +]; diff --git a/packages/media/__tests__/__dataSets__/index.ts b/packages/media/__tests__/__dataSets__/index.ts new file mode 100644 index 00000000..3509d542 --- /dev/null +++ b/packages/media/__tests__/__dataSets__/index.ts @@ -0,0 +1,18 @@ +import getTests from './get'; +import deleteTests from './delete'; +import putTests from './put'; + +export default [ + { + label: 'GET test', + tests: getTests, + }, + { + label: 'DELETE test', + tests: deleteTests, + }, + { + label: 'PUT test', + tests: putTests, + }, +]; diff --git a/packages/media/__tests__/__dataSets__/put.ts b/packages/media/__tests__/__dataSets__/put.ts new file mode 100644 index 00000000..f8d49c1c --- /dev/null +++ b/packages/media/__tests__/__dataSets__/put.ts @@ -0,0 +1,43 @@ +export default [ + { + label: 'update media item', + requests: [ + [ + '/v3/media/00000000-0000-0000-0000-000000000000', + 'PUT', + { + public: false, + metadata_primary: 'fizz', + metadata_secondary: 'buzz', + title: 'foo', + description: 'bar', + mime_type: 'audio/vnd.wave', + max_downloads_allowed: 42, + }, + ], + ], + responses: [[204]], + clientMethod: 'updateMediaItem', + parameters: [ + { + id: '00000000-0000-0000-0000-000000000000', + title: 'foo', + description: 'bar', + originalFileName: 'test.wav', + mimeType: 'audio/vnd.wave', + accountId: 'my_account', + storeId: 's3', + maxDownloadsAllowed: 42, + timesDownloaded: 0, + etag: '00000000000000000000000000000000', + mediaSize: 1234567, + timeCreated: '2020-01-01T14:00:00.000Z', + timeLastUpdated: '2020-01-01T14:00:00.000Z', + public: false, + metadataPrimary: 'fizz', + metadataSecondary: 'buzz', + }, + ], + expected: undefined, + }, +]; diff --git a/packages/media/__tests__/common.ts b/packages/media/__tests__/common.ts new file mode 100644 index 00000000..68a7132f --- /dev/null +++ b/packages/media/__tests__/common.ts @@ -0,0 +1 @@ +export const BASE_URL = 'https://api.nexmo.com'; diff --git a/packages/media/__tests__/media.test.ts b/packages/media/__tests__/media.test.ts new file mode 100644 index 00000000..18fd2126 --- /dev/null +++ b/packages/media/__tests__/media.test.ts @@ -0,0 +1,82 @@ +import { Media } from '../lib/index'; +import nock from 'nock'; +import { Auth } from '@vonage/auth'; +import { BASE_URL } from './common'; +import testDataSets from './__dataSets__/index'; +import { readFileSync } from 'fs'; + +const key = readFileSync(`${__dirname}/private.test.key`).toString(); + +const getResults = async ( + generator: boolean, + client: Media, + clientMethod: string, + parameters: Array, +): Promise> => { + if (!generator) { + return await client[clientMethod](...parameters); + } + + const results = []; + for await (const result of client[clientMethod](...parameters)) { + results.push(result as never); + } + + return results; +}; + +describe.each(testDataSets)('$label', ({ tests }) => { + let client: Media | null; + let scope: nock.Scope; + + beforeEach(function () { + client = new Media( + new Auth({ + privateKey: key, + applicationId: 'my-application', + }), + ); + + scope = nock(BASE_URL, { + reqheaders: { + authorization: (value) => value.startsWith('Bearer '), + }, + }).persist(); + }); + + afterEach(function () { + client = null; + scope = null; + nock.cleanAll(); + }); + + test.each(tests as any[])( + 'Can $label using: $clientMethod', + async ({ + requests, + responses, + clientMethod, + parameters, + expected, + generator = false, + }) => { + requests.forEach((request: Array, index: number) => { + scope.intercept( + request[0], + request[1], + request[2], + ).reply(...responses[index]); + }); + + const results = await getResults( + generator, + client as Media, + clientMethod, + parameters, + ); + + expect(results).toEqual(expected); + expect(nock.isDone()).toBeTruthy(); + }, + ); +}); diff --git a/packages/media/__tests__/private.test.key b/packages/media/__tests__/private.test.key new file mode 100644 index 00000000..d127da04 --- /dev/null +++ b/packages/media/__tests__/private.test.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTH8cEhJKsu2hB +ucgs0Blf3tvgdXuIa5sMRI3zIZGok8jqaj6DC0WdM1eiJlQCWnVL0vR25MkopMZN +MTphoaVpdK9wywMVx7PsgMCDXJjW77QFJFbbcbV9KG2xvMsjJGttmVrn+9aPpCnX +yT27bWkTR0k/wCAvra/st5MDKg2kB3SMc+97zlO3GqIkJJKfKYQFAO8oRBcsZ1Bx +ydPWTQvyLYW15Cjv30aIGLfceFwDeUOBgBsesGFtcXvVF6sVxd5D/USunX/9es95 +Rdr4+9Qq4tIKZRkBz2KWD0eo256wmmq2lQoGaR9x6XgLHhUlsi6OXILcyChi2Qcc +a01Hn7YvAgMBAAECggEAJsS+lIdNsddmIS+e4Q/DoRW49aJNMXNlEN8j2+Itr7GX +ougom4K94UyUyotUQOxgfrB5wL1pbQO5AGLKUDRRPii1sLYu1liKIyNPdq/RxyJU +Qd927awXQiji39EF0mm1KnaPOWtG7rCcGGp1Yg4Izgf4nPLIVkkENalOHzYhNB3u +4W4OIT49iw/auBF4wnl1RmXWXjkxDuk2cYT28a8hWqyQjJqXTsO+u4BaXYxSf4nP +Be2yoUEFRbcxvJrhEpfODhPP83I1EBipJkhUTc5WMb/vtH2b49+TYd2tPR0LOxom +mcNUWF6++ae+vL6K8Dlfcvx+CA7g7KBHHcgFCzn7GQKBgQDzc2ow5LlQQ/VfXZTz +n07V/QgVQ15sA5Cf/gsvmwnGPy06Qx/WRHsz6NG8nvW2mHZwfDIHuLjBW1gcssEx +mLpqav5XLZfSyjjRO/AxLIfJDx/aARp3+7Ny5aY2e3wtNx8wz4J80i7P+eX3fETM +70cWhc2PvYMDjG+O7cDW2FWAFwKBgQDeAcc/FBHLl9/HqiBvYf/Y/k0t1TUoHujO +PSbP6SaN06JnvJmBANyED7sWeIPuoRFXXEr4Auu7y0C55Wlsno/ImTbJsopZ1rgU +k5q4t9vcu7cGiOr7L7UkySNYZqRjwvKEJ610COexTThSwl0v3GNLP8r4AMdBaqdK +uO6fVfxxqQKBgFc5ne2Atai9gJe3ltum0382FoRPy+/VYyb/xZA780eVcSXz0N9b +T+0sWKFFLvJKM/1fcil0FLYqfSpjHXcgqoHgbdpcWo5KqArHd+qWctwl0Bqy1IHy +q7vZ7jCNE9O7cTBy2OTSBbW8apm+a4Qlowm9zQXYN624zmueYb5YamHnAoGAZvJA +KHnv/o7AkF/NhpjVARR7SYOSkLY0kl48/zBIVoAK0TvdmrqBhyOcR8E+vIsn9XCw +uuzvzzdjHlDJYDruxcB2bXVDPoGY/sGrf3iSlXreVkNrY2st/o7euwFtvW0K9ElJ +34K5nbgHJClI+QajbKN6RSJnQ2hnhvjWfkBrPXECgYEA4MCEm9EyrguEO51am8va +OjIAiQMkj/iyjsMDL8eH0VM+OMdieHwbkKyajyrB9dFikvWfxiuo3dU1N5vJTzty +LmzkB8M/rKlAYKD8iKA8cRun4tKzRepHT3JPMu0GYTfcP9ovs5F3aEjX+UuWOO7n +doWDENAr/VU1RNCDwFdxYFg= +-----END PRIVATE KEY----- diff --git a/packages/media/lib/index.ts b/packages/media/lib/index.ts new file mode 100644 index 00000000..64350c18 --- /dev/null +++ b/packages/media/lib/index.ts @@ -0,0 +1,2 @@ +export * from './types/index'; +export * from './media'; diff --git a/packages/media/lib/media.ts b/packages/media/lib/media.ts new file mode 100644 index 00000000..b8d12395 --- /dev/null +++ b/packages/media/lib/media.ts @@ -0,0 +1,69 @@ +import { Client, AuthenticationType, APILink } from '@vonage/server-client'; +import { + MediaItem, + MediaParameters, + MediaItemPageResponse, + MediaItemResponse, +} from './types/index'; + +const apiToSdk = (media: MediaItemResponse): MediaItem => + Client.transformers.camelCaseObjectKeys(media); + +export class Media extends Client { + protected authType = AuthenticationType.JWT; + + async *listAllMediaItems( + params: MediaParameters = {}, + ): AsyncGenerator { + let pageIndex = params.pageIndex || 0; + let next: APILink; + do { + params.pageIndex = pageIndex; + const resp = await this.getMediaPage(params); + + yield* resp._embedded?.media?.map(apiToSdk); + + pageIndex++; + next = resp._links?.next; + } while (next); + } + + async getMediaPage( + params: MediaParameters = {}, + ): Promise { + const resp = await this.sendGetRequest( + `${this.config.apiHost}/v3/media`, + Client.transformers.snakeCaseObjectKeys(params, true), + ); + + return resp.data; + } + + async getMediaItem(mediaId: string): Promise { + const resp = await this.sendGetRequest( + `${this.config.apiHost}/v3/media/${mediaId}/info`, + ); + + return apiToSdk(resp.data); + } + + async updateMediaItem(media: MediaItem): Promise { + await this.sendPutRequest( + `${this.config.apiHost}/v3/media/${media.id}`, + { + public: media.public, + metadata_primary: media.metadataPrimary, + metadata_secondary: media.metadataSecondary, + title: media.title, + description: media.description, + mime_type: media.mimeType, + max_downloads_allowed: media.maxDownloadsAllowed, + }, + 'PUT', + ); + } + + async deleteMediaItem(mediaId: string): Promise { + await this.sendDeleteRequest(`${this.config.apiHost}/v3/media/${mediaId}`); + } +} diff --git a/packages/media/lib/types/Responses/index.ts b/packages/media/lib/types/Responses/index.ts new file mode 100644 index 00000000..4ece5812 --- /dev/null +++ b/packages/media/lib/types/Responses/index.ts @@ -0,0 +1,2 @@ +export * from './mediaItemResponse'; +export * from './mediaItemResponsePage'; diff --git a/packages/media/lib/types/Responses/mediaItemResponse.ts b/packages/media/lib/types/Responses/mediaItemResponse.ts new file mode 100644 index 00000000..3e2537e3 --- /dev/null +++ b/packages/media/lib/types/Responses/mediaItemResponse.ts @@ -0,0 +1,16 @@ +import { MediaItem } from '../mediaItem'; + +export type MediaItemResponse = { + original_file_name: string; + mime_type: string; + account_id: string; + store_id: string; + max_downloads_allowed: number; + times_downloaded: number; + media_size: number; + time_created: string; + time_last_updated: string; + public: boolean; + metadata_primary: string; + metadata_secondary: string; +} & Pick; diff --git a/packages/media/lib/types/Responses/mediaItemResponsePage.ts b/packages/media/lib/types/Responses/mediaItemResponsePage.ts new file mode 100644 index 00000000..9c618fab --- /dev/null +++ b/packages/media/lib/types/Responses/mediaItemResponsePage.ts @@ -0,0 +1,18 @@ +import { APILinks, APILink } from '@vonage/server-client'; +import { MediaItemResponse } from './mediaItemResponse'; + +export type MediaItemPageResponse = { + page_size: number; + page_index: number; + count: number; + _embedded: { + media: Array; + }; + _links: { + first?: APILink; + last?: APILink; + next?: APILink; + prev?: APILink; + start?: APILink; + }; +} & APILinks; diff --git a/packages/media/lib/types/index.ts b/packages/media/lib/types/index.ts new file mode 100644 index 00000000..8d1feb41 --- /dev/null +++ b/packages/media/lib/types/index.ts @@ -0,0 +1,3 @@ +export * from './Responses/'; +export * from './mediaItem'; +export * from './mediaParameters'; diff --git a/packages/media/lib/types/mediaItem.ts b/packages/media/lib/types/mediaItem.ts new file mode 100644 index 00000000..521e3404 --- /dev/null +++ b/packages/media/lib/types/mediaItem.ts @@ -0,0 +1,18 @@ +export type MediaItem = { + id: string; + title?: string; + description?: string; + originalFileName: string; + mimeType: string; + accountId: string; + storeId: string; + maxDownloadsAllowed: number; + timesDownloaded: number; + etag: string; + mediaSize: number; + timeCreated: string; + timeLastUpdated: string; + public: boolean; + metadataPrimary: string; + metadataSecondary: string; +}; diff --git a/packages/media/lib/types/mediaParameters.ts b/packages/media/lib/types/mediaParameters.ts new file mode 100644 index 00000000..7e6173a6 --- /dev/null +++ b/packages/media/lib/types/mediaParameters.ts @@ -0,0 +1,7 @@ +export type MediaParameters = { + order?: 'ascending' | 'descending'; + pageIndex?: number; + pageSize?: number; + startTime?: string; + endTime?: string; +}; diff --git a/packages/media/package.json b/packages/media/package.json new file mode 100644 index 00000000..0380a0ac --- /dev/null +++ b/packages/media/package.json @@ -0,0 +1,33 @@ +{ + "name": "@vonage/media", + "version": "1.0.0", + "description": "The Media API can be used to query, download and delete media items such as audio files for use with other Vonage APIs.", + "homepage": "https://github.com/vonage/vonage-node-sdk/tree/main/packages/media#readme", + "bugs": { + "url": "https://github.com/Vonage/vonage-node-sdk/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Vonage/vonage-node-sdk.git" + }, + "license": "Apache-2.0", + "author": "Chuck MANCHUCK Reeves ", + "main": "dist/index.js", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "scripts": { + "test": "node ./__tests__/media.test.js" + }, + "dependencies": { + "@vonage/server-client": "1.6.0" + }, + "devDependencies": { + "@vonage/auth": "1.5.0", + "nock": "13.3.2" + } +}