lastfm-nodejs-client 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -5
- package/.github/workflows/playwright.yml +36 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +11 -0
- package/SECURITY.md +2 -3
- package/dist/config.js +25 -0
- package/dist/index.js +99 -33
- package/dist/request.d.ts +7 -1
- package/dist/request.js +15 -3
- package/package.json +15 -12
- package/playwright.config.ts +37 -0
- package/src/config.ts +3 -0
- package/src/index.ts +110 -44
- package/src/request.ts +20 -12
- package/tests/env.spec.ts +21 -0
- package/tsconfig.dev.json +7 -0
- package/tsconfig.json +1 -0
package/.env.example
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
LASTFM_API_BASE_URL=""
|
|
2
|
-
LASTFM_API_KEY=""
|
|
3
|
-
LASTFM_APPNAME=""
|
|
4
|
-
LASTFM_SHARED_SECRET=""
|
|
5
|
-
LASTFM_USER=""
|
|
1
|
+
LASTFM_API_BASE_URL="https://ws.audioscrobbler.com/2.0/"
|
|
2
|
+
LASTFM_API_KEY="abcdefghijkhlmnopqrstuvwxyz"
|
|
3
|
+
LASTFM_APPNAME="your app name"
|
|
4
|
+
LASTFM_SHARED_SECRET="xxxxxxxxxxxxxxxxxxxxx"
|
|
5
|
+
LASTFM_USER="your username"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Playwright Tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main, master]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: [main, master]
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
timeout-minutes: 60
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v3
|
|
13
|
+
- uses: actions/setup-node@v3
|
|
14
|
+
with:
|
|
15
|
+
node-version: 16
|
|
16
|
+
- uses: pnpm/action-setup@v2
|
|
17
|
+
with:
|
|
18
|
+
version: 7.14.1
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: pnpm install
|
|
21
|
+
- name: Install Playwright Browsers
|
|
22
|
+
run: npx playwright install --with-deps
|
|
23
|
+
- name: Install @playwright/test package
|
|
24
|
+
run: pnpm add -D @playwright/test
|
|
25
|
+
- name: Creates environment variables
|
|
26
|
+
run: |
|
|
27
|
+
echo "LASTFM_API_BASE_URL: https://ws.audioscrobbler.com/2.0/"
|
|
28
|
+
echo "LASTFM_API_KEY: abcdefghijklmnopqrstuvxyz"
|
|
29
|
+
- name: Run Playwright tests
|
|
30
|
+
run: pnpm dlx playwright test
|
|
31
|
+
- uses: actions/upload-artifact@v2
|
|
32
|
+
if: always()
|
|
33
|
+
with:
|
|
34
|
+
name: playwright-report
|
|
35
|
+
path: playwright-report/
|
|
36
|
+
retention-days: 30
|
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v20
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.4
|
|
4
|
+
|
|
5
|
+
- Updates npm dependencies
|
|
6
|
+
- Refactors request methods options and updates all callsites.
|
|
7
|
+
- Add nvmrc file for easy switching node version.
|
|
8
|
+
|
|
9
|
+
## 1.2.3
|
|
10
|
+
|
|
11
|
+
- Adds tests, using Playwright
|
|
12
|
+
- Adds dotenv npm module as a new dependency
|
|
13
|
+
|
|
3
14
|
## 1.2.2
|
|
4
15
|
|
|
5
16
|
- Put log back, some APIs do get Bad Request for MBIDs that don't exist, don't have solve for this yet, so not throwing any more as it grinds future request to a halt. This is a working version.
|
package/SECURITY.md
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
# Security Policy
|
|
1
|
+
# 🔐 Security Policy
|
|
2
2
|
|
|
3
3
|
## Supported Versions
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Dependabot alerts have been enabled and security patches to any dependencies will be brought to light and merged manually by maintainer.
|
|
6
6
|
|
|
7
7
|
| Version | Supported |
|
|
8
8
|
| ------- | ------------------ |
|
|
9
9
|
| 1.0.x | :white_check_mark: |
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
## Reporting a Vulnerability
|
|
13
12
|
|
|
14
13
|
If you find anything at all kindly report it as bug report here on github ✌️
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const dotenv = __importStar(require("dotenv"));
|
|
27
|
+
dotenv.config();
|
|
3
28
|
exports.default = {
|
|
4
29
|
api_key: `${process.env.LASTFM_API_KEY}`,
|
|
5
30
|
app_name: `${process.env.LASTFM_APPNAME}`,
|
package/dist/index.js
CHANGED
|
@@ -17,99 +17,165 @@ function LastFmApi() {
|
|
|
17
17
|
* Can only used once (they are consumed when a session is created).
|
|
18
18
|
* @returns Auth token
|
|
19
19
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
function auth(method, user, period, limit) {
|
|
21
|
+
const options = {
|
|
22
|
+
method,
|
|
23
|
+
user,
|
|
24
|
+
period,
|
|
25
|
+
limit,
|
|
26
|
+
};
|
|
27
|
+
return (0, request_1.default)(options);
|
|
28
|
+
}
|
|
23
29
|
/**
|
|
24
30
|
* GET: User profile information - LastFM
|
|
25
31
|
*
|
|
26
32
|
* https://www.last.fm/api/show/user.getInfo
|
|
27
33
|
* @returns User profile data
|
|
28
34
|
*/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
function getInfo(method, user, period, limit) {
|
|
36
|
+
const options = {
|
|
37
|
+
method,
|
|
38
|
+
user,
|
|
39
|
+
period,
|
|
40
|
+
limit,
|
|
41
|
+
};
|
|
42
|
+
return (0, request_1.default)(options);
|
|
43
|
+
}
|
|
32
44
|
/**
|
|
33
45
|
* GET: Love Tracks - LastFM
|
|
34
46
|
*
|
|
35
47
|
* https://www.last.fm/api/show/user.getLovedTracks
|
|
36
48
|
* @returns Loved Tracks;
|
|
37
49
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
function getLovedTracks(method, user, period, limit) {
|
|
51
|
+
const options = {
|
|
52
|
+
method,
|
|
53
|
+
user,
|
|
54
|
+
period,
|
|
55
|
+
limit,
|
|
56
|
+
};
|
|
57
|
+
return (0, request_1.default)(options);
|
|
58
|
+
}
|
|
41
59
|
/**
|
|
42
60
|
* GET: Recent Tracks - LastFM
|
|
43
61
|
*
|
|
44
62
|
* https://www.last.fm/api/show/user.getRecentTracks
|
|
45
63
|
* @returns Recent Tracks
|
|
46
64
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
function getRecentTracks(method, user, period, limit) {
|
|
66
|
+
const options = {
|
|
67
|
+
method,
|
|
68
|
+
user,
|
|
69
|
+
period,
|
|
70
|
+
limit,
|
|
71
|
+
};
|
|
72
|
+
return (0, request_1.default)(options);
|
|
73
|
+
}
|
|
50
74
|
/**
|
|
51
75
|
* GET: Top Albums - LastFM
|
|
52
76
|
*
|
|
53
77
|
* https://www.last.fm/api/show/user.getTopAlbums
|
|
54
78
|
* @returns Top Albums
|
|
55
79
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
80
|
+
function getTopAlbums(method, user, period, limit) {
|
|
81
|
+
const options = {
|
|
82
|
+
method,
|
|
83
|
+
user,
|
|
84
|
+
period,
|
|
85
|
+
limit,
|
|
86
|
+
};
|
|
87
|
+
return (0, request_1.default)(options);
|
|
88
|
+
}
|
|
59
89
|
/**
|
|
60
90
|
* GET: Top Artist - LastFM
|
|
61
91
|
*
|
|
62
92
|
* https://www.last.fm/api/show/user.getTopArtists
|
|
63
93
|
* @returns Top Artists
|
|
64
94
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
function getTopArtists(method, user, period, limit) {
|
|
96
|
+
const options = {
|
|
97
|
+
method,
|
|
98
|
+
user,
|
|
99
|
+
period,
|
|
100
|
+
limit,
|
|
101
|
+
};
|
|
102
|
+
return (0, request_1.default)(options);
|
|
103
|
+
}
|
|
68
104
|
/**
|
|
69
105
|
* GET: Top Tracks - LastFM
|
|
70
106
|
*
|
|
71
107
|
* https://www.last.fm/api/show/user.getTopTracks
|
|
72
108
|
* @returns Top Tracks
|
|
73
109
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
110
|
+
function getTopTracks(method, user, period, limit) {
|
|
111
|
+
const options = {
|
|
112
|
+
method,
|
|
113
|
+
user,
|
|
114
|
+
period,
|
|
115
|
+
limit,
|
|
116
|
+
};
|
|
117
|
+
return (0, request_1.default)(options);
|
|
118
|
+
}
|
|
77
119
|
/**
|
|
78
120
|
* GET: Weekly album chart - LastFM
|
|
79
121
|
*
|
|
80
122
|
* https://www.last.fm/api/show/user.getWeeklyAlbumChart
|
|
81
123
|
* @returns Weekly album chart
|
|
82
124
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
125
|
+
function getWeeklyAlbumChart(method, user, period, limit) {
|
|
126
|
+
const options = {
|
|
127
|
+
method,
|
|
128
|
+
user,
|
|
129
|
+
period,
|
|
130
|
+
limit,
|
|
131
|
+
};
|
|
132
|
+
return (0, request_1.default)(options);
|
|
133
|
+
}
|
|
86
134
|
/**
|
|
87
135
|
* GET: Weekly artist chart - LastFM
|
|
88
136
|
*
|
|
89
137
|
* https://www.last.fm/api/show/user.getWeeklyArtistChart
|
|
90
138
|
* @returns Weekly artist chart
|
|
91
139
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
140
|
+
function getWeeklyArtistChart(method, user, period, limit) {
|
|
141
|
+
const options = {
|
|
142
|
+
method,
|
|
143
|
+
user,
|
|
144
|
+
period,
|
|
145
|
+
limit,
|
|
146
|
+
};
|
|
147
|
+
return (0, request_1.default)(options);
|
|
148
|
+
}
|
|
95
149
|
/**
|
|
96
150
|
* GET: Weekly chart list - LastFM
|
|
97
151
|
*
|
|
98
152
|
* https://www.last.fm/api/show/user.getWeeklyChartList
|
|
99
153
|
* @returns Weekly chart list
|
|
100
154
|
*/
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
155
|
+
function getWeeklyChartList(method, user, period, limit) {
|
|
156
|
+
const options = {
|
|
157
|
+
method,
|
|
158
|
+
user,
|
|
159
|
+
period,
|
|
160
|
+
limit,
|
|
161
|
+
};
|
|
162
|
+
return (0, request_1.default)(options);
|
|
163
|
+
}
|
|
104
164
|
/**
|
|
105
165
|
* GET: Weekly track chart - LastFM
|
|
106
166
|
*
|
|
107
167
|
* https://www.last.fm/api/show/user.getWeeklyTrackChart
|
|
108
168
|
* @returns Weekly track chart
|
|
109
169
|
*/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
170
|
+
function getWeeklyTrackChart(method, user, period, limit) {
|
|
171
|
+
const options = {
|
|
172
|
+
method,
|
|
173
|
+
user,
|
|
174
|
+
period,
|
|
175
|
+
limit,
|
|
176
|
+
};
|
|
177
|
+
return (0, request_1.default)(options);
|
|
178
|
+
}
|
|
113
179
|
return {
|
|
114
180
|
auth,
|
|
115
181
|
config: config_1.default,
|
package/dist/request.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
interface RequestOptions {
|
|
2
|
+
method: string;
|
|
3
|
+
user?: string;
|
|
4
|
+
period?: string;
|
|
5
|
+
limit?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const request: <Response_1>(options: RequestOptions) => Promise<Response_1>;
|
|
2
8
|
export default request;
|
package/dist/request.js
CHANGED
|
@@ -14,9 +14,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const cross_fetch_1 = __importDefault(require("cross-fetch"));
|
|
16
16
|
const config_1 = __importDefault(require("./config"));
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
17
|
+
const buildUrl = (options) => {
|
|
18
|
+
const params = new URLSearchParams();
|
|
19
|
+
params.append('method', options.method);
|
|
20
|
+
if (options.user)
|
|
21
|
+
params.append('user', options.user);
|
|
22
|
+
if (options.period)
|
|
23
|
+
params.append('period', options.period);
|
|
24
|
+
if (options.limit)
|
|
25
|
+
params.append('limit', options.limit);
|
|
26
|
+
params.append('api_key', config_1.default.api_key);
|
|
27
|
+
params.append('format', config_1.default.format.json);
|
|
28
|
+
return `${config_1.default.base_url}?${params.toString()}`;
|
|
29
|
+
};
|
|
30
|
+
const request = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const url = buildUrl(options);
|
|
20
32
|
return (yield (0, cross_fetch_1.default)(url, {
|
|
21
33
|
headers: {
|
|
22
34
|
'Content-Type': 'application/json',
|
package/package.json
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lastfm-nodejs-client",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "A NodeJS wrapper client for LastFm API. Fetching public data by username using the LastFm public API",
|
|
5
5
|
"main": "./dist",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "rimraf dist && tsc",
|
|
8
|
+
"clean": "rimraf dist",
|
|
9
|
+
"dev": "npm run clean && tsc --watch --project tsconfig.dev.json",
|
|
10
|
+
"test": "npx playwright test --reporter=list"
|
|
11
|
+
},
|
|
6
12
|
"keywords": [
|
|
7
13
|
"client",
|
|
8
14
|
"lastFm",
|
|
@@ -16,12 +22,14 @@
|
|
|
16
22
|
],
|
|
17
23
|
"license": "MIT",
|
|
18
24
|
"dependencies": {
|
|
19
|
-
"cross-fetch": "^
|
|
20
|
-
"
|
|
25
|
+
"cross-fetch": "^4.0.0",
|
|
26
|
+
"dotenv": "^16.3.1",
|
|
27
|
+
"rimraf": "^5.0.1"
|
|
21
28
|
},
|
|
22
29
|
"devDependencies": {
|
|
23
|
-
"@
|
|
24
|
-
"
|
|
30
|
+
"@playwright/test": "^1.37.1",
|
|
31
|
+
"@types/node": "^20.5.1",
|
|
32
|
+
"typescript": "^5.1.6"
|
|
25
33
|
},
|
|
26
34
|
"repository": {
|
|
27
35
|
"type": "git",
|
|
@@ -30,10 +38,5 @@
|
|
|
30
38
|
"bugs": {
|
|
31
39
|
"url": "https://github.com/mannuelf/lastfm-nodejs-client/issues"
|
|
32
40
|
},
|
|
33
|
-
"homepage": "https://github.com/mannuelf/lastfm-nodejs-client#readme"
|
|
34
|
-
|
|
35
|
-
"build": "rimraf dist && tsc",
|
|
36
|
-
"dev": "tsc --watch",
|
|
37
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
41
|
+
"homepage": "https://github.com/mannuelf/lastfm-nodejs-client#readme"
|
|
42
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { devices, PlaywrightTestConfig } from '@playwright/test';
|
|
2
|
+
import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
|
|
3
|
+
dotenv.config();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* See https://playwright.dev/docs/test-configuration.
|
|
7
|
+
*/
|
|
8
|
+
const config: PlaywrightTestConfig = {
|
|
9
|
+
testDir: './tests',
|
|
10
|
+
timeout: 30 * 1000,
|
|
11
|
+
expect: {
|
|
12
|
+
timeout: 5000,
|
|
13
|
+
},
|
|
14
|
+
fullyParallel: true,
|
|
15
|
+
forbidOnly: !!process.env.CI,
|
|
16
|
+
retries: process.env.CI ? 2 : 0,
|
|
17
|
+
workers: process.env.CI ? 1 : undefined,
|
|
18
|
+
reporter: 'html',
|
|
19
|
+
use: {
|
|
20
|
+
actionTimeout: 0,
|
|
21
|
+
trace: 'on-first-retry',
|
|
22
|
+
headless: true,
|
|
23
|
+
},
|
|
24
|
+
projects: [
|
|
25
|
+
{
|
|
26
|
+
name: 'chromium',
|
|
27
|
+
use: { ...devices['Desktop Chrome'] },
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
// outputDir: 'test-results/',
|
|
31
|
+
// webServer: {
|
|
32
|
+
// command: 'npm run dev',
|
|
33
|
+
// port: 3000,
|
|
34
|
+
// },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default config;
|
package/src/config.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -26,14 +26,20 @@ function LastFmApi() {
|
|
|
26
26
|
* Can only used once (they are consumed when a session is created).
|
|
27
27
|
* @returns Auth token
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
function auth(
|
|
30
30
|
method: string,
|
|
31
31
|
user: string,
|
|
32
32
|
period: string,
|
|
33
33
|
limit: string,
|
|
34
|
-
): Promise<AuthResponse>
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
): Promise<AuthResponse> {
|
|
35
|
+
const options = {
|
|
36
|
+
method,
|
|
37
|
+
user,
|
|
38
|
+
period,
|
|
39
|
+
limit,
|
|
40
|
+
}
|
|
41
|
+
return request<AuthResponse>(options);
|
|
42
|
+
}
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
45
|
* GET: User profile information - LastFM
|
|
@@ -41,14 +47,20 @@ function LastFmApi() {
|
|
|
41
47
|
* https://www.last.fm/api/show/user.getInfo
|
|
42
48
|
* @returns User profile data
|
|
43
49
|
*/
|
|
44
|
-
|
|
50
|
+
function getInfo(
|
|
45
51
|
method: string,
|
|
46
52
|
user: string,
|
|
47
53
|
period: string,
|
|
48
54
|
limit: string,
|
|
49
|
-
): Promise<UserResponse>
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
): Promise<UserResponse> {
|
|
56
|
+
const options = {
|
|
57
|
+
method,
|
|
58
|
+
user,
|
|
59
|
+
period,
|
|
60
|
+
limit,
|
|
61
|
+
}
|
|
62
|
+
return request<UserResponse>(options);
|
|
63
|
+
}
|
|
52
64
|
|
|
53
65
|
/**
|
|
54
66
|
* GET: Love Tracks - LastFM
|
|
@@ -56,14 +68,20 @@ function LastFmApi() {
|
|
|
56
68
|
* https://www.last.fm/api/show/user.getLovedTracks
|
|
57
69
|
* @returns Loved Tracks;
|
|
58
70
|
*/
|
|
59
|
-
|
|
71
|
+
function getLovedTracks(
|
|
60
72
|
method: string,
|
|
61
73
|
user: string,
|
|
62
74
|
period: string,
|
|
63
75
|
limit: string,
|
|
64
|
-
): Promise<LovedTracksResponse>
|
|
65
|
-
|
|
66
|
-
|
|
76
|
+
): Promise<LovedTracksResponse> {
|
|
77
|
+
const options = {
|
|
78
|
+
method,
|
|
79
|
+
user,
|
|
80
|
+
period,
|
|
81
|
+
limit,
|
|
82
|
+
}
|
|
83
|
+
return request<LovedTracksResponse>(options);
|
|
84
|
+
}
|
|
67
85
|
|
|
68
86
|
/**
|
|
69
87
|
* GET: Recent Tracks - LastFM
|
|
@@ -71,14 +89,20 @@ function LastFmApi() {
|
|
|
71
89
|
* https://www.last.fm/api/show/user.getRecentTracks
|
|
72
90
|
* @returns Recent Tracks
|
|
73
91
|
*/
|
|
74
|
-
|
|
92
|
+
function getRecentTracks(
|
|
75
93
|
method: string,
|
|
76
94
|
user: string,
|
|
77
95
|
period: string,
|
|
78
96
|
limit: string,
|
|
79
|
-
): Promise<RecentTracksResponse>
|
|
80
|
-
|
|
81
|
-
|
|
97
|
+
): Promise<RecentTracksResponse> {
|
|
98
|
+
const options = {
|
|
99
|
+
method,
|
|
100
|
+
user,
|
|
101
|
+
period,
|
|
102
|
+
limit,
|
|
103
|
+
}
|
|
104
|
+
return request<RecentTracksResponse>(options);
|
|
105
|
+
}
|
|
82
106
|
|
|
83
107
|
/**
|
|
84
108
|
* GET: Top Albums - LastFM
|
|
@@ -86,14 +110,20 @@ function LastFmApi() {
|
|
|
86
110
|
* https://www.last.fm/api/show/user.getTopAlbums
|
|
87
111
|
* @returns Top Albums
|
|
88
112
|
*/
|
|
89
|
-
|
|
113
|
+
function getTopAlbums(
|
|
90
114
|
method: string,
|
|
91
115
|
user: string,
|
|
92
116
|
period: string,
|
|
93
117
|
limit: string,
|
|
94
|
-
): Promise<TopAlbumsResponse>
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
): Promise<TopAlbumsResponse> {
|
|
119
|
+
const options = {
|
|
120
|
+
method,
|
|
121
|
+
user,
|
|
122
|
+
period,
|
|
123
|
+
limit,
|
|
124
|
+
}
|
|
125
|
+
return request<TopAlbumsResponse>(options);
|
|
126
|
+
}
|
|
97
127
|
|
|
98
128
|
/**
|
|
99
129
|
* GET: Top Artist - LastFM
|
|
@@ -101,14 +131,20 @@ function LastFmApi() {
|
|
|
101
131
|
* https://www.last.fm/api/show/user.getTopArtists
|
|
102
132
|
* @returns Top Artists
|
|
103
133
|
*/
|
|
104
|
-
|
|
134
|
+
function getTopArtists(
|
|
105
135
|
method: string,
|
|
106
136
|
user: string,
|
|
107
137
|
period: string,
|
|
108
138
|
limit: string,
|
|
109
|
-
): Promise<TopArtistsResponse>
|
|
110
|
-
|
|
111
|
-
|
|
139
|
+
): Promise<TopArtistsResponse> {
|
|
140
|
+
const options = {
|
|
141
|
+
method,
|
|
142
|
+
user,
|
|
143
|
+
period,
|
|
144
|
+
limit,
|
|
145
|
+
}
|
|
146
|
+
return request<TopArtistsResponse>(options);
|
|
147
|
+
}
|
|
112
148
|
|
|
113
149
|
/**
|
|
114
150
|
* GET: Top Tracks - LastFM
|
|
@@ -116,14 +152,20 @@ function LastFmApi() {
|
|
|
116
152
|
* https://www.last.fm/api/show/user.getTopTracks
|
|
117
153
|
* @returns Top Tracks
|
|
118
154
|
*/
|
|
119
|
-
|
|
155
|
+
function getTopTracks(
|
|
120
156
|
method: string,
|
|
121
157
|
user: string,
|
|
122
158
|
period: string,
|
|
123
159
|
limit: string,
|
|
124
|
-
): Promise<TopTrackResponse>
|
|
125
|
-
|
|
126
|
-
|
|
160
|
+
): Promise<TopTrackResponse> {
|
|
161
|
+
const options = {
|
|
162
|
+
method,
|
|
163
|
+
user,
|
|
164
|
+
period,
|
|
165
|
+
limit,
|
|
166
|
+
}
|
|
167
|
+
return request<TopTrackResponse>(options);
|
|
168
|
+
}
|
|
127
169
|
|
|
128
170
|
/**
|
|
129
171
|
* GET: Weekly album chart - LastFM
|
|
@@ -131,14 +173,20 @@ function LastFmApi() {
|
|
|
131
173
|
* https://www.last.fm/api/show/user.getWeeklyAlbumChart
|
|
132
174
|
* @returns Weekly album chart
|
|
133
175
|
*/
|
|
134
|
-
|
|
176
|
+
function getWeeklyAlbumChart(
|
|
135
177
|
method: string,
|
|
136
178
|
user: string,
|
|
137
179
|
period: string,
|
|
138
180
|
limit: string,
|
|
139
|
-
): Promise<WeeklyAlbumChartResponse>
|
|
140
|
-
|
|
141
|
-
|
|
181
|
+
): Promise<WeeklyAlbumChartResponse> {
|
|
182
|
+
const options = {
|
|
183
|
+
method,
|
|
184
|
+
user,
|
|
185
|
+
period,
|
|
186
|
+
limit,
|
|
187
|
+
}
|
|
188
|
+
return request<WeeklyAlbumChartResponse>(options);
|
|
189
|
+
}
|
|
142
190
|
|
|
143
191
|
/**
|
|
144
192
|
* GET: Weekly artist chart - LastFM
|
|
@@ -146,14 +194,20 @@ function LastFmApi() {
|
|
|
146
194
|
* https://www.last.fm/api/show/user.getWeeklyArtistChart
|
|
147
195
|
* @returns Weekly artist chart
|
|
148
196
|
*/
|
|
149
|
-
|
|
197
|
+
function getWeeklyArtistChart(
|
|
150
198
|
method: string,
|
|
151
199
|
user: string,
|
|
152
200
|
period: string,
|
|
153
201
|
limit: string,
|
|
154
|
-
): Promise<WeeklyArtistChartResponse>
|
|
155
|
-
|
|
156
|
-
|
|
202
|
+
): Promise<WeeklyArtistChartResponse> {
|
|
203
|
+
const options = {
|
|
204
|
+
method,
|
|
205
|
+
user,
|
|
206
|
+
period,
|
|
207
|
+
limit,
|
|
208
|
+
}
|
|
209
|
+
return request<WeeklyArtistChartResponse>(options);
|
|
210
|
+
}
|
|
157
211
|
|
|
158
212
|
/**
|
|
159
213
|
* GET: Weekly chart list - LastFM
|
|
@@ -161,14 +215,20 @@ function LastFmApi() {
|
|
|
161
215
|
* https://www.last.fm/api/show/user.getWeeklyChartList
|
|
162
216
|
* @returns Weekly chart list
|
|
163
217
|
*/
|
|
164
|
-
|
|
218
|
+
function getWeeklyChartList(
|
|
165
219
|
method: string,
|
|
166
220
|
user: string,
|
|
167
221
|
period: string,
|
|
168
222
|
limit: string,
|
|
169
|
-
): Promise<WeeklyChartListResponse>
|
|
170
|
-
|
|
171
|
-
|
|
223
|
+
): Promise<WeeklyChartListResponse> {
|
|
224
|
+
const options = {
|
|
225
|
+
method,
|
|
226
|
+
user,
|
|
227
|
+
period,
|
|
228
|
+
limit,
|
|
229
|
+
}
|
|
230
|
+
return request<WeeklyChartListResponse>(options);
|
|
231
|
+
}
|
|
172
232
|
|
|
173
233
|
/**
|
|
174
234
|
* GET: Weekly track chart - LastFM
|
|
@@ -176,14 +236,20 @@ function LastFmApi() {
|
|
|
176
236
|
* https://www.last.fm/api/show/user.getWeeklyTrackChart
|
|
177
237
|
* @returns Weekly track chart
|
|
178
238
|
*/
|
|
179
|
-
|
|
239
|
+
function getWeeklyTrackChart(
|
|
180
240
|
method: string,
|
|
181
241
|
user: string,
|
|
182
242
|
period: string,
|
|
183
243
|
limit: string,
|
|
184
|
-
): Promise<WeeklyTrackChartResponse>
|
|
185
|
-
|
|
186
|
-
|
|
244
|
+
): Promise<WeeklyTrackChartResponse> {
|
|
245
|
+
const options = {
|
|
246
|
+
method,
|
|
247
|
+
user,
|
|
248
|
+
period,
|
|
249
|
+
limit,
|
|
250
|
+
}
|
|
251
|
+
return request<WeeklyTrackChartResponse>(options);
|
|
252
|
+
}
|
|
187
253
|
|
|
188
254
|
return {
|
|
189
255
|
auth,
|
package/src/request.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import fetch from 'cross-fetch';
|
|
2
2
|
import config from './config';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
method: string
|
|
6
|
-
user
|
|
7
|
-
period?: string
|
|
8
|
-
limit?: string
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
interface RequestOptions {
|
|
5
|
+
method: string;
|
|
6
|
+
user?: string;
|
|
7
|
+
period?: string;
|
|
8
|
+
limit?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const buildUrl = (options: RequestOptions): string => {
|
|
12
|
+
const params = new URLSearchParams();
|
|
13
|
+
params.append('method', options.method);
|
|
14
|
+
if (options.user) params.append('user', options.user);
|
|
15
|
+
if (options.period) params.append('period', options.period);
|
|
16
|
+
if (options.limit) params.append('limit', options.limit);
|
|
17
|
+
params.append('api_key', config.api_key);
|
|
18
|
+
params.append('format', config.format.json);
|
|
19
|
+
return `${config.base_url}?${params.toString()}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const request = async <Response>(options: RequestOptions): Promise<Response> => {
|
|
23
|
+
const url = buildUrl(options);
|
|
16
24
|
|
|
17
25
|
return (await fetch(url, {
|
|
18
26
|
headers: {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
dotenv.config({ path: path.resolve(__dirname, '..', process.env.CI ? '.env.example' : '.env') });
|
|
7
|
+
|
|
8
|
+
const { LASTFM_API_BASE_URL, LASTFM_API_KEY } = process.env;
|
|
9
|
+
|
|
10
|
+
let environmentVarWarning =
|
|
11
|
+
'❗ No environment variable found, use the .env.example file to create your own .env file with required properties and values.';
|
|
12
|
+
|
|
13
|
+
test.describe('Environment variables present and configured', async () => {
|
|
14
|
+
test('LASTFM_API_BASE_URL is present', async () => {
|
|
15
|
+
expect(LASTFM_API_BASE_URL, environmentVarWarning).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('LASTFM_API_KEY is present', async () => {
|
|
19
|
+
expect(LASTFM_API_KEY, environmentVarWarning).toBeDefined();
|
|
20
|
+
});
|
|
21
|
+
});
|