Socket
Socket
Sign inDemoInstall

graphql-spotify

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-spotify - npm Package Compare versions

Comparing version 0.43.0 to 0.44.0

401

dist/lib.js

@@ -85,3 +85,3 @@ module.exports =

var _resolvers = __webpack_require__(19);
var _resolvers = __webpack_require__(21);

@@ -148,31 +148,39 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var _AudioFeatures = __webpack_require__(11);
var _TimeRange = __webpack_require__(11);
var _TimeRange2 = _interopRequireDefault(_TimeRange);
var _TopType = __webpack_require__(12);
var _TopType2 = _interopRequireDefault(_TopType);
var _AudioFeatures = __webpack_require__(13);
var _AudioFeatures2 = _interopRequireDefault(_AudioFeatures);
var _PlayHistory = __webpack_require__(12);
var _PlayHistory = __webpack_require__(14);
var _PlayHistory2 = _interopRequireDefault(_PlayHistory);
var _ExternalUrls = __webpack_require__(13);
var _ExternalUrls = __webpack_require__(15);
var _ExternalUrls2 = _interopRequireDefault(_ExternalUrls);
var _Category = __webpack_require__(14);
var _Category = __webpack_require__(16);
var _Category2 = _interopRequireDefault(_Category);
var _RecommendationParameters = __webpack_require__(15);
var _RecommendationParameters = __webpack_require__(17);
var _RecommendationParameters2 = _interopRequireDefault(_RecommendationParameters);
var _RecommendationsResponse = __webpack_require__(16);
var _RecommendationsResponse = __webpack_require__(18);
var _RecommendationsResponse2 = _interopRequireDefault(_RecommendationsResponse);
var _RecommendationsSeedObject = __webpack_require__(17);
var _RecommendationsSeedObject = __webpack_require__(19);
var _RecommendationsSeedObject2 = _interopRequireDefault(_RecommendationsSeedObject);
var _RootQuery = __webpack_require__(18);
var _RootQuery = __webpack_require__(20);

@@ -190,3 +198,3 @@ var _RootQuery2 = _interopRequireDefault(_RootQuery);

const typeDefs = [SchemaDefinition, _RootQuery2.default, _Playlist2.default, _Image2.default, _User2.default, _PlaylistTrack2.default, _Track2.default, _Album2.default, _Artist2.default, _Paging2.default, _AudioFeatures2.default, _PlayHistory2.default, _Category2.default, _RecommendationParameters2.default, _RecommendationsResponse2.default, _RecommendationsSeedObject2.default, _ExternalUrls2.default];
const typeDefs = [SchemaDefinition, _RootQuery2.default, _Playlist2.default, _Image2.default, _User2.default, _PlaylistTrack2.default, _Track2.default, _Album2.default, _Artist2.default, _Paging2.default, _AudioFeatures2.default, _PlayHistory2.default, _Category2.default, _RecommendationParameters2.default, _RecommendationsResponse2.default, _RecommendationsSeedObject2.default, _ExternalUrls2.default, _TimeRange2.default, _TopType2.default];

@@ -252,2 +260,11 @@ exports.default = typeDefs;

uri: String
"""
Check to see if one or more Spotify users are following the playlist.
"""
followersContains(userIds: [String]!): [Boolean]
"""
Check to see the user is following the playlist.
**Required Scope**: playlist-read-private
"""
following: Boolean
}

@@ -389,2 +406,3 @@ `;

saved: Boolean
type: String
}

@@ -450,2 +468,3 @@ `;

external_urls: ExternalUrls
type: String
}

@@ -467,3 +486,3 @@ `;

const Paging = `
union Item = Playlist | PlaylistTrack | Category
union Item = Playlist | PlaylistTrack | Category | Artist | Track
type Paging {

@@ -488,2 +507,54 @@ href: String

Object.defineProperty(exports, "__esModule", {
value: true
});
const TimeRange = `
"""
Over what time frame the affinities are computed
"""
enum TimeRange {
"""
calculated from several years of data and including all new data as it becomes available
"""
long_term
"""
approximately last 6 months
"""
medium_term
"""
approximately last 4 weeks
"""
short_term
}
`;
exports.default = TimeRange;
/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const TopType = `
"""
The type of entity to return
"""
enum TopType {
artists
tracks
}
`;
exports.default = TopType;
/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true

@@ -514,3 +585,3 @@ });

/***/ }),
/* 12 */
/* 14 */
/***/ (function(module, exports, __webpack_require__) {

@@ -541,3 +612,3 @@

/***/ }),
/* 13 */
/* 15 */
/***/ (function(module, exports, __webpack_require__) {

@@ -560,3 +631,3 @@

/***/ }),
/* 14 */
/* 16 */
/***/ (function(module, exports, __webpack_require__) {

@@ -590,3 +661,3 @@

/***/ }),
/* 15 */
/* 17 */
/***/ (function(module, exports, __webpack_require__) {

@@ -613,3 +684,3 @@

/***/ }),
/* 16 */
/* 18 */
/***/ (function(module, exports, __webpack_require__) {

@@ -636,3 +707,3 @@

/***/ }),
/* 17 */
/* 19 */
/***/ (function(module, exports, __webpack_require__) {

@@ -678,3 +749,3 @@

/***/ }),
/* 18 */
/* 20 */
/***/ (function(module, exports, __webpack_require__) {

@@ -727,8 +798,37 @@

recommendations(parameters: RecommendationParameters): RecommendationsResponse
"""
Get the current user’s top artists or tracks based on calculated affinity.
(https://beta.developer.spotify.com/documentation/web-api/reference/personalization/get-users-top-artists-and-tracks/)
Required Scope: **user-top-read**
"""
top(type: TopType!, limit: Int, offset: Int, time_range: TimeRange): Paging
}
type Mutation {
"""
save a track
***returned Track only contains { id, saved }, won't resolve other fields***
"""
saveTrack(trackId: String!): Track
"""
save several tracks. Max 50
***returned Track only contains { id, saved }, won't resolve other fields***
"""
saveTracks(trackIds: [String]!): [Track]
"""
remove several tracks. Max 50
***returned Track only contains { id, saved }, won't resolve other fields***
"""
removeTracks(trackIds: [String]!): [Track]
"""
follow a playlist
***returned Playlist only contains { id, following }, won't resolve other fields***
assuming id is unique ATM so client with defaultDataIdFromObject will update its cache automatically
"""
followPlaylist(ownerId: String!, playlistId: String!, isPublic: Boolean = true): Playlist
"""
unfollow a playlist
***returned Playlist only contains { id, following }, won't resolve other fields***
assuming id is unique ATM so client with defaultDataIdFromObject will update its cache automatically
"""
unfollowPlaylist(ownerId: String!, playlistId: String!): Playlist
}

@@ -740,3 +840,3 @@ `;

/***/ }),
/* 19 */
/* 21 */
/***/ (function(module, exports, __webpack_require__) {

@@ -752,4 +852,71 @@

var _SpotifyWebApi = __webpack_require__(20);
var _SpotifyWebApi = __webpack_require__(22);
const MAX_PLAYLIST_TRACKS_FETCH_LIMIT = 100;
const MAX_TOP_TYPE_FETCH_LIMIT = 50;
const MAX_PLAYLIST_FOLLOWERS_CONTAINS_LIMIT = 5;
const makePlaylistResolver = ({ PlaylistLoader, PlaylistTracksLoader, PlaylistFollowersContainsLoader, MeLoader }) => {
return {
description: async object => {
const { id: playlistId, owner: { id: userId } } = object;
const playlistFull = await PlaylistLoader.load({ playlistId, userId });
return playlistFull.description;
},
totalTracks: async ({ tracks: { total } }) => {
return total;
},
followerCount: obj => {
return obj.followers.total;
},
tracks: async (obj, args) => {
const { id: playlistId, owner: { id: userId }, tracks: { total, offset, items } } = obj;
// fetch with limit and offset when specified
if (args.limit && args.offset) {
return await PlaylistTracksLoader.load(Object.assign({ playlistId, userId }, args));
}
// otherwise always fetch all of the tracks
// when resolving a full playlist, tracks are set the first 100 tracks
let allItems = items || [];
let currentOffset = allItems.length;
let fetches = [];
while (currentOffset < total) {
const fetchSize = Math.min(MAX_PLAYLIST_TRACKS_FETCH_LIMIT, total - currentOffset);
fetches.push(PlaylistTracksLoader.load({ playlistId, userId, limit: fetchSize, offset: currentOffset }));
currentOffset = currentOffset + fetchSize;
}
const fetchResults = await Promise.all(fetches);
fetchResults.forEach(result => {
allItems = allItems.concat(result.items);
});
return { total, items: allItems, limit: total, offset };
},
followersContains: async (obj, { userIds }) => {
const { id: playlistId, owner: { id: playlistUserId } } = obj;
let currentOffset = 0;
let fetches = [];
let total = userIds.length;
while (currentOffset < total) {
const fetchSize = Math.min(MAX_PLAYLIST_FOLLOWERS_CONTAINS_LIMIT, total - currentOffset);
fetches.push(PlaylistFollowersContainsLoader.load({ playlistUserId, playlistId,
userIds: userIds.slice(currentOffset, currentOffset + fetchSize)
}));
currentOffset = currentOffset + fetchSize;
}
const fetchResults = await Promise.all(fetches);
return fetchResults.reduce((accu, value) => {
return accu.concat(value);
}, []);
},
following: async obj => {
if (obj.following || obj.following === false) return obj.following;
const { id: playlistId, owner: { id: playlistUserId } } = obj;
const me = await MeLoader.load();
const userIds = [me.id];
const [following] = await PlaylistFollowersContainsLoader.load({ playlistUserId, playlistId, userIds });
return following;
}
};
};
function makeResolvers(token) {

@@ -759,3 +926,3 @@ const {

AudioFeaturesLoader, SavedContainsLoader, TracksLoader, CategoriesLoader, RecommendationsLoader,
CategoryPlaylistLoader, CategoryLoader
CategoryPlaylistLoader, CategoryLoader, TopTypeLoader, PlaylistFollowersContainsLoader, MeLoader
} = (0, _SpotifyWebApi.makeLoaders)(token);

@@ -795,33 +962,17 @@

return await RecommendationsLoader.load(args.parameters);
}
},
Mutation: {
saveTrack: async (obj, { trackId }) => {
await (0, _SpotifyWebApi.saveTrackToLib)(token, [trackId]);
return { id: trackId, saved: true };
}
},
Playlist: {
description: async object => {
const { id: playlistId, owner: { id: userId } } = object;
const playlistFull = await PlaylistLoader.load({ playlistId, userId });
return playlistFull.description;
},
totalTracks: async ({ tracks: { total } }) => {
return total;
},
tracks: async (obj, args) => {
const { id: playlistId, owner: { id: userId }, tracks: { total, offset, items, limit } } = obj;
// fetch with limit and offset when specified
if (args.limit && args.offset) {
return await PlaylistTracksLoader.load(Object.assign({ playlistId, userId }, args));
top: async (obj, args) => {
const { type, limit, offset, time_range } = args;
const result = await TopTypeLoader.load({ type, limit, offset, time_range });
if (result.items.length >= limit) {
return result;
}
// otherwise always fetch all of the tracks
// when resolving a full playlist there are already items
let allItems = items || [];
let allItems = result.items;
const totalFetchSize = Math.min(limit, result.total);
let currentOffset = allItems.length;
let fetches = [];
while (currentOffset < total) {
fetches.push(PlaylistTracksLoader.load({ playlistId, userId, limit, offset: currentOffset }));
currentOffset = currentOffset + limit;
while (currentOffset < totalFetchSize) {
const fetchSize = Math.min(MAX_TOP_TYPE_FETCH_LIMIT, totalFetchSize - currentOffset);
fetches.push(TopTypeLoader.load({ type, time_range, limit: fetchSize, offset: currentOffset }));
currentOffset = currentOffset + fetchSize;
}

@@ -832,8 +983,36 @@ const fetchResults = await Promise.all(fetches);

});
return { total, items: allItems, limit: total, offset };
return { total: result.total, items: allItems, limit: allItems.length, offset };
}
},
Mutation: {
saveTrack: async (obj, { trackId }) => {
const res = await (0, _SpotifyWebApi.saveTracksToLib)(token, [trackId]);
if (res.status !== 200) return;
return { id: trackId, saved: true };
},
saveTracks: async (obj, { trackIds }) => {
const res = await (0, _SpotifyWebApi.saveTracksToLib)(token, trackIds);
if (res.status !== 200) return;
return trackIds.map(id => ({ id, saved: true }));
},
removeTracks: async (obj, { trackIds }) => {
const res = await (0, _SpotifyWebApi.removeTracksFromLib)(token, trackIds);
if (res.status !== 200) return;
return trackIds.map(id => ({ id, saved: false }));
},
followPlaylist: async (obj, { ownerId, playlistId, isPublic }) => {
const res = await (0, _SpotifyWebApi.followPlaylist)(token, { ownerId, playlistId, isPublic });
if (res.status !== 200) return;
return { id: playlistId, following: true };
},
unfollowPlaylist: async (obj, { ownerId, playlistId }) => {
const res = await (0, _SpotifyWebApi.unfollowPlaylist)(token, { ownerId, playlistId });
if (res.status !== 200) return;
return { id: playlistId, following: false };
}
},
Playlist: makePlaylistResolver({ PlaylistLoader, PlaylistTracksLoader, PlaylistFollowersContainsLoader, MeLoader }),
Track: {
audio_features: async ({ id }) => {
return await AudioFeatureLoader.load(id);
return await AudioFeaturesLoader.load(id);
},

@@ -903,2 +1082,8 @@ saved: async ({ id }) => {

}
if (type === 'artist') {
return 'Artist';
}
if (type === 'track') {
return 'Track';
}
if (type === 'playlist') {

@@ -918,3 +1103,3 @@ return 'Playlist';

/***/ }),
/* 20 */
/* 22 */
/***/ (function(module, exports, __webpack_require__) {

@@ -928,3 +1113,6 @@

});
exports.saveTrackToLib = saveTrackToLib;
exports.saveTracksToLib = saveTracksToLib;
exports.removeTracksFromLib = removeTracksFromLib;
exports.followPlaylist = followPlaylist;
exports.unfollowPlaylist = unfollowPlaylist;
exports.getSavedContains = getSavedContains;

@@ -937,5 +1125,8 @@ exports.getFeaturedPlaylists = getFeaturedPlaylists;

exports.getRecentlyPlayed = getRecentlyPlayed;
exports.getTopType = getTopType;
exports.getPlaylist = getPlaylist;
exports.getUser = getUser;
exports.getMe = getMe;
exports.getPlaylistTracks = getPlaylistTracks;
exports.getPlaylistFollowersContains = getPlaylistFollowersContains;
exports.getAlbums = getAlbums;

@@ -957,7 +1148,10 @@ exports.getTracks = getTracks;

exports.makeRecommendationsLoader = makeRecommendationsLoader;
exports.makeGetTopTypeLoader = makeGetTopTypeLoader;
exports.makePlaylistFollowersContainsLoader = makePlaylistFollowersContainsLoader;
exports.makeMeLoader = makeMeLoader;
exports.makeLoaders = makeLoaders;
__webpack_require__(21);
__webpack_require__(23);
var _dataloader = __webpack_require__(22);
var _dataloader = __webpack_require__(24);

@@ -977,10 +1171,10 @@ var _dataloader2 = _interopRequireDefault(_dataloader);

function cacheKeyFnForQueryKeys(key) {
return JSON.stringify(key);
return serializeToURLParameters(key);
}
function serializeToURLParameters(obj) {
return Object.entries(obj).map(([key, val]) => `${key}=${val}`).join('&');
return Object.entries(obj).map(([key, val]) => val && `${key}=${val}`).join('&');
}
async function saveTrackToLib(token, trackIds) {
async function saveTracksToLib(token, trackIds) {
const url = `https://api.spotify.com/v1/me/tracks?ids=${trackIds.toString()}`;

@@ -993,2 +1187,27 @@ return await fetch(url, {

async function removeTracksFromLib(token, trackIds) {
const url = `https://api.spotify.com/v1/me/tracks?ids=${trackIds.toString()}`;
return await fetch(url, {
method: 'DELETE',
headers: makeHeaders(token)
});
}
async function followPlaylist(token, { ownerId, playlistId, isPublic = true }) {
const url = `https://api.spotify.com/v1/users/${ownerId}/playlists/${playlistId}/followers`;
return await fetch(url, {
method: 'PUT',
headers: makeHeaders(token),
body: JSON.stringify({ public: isPublic })
});
}
async function unfollowPlaylist(token, { ownerId, playlistId }) {
const url = `https://api.spotify.com/v1/users/${ownerId}/playlists/${playlistId}/followers`;
return await fetch(url, {
method: 'DELETE',
headers: makeHeaders(token)
});
}
async function getSavedContains(token, trackIds) {

@@ -1059,2 +1278,12 @@ const url = `https://api.spotify.com/v1/me/tracks/contains?ids=${trackIds.toString()}`;

async function getTopType(token, params) {
const { type, limit, offset, time_range } = params;
let res = await fetch(`https://api.spotify.com/v1/me/top/${type}?${serializeToURLParameters({ limit, offset, time_range })}`, {
method: 'GET',
headers: makeHeaders(token)
});
res = await res.json();
return res;
}
async function getPlaylist(token, userId, playlistId) {

@@ -1078,2 +1307,11 @@ let res = await fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}`, {

async function getMe(token) {
let res = await fetch(`https://api.spotify.com/v1/me`, {
method: 'GET',
headers: makeHeaders(token)
});
res = await res.json();
return res;
}
async function getPlaylistTracks(token, { userId, playlistId, limit = 100, offset = 0 }) {

@@ -1088,2 +1326,11 @@ let res = await fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks?${serializeToURLParameters({ limit, offset })}`, {

async function getPlaylistFollowersContains(token, { playlistUserId, playlistId, userIds }) {
let res = await fetch(`https://api.spotify.com/v1/users/${playlistUserId}/playlists/${playlistId}/followers/contains?ids=${userIds.toString()}`, {
method: 'GET',
headers: makeHeaders(token)
});
res = await res.json();
return res;
}
async function getAlbums(token, ids) {

@@ -1211,2 +1458,3 @@ let res = await fetch(`https://api.spotify.com/v1/albums?ids=${ids.toString()}`, {

}
function makeRecommendationsLoader(token) {

@@ -1219,2 +1467,30 @@ const batchLoadFn = async ([key]) => {

function makeGetTopTypeLoader(token) {
const batchLoadFn = async ([key]) => {
return [await getTopType(token, key)];
};
return new _dataloader2.default(batchLoadFn, { batch: false, cacheKeyFn: cacheKeyFnForQueryKeys });
}
function makePlaylistFollowersContainsLoader(token) {
const batchLoadFn = async ([key]) => {
return [await getPlaylistFollowersContains(token, key)];
};
return new _dataloader2.default(batchLoadFn, { batch: false, cacheKeyFn: cacheKeyFnForQueryKeys });
}
// Skipping the dataloader just here since the loader is meant to called with only .load()
// Use it the same way as you would with a dataloader, i.e only on per request basis
function makeMeLoader(token) {
let cacheMe = null;
return {
load: async () => {
if (!cacheMe) {
cacheMe = await getMe(token);
}
return cacheMe;
}
};
}
function makeLoaders(token) {

@@ -1233,3 +1509,6 @@ return {

CategoryPlaylistLoader: makeCategoriesPlaylistsLoader(token),
CategoryLoader: makeCategoryLoader(token)
CategoryLoader: makeCategoryLoader(token),
TopTypeLoader: makeGetTopTypeLoader(token),
PlaylistFollowersContainsLoader: makePlaylistFollowersContainsLoader(token),
MeLoader: makeMeLoader(token)
};

@@ -1239,3 +1518,3 @@ }

/***/ }),
/* 21 */
/* 23 */
/***/ (function(module, exports) {

@@ -1246,3 +1525,3 @@

/***/ }),
/* 22 */
/* 24 */
/***/ (function(module, exports) {

@@ -1249,0 +1528,0 @@

2

package.json
{
"name": "graphql-spotify",
"version": "0.43.0",
"version": "0.44.0",
"description": "GraphQL Schema And Resolvers For Spotify Web API",

@@ -5,0 +5,0 @@ "main": "dist/lib.js",

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc