@anmiles/downloader 4.0.2 → 5.0.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/.eslintrc.js CHANGED
@@ -1,11 +1,14 @@
1
1
  module.exports = {
2
- root : true,
2
+ root : true,
3
+
3
4
  extends : [
4
- './node_modules/@anmiles/eslint-config/.eslintrc.js',
5
+ './node_modules/@anmiles/eslint-config/src/base.preset.js',
6
+ './node_modules/@anmiles/eslint-config/src/ts.preset.js',
7
+ './node_modules/@anmiles/eslint-config/src/jest.preset.js',
5
8
  ],
9
+
6
10
  ignorePatterns : [
7
- '**/node_modules/',
8
- 'coverage/',
9
- 'dist/',
11
+ 'coverage',
12
+ 'dist',
10
13
  ],
11
14
  };
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [5.0.0](../../tags/v5.0.0) - 2024-03-16
9
+ ### Changed
10
+ - Update eslint config and raise minimum supported NodeJS version to match one in typescript-eslint plugin
11
+ - Update .npmignore
12
+ - Unify jest.config.js by removing redundant patterns and providing support for both ts and tsx
13
+
8
14
  ## [4.0.2](../../tags/v4.0.2) - 2024-01-31
9
15
  ### Changed
10
16
  - Migrate to GitHub
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ /* istanbul ignore file */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.downloadJSON = exports.downloadString = exports.download = void 0;
4
5
  var downloader_1 = require("./lib/downloader");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAA0E;AAAjE,sGAAA,QAAQ,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,0GAAA,YAAY,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,0BAA0B;;;AAE1B,+CAA0E;AAAjE,sGAAA,QAAQ,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,0GAAA,YAAY,OAAA"}
@@ -1,4 +1,11 @@
1
1
  /// <reference types="node" />
2
+ type BufferEncoding = Parameters<Buffer['toString']>[0];
3
+ declare function download(url: string): Promise<Buffer>;
4
+ declare function download(url: string, file: string, options?: {
5
+ append?: boolean;
6
+ }): Promise<undefined>;
7
+ declare function downloadString(url: string, encoding?: BufferEncoding): Promise<string>;
8
+ declare function downloadJSON(url: string, encoding?: BufferEncoding): Promise<unknown>;
2
9
  export { download, downloadString, downloadJSON };
3
10
  declare const _default: {
4
11
  download: typeof download;
@@ -6,11 +13,4 @@ declare const _default: {
6
13
  downloadJSON: typeof downloadJSON;
7
14
  };
8
15
  export default _default;
9
- type BufferEncoding = Parameters<Buffer['toString']>[0];
10
- declare function download(url: string): Promise<Buffer>;
11
- declare function download(url: string, file: string, options?: {
12
- append?: boolean;
13
- }): Promise<void>;
14
- declare function downloadString(url: string, encoding?: BufferEncoding): Promise<string>;
15
- declare function downloadJSON(url: string, encoding?: BufferEncoding): Promise<any>;
16
16
  //# sourceMappingURL=downloader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"downloader.d.ts","sourceRoot":"","sources":["../../src/lib/downloader.ts"],"names":[],"mappings":";AAOA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;;;;;;AAClD,wBAA0D;AAE1D,KAAK,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAChD,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAgD5F,iBAAe,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,mBAO3E;AAED,iBAAe,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,gBAGzE"}
1
+ {"version":3,"file":"downloader.d.ts","sourceRoot":"","sources":["../../src/lib/downloader.ts"],"names":[],"mappings":";AAOA,KAAK,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAChD,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAG,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAgDlG,iBAAe,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7F;AAED,iBAAe,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAG5F;AAED,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;;;;;;AAClD,wBAA0D"}
@@ -9,8 +9,7 @@ const http_1 = __importDefault(require("http"));
9
9
  const https_1 = __importDefault(require("https"));
10
10
  const iconv_lite_1 = __importDefault(require("iconv-lite"));
11
11
  const downloader_1 = __importDefault(require("./downloader"));
12
- exports.default = { download, downloadString, downloadJSON };
13
- function download(url, file, options) {
12
+ async function download(url, file, options) {
14
13
  return new Promise((resolve, reject) => {
15
14
  let protocol;
16
15
  if (url.startsWith('https://')) {
@@ -20,7 +19,7 @@ function download(url, file, options) {
20
19
  protocol = http_1.default;
21
20
  }
22
21
  else {
23
- throw `Unknown protocol in url ${url}, expected one of "http" or "https"`;
22
+ throw new Error(`Unknown protocol in url ${url}, expected one of "http" or "https"`);
24
23
  }
25
24
  const reqOptions = {
26
25
  headers: {
@@ -29,7 +28,7 @@ function download(url, file, options) {
29
28
  };
30
29
  protocol.get(url, reqOptions, function (res) {
31
30
  if (res.statusCode !== 200) {
32
- reject(`Request to ${url} returned with status code: ${res.statusCode}`);
31
+ reject(new Error(`Request to ${url} returned with status code: ${res.statusCode}`));
33
32
  res.resume();
34
33
  }
35
34
  const chunks = [];
@@ -44,18 +43,18 @@ function download(url, file, options) {
44
43
  else {
45
44
  res.pipe(fs_1.default.createWriteStream(file, { flags: options?.append ? 'a' : 'w' }));
46
45
  res.on('end', function () {
47
- resolve();
46
+ resolve(undefined);
48
47
  });
49
48
  }
50
49
  }).on('error', (e) => {
51
- reject(`Request to ${url} failed with error: ${e.message}`);
50
+ reject(new Error(`Request to ${url} failed with error: ${e.message}`));
52
51
  });
53
52
  });
54
53
  }
55
54
  exports.download = download;
56
55
  async function downloadString(url, encoding = 'utf8') {
57
56
  if (!Buffer.isEncoding(encoding)) {
58
- throw `Unknown encoding ${encoding}`;
57
+ throw new Error(`Unknown encoding ${String(encoding)}`);
59
58
  }
60
59
  const buffer = await downloader_1.default.download(url);
61
60
  return iconv_lite_1.default.decode(buffer, encoding);
@@ -66,4 +65,5 @@ async function downloadJSON(url, encoding = 'utf8') {
66
65
  return JSON.parse(json);
67
66
  }
68
67
  exports.downloadJSON = downloadJSON;
68
+ exports.default = { download, downloadString, downloadJSON };
69
69
  //# sourceMappingURL=downloader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"downloader.js","sourceRoot":"","sources":["../../src/lib/downloader.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,kDAA0B;AAC1B,4DAA+B;AAE/B,8DAAsC;AAGtC,kBAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAM1D,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAa,EAAE,OAA8B;IAC3E,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrD,IAAI,QAAqC,CAAC;QAE1C,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,QAAQ,GAAG,eAAK,CAAC;QAClB,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,QAAQ,GAAG,cAAI,CAAC;QACjB,CAAC;aAAM,CAAC;YACP,MAAM,2BAA2B,GAAG,qCAAqC,CAAC;QAC3E,CAAC;QAED,MAAM,UAAU,GAAG;YAClB,OAAO,EAAG;gBACT,YAAY,EAAG,iHAAiH;aAChI;SACD,CAAC;QAEF,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,UAAS,GAAG;YACzC,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,CAAC,cAAc,GAAG,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;gBACzE,GAAG,CAAC,MAAM,EAAE,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAiB,EAAE,CAAC;YAEhC,IAAI,OAAO,IAAI,KAAK,WAAW,EAAE,CAAC;gBACjC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,UAAS,KAAK;oBAC5B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACpB,CAAC,CAAC,CAAC;gBAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;oBACb,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,GAAG,CAAC,IAAI,CAAC,YAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAE9E,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;oBACb,OAAO,EAAE,CAAC;gBACX,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACpB,MAAM,CAAC,cAAc,GAAG,uBAAuB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AApDQ,4BAAQ;AAsDjB,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,WAA2B,MAAM;IAC3E,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,MAAM,oBAAoB,QAAQ,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,oBAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9C,OAAO,oBAAK,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AA7DkB,wCAAc;AA+DjC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,WAA2B,MAAM;IACzE,MAAM,IAAI,GAAG,MAAM,oBAAU,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAlEkC,oCAAY"}
1
+ {"version":3,"file":"downloader.js","sourceRoot":"","sources":["../../src/lib/downloader.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,kDAA0B;AAC1B,4DAA+B;AAE/B,8DAAsC;AAMtC,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAa,EAAE,OAA+B;IAClF,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1D,IAAI,QAAqC,CAAC;QAE1C,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,QAAQ,GAAG,eAAK,CAAC;QAClB,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,QAAQ,GAAG,cAAI,CAAC;QACjB,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,qCAAqC,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,UAAU,GAAG;YAClB,OAAO,EAAG;gBACT,YAAY,EAAG,iHAAiH;aAChI;SACD,CAAC;QAEF,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,UAAS,GAAG;YACzC,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,GAAG,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBACpF,GAAG,CAAC,MAAM,EAAE,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAiB,EAAE,CAAC;YAEhC,IAAI,OAAO,IAAI,KAAK,WAAW,EAAE,CAAC;gBACjC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,UAAS,KAAiB;oBACxC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACpB,CAAC,CAAC,CAAC;gBAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;oBACb,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,GAAG,CAAC,IAAI,CAAC,YAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAE9E,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;oBACb,OAAO,CAAC,SAAS,CAAC,CAAC;gBACpB,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACpB,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,GAAG,uBAAuB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAgBQ,4BAAQ;AAdjB,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,WAA2B,MAAM;IAC3E,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,oBAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9C,OAAO,oBAAK,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAOkB,wCAAc;AALjC,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,WAA2B,MAAM;IACzE,MAAM,IAAI,GAAG,MAAM,oBAAU,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;AACpC,CAAC;AAEkC,oCAAY;AAC/C,kBAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC"}
package/jest.config.js CHANGED
@@ -7,18 +7,10 @@ module.exports = {
7
7
  clearMocks : true,
8
8
 
9
9
  roots : [ '<rootDir>/src' ],
10
- testMatch : [ '<rootDir>/src/**/__tests__/*.test.ts' ],
10
+ testMatch : [ '<rootDir>/src/**/__tests__/*.test.{ts,tsx}' ],
11
11
 
12
12
  collectCoverageFrom : [
13
- '<rootDir>/src/**/*.ts',
14
- '!<rootDir>/src/**/*.d.ts',
15
- '!<rootDir>/src/*.ts',
16
- '!<rootDir>/src/types/*.ts',
17
-
18
- '!**/node_modules/**',
19
- '!**/__tests__/**',
20
-
21
- '!<rootDir>/coverage/**',
22
- '!<rootDir>/dist/**',
13
+ '<rootDir>/src/**/*.{ts,tsx}',
14
+ '!<rootDir>/src/**/__tests__/**',
23
15
  ],
24
16
  };
package/package.json CHANGED
@@ -1,51 +1,56 @@
1
1
  {
2
- "name": "@anmiles/downloader",
3
- "version": "4.0.2",
4
- "description": "Wrapper for downloading data as string, buffer or complex types",
5
- "keywords": [
6
- "download",
7
- "http",
8
- "request"
9
- ],
10
- "author": "Anatoliy Oblaukhov",
11
- "homepage": "https://github.com/anmiles/downloader",
12
- "repository": "github:anmiles/downloader",
13
- "license": "MIT",
14
- "engines": {
15
- "node": ">=18.14.2"
16
- },
17
- "main": "dist/index.js",
18
- "scripts": {
19
- "build": "rimraf dist && tsc -p ./tsconfig.build.json",
20
- "build:ci": "tsc -noEmit -p ./tsconfig.build.json",
21
- "lint": "eslint --ext .js,.ts .",
22
- "lint:fix": "npm run lint -- --fix",
23
- "test": "jest --verbose",
24
- "test:coverage": "npm test -- --coverage",
25
- "test:ci": "npm test -- --ci --coverage",
26
- "test:watch": "npm test -- --watch",
27
- "test:watch:coverage": "npm test -- --watch --coverage",
28
- "test:report:coverage": "nyc report --nycrc-path ./coverage.config.js -t ./coverage --report-dir ./coverage"
29
- },
30
- "dependencies": {
31
- "iconv-lite": "^0.6.3"
32
- },
33
- "devDependencies": {
34
- "@anmiles/eslint-config": "^5.0.2",
35
- "@anmiles/tsconfig": "^2.0.1",
36
- "@types/event-emitter": "^0.3.5",
37
- "@types/jest": "^29.5.11",
38
- "@typescript-eslint/eslint-plugin": "^6.20.0",
39
- "@typescript-eslint/parser": "^6.20.0",
40
- "eslint": "^8.56.0",
41
- "eslint-plugin-align-assignments": "^1.1.2",
42
- "eslint-plugin-import": "^2.29.1",
43
- "eslint-plugin-jest": "^27.6.3",
44
- "event-emitter": "^0.3.5",
45
- "jest": "^29.7.0",
46
- "nyc": "^15.1.0",
47
- "rimraf": "^5.0.5",
48
- "ts-jest": "^29.1.2",
49
- "typescript": "^5.3.3"
50
- }
2
+ "name": "@anmiles/downloader",
3
+ "version": "5.0.0",
4
+ "description": "Wrapper for downloading data as string, buffer or complex types",
5
+ "keywords": [
6
+ "download",
7
+ "http",
8
+ "request"
9
+ ],
10
+ "author": "Anatoliy Oblaukhov",
11
+ "homepage": "https://github.com/anmiles/downloader",
12
+ "repository": "github:anmiles/downloader",
13
+ "license": "MIT",
14
+ "engines": {
15
+ "node": ">=18.18.0"
16
+ },
17
+ "main": "dist/index.js",
18
+ "scripts": {
19
+ "build": "rimraf dist && tsc -p ./tsconfig.build.json",
20
+ "build:ci": "tsc -noEmit -p ./tsconfig.build.json",
21
+ "lint": "eslint .",
22
+ "lint:fix": "npm run lint -- --fix",
23
+ "test": "jest --verbose",
24
+ "test:coverage": "npm test -- --coverage",
25
+ "test:ci": "npm test -- --ci --coverage",
26
+ "test:watch": "npm test -- --watch",
27
+ "test:watch:coverage": "npm test -- --watch --coverage",
28
+ "test:report:coverage": "nyc report --nycrc-path ./coverage.config.js -t ./coverage --report-dir ./coverage"
29
+ },
30
+ "dependencies": {
31
+ "iconv-lite": "^0.6.3"
32
+ },
33
+ "devDependencies": {
34
+ "@anmiles/eslint-config": "^7.0.1",
35
+ "@anmiles/tsconfig": "^2.0.1",
36
+ "@stylistic/eslint-plugin": "^1.7.0",
37
+ "@types/event-emitter": "^0.3.5",
38
+ "@types/jest": "^29.5.12",
39
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
40
+ "@typescript-eslint/parser": "^7.2.0",
41
+ "eslint": "^8.57.0",
42
+ "eslint-import-resolver-typescript": "^3.6.1",
43
+ "eslint-plugin-align-assignments": "^1.1.2",
44
+ "eslint-plugin-import": "^2.29.1",
45
+ "eslint-plugin-jest": "^27.9.0",
46
+ "eslint-plugin-jsonc": "^2.13.0",
47
+ "eslint-plugin-n": "^16.6.2",
48
+ "eslint-plugin-promise": "^6.1.1",
49
+ "event-emitter": "^0.3.5",
50
+ "jest": "^29.7.0",
51
+ "nyc": "^15.1.0",
52
+ "rimraf": "^5.0.5",
53
+ "ts-jest": "^29.1.2",
54
+ "typescript": "^5.4.2"
55
+ }
51
56
  }
package/src/index.ts CHANGED
@@ -1 +1,3 @@
1
+ /* istanbul ignore file */
2
+
1
3
  export { download, downloadString, downloadJSON } from './lib/downloader';
@@ -5,23 +5,26 @@ import emitter from 'event-emitter';
5
5
  import iconv from 'iconv-lite';
6
6
 
7
7
  import downloader from '../downloader';
8
- const original = jest.requireActual('../downloader').default as typeof downloader;
8
+
9
+ const original = jest.requireActual<{ default : typeof downloader }>('../downloader').default;
9
10
 
10
11
  jest.mock<Partial<typeof downloader>>('../downloader', () => ({
11
12
  download : jest.fn().mockImplementation(() => downloaded),
12
- downloadString : jest.fn().mockImplementation((...args: Parameters<typeof original.downloadString>) => original.downloadString(...args)),
13
+ downloadString : jest.fn().mockImplementation(async (...args: Parameters<typeof original.downloadString>) => original.downloadString(...args)),
13
14
  }));
14
15
 
15
16
  let request: http.ClientRequest;
16
17
  let response: http.IncomingMessage;
17
18
 
18
- function get(_url: string | URL, _options: https.RequestOptions, callback?: ((res: http.IncomingMessage) => void) | undefined): http.ClientRequest {
19
+ /* eslint-disable promise/prefer-await-to-callbacks -- similar signature to original http.get */
20
+ function get(_url: URL | string, _options: https.RequestOptions, callback?: ((res: http.IncomingMessage) => void) | undefined): http.ClientRequest {
19
21
  if (callback) {
20
22
  callback(response);
21
23
  }
22
24
 
23
25
  return request;
24
26
  }
27
+ /* eslint-enable promise/prefer-await-to-callbacks */
25
28
 
26
29
  beforeEach(() => {
27
30
  request = emitter() as typeof request;
@@ -33,49 +36,36 @@ beforeEach(() => {
33
36
  response.statusCode = 200;
34
37
  });
35
38
 
36
- let httpGetSpy: jest.SpyInstance;
37
- let httpsGetSpy: jest.SpyInstance;
39
+ const httpGetSpy = jest.spyOn(http, 'get').mockImplementation(get);
40
+ const httpsGetSpy = jest.spyOn(https, 'get').mockImplementation(get);
38
41
  let downloaded: Buffer;
39
42
 
40
- beforeAll(() => {
41
- httpGetSpy = jest.spyOn(http, 'get');
42
- httpsGetSpy = jest.spyOn(https, 'get');
43
- });
44
-
45
- beforeEach(() => {
46
- httpGetSpy.mockImplementation(get);
47
- httpsGetSpy.mockImplementation(get);
48
- });
49
-
50
- afterAll(() => {
51
- httpGetSpy.mockRestore();
52
- });
53
-
54
43
  describe('src/lib/downloader', () => {
55
44
  describe('download', () => {
56
45
  it('should throw if url protocol is not supported', async () => {
57
- await expect(() => original.download('ftp://url')).rejects.toEqual('Unknown protocol in url ftp://url, expected one of "http" or "https"');
46
+ const promise: () => Promise<Buffer> = async () => original.download('ftp://url');
47
+ await expect(promise).rejects.toEqual(new Error('Unknown protocol in url ftp://url, expected one of "http" or "https"'));
58
48
  });
59
49
 
60
50
  it('should call http.get if url protocol is http', async () => {
61
51
  const promise = original.download('http://url');
62
52
  response.emit('end');
63
53
  await promise;
64
- expect(httpGetSpy.mock.calls[0][0]).toEqual('http://url');
54
+ expect(httpGetSpy.mock.calls[0]?.[0]).toEqual('http://url');
65
55
  });
66
56
 
67
57
  it('should call https.get if url protocol is https', async () => {
68
58
  const promise = original.download('https://url');
69
59
  response.emit('end');
70
60
  await promise;
71
- expect(httpsGetSpy.mock.calls[0][0]).toEqual('https://url');
61
+ expect(httpsGetSpy.mock.calls[0]?.[0]).toEqual('https://url');
72
62
  });
73
63
 
74
64
  it('should pass user-agent in options', async () => {
75
65
  const promise = original.download('http://url');
76
66
  response.emit('end');
77
67
  await promise;
78
- expect(httpGetSpy.mock.calls[0][1]).toEqual(expect.objectContaining({
68
+ expect(httpGetSpy.mock.calls[0]?.[1]).toEqual(expect.objectContaining({
79
69
  headers : {
80
70
  'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
81
71
  },
@@ -83,15 +73,16 @@ describe('src/lib/downloader', () => {
83
73
  });
84
74
 
85
75
  it('should reject and resume response if status code is not 200', async () => {
86
- response.statusCode = 404;
87
- await expect(() => original.download('http://url')).rejects.toEqual('Request to http://url returned with status code: 404');
76
+ response.statusCode = 404;
77
+ const promise: () => Promise<Buffer> = async () => original.download('http://url');
78
+ await expect(promise).rejects.toEqual(new Error('Request to http://url returned with status code: 404'));
88
79
  expect(response.resume).toHaveBeenCalled();
89
80
  });
90
81
 
91
82
  it('should reject if response errored', async () => {
92
83
  const promise = original.download('http://url');
93
84
  request.emit('error', new Error('request error'));
94
- await expect(() => promise).rejects.toEqual('Request to http://url failed with error: request error');
85
+ await expect(promise).rejects.toEqual(new Error('Request to http://url failed with error: request error'));
95
86
  });
96
87
 
97
88
  it('should concat and resolve received data if no file specified', async () => {
@@ -112,10 +103,9 @@ describe('src/lib/downloader', () => {
112
103
  response.emit('data', new Uint8Array([ 20, 21, 22 ]));
113
104
  response.emit('data', new Uint8Array([ 30, 31, 32 ]));
114
105
  response.emit('end');
115
- const result = await promise;
106
+ await promise;
116
107
  expect(createWriteStreamSpy).toHaveBeenCalledWith('file', { flags : 'w' });
117
108
  expect(response.pipe).toHaveBeenCalledWith(stream);
118
- expect(result).toEqual(undefined);
119
109
  createWriteStreamSpy.mockRestore();
120
110
  });
121
111
 
@@ -127,17 +117,17 @@ describe('src/lib/downloader', () => {
127
117
  response.emit('data', new Uint8Array([ 20, 21, 22 ]));
128
118
  response.emit('data', new Uint8Array([ 30, 31, 32 ]));
129
119
  response.emit('end');
130
- const result = await promise;
120
+ await promise;
131
121
  expect(createWriteStreamSpy).toHaveBeenCalledWith('file', { flags : 'a' });
132
122
  expect(response.pipe).toHaveBeenCalledWith(stream);
133
- expect(result).toEqual(undefined);
134
123
  createWriteStreamSpy.mockRestore();
135
124
  });
136
125
  });
137
126
 
138
127
  describe('downloadString', () => {
139
128
  it('should throw if unknown encoding specified', async () => {
140
- await expect(() => original.downloadString('http://url', 'wrong_encoding' as any)).rejects.toEqual('Unknown encoding wrong_encoding');
129
+ const promise: () => Promise<string> = async () => original.downloadString('http://url', 'wrong_encoding' as unknown as BufferEncoding);
130
+ await expect(promise).rejects.toEqual(new Error('Unknown encoding wrong_encoding'));
141
131
  });
142
132
 
143
133
  it('should return string decoded with utf8', async () => {
@@ -5,23 +5,20 @@ import iconv from 'iconv-lite';
5
5
 
6
6
  import downloader from './downloader';
7
7
 
8
- export { download, downloadString, downloadJSON };
9
- export default { download, downloadString, downloadJSON };
10
-
11
8
  type BufferEncoding = Parameters<Buffer['toString']>[0];
12
9
 
13
10
  function download(url: string): Promise<Buffer>;
14
- function download(url: string, file: string, options?: { append?: boolean }): Promise<void>;
15
- function download(url: string, file?: string, options?: { append?: boolean }): Promise<Buffer | void> {
16
- return new Promise<Buffer | void>((resolve, reject) => {
17
- let protocol : typeof https | typeof http;
11
+ function download(url: string, file: string, options?: { append? : boolean }): Promise<undefined>;
12
+ async function download(url: string, file?: string, options?: { append? : boolean }): Promise<Buffer | undefined> {
13
+ return new Promise<Buffer | undefined>((resolve, reject) => {
14
+ let protocol : typeof http | typeof https;
18
15
 
19
16
  if (url.startsWith('https://')) {
20
17
  protocol = https;
21
18
  } else if (url.startsWith('http://')) {
22
19
  protocol = http;
23
20
  } else {
24
- throw `Unknown protocol in url ${url}, expected one of "http" or "https"`;
21
+ throw new Error(`Unknown protocol in url ${url}, expected one of "http" or "https"`);
25
22
  }
26
23
 
27
24
  const reqOptions = {
@@ -32,14 +29,14 @@ function download(url: string, file?: string, options?: { append?: boolean }): P
32
29
 
33
30
  protocol.get(url, reqOptions, function(res) {
34
31
  if (res.statusCode !== 200) {
35
- reject(`Request to ${url} returned with status code: ${res.statusCode}`);
32
+ reject(new Error(`Request to ${url} returned with status code: ${res.statusCode}`));
36
33
  res.resume();
37
34
  }
38
35
 
39
36
  const chunks: Uint8Array[] = [];
40
37
 
41
38
  if (typeof file === 'undefined') {
42
- res.on('data', function(chunk) {
39
+ res.on('data', function(chunk: Uint8Array) {
43
40
  chunks.push(chunk);
44
41
  });
45
42
 
@@ -50,25 +47,28 @@ function download(url: string, file?: string, options?: { append?: boolean }): P
50
47
  res.pipe(fs.createWriteStream(file, { flags : options?.append ? 'a' : 'w' }));
51
48
 
52
49
  res.on('end', function() {
53
- resolve();
50
+ resolve(undefined);
54
51
  });
55
52
  }
56
53
  }).on('error', (e) => {
57
- reject(`Request to ${url} failed with error: ${e.message}`);
54
+ reject(new Error(`Request to ${url} failed with error: ${e.message}`));
58
55
  });
59
56
  });
60
57
  }
61
58
 
62
- async function downloadString(url: string, encoding: BufferEncoding = 'utf8') {
59
+ async function downloadString(url: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
63
60
  if (!Buffer.isEncoding(encoding)) {
64
- throw `Unknown encoding ${encoding}`;
61
+ throw new Error(`Unknown encoding ${String(encoding)}`);
65
62
  }
66
63
 
67
64
  const buffer = await downloader.download(url);
68
65
  return iconv.decode(buffer, encoding);
69
66
  }
70
67
 
71
- async function downloadJSON(url: string, encoding: BufferEncoding = 'utf8') {
68
+ async function downloadJSON(url: string, encoding: BufferEncoding = 'utf8'): Promise<unknown> {
72
69
  const json = await downloader.downloadString(url, encoding);
73
- return JSON.parse(json);
70
+ return JSON.parse(json) as unknown;
74
71
  }
72
+
73
+ export { download, downloadString, downloadJSON };
74
+ export default { download, downloadString, downloadJSON };
@@ -1,7 +1,7 @@
1
1
  {
2
- "extends": "./tsconfig.json",
2
+ "extends" : "./tsconfig.json",
3
3
 
4
- "exclude": [
4
+ "exclude" : [
5
5
  "**/__tests__/",
6
6
  ],
7
7
  }
package/tsconfig.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "extends": "./node_modules/@anmiles/tsconfig/tsconfig.json",
2
+ "extends" : "./node_modules/@anmiles/tsconfig/tsconfig.json",
3
3
 
4
- "compilerOptions": {
5
- "rootDir": "./src",
6
- "outDir": "./dist",
4
+ "compilerOptions" : {
5
+ "rootDir" : "./src",
6
+ "outDir" : "./dist",
7
7
  },
8
8
 
9
- "include": [
9
+ "include" : [
10
10
  "src",
11
11
  ],
12
12
  }
@@ -1,94 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- pull_request:
8
- workflow_dispatch:
9
-
10
- concurrency:
11
- group: "${{ github.workflow }}-${{ github.ref }}"
12
- cancel-in-progress: true
13
-
14
- jobs:
15
- install:
16
- runs-on: ubuntu-latest
17
- container:
18
- image: node:18.14
19
- timeout-minutes: 30
20
- steps:
21
- - uses: actions/checkout@v4
22
- - uses: actions/cache@v4
23
- with:
24
- path: node_modules
25
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
26
- lookup-only: true
27
- - run: npm ci
28
-
29
- build:
30
- needs: install
31
- runs-on: ubuntu-latest
32
- container:
33
- image: node:18.14
34
- timeout-minutes: 30
35
- steps:
36
- - uses: actions/checkout@v4
37
- - uses: actions/cache@v4
38
- with:
39
- path: node_modules
40
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
41
- - run: npm run build:ci
42
-
43
- lint:
44
- needs: build
45
- runs-on: ubuntu-latest
46
- container:
47
- image: node:18.14
48
- timeout-minutes: 30
49
- steps:
50
- - uses: actions/checkout@v4
51
- - uses: actions/cache@v4
52
- with:
53
- path: node_modules
54
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
55
- - run: npm run lint
56
-
57
- test:
58
- needs: build
59
- runs-on: ubuntu-latest
60
- container:
61
- image: node:18.14
62
- timeout-minutes: 30
63
- steps:
64
- - uses: actions/checkout@v4
65
- - uses: actions/cache@v4
66
- with:
67
- path: node_modules
68
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
69
- - uses: actions/cache@v4
70
- with:
71
- path: coverage
72
- key: "coverage-${{ hashFiles('package-lock.json') }}"
73
- lookup-only: true
74
- - run: npm run test:ci
75
-
76
- coverage:
77
- needs:
78
- - lint
79
- - test
80
- runs-on: ubuntu-latest
81
- container:
82
- image: node:18.14
83
- timeout-minutes: 30
84
- steps:
85
- - uses: actions/checkout@v4
86
- - uses: actions/cache@v4
87
- with:
88
- path: node_modules
89
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
90
- - uses: actions/cache@v4
91
- with:
92
- path: coverage
93
- key: "coverage-${{ hashFiles('package-lock.json') }}"
94
- - run: npm run test:report:coverage