@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 +13 -9
- package/lib/readFile.js +32 -3
- package/modules/endnoteXml.js +1 -0
- package/modules/interface.js +1 -0
- package/modules/json.js +3 -2
- package/modules/medline.js +1 -0
- package/modules/ris.js +1 -0
- package/package.json +1 -1
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 = {
|
|
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
|
-
|
|
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
|
}
|
package/modules/endnoteXml.js
CHANGED
|
@@ -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
|
}
|
package/modules/interface.js
CHANGED
|
@@ -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
|
}
|
package/modules/medline.js
CHANGED
|
@@ -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
|