gerdur 2.15.0 → 2.16.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.16.0 - 2026-08-31
4
+
5
+ ### Changed
6
+
7
+ - **The CLI starts about twice as fast: ~249 ms → 120 ms** (min of 10 runs;
8
+ mean 137 ms). Two things were being loaded before they could possibly be
9
+ needed:
10
+ - `gerdur-core@^2.20.0` now defers the Spotify SDK and the HTML parser, so
11
+ `require('gerdur-core')` costs 43 ms instead of 160 ms.
12
+ - `got` (~53 ms to require) is now loaded on first use rather than at import.
13
+ Every call site was already inside a function, so this is a pure deferral —
14
+ but it means `--help`, `gerdur setup`, `--set-arl` and the interactive prompt
15
+ no longer pay for an HTTP client before you have typed anything.
16
+
17
+ Verified against live downloads: a full 320 kbps track (9.19 MB, 226 s,
18
+ decodes clean under ffmpeg) and a `--preview` clip (480 KB, 30 s).
19
+
3
20
  ## 2.15.0 - 2026-08-31
4
21
 
5
22
  ### Changed
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Command-line music downloader for Deezer (Spotify/Tidal links resolved via ISRC matching) with automatic MP3/FLAC tagging, synced lyrics and a side-effect-free programmatic API.",
5
5
  "keywords": [
6
6
  "deezer",
@@ -63,7 +63,7 @@
63
63
  "adm-zip": "^0.5.16",
64
64
  "chalk": "^4.1.2",
65
65
  "commander": "^9.5.0",
66
- "gerdur-core": "^2.19.0",
66
+ "gerdur-core": "^2.20.0",
67
67
  "dot-prop": "^6.0.1",
68
68
  "got": "^11.8.6",
69
69
  "gradient-string": "^2.0.2",
@@ -9,7 +9,10 @@ const fs_1 = require("fs");
9
9
  const path_1 = require("path");
10
10
  const commander_1 = require("commander");
11
11
  const gradient_string_1 = __importDefault(require("gradient-string"));
12
- const got_1 = __importDefault(require("got"));
12
+ /* eslint-disable @typescript-eslint/no-var-requires */
13
+ // `got` costs ~53 ms to require and is only needed once a transfer actually
14
+ // starts — deferring it keeps `--help`, setup and the interactive prompt snappy.
15
+ const got = () => require('got');
13
16
  const gerdur_core_1 = require("gerdur-core");
14
17
  const prompts_1 = __importDefault(require("prompts"));
15
18
  const log_update_1 = __importDefault(require("log-update"));
@@ -369,7 +372,7 @@ const startDownload = async (saveLayout, url, skipPrompt) => {
369
372
  console.log(signale_1.default.info(`Downloading episode: ${episode.EPISODE_TITLE}`));
370
373
  if (options.overwrite || !(0, fs_1.existsSync)(dest)) {
371
374
  (0, fs_1.mkdirSync)(dir, { recursive: true });
372
- const { body } = await (0, got_1.default)(episode.EPISODE_DIRECT_STREAM_URL, { responseType: 'buffer' });
375
+ const { body } = await got()(episode.EPISODE_DIRECT_STREAM_URL, { responseType: 'buffer' });
373
376
  (0, fs_1.writeFileSync)(dest, body);
374
377
  }
375
378
  console.log(signale_1.default.success(`Saved ${dest}`));
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.downloadTrackToFile = exports.getTaggedTrack = exports.getTrackBuffer = void 0;
7
4
  const fs_1 = require("fs");
8
5
  const path_1 = require("path");
9
- const got_1 = __importDefault(require("got"));
6
+ /* eslint-disable @typescript-eslint/no-var-requires */
7
+ // `got` costs ~53 ms to require and is only needed once a transfer actually
8
+ // starts — deferring it keeps `--help`, setup and the interactive prompt snappy.
9
+ const got = () => require('got');
10
10
  const gerdur_core_1 = require("gerdur-core");
11
11
  const decrypt_1 = require("./decrypt");
12
12
  const util_1 = require("./util");
@@ -48,7 +48,10 @@ const fetchDecryptTag = async (track, quality, options) => {
48
48
  if (!trackData) {
49
49
  continue;
50
50
  }
51
- const { body } = await (0, got_1.default)(trackData.trackUrl, { responseType: 'buffer', agent: { http: gerdur_core_1.httpAgent, https: gerdur_core_1.httpsAgent } });
51
+ const { body } = await got()(trackData.trackUrl, {
52
+ responseType: 'buffer',
53
+ agent: { http: gerdur_core_1.httpAgent, https: gerdur_core_1.httpsAgent },
54
+ });
52
55
  const decrypted = trackData.isEncrypted ? (0, decrypt_1.decryptDownload)(body, track.SNG_ID) : body;
53
56
  return (0, gerdur_core_1.addTrackTags)(decrypted, track, tagOptions(options));
54
57
  }
@@ -4,7 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_1 = require("fs");
7
- const got_1 = __importDefault(require("got"));
7
+ /* eslint-disable @typescript-eslint/no-var-requires */
8
+ // `got` costs ~53 ms to require and is only needed once a transfer actually
9
+ // starts — deferring it keeps `--help`, setup and the interactive prompt snappy.
10
+ const got = () => require('got');
8
11
  const adm_zip_1 = __importDefault(require("adm-zip"));
9
12
  const chalk_1 = __importDefault(require("chalk"));
10
13
  const log_update_1 = __importDefault(require("log-update"));
@@ -12,7 +15,7 @@ const signale_1 = __importDefault(require("./signale"));
12
15
  const util_1 = require("./util");
13
16
  const updateCheck = async (pkg) => {
14
17
  const beta = pkg.version.includes('beta');
15
- const releases = await (0, got_1.default)('https://api.github.com/repos/soulwax/gerdur/releases').json();
18
+ const releases = await got()('https://api.github.com/repos/soulwax/gerdur/releases').json();
16
19
  const data = releases.filter((r) => r.prerelease === beta)[0];
17
20
  if (data.tag_name > pkg.version) {
18
21
  return data;
@@ -51,7 +54,7 @@ const updateBinary = async (pkg) => {
51
54
  console.log(` Downloading ${asset.browser_download_url}`);
52
55
  const bar = (0, util_1.progressBar)(asset.size, 40);
53
56
  const humanSizeTotal = (asset.size / 1024 / 1024).toFixed(2);
54
- const { body } = await (0, got_1.default)(asset.browser_download_url, { responseType: 'buffer' }).on('downloadProgress', ({ transferred }) => {
57
+ const { body } = await got()(asset.browser_download_url, { responseType: 'buffer' }).on('downloadProgress', ({ transferred }) => {
55
58
  (0, log_update_1.default)(` ${bar(transferred)} | ${humanSizeTotal}MiB`);
56
59
  });
57
60
  log_update_1.default.done();
@@ -3,7 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const got_1 = __importDefault(require("got"));
6
+ /* eslint-disable @typescript-eslint/no-var-requires */
7
+ // `got` costs ~53 ms to require and is only needed once a transfer actually
8
+ // starts — deferring it keeps `--help`, setup and the interactive prompt snappy.
9
+ const got = () => require('got');
7
10
  const stream_1 = __importDefault(require("stream"));
8
11
  const fs_1 = require("fs");
9
12
  const util_1 = require("util");
@@ -127,7 +130,7 @@ const downloadTrack = async ({ track, quality, info, coverSizes, path, totalTrac
127
130
  const bar = (0, util_2.progressBar)(fileSize, 40);
128
131
  const humanSizeTotal = (fileSize / 1024 / 1024).toFixed(2);
129
132
  let transferredLast = downloaded;
130
- await pipeline(got_1.default
133
+ await pipeline(got()
131
134
  .stream(trackData.trackUrl, {
132
135
  responseType: 'buffer',
133
136
  headers,
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.loginWithEmail = void 0;
7
4
  const crypto_1 = require("crypto");
8
- const got_1 = __importDefault(require("got"));
5
+ /* eslint-disable @typescript-eslint/no-var-requires */
6
+ // `got` costs ~53 ms to require and is only needed once a transfer actually
7
+ // starts — deferring it keeps `--help`, setup and the interactive prompt snappy.
8
+ const got = () => require('got');
9
9
  /**
10
10
  * Email/password -> arl login for Deezer.
11
11
  *
@@ -55,7 +55,7 @@ const loginWithEmail = async (email, password) => {
55
55
  const jar = new Map();
56
56
  try {
57
57
  // 1. Bootstrap a session so Deezer sets an initial sid cookie.
58
- const boot = await (0, got_1.default)('https://www.deezer.com', {
58
+ const boot = await got()('https://www.deezer.com', {
59
59
  method: 'POST',
60
60
  headers: { 'User-Agent': UA },
61
61
  timeout: { request: 15000 },
@@ -67,7 +67,7 @@ const loginWithEmail = async (email, password) => {
67
67
  const passwordHash = md5(password);
68
68
  const hash = md5([CLIENT_ID, email, passwordHash, CLIENT_SECRET].join(''));
69
69
  let accessToken = null;
70
- const auth = await (0, got_1.default)('https://connect.deezer.com/oauth/user_auth.php', {
70
+ const auth = await got()('https://connect.deezer.com/oauth/user_auth.php', {
71
71
  searchParams: { app_id: CLIENT_ID, login: email, password: passwordHash, hash },
72
72
  headers: { 'User-Agent': UA, cookie: cookieHeader(jar) },
73
73
  responseType: 'json',
@@ -83,7 +83,7 @@ const loginWithEmail = async (email, password) => {
83
83
  return { ok: false, reason: 'wrong-credentials', message: 'Login failed — check your email and password.' };
84
84
  }
85
85
  // 3. Read the arl for the now-authenticated session.
86
- const arlResp = await (0, got_1.default)('https://www.deezer.com/ajax/gw-light.php', {
86
+ const arlResp = await got()('https://www.deezer.com/ajax/gw-light.php', {
87
87
  searchParams: { method: 'user.getArl', input: 3, api_version: '1.0', api_token: 'null' },
88
88
  headers: { 'User-Agent': UA, cookie: cookieHeader(jar) },
89
89
  responseType: 'json',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gerdur",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Command-line music downloader for Deezer (Spotify/Tidal links resolved via ISRC matching) with automatic MP3/FLAC tagging, synced lyrics and a side-effect-free programmatic API.",
5
5
  "keywords": [
6
6
  "deezer",
@@ -63,7 +63,7 @@
63
63
  "adm-zip": "^0.5.16",
64
64
  "chalk": "^4.1.2",
65
65
  "commander": "^9.5.0",
66
- "gerdur-core": "^2.19.0",
66
+ "gerdur-core": "^2.20.0",
67
67
  "dot-prop": "^6.0.1",
68
68
  "got": "^11.8.6",
69
69
  "gradient-string": "^2.0.2",