searchitunes
Advanced tools
Comparing version 2.4.0 to 2.5.0
@@ -5,3 +5,3 @@ // Load module | ||
// Search parameters | ||
const params = { | ||
const parameters = { | ||
entity: 'software', | ||
@@ -11,11 +11,12 @@ country: 'NL', | ||
limit: 1, | ||
price: 0 | ||
price: 0, | ||
}; | ||
// Do the search | ||
itunes (params) | ||
itunes ({ parameters }) | ||
.then (data => console.dir (data, { | ||
depth: null, | ||
colors: true | ||
colors: true, | ||
})) | ||
.catch (console.error); | ||
.catch (console.error) | ||
; |
{ | ||
"author": { | ||
"name": "Franklin van de Meent", | ||
"email": "fr@nkl.in", | ||
"url": "https://frankl.in" | ||
"name": "Franklin", | ||
"email": "info@fvdm.com", | ||
"url": "https://fvdm.com" | ||
}, | ||
"name": "searchitunes", | ||
"description": "Search the Apple iTunes Store and App Store with this lightweight module", | ||
"version": "2.4.0", | ||
"version": "2.5.0", | ||
"repository": { | ||
@@ -18,11 +18,13 @@ "type": "git", | ||
"main": "searchitunes.js", | ||
"files": [ | ||
"example.js" | ||
], | ||
"dependencies": { | ||
"es6-promisify": "^6.0.0", | ||
"httpreq": "^0.4.24" | ||
"httpreq": "^0.5.2" | ||
}, | ||
"devDependencies": { | ||
"dotest": "^2.3.0" | ||
"dotest": "^2.9.0" | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0" | ||
"node": ">=12" | ||
}, | ||
@@ -34,9 +36,6 @@ "keywords": [ | ||
"appstore", | ||
"id", | ||
"itunes", | ||
"lookup", | ||
"music", | ||
"search", | ||
"term", | ||
"terms" | ||
"search" | ||
], | ||
@@ -43,0 +42,0 @@ "license": "Unlicense", |
@@ -6,7 +6,4 @@ # searchitunes | ||
[![npm](https://img.shields.io/npm/v/searchitunes.svg?maxAge=3600)](https://github.com/fvdm/nodejs-searchitunes/blob/master/CHANGELOG.md) | ||
[![Build Status](https://travis-ci.org/fvdm/nodejs-searchitunes.svg?branch=master)](https://travis-ci.org/fvdm/nodejs-searchitunes) | ||
[![Build Status](https://github.com/fvdm/nodejs-searchitunes/actions/workflows/node.js.yml/badge.svg?branch=master)](https://github.com/fvdm/nodejs-searchitunes/actions/workflows/node.js.yml) | ||
[![Coverage Status](https://coveralls.io/repos/github/fvdm/nodejs-searchitunes/badge.svg?branch=master)](https://coveralls.io/github/fvdm/nodejs-searchitunes?branch=master) | ||
[![bitHound Dependencies](https://www.bithound.io/github/fvdm/nodejs-searchitunes/badges/dependencies.svg)](https://www.bithound.io/github/fvdm/nodejs-searchitunes/develop/dependencies/npm) | ||
[![bitHound Code](https://www.bithound.io/github/fvdm/nodejs-searchitunes/badges/code.svg)](https://www.bithound.io/github/fvdm/nodejs-searchitunes) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/fvdm/nodejs-searchitunes.svg)](https://greenkeeper.io/) | ||
@@ -18,2 +15,4 @@ | ||
const searchitunes = require ('searchitunes'); | ||
// Find free Github app for iPhone in Dutch App Store | ||
const params = { | ||
@@ -24,10 +23,15 @@ entity: 'software', | ||
limit: 1, | ||
price: 0 | ||
price: 0, | ||
}; | ||
// Find free Github app for iPhone in Dutch App Store | ||
searchitunes (params).then (console.log); | ||
searchitunes (params) | ||
.then (console.log) | ||
.catch (console.error) | ||
; | ||
// Get one specific item by ID | ||
searchitunes ({ id: 512939461 }).then (console.log); | ||
searchitunes ({ id: 512939461 }) | ||
.then (console.log) | ||
.catch (console.error) | ||
; | ||
``` | ||
@@ -41,17 +45,16 @@ | ||
## Usage | ||
**( params, [timeout], [callback] )** | ||
## Search by parameters | ||
The module returns promises but also supports the callback argument. | ||
It's up to you which you prefer. | ||
**( params )** | ||
argument | type | required | default | description | ||
:---------|:---------|:---------|:--------|:------------------------------ | ||
params | object | yes | | Search parameters | ||
timeout | int | no | 5000 | Wait time out in ms | ||
callback | function | no | | `(err, data)` or use promises | ||
The module returns a promise. | ||
param | type | default | description | ||
:-----------|:-------|:----------------|:----------- | ||
[timeout] | number | 5000 | Wait time out in ms | ||
[userAgent] | string | searchitunes.js | User-Agent header | ||
... | mixed | | API parameters | ||
* [Search-API docs](https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#overview) | ||
* [Live demo](https://npm.runkit.com/searchitunes) | ||
- [Search-API docs](https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#overview) | ||
- [Live demo](https://npm.runkit.com/searchitunes) | ||
@@ -61,7 +64,7 @@ | ||
When you wish to retrieve one specific item by its ID, | ||
include one of the following params to use the Lookup API. | ||
The result data will be only the _object_ with the item's details. | ||
When you wish to retrieve one specific item by its ID, include one of the ID | ||
params to use the Lookup API. The result data will be only the `object` with | ||
the item's details. | ||
* [Lookup-API docs](https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#lookup) | ||
- [Lookup-API docs](https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#lookup) | ||
@@ -71,14 +74,18 @@ | ||
* amgAlbumId | ||
* amgArtistId | ||
* amgVideoId | ||
* id | ||
* isbn | ||
* upc | ||
- amgAlbumId | ||
- amgArtistId | ||
- amgVideoId | ||
- id | ||
- isbn | ||
- upc | ||
When you lookup a `trackId` from a search response it will be automatically | ||
converted to the `id` parameter instead. Otherwise the API won't understand it. | ||
```js | ||
searchitunes ({ id: 123456 }) | ||
.then (console.log) | ||
.catch (console.error); | ||
.catch (console.error) | ||
; | ||
``` | ||
@@ -127,6 +134,3 @@ | ||
[Franklin van de Meent](https://frankl.in) | ||
Is this project useful to you? | ||
[Buy me a coffee](https://ko-fi.com/franklin) | ||
to help me stay awake while debugging. | ||
[Franklin](https://fvdm.com) | ||
| [buy me a coffee](https://fvdm.com/donating) |
/* | ||
Name: searchitunes | ||
Description: Search the Apple iTunes Store and App Store. | ||
Author: Franklin van de Meent (https://frankl.in) | ||
Author: Franklin (https://fvdm.com) | ||
Source: https://github.com/fvdm/nodejs-searchitunes | ||
Feedback: https://github.com/fvdm/nodejs-searchitunes/issues | ||
API docs: https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ | ||
License: Unlicense (Public Domain, see UNLICENSE file) | ||
(https://github.com/fvdm/nodejs-searchitunes/raw/master/UNLICENSE) | ||
*/ | ||
const { doRequest } = require ('httpreq'); | ||
const { promisify } = require ('es6-promisify'); | ||
let config = { | ||
timeout: 5000, | ||
idKeys: [ | ||
'amgAlbumId', | ||
'amgArtistId', | ||
'amgVideoId', | ||
'id', | ||
'isbn', | ||
'upc' | ||
] | ||
}; | ||
/** | ||
* Check if one of the keys is a property | ||
* | ||
* @return {boolean} `true` = yes | ||
* @return {Promise<boolean>} `true` = yes | ||
* | ||
* @param {array} keys Property names to check | ||
* @param {object} obj Object to process | ||
*/ | ||
function keysInObject (keys, obj) { | ||
let i = 0; | ||
function keysInObject (obj) { | ||
const keys = [ | ||
'amgAlbumId', | ||
'amgArtistId', | ||
'amgVideoId', | ||
'id', | ||
'isbn', | ||
'upc', | ||
]; | ||
for (i; i < keys.length; i++) { | ||
if (obj [keys [i]]) { | ||
for (let i = 0; i < keys.length; i++) { | ||
if (obj[keys[i]]) { | ||
return true; | ||
@@ -51,20 +41,19 @@ } | ||
/** | ||
* Callback a request error | ||
* Send HTTP request | ||
* | ||
* @callback callback | ||
* @return {Error} error | ||
* | ||
* @param {error} err The error to include in `.error` | ||
* @param {object} res Response details from httpreq | ||
* @param {string} message Error message to report | ||
* @return {Promise<object>} | ||
* @param {object} options httpreq.doRequest options | ||
*/ | ||
function httpError (err, res, message) { | ||
let error = new Error (message); | ||
function httpRequest (options) { | ||
return new Promise ((resolve, reject) => { | ||
doRequest (options, (err, res) => { | ||
if (err) { | ||
reject (err); | ||
return; | ||
} | ||
error.code = res && res.statusCode; | ||
error.body = res && res.body; | ||
error.error = err; | ||
return error; | ||
resolve (res); | ||
}); | ||
}); | ||
} | ||
@@ -76,36 +65,27 @@ | ||
* | ||
* @callback callback | ||
* @return {void} | ||
* @return {Promise<object|array>} | ||
* | ||
* @param {Error|null} err Client error | ||
* @param {object} [res] Response details | ||
* @param {function} [callback] `(err, data)` | ||
* @param {bool} [firstResult=false] Call back only first result | ||
* @param {object} res Response | ||
* @param {bool} [first=false] Only first result | ||
*/ | ||
function httpResponse (err, res, callback, firstResult) { | ||
let data = res && res.body || ''; | ||
let error = null; | ||
function httpResponse ({ | ||
res, | ||
first, | ||
}) { | ||
return new Promise ((resolve, reject) => { | ||
const data = JSON.parse (res.body); | ||
try { | ||
data = JSON.parse (data); | ||
if (!data.results || !data.results.length) { | ||
reject (new Error ('no results')); | ||
return; | ||
} | ||
if (!(data.results instanceof Array) || !data.results.length) { | ||
error = new Error ('no results'); | ||
} else if (firstResult) { | ||
data = data.results [0]; | ||
if (first) { | ||
resolve (data.results[0]); | ||
return; | ||
} | ||
} catch (e) { | ||
error = httpError (e, res, 'invalid response'); | ||
} | ||
if (err) { | ||
error = httpError (err, res, 'http error'); | ||
} | ||
if (error) { | ||
callback (error); | ||
} else { | ||
callback (null, data); | ||
} | ||
resolve (data); | ||
}); | ||
} | ||
@@ -117,65 +97,49 @@ | ||
* | ||
* @callback callback | ||
* @return {void} | ||
* @return {Promise<object|array>} | ||
* | ||
* @param {object} props Request details | ||
* @param {string} props.url URL to fetch | ||
* @param {object} props.params Parameters to send along | ||
* @param {int} [props.timeout=5000] Wait time out in ms | ||
* @param {function} callback `(err, data)` | ||
* @param {object} params Parameters to send along | ||
* @param {number} [timeout=5000] Wait timeout in ms | ||
* @param {string} [userAgent] Custom User-Agent header | ||
*/ | ||
function httpRequest (props, callback) { | ||
let firstResult = false; | ||
module.exports = async params => { | ||
let res; | ||
let first = false; | ||
let options = { | ||
method: 'POST', | ||
url: 'https://itunes.apple.com/search', | ||
method: 'GET', | ||
parameters: props.params || {}, | ||
timeout: parseInt (props.timeout || config.timeout, 10), | ||
parameters: params, | ||
timeout: 5000, | ||
headers: { | ||
'Accept': 'application/json', | ||
'User-Agent': 'searchitunes.js' | ||
} | ||
'User-Agent': 'searchitunes.js', | ||
}, | ||
}; | ||
if (keysInObject (config.idKeys, options.parameters)) { | ||
options.url = 'https://itunes.apple.com/lookup'; | ||
firstResult = true; | ||
// Process internal settings | ||
if (params.timeout) { | ||
options.timeout = params.timeout; | ||
delete options.parameters.timeout; | ||
} | ||
doRequest (options, (err, res) => { | ||
httpResponse (err, res, callback, firstResult); | ||
}); | ||
} | ||
if (params.userAgent) { | ||
options.headers['User-Agent'] = params.userAgent; | ||
delete options.parameters.userAgent; | ||
} | ||
/** | ||
* Module interface | ||
* | ||
* @callback callback | ||
* @return {object} Promises then & catch | ||
* | ||
* @param {object} params Parameters to send to API | ||
* @param {int} [timeout=5000] Wait time out in ms | ||
* @param {function} callback `(err, data)` | ||
*/ | ||
module.exports = promisify ((params, timeout, callback) => { | ||
let options = { | ||
params: params || {} | ||
}; | ||
if (typeof timeout === 'function') { | ||
callback = timeout; | ||
timeout = null; | ||
// Convert trackId from a search response | ||
if (params.trackId) { | ||
options.parameters.id = params.trackId; | ||
delete options.parameters.trackId; | ||
} | ||
if (!params || !(params instanceof Object)) { | ||
callback (new Error ('invalid params')); | ||
return; | ||
// Search or lookup | ||
if (keysInObject (options.parameters)) { | ||
options.url = 'https://itunes.apple.com/lookup'; | ||
first = true; | ||
} | ||
options.params.version = params.version || 2; | ||
options.timeout = timeout; | ||
httpRequest (options, callback); | ||
}); | ||
// Process request | ||
res = await httpRequest (options); | ||
return httpResponse ({ res, first }); | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
1
130
0
9081
5
136
2
+ Addedhttpreq@0.5.2(transitive)
- Removedes6-promisify@^6.0.0
- Removedes6-promisify@6.1.1(transitive)
- Removedhttpreq@0.4.24(transitive)
Updatedhttpreq@^0.5.2