@anmiles/downloader 2.0.5 → 2.1.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
@@ -5,6 +5,14 @@ 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
+ ## [2.1.0](../../tags/v2.1.0) - 2023-08-23
9
+ ### Added
10
+ - Append mode for file stream
11
+
12
+ ## [2.0.6](../../tags/v2.0.6) - 2023-05-26
13
+ ### Changed
14
+ - Re-initialize emitter instance before each test
15
+
8
16
  ## [2.0.5](../../tags/v2.0.5) - 2023-05-08
9
17
  ### Changed
10
18
  - Use shared eslint config * explicitly specify ignorePatterns
package/README.md CHANGED
@@ -20,6 +20,11 @@ import { download } from '@anmiles/downloader';
20
20
  await download('http://url/file', '/path/to/file');
21
21
  ```
22
22
 
23
+ ```js
24
+ import { download } from '@anmiles/downloader';
25
+ await download('http://url/file', '/path/to/file', { append: true });
26
+ ```
27
+
23
28
  ```js
24
29
  import { downloadString } from '@anmiles/downloader';
25
30
  const str = downloadString('http://url/string');
@@ -8,6 +8,8 @@ declare const _default: {
8
8
  export default _default;
9
9
  type BufferEncoding = Parameters<Buffer['toString']>[0];
10
10
  declare function download(url: string): Promise<Buffer>;
11
- declare function download(url: string, file: string): Promise<void>;
11
+ declare function download(url: string, file: string, options?: {
12
+ append?: boolean;
13
+ }): Promise<void>;
12
14
  declare function downloadString(url: string, encoding?: BufferEncoding): Promise<string>;
13
15
  declare function downloadJSON(url: string, encoding?: BufferEncoding): Promise<any>;
@@ -10,7 +10,7 @@ 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
12
  exports.default = { download, downloadString, downloadJSON };
13
- function download(url, file) {
13
+ function download(url, file, options) {
14
14
  return new Promise((resolve, reject) => {
15
15
  let protocol;
16
16
  if (url.startsWith('https://')) {
@@ -22,12 +22,12 @@ function download(url, file) {
22
22
  else {
23
23
  throw `Unknown protocol in url ${url}, expected one of "http" or "https"`;
24
24
  }
25
- const options = {
25
+ const reqOptions = {
26
26
  headers: {
27
27
  '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',
28
28
  },
29
29
  };
30
- protocol.get(url, options, function (res) {
30
+ protocol.get(url, reqOptions, function (res) {
31
31
  if (res.statusCode !== 200) {
32
32
  reject(`Request to ${url} returned with status code: ${res.statusCode}`);
33
33
  res.resume();
@@ -42,7 +42,7 @@ function download(url, file) {
42
42
  });
43
43
  }
44
44
  else {
45
- res.pipe(fs_1.default.createWriteStream(file));
45
+ res.pipe(fs_1.default.createWriteStream(file, { flags: (options === null || options === void 0 ? void 0 : options.append) ? 'a' : 'w' }));
46
46
  res.on('end', function () {
47
47
  resolve();
48
48
  });
@@ -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;IAC3C,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrD,IAAI,QAAqC,CAAC;QAE1C,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC/B,QAAQ,GAAG,eAAK,CAAC;SACjB;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACrC,QAAQ,GAAG,cAAI,CAAC;SAChB;aAAM;YACN,MAAM,2BAA2B,GAAG,qCAAqC,CAAC;SAC1E;QAED,MAAM,OAAO,GAAG;YACf,OAAO,EAAG;gBACT,YAAY,EAAG,iHAAiH;aAChI;SACD,CAAC;QAEF,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,UAAS,GAAG;YACtC,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE;gBAC3B,MAAM,CAAC,cAAc,GAAG,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;gBACzE,GAAG,CAAC,MAAM,EAAE,CAAC;aACb;YAED,MAAM,MAAM,GAAiB,EAAE,CAAC;YAEhC,IAAI,OAAO,IAAI,KAAK,WAAW,EAAE;gBAChC,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;aACH;iBAAM;gBACN,GAAG,CAAC,IAAI,CAAC,YAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;gBAErC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE;oBACb,OAAO,EAAE,CAAC;gBACX,CAAC,CAAC,CAAC;aACH;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;QACjC,MAAM,oBAAoB,QAAQ,EAAE,CAAC;KACrC;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;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;YAC/B,QAAQ,GAAG,eAAK,CAAC;SACjB;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACrC,QAAQ,GAAG,cAAI,CAAC;SAChB;aAAM;YACN,MAAM,2BAA2B,GAAG,qCAAqC,CAAC;SAC1E;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;gBAC3B,MAAM,CAAC,cAAc,GAAG,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;gBACzE,GAAG,CAAC,MAAM,EAAE,CAAC;aACb;YAED,MAAM,MAAM,GAAiB,EAAE,CAAC;YAEhC,IAAI,OAAO,IAAI,KAAK,WAAW,EAAE;gBAChC,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;aACH;iBAAM;gBACN,GAAG,CAAC,IAAI,CAAC,YAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,EAAC,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;aACH;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;QACjC,MAAM,oBAAoB,QAAQ,EAAE,CAAC;KACrC;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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anmiles/downloader",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Wrapper for downloading data as string, buffer or complex types",
5
5
  "keywords": [
6
6
  "download",
@@ -12,10 +12,8 @@ jest.mock<Partial<typeof downloader>>('../downloader', () => ({
12
12
  downloadString : jest.fn().mockImplementation((...args: Parameters<typeof original.downloadString>) => original.downloadString(...args)),
13
13
  }));
14
14
 
15
- const request = emitter() as http.ClientRequest;
16
- const response = emitter() as http.IncomingMessage;
17
- response.pipe = jest.fn();
18
- response.resume = jest.fn();
15
+ let request: http.ClientRequest;
16
+ let response: http.IncomingMessage;
19
17
 
20
18
  function get(url: string | URL, options: https.RequestOptions, callback?: ((res: http.IncomingMessage) => void) | undefined): http.ClientRequest {
21
19
  if (callback) {
@@ -26,6 +24,12 @@ function get(url: string | URL, options: https.RequestOptions, callback?: ((res:
26
24
  }
27
25
 
28
26
  beforeEach(() => {
27
+ request = emitter() as typeof request;
28
+ response = emitter() as typeof response;
29
+
30
+ response.pipe = jest.fn();
31
+ response.resume = jest.fn();
32
+
29
33
  response.statusCode = 200;
30
34
  });
31
35
 
@@ -100,7 +104,7 @@ describe('src/lib/downloader', () => {
100
104
  expect(result).toEqual(Buffer.from([ 10, 11, 12, 20, 21, 22, 30, 31, 32 ]));
101
105
  });
102
106
 
103
- it('should pipe response stream to file if specified', async () => {
107
+ it('should pipe response stream to file if specified with write mode', async () => {
104
108
  const stream = {} as fs.WriteStream;
105
109
  const createWriteStreamSpy = jest.spyOn(fs, 'createWriteStream').mockReturnValue(stream);
106
110
  const promise = original.download('http://url', 'file');
@@ -109,7 +113,22 @@ describe('src/lib/downloader', () => {
109
113
  response.emit('data', new Uint8Array([ 30, 31, 32 ]));
110
114
  response.emit('end');
111
115
  const result = await promise;
112
- expect(createWriteStreamSpy).toHaveBeenCalledWith('file');
116
+ expect(createWriteStreamSpy).toHaveBeenCalledWith('file', { flags : 'w' });
117
+ expect(response.pipe).toHaveBeenCalledWith(stream);
118
+ expect(result).toEqual(undefined);
119
+ createWriteStreamSpy.mockRestore();
120
+ });
121
+
122
+ it('should pipe response stream to file if specified with append mode', async () => {
123
+ const stream = {} as fs.WriteStream;
124
+ const createWriteStreamSpy = jest.spyOn(fs, 'createWriteStream').mockReturnValue(stream);
125
+ const promise = original.download('http://url', 'file', { append : true });
126
+ response.emit('data', new Uint8Array([ 10, 11, 12 ]));
127
+ response.emit('data', new Uint8Array([ 20, 21, 22 ]));
128
+ response.emit('data', new Uint8Array([ 30, 31, 32 ]));
129
+ response.emit('end');
130
+ const result = await promise;
131
+ expect(createWriteStreamSpy).toHaveBeenCalledWith('file', { flags : 'a' });
113
132
  expect(response.pipe).toHaveBeenCalledWith(stream);
114
133
  expect(result).toEqual(undefined);
115
134
  createWriteStreamSpy.mockRestore();
@@ -11,8 +11,8 @@ export default { download, downloadString, downloadJSON };
11
11
  type BufferEncoding = Parameters<Buffer['toString']>[0];
12
12
 
13
13
  function download(url: string): Promise<Buffer>;
14
- function download(url: string, file: string): Promise<void>;
15
- function download(url: string, file?: string): Promise<Buffer | void> {
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
16
  return new Promise<Buffer | void>((resolve, reject) => {
17
17
  let protocol : typeof https | typeof http;
18
18
 
@@ -24,13 +24,13 @@ function download(url: string, file?: string): Promise<Buffer | void> {
24
24
  throw `Unknown protocol in url ${url}, expected one of "http" or "https"`;
25
25
  }
26
26
 
27
- const options = {
27
+ const reqOptions = {
28
28
  headers : {
29
29
  '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',
30
30
  },
31
31
  };
32
32
 
33
- protocol.get(url, options, function(res) {
33
+ protocol.get(url, reqOptions, function(res) {
34
34
  if (res.statusCode !== 200) {
35
35
  reject(`Request to ${url} returned with status code: ${res.statusCode}`);
36
36
  res.resume();
@@ -47,7 +47,7 @@ function download(url: string, file?: string): Promise<Buffer | void> {
47
47
  resolve(Buffer.concat(chunks));
48
48
  });
49
49
  } else {
50
- res.pipe(fs.createWriteStream(file));
50
+ res.pipe(fs.createWriteStream(file, { flags : options?.append ? 'a' : 'w' }));
51
51
 
52
52
  res.on('end', function() {
53
53
  resolve();