@iebh/reflib 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/README.md CHANGED
@@ -193,6 +193,19 @@ reflib.readFile('./data/json/json1.json')
193
193
  .then(refs => /* Do something with Ref collection */)
194
194
  ```
195
195
 
196
+ An emitter is available to track progress while reading. Note that due to the chainable nature of promises the first return contains the `emitter` key only:
197
+
198
+ ```javascript
199
+ let reader = reflib.readFile('./data/json/json1.json');
200
+
201
+ reader.emitter
202
+ .on('progress', ({readBytes, totalSize, refsFound}) => /* Report progress somehow */);
203
+ .on('end', ({refsFound}) => /* Report progress somehow */);
204
+
205
+ reader
206
+ .then(refs => /* Do something with Ref collection */)
207
+ ```
208
+
196
209
  uploadFile(options)
197
210
  ===================
198
211
  Available: Browser
@@ -257,12 +270,3 @@ Credits
257
270
  =======
258
271
  Developed for the [Bond University Institute for Evidence-Based Healthcare](https://iebh.bond.edu.au).
259
272
  Please contact [the author](mailto:matt_carter@bond.edu.au) with any issues.
260
-
261
-
262
- TODO
263
- ====
264
- - [x] Basic parsing iterfaces
265
- - [ ] "progress" emitter for files
266
- - [x] `.uploadFile()` browser compatibility
267
- - [ ] `.downloadFile()` browser compatibility
268
- - [x] `setup()` functions per module to avoid things like map calculations unless the module is actually needed
package/lib/readFile.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {createReadStream} from 'node:fs';
2
+ import Emitter from '../shared/emitter.js';
2
3
  import {stat} from 'node:fs/promises';
3
4
  import {identifyFormat} from './identifyFormat.js';
4
5
  import {readStream} from './readStream.js';
@@ -9,16 +10,26 @@ import {readStream} from './readStream.js';
9
10
  * @param {string} path The file path to parse
10
11
  * @param {Object} [options] Additional options to pass to the parser
11
12
  * @param {string} [options.module] The module to use if overriding from the file path
13
+ *
12
14
  * @returns {Promise<Array>} An eventual array of all references parsed from the file
15
+ * @property {EventEmitter} emitter An event emitter which will fire the below events
16
+ *
17
+ * @fires progress Emitted as `({readBytes: Number, totalSize: Number, refsFound: Number})`
18
+ * @fires end Emitted as `({refsFound: Number})` when the reading operation has completed
13
19
  */
14
20
  export function readFile(path, options) {
15
- let settings = {...options};
21
+ let settings = {
22
+ progressTotal: false,
23
+ ...options,
24
+ };
16
25
  let module = options?.module || identifyFormat(path)?.id;
17
26
  if (!module) throw new Error(`Unable to identify reference library format for file path "${path}"`);
18
27
 
19
- return stat(path)
28
+ let promiseEmitter = Promise.resolve()
29
+ .then(()=> stat(path))
20
30
  .then(stats => new Promise((resolve, reject) => {
21
- let refs = [];
31
+ let refs = []; // eslint-disable-line no-unused-vars
32
+
22
33
  readStream(
23
34
  module,
24
35
  createReadStream(path),
@@ -30,5 +41,23 @@ export function readFile(path, options) {
30
41
  .on('end', ()=> resolve(refs))
31
42
  .on('error', reject)
32
43
  .on('ref', ref => refs.push(ref))
44
+ .on('progress', readBytes => promiseEmitter.emitter.emit('progress', {
45
+ readBytes,
46
+ totalSize: stats.size,
47
+ refsFound: refs.length,
48
+ }))
33
49
  }))
50
+ .then(refs => {
51
+ promiseEmitter.emitter.emit('end', {refsFound: refs.length})
52
+ return refs;
53
+ })
54
+
55
+ // Extend our base promise with an emitter subkey
56
+ return Object.defineProperties(promiseEmitter, {
57
+ emitter: {
58
+ value: Emitter(),
59
+ enumerable: true,
60
+ writable: false,
61
+ },
62
+ });
34
63
  }
@@ -108,6 +108,7 @@ export function readStream(stream) {
108
108
  if (typeof stream.pipe === 'function') {
109
109
  // We are on the node.js client
110
110
  let parser = new XMLParser(parserOptions);
111
+ stream.on('data', ()=> emitter.emit('progress', stream.bytesRead))
111
112
  stream.pipe(parser)
112
113
  return;
113
114
  }
@@ -14,6 +14,7 @@
14
14
  * @emits ref Emitted with a single ref object when found
15
15
  * @emits end Emitted when parsing has completed
16
16
  * @emits error Emitted when an error has been raised
17
+ * @emits progress Emitted as (bytesRead) when reading a stream
17
18
  */
18
19
  export function readStream(stream, options) {
19
20
  // Stub
package/modules/json.js CHANGED
@@ -9,7 +9,8 @@ export function readStream(stream) {
9
9
  let emitter = Emitter();
10
10
 
11
11
  // Queue up the parser in the next tick (so we can return the emitter first)
12
- setTimeout(()=>
12
+ setTimeout(()=> {
13
+ stream.on('data', ()=> emitter.emit('progress', stream.bytesRead));
13
14
  stream.pipe(
14
15
  JSONStream.parse('*')
15
16
  .on('data', ref => emitter.emit('ref', {
@@ -19,7 +20,7 @@ export function readStream(stream) {
19
20
  .on('end', ()=> emitter.emit('end'))
20
21
  .on('error', emitter.emit.bind('error'))
21
22
  )
22
- );
23
+ });
23
24
 
24
25
  return emitter;
25
26
  }
@@ -122,6 +122,7 @@ export function readStream(stream, options) {
122
122
  setTimeout(()=> {
123
123
  stream
124
124
  .on('data', chunkBuffer => {
125
+ emitter.emit('progress', stream.bytesRead);
125
126
  buffer += chunkBuffer.toString(); // Append incomming data to the partial-buffer we're holding in memory
126
127
 
127
128
  let bufferCrop = 0; // How many bytes to shift off the front of the buffer based on the last full reference we saw, should end up at the last byte offset of buffer that is valid to shift-truncate to
package/modules/ris.js CHANGED
@@ -21,6 +21,7 @@ export function readStream(stream, options) {
21
21
  setTimeout(()=> {
22
22
  stream
23
23
  .on('data', chunkBuffer => {
24
+ emitter.emit('progress', stream.bytesRead);
24
25
  buffer += chunkBuffer.toString(); // Append incomming data to the partial-buffer we're holding in memory
25
26
 
26
27
  let bufferCrop = 0; // How many bytes to shift off the front of the buffer based on the last full reference we saw, should end up at the last byte offset of buffer that is valid to shift-truncate to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iebh/reflib",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Reference / Citation reference library utilities",
5
5
  "scripts": {
6
6
  "lint": "eslint lib modules shared test",