@ezs/basics 2.0.0 → 2.1.1
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 +25 -0
- package/README.md +72 -0
- package/lib/fetch.js +74 -0
- package/lib/index.js +3 -0
- package/lib/obj-columns.js +53 -0
- package/lib/skos-object.js +73 -0
- package/lib/txt-inflection.js +66 -0
- package/lib/url-connect.js +3 -1
- package/lib/url-pager.js +179 -0
- package/lib/utils.js +18 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.1.1](https://github.com/Inist-CNRS/ezs/compare/@ezs/basics@2.1.0...@ezs/basics@2.1.1) (2023-05-12)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @ezs/basics
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [2.1.0](https://github.com/Inist-CNRS/ezs/compare/@ezs/basics@2.0.0...@ezs/basics@2.1.0) (2023-04-12)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* 🐛 improve coverage ([1173137](https://github.com/Inist-CNRS/ezs/commit/1173137e5a2cd6f1f6bfda8ad2a89720ae991e91))
|
|
20
|
+
* 🐛 missing files ([cd091ac](https://github.com/Inist-CNRS/ezs/commit/cd091acd91a6b0042e6c0e1b9cfef87e64126007))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* 🎸 add [TXTInflection] ([880b2bc](https://github.com/Inist-CNRS/ezs/commit/880b2bc4795f8bfb51fe11803cebfe38d2097487))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
6
31
|
# [2.0.0](https://github.com/Inist-CNRS/ezs/compare/@ezs/basics@1.24.0...@ezs/basics@2.0.0) (2023-03-29)
|
|
7
32
|
|
|
8
33
|
|
package/README.md
CHANGED
|
@@ -23,11 +23,13 @@ npm install @ezs/basics
|
|
|
23
23
|
- [INIString](#inistring)
|
|
24
24
|
- [JSONParse](#jsonparse)
|
|
25
25
|
- [JSONString](#jsonstring)
|
|
26
|
+
- [OBJColumns](#objcolumns)
|
|
26
27
|
- [OBJCount](#objcount)
|
|
27
28
|
- [OBJFlatten](#objflatten)
|
|
28
29
|
- [OBJNamespaces](#objnamespaces)
|
|
29
30
|
- [OBJStandardize](#objstandardize)
|
|
30
31
|
- [TXTConcat](#txtconcat)
|
|
32
|
+
- [TXTInflection](#txtinflection)
|
|
31
33
|
- [TXTObject](#txtobject)
|
|
32
34
|
- [TXTParse](#txtparse)
|
|
33
35
|
- [TXTSentences](#txtsentences)
|
|
@@ -391,6 +393,38 @@ Output:
|
|
|
391
393
|
|
|
392
394
|
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
|
|
393
395
|
|
|
396
|
+
### OBJColumns
|
|
397
|
+
|
|
398
|
+
Take an `Object` and flatten it to get only one level of keys.
|
|
399
|
+
|
|
400
|
+
<caption>Input:</caption>
|
|
401
|
+
|
|
402
|
+
```json
|
|
403
|
+
[{
|
|
404
|
+
"foo": {
|
|
405
|
+
"hello": "world"
|
|
406
|
+
},
|
|
407
|
+
"bar": "anything else",
|
|
408
|
+
"baz": 1
|
|
409
|
+
}]
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
<caption>Output:</caption>
|
|
413
|
+
|
|
414
|
+
```json
|
|
415
|
+
[{
|
|
416
|
+
"foo": "{\"hello\":\"world\"}",
|
|
417
|
+
"bar": "anything else",
|
|
418
|
+
"baz": 1
|
|
419
|
+
}]
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
#### Parameters
|
|
423
|
+
|
|
424
|
+
- `none` **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)**
|
|
425
|
+
|
|
426
|
+
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**
|
|
427
|
+
|
|
394
428
|
### OBJCount
|
|
395
429
|
|
|
396
430
|
Count how many objects are received, and yield the total.
|
|
@@ -557,6 +591,43 @@ Output:
|
|
|
557
591
|
|
|
558
592
|
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
|
|
559
593
|
|
|
594
|
+
### TXTInflection
|
|
595
|
+
|
|
596
|
+
- **See: <https://www.npmjs.com/package/inflection>
|
|
597
|
+
**
|
|
598
|
+
|
|
599
|
+
Take a `String` and inflect it with or more transformers from this list
|
|
600
|
+
pluralize, singularize, camelize, underscore, humanize, capitalize,
|
|
601
|
+
dasherize, titleize, demodulize, tableize, classify, foreign_key, ordinalize
|
|
602
|
+
|
|
603
|
+
Input:
|
|
604
|
+
|
|
605
|
+
```json
|
|
606
|
+
{ "id": 1, "value": "all job" }
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Script:
|
|
610
|
+
|
|
611
|
+
```ini
|
|
612
|
+
[TXTInflection]
|
|
613
|
+
transform = pluralize
|
|
614
|
+
transform = capitalize
|
|
615
|
+
transform = dasherize
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Output:
|
|
619
|
+
|
|
620
|
+
```json
|
|
621
|
+
{ "id": 1, "value": "All-jobs" }
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
#### Parameters
|
|
625
|
+
|
|
626
|
+
- `path` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** path of the field to segment (optional, default `"value"`)
|
|
627
|
+
- `transform` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** name of a transformer
|
|
628
|
+
|
|
629
|
+
Returns **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>**
|
|
630
|
+
|
|
560
631
|
### TXTObject
|
|
561
632
|
|
|
562
633
|
Take an array of values and generate an array containing objects with the
|
|
@@ -657,6 +728,7 @@ read to be buffered and sent to the server (n times)
|
|
|
657
728
|
- `timeout` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Timeout in milliseconds (optional, default `1000`)
|
|
658
729
|
- `noerror` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Ignore all errors (optional, default `false`)
|
|
659
730
|
- `retries` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** The maximum amount of times to retry the connection (optional, default `5`)
|
|
731
|
+
- `encoder` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The statement to encode each chunk to a string (optional, default `dump`)
|
|
660
732
|
|
|
661
733
|
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**
|
|
662
734
|
|
package/lib/fetch.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = fetch;
|
|
7
|
+
|
|
8
|
+
var _crossFetch = _interopRequireDefault(require("cross-fetch"));
|
|
9
|
+
|
|
10
|
+
var _proxyFromEnv = require("proxy-from-env");
|
|
11
|
+
|
|
12
|
+
var _http = _interopRequireDefault(require("http"));
|
|
13
|
+
|
|
14
|
+
var _https = _interopRequireDefault(require("https"));
|
|
15
|
+
|
|
16
|
+
var _betterHttpsProxyAgent = require("better-https-proxy-agent");
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
const DefaultOptions = {
|
|
21
|
+
keepAlive: true,
|
|
22
|
+
timeout: 1000,
|
|
23
|
+
keepAliveMsecs: 500,
|
|
24
|
+
maxSockets: 200,
|
|
25
|
+
maxFreeSockets: 5,
|
|
26
|
+
maxCachedSessions: 500
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const chooseAgent = (parsedURL, options) => {
|
|
30
|
+
const proxyurl = (0, _proxyFromEnv.getProxyForUrl)(parsedURL.href);
|
|
31
|
+
|
|
32
|
+
if (proxyurl) {
|
|
33
|
+
const proxyRequestOptions = new URL(proxyurl);
|
|
34
|
+
return new _betterHttpsProxyAgent.Agent(options, proxyRequestOptions);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (parsedURL.protocol === 'https:') {
|
|
38
|
+
return new _https.default.Agent(options);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new _http.default.Agent(options);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function fetch(url, options) {
|
|
45
|
+
const opts = options || {};
|
|
46
|
+
const {
|
|
47
|
+
keepAlive,
|
|
48
|
+
timeout,
|
|
49
|
+
keepAliveMsecs,
|
|
50
|
+
maxSockets,
|
|
51
|
+
maxFreeSockets,
|
|
52
|
+
maxCachedSessions
|
|
53
|
+
} = { ...options,
|
|
54
|
+
...DefaultOptions
|
|
55
|
+
};
|
|
56
|
+
let agent = chooseAgent(new URL(url), {
|
|
57
|
+
keepAlive,
|
|
58
|
+
timeout,
|
|
59
|
+
keepAliveMsecs,
|
|
60
|
+
maxSockets,
|
|
61
|
+
maxFreeSockets,
|
|
62
|
+
maxCachedSessions
|
|
63
|
+
});
|
|
64
|
+
opts.agent = agent;
|
|
65
|
+
|
|
66
|
+
if (opts.signal) {
|
|
67
|
+
opts.signal.addEventListener('abort', () => {
|
|
68
|
+
agent.destroy();
|
|
69
|
+
agent = null;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (0, _crossFetch.default)(url, options);
|
|
74
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -23,6 +23,8 @@ var _txtParse = _interopRequireDefault(require("./txt-parse"));
|
|
|
23
23
|
|
|
24
24
|
var _txtSentences = _interopRequireDefault(require("./txt-sentences"));
|
|
25
25
|
|
|
26
|
+
var _txtInflection = _interopRequireDefault(require("./txt-inflection"));
|
|
27
|
+
|
|
26
28
|
var _xmlParse = _interopRequireDefault(require("./xml-parse"));
|
|
27
29
|
|
|
28
30
|
var _xmlString = _interopRequireDefault(require("./xml-string"));
|
|
@@ -75,6 +77,7 @@ const funcs = {
|
|
|
75
77
|
TXTObject: _txtObject.default,
|
|
76
78
|
TXTConcat: _txtConcat.default,
|
|
77
79
|
TXTSentences: _txtSentences.default,
|
|
80
|
+
TXTInflection: _txtInflection.default,
|
|
78
81
|
XMLParse: _xmlParse.default,
|
|
79
82
|
XMLString: _xmlString.default,
|
|
80
83
|
XMLConvert: _xmlConvert.default,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = OBJColumns;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Take an `Object` and flatten it to get only one level of keys.
|
|
10
|
+
*
|
|
11
|
+
* <caption>Input:</caption>
|
|
12
|
+
*
|
|
13
|
+
* ```json
|
|
14
|
+
* [{
|
|
15
|
+
* "foo": {
|
|
16
|
+
* "hello": "world"
|
|
17
|
+
* },
|
|
18
|
+
* "bar": "anything else",
|
|
19
|
+
* "baz": 1
|
|
20
|
+
* }]
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* <caption>Output:</caption>
|
|
24
|
+
*
|
|
25
|
+
* ```json
|
|
26
|
+
* [{
|
|
27
|
+
* "foo": "{\"hello\":\"world\"}",
|
|
28
|
+
* "bar": "anything else",
|
|
29
|
+
* "baz": 1
|
|
30
|
+
* }]
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @name OBJColumns
|
|
34
|
+
* @alias flatten
|
|
35
|
+
* @param {undefined} none
|
|
36
|
+
* @returns {Object}
|
|
37
|
+
*/
|
|
38
|
+
function OBJColumns(data, feed) {
|
|
39
|
+
if (this.isLast()) {
|
|
40
|
+
feed.close();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const obj = {};
|
|
45
|
+
Object.keys(data).sort((x, y) => x.localeCompare(y)).forEach(key => {
|
|
46
|
+
if (typeof data[key] === 'object') {
|
|
47
|
+
obj[key] = JSON.stringify(data[key]);
|
|
48
|
+
} else {
|
|
49
|
+
obj[key] = data[key];
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
feed.send(obj);
|
|
53
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
function Concept(data, feed) {
|
|
9
|
+
const obj = {};
|
|
10
|
+
Object.keys(data).forEach(key => {
|
|
11
|
+
const newkey = key.replace('skos$', '');
|
|
12
|
+
|
|
13
|
+
if (Array.isArray(data[key])) {
|
|
14
|
+
data[key].filter(x => x.xml$lang).forEach(item => {
|
|
15
|
+
const localkey = newkey.concat('@').concat(item.xml$lang);
|
|
16
|
+
obj[localkey] = item.$t;
|
|
17
|
+
});
|
|
18
|
+
} else if (data[key].rdf$resource && !obj[newkey]) {
|
|
19
|
+
obj[newkey] = data[key].rdf$resource;
|
|
20
|
+
} else if (data[key].rdf$resource && obj[newkey]) {
|
|
21
|
+
obj[newkey] = [obj[newkey], data[key].rdf$resource];
|
|
22
|
+
} else if (data[key].$t && data[key].xml$lang) {
|
|
23
|
+
const localkey = newkey.concat('@').concat(data[key].xml$lang);
|
|
24
|
+
obj[localkey] = data[key].$t;
|
|
25
|
+
} else if (data[key].$t && Array.isArray(obj[newkey])) {
|
|
26
|
+
obj[newkey].push(data[key].$t);
|
|
27
|
+
} else if (data[key].$t && obj[newkey]) {
|
|
28
|
+
obj[newkey] = [obj[newkey], data[key].$t];
|
|
29
|
+
} else if (data[key].$t && !obj[newkey]) {
|
|
30
|
+
obj[newkey] = data[key].$t;
|
|
31
|
+
} else if (typeof data[key] === 'object') {
|
|
32
|
+
obj[newkey] = (this.getIndex().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase();
|
|
33
|
+
let counter = 0;
|
|
34
|
+
Object.keys(data[key]).forEach(key2 => {
|
|
35
|
+
if (typeof data[key][key2] === 'object') {
|
|
36
|
+
data[key][key2].rdf$about = obj[newkey];
|
|
37
|
+
Concept.call(this, data[key][key2], feed);
|
|
38
|
+
counter += 1;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (counter === 0) {
|
|
43
|
+
delete obj[newkey];
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
obj[newkey] = data[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
feed.write(obj);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function SKOSObject(data, feed) {
|
|
53
|
+
if (this.isLast()) {
|
|
54
|
+
feed.close();
|
|
55
|
+
} else {
|
|
56
|
+
Concept.call(this, data, feed);
|
|
57
|
+
feed.end();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Take `Object` generated by XMLMapping & SKOS data and
|
|
62
|
+
* create a new basic object with only keys & values
|
|
63
|
+
*
|
|
64
|
+
* @name SKOSObject
|
|
65
|
+
* @param {undefined} none
|
|
66
|
+
* @returns {Object}
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
var _default = {
|
|
71
|
+
SKOSObject
|
|
72
|
+
};
|
|
73
|
+
exports.default = _default;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _lodash = _interopRequireDefault(require("lodash.get"));
|
|
9
|
+
|
|
10
|
+
var _inflection = require("inflection");
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
const transformer = transformations => str => str && typeof str === 'string' ? (0, _inflection.transform)(str, transformations) : str;
|
|
15
|
+
|
|
16
|
+
const TXTInflection = (data, feed, ctx) => {
|
|
17
|
+
if (ctx.isLast()) {
|
|
18
|
+
return feed.close();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const transformations = [].concat(ctx.getParam('transform', [])).filter(Boolean);
|
|
22
|
+
const path = ctx.getParam('path', 'value');
|
|
23
|
+
const value = (0, _lodash.default)(data, path, '');
|
|
24
|
+
const process = transformer(transformations);
|
|
25
|
+
const result = Array.isArray(value) ? value.map(item => process(item)) : process(value);
|
|
26
|
+
feed.write({ ...data,
|
|
27
|
+
[path]: result
|
|
28
|
+
});
|
|
29
|
+
return feed.end();
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Take a `String` and inflect it with or more transformers from this list
|
|
33
|
+
* pluralize, singularize, camelize, underscore, humanize, capitalize,
|
|
34
|
+
* dasherize, titleize, demodulize, tableize, classify, foreign_key, ordinalize
|
|
35
|
+
*
|
|
36
|
+
* Input:
|
|
37
|
+
*
|
|
38
|
+
* ```json
|
|
39
|
+
* { "id": 1, "value": "all job" }
|
|
40
|
+
* ```
|
|
41
|
+
* Script:
|
|
42
|
+
* ```ini
|
|
43
|
+
* [TXTInflection]
|
|
44
|
+
* transform = pluralize
|
|
45
|
+
* transform = capitalize
|
|
46
|
+
* transform = dasherize
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* Output:
|
|
50
|
+
*
|
|
51
|
+
* ```json
|
|
52
|
+
* { "id": 1, "value": "All-jobs" }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @name TXTInflection
|
|
56
|
+
* @param {String} [path="value"] path of the field to segment
|
|
57
|
+
* @param {String} [transform] name of a transformer
|
|
58
|
+
* @returns {String[]}
|
|
59
|
+
* @see https://www.npmjs.com/package/inflection
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
var _default = {
|
|
64
|
+
TXTInflection
|
|
65
|
+
};
|
|
66
|
+
exports.default = _default;
|
package/lib/url-connect.js
CHANGED
|
@@ -43,6 +43,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
43
43
|
* @param {Number} [timeout=1000] Timeout in milliseconds
|
|
44
44
|
* @param {Boolean} [noerror=false] Ignore all errors
|
|
45
45
|
* @param {Number} [retries=5] The maximum amount of times to retry the connection
|
|
46
|
+
* @param {String} [encoder=dump] The statement to encode each chunk to a string
|
|
46
47
|
* @returns {Object}
|
|
47
48
|
*/
|
|
48
49
|
async function URLConnect(data, feed) {
|
|
@@ -50,6 +51,7 @@ async function URLConnect(data, feed) {
|
|
|
50
51
|
const retries = Number(this.getParam('retries', 5));
|
|
51
52
|
const noerror = Boolean(this.getParam('noerror', false));
|
|
52
53
|
const json = this.getParam('json', true);
|
|
54
|
+
const encoder = this.getParam('encoder', 'dump');
|
|
53
55
|
const {
|
|
54
56
|
ezs
|
|
55
57
|
} = this;
|
|
@@ -61,7 +63,7 @@ async function URLConnect(data, feed) {
|
|
|
61
63
|
const output = ezs.createStream(ezs.objectMode());
|
|
62
64
|
this.whenFinish = feed.flow(output);
|
|
63
65
|
(0, _streamWrite.default)(this.input, data, () => feed.end());
|
|
64
|
-
const streamIn = this.input.pipe(ezs(
|
|
66
|
+
const streamIn = this.input.pipe(ezs(encoder));
|
|
65
67
|
let bodyIn;
|
|
66
68
|
|
|
67
69
|
if (retries === 1) {
|
package/lib/url-pager.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = URLPager;
|
|
7
|
+
|
|
8
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
9
|
+
|
|
10
|
+
var _url = require("url");
|
|
11
|
+
|
|
12
|
+
var _nodeAbortController = _interopRequireDefault(require("node-abort-controller"));
|
|
13
|
+
|
|
14
|
+
var _lodash = _interopRequireDefault(require("lodash.get"));
|
|
15
|
+
|
|
16
|
+
var _parseHeaders = _interopRequireDefault(require("parse-headers"));
|
|
17
|
+
|
|
18
|
+
var _asyncRetry = _interopRequireDefault(require("async-retry"));
|
|
19
|
+
|
|
20
|
+
var _request = _interopRequireDefault(require("./request"));
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Take `Object` as parameters of URL, throw each chunk from the result
|
|
26
|
+
*
|
|
27
|
+
*
|
|
28
|
+
* Input:
|
|
29
|
+
*
|
|
30
|
+
* ```json
|
|
31
|
+
* [{"q": "a"}]
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Script:
|
|
35
|
+
*
|
|
36
|
+
* ```ini
|
|
37
|
+
* [URLPager]
|
|
38
|
+
* url = https://api.search.net
|
|
39
|
+
* path = total
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Output:
|
|
43
|
+
*
|
|
44
|
+
* ```json
|
|
45
|
+
* [
|
|
46
|
+
* {
|
|
47
|
+
* "q": "a",
|
|
48
|
+
* "total": 22
|
|
49
|
+
* "offset": 0,
|
|
50
|
+
* "pageNumber": 1,
|
|
51
|
+
* "totalPages", 3,
|
|
52
|
+
* "maxPages": 1000,
|
|
53
|
+
* "limit": 10
|
|
54
|
+
* },
|
|
55
|
+
* {
|
|
56
|
+
* "q": "a",
|
|
57
|
+
* "total": 22
|
|
58
|
+
* "offset": 10,
|
|
59
|
+
* "pageNumber": 2,
|
|
60
|
+
* "totalPages", 3,
|
|
61
|
+
* "maxPages": 1000,
|
|
62
|
+
* "limit": 10
|
|
63
|
+
* },
|
|
64
|
+
* {
|
|
65
|
+
* "q": "a",
|
|
66
|
+
* "total": 22
|
|
67
|
+
* "offset": 20,
|
|
68
|
+
* "pageNumber": 3,
|
|
69
|
+
* "totalPages", 3,
|
|
70
|
+
* "maxPages": 1000,
|
|
71
|
+
* "limit": 10
|
|
72
|
+
* }
|
|
73
|
+
* ]
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* #### Example with URLs
|
|
77
|
+
*
|
|
78
|
+
* Input:
|
|
79
|
+
*
|
|
80
|
+
* ```json
|
|
81
|
+
* [
|
|
82
|
+
* "https://httpbin.org/get?a=a",
|
|
83
|
+
* "https://httpbin.org/get?a=b",
|
|
84
|
+
* "https://httpbin.org/get?a=c"
|
|
85
|
+
* ]
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* Script:
|
|
89
|
+
*
|
|
90
|
+
* ```ini
|
|
91
|
+
* [URLPager]
|
|
92
|
+
* path = .args
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* Output:
|
|
96
|
+
*
|
|
97
|
+
* ```json
|
|
98
|
+
* [{"a": "a"}, {"a": "b"}, {"a": "c" }]
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @name URLPager
|
|
102
|
+
* @param {String} [url] URL to fetch (by default input string is taken)
|
|
103
|
+
* @param {String} [path=total] choose the path to find the number of result
|
|
104
|
+
* @param {Number} [timeout=1000] Timeout in milliseconds
|
|
105
|
+
* @param {Boolean} [noerror=false] Ignore all errors, the target field will remain undefined
|
|
106
|
+
* @param {Number} [retries=5] The maximum amount of times to retry the connection
|
|
107
|
+
* @returns {Object}
|
|
108
|
+
*/
|
|
109
|
+
async function URLPager(data, feed) {
|
|
110
|
+
if (this.isLast()) {
|
|
111
|
+
return feed.close();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const url = this.getParam('url');
|
|
115
|
+
const path = this.getParam('path', 'total');
|
|
116
|
+
const limit = Number(this.getParam('limit', 10));
|
|
117
|
+
const maxPages = Number(this.getParam('maxPages', 1000));
|
|
118
|
+
const retries = Number(this.getParam('retries', 5));
|
|
119
|
+
const noerror = Boolean(this.getParam('noerror', false));
|
|
120
|
+
const timeout = Number(this.getParam('timeout')) || 1000;
|
|
121
|
+
const headers = (0, _parseHeaders.default)([].concat(this.getParam('header')).filter(Boolean).join('\n'));
|
|
122
|
+
const cURL = new _url.URL(url || data);
|
|
123
|
+
const controller = new _nodeAbortController.default();
|
|
124
|
+
const parameters = {
|
|
125
|
+
timeout,
|
|
126
|
+
headers,
|
|
127
|
+
signal: controller.signal
|
|
128
|
+
};
|
|
129
|
+
const options = {
|
|
130
|
+
retries
|
|
131
|
+
};
|
|
132
|
+
cURL.search = new _url.URLSearchParams(data);
|
|
133
|
+
|
|
134
|
+
const onError = e => {
|
|
135
|
+
controller.abort();
|
|
136
|
+
|
|
137
|
+
if (noerror) {
|
|
138
|
+
(0, _debug.default)('ezs')(`Ignore item #${this.getIndex()} [URLPager] <${e}>`);
|
|
139
|
+
return feed.send(data);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
(0, _debug.default)('ezs')(`Break item #${this.getIndex()} [URLPager] <${e}>`);
|
|
143
|
+
return feed.send(e);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const response = await (0, _asyncRetry.default)((0, _request.default)(cURL.href, parameters), options);
|
|
148
|
+
const json = await response.json();
|
|
149
|
+
const total = (0, _lodash.default)(json, path);
|
|
150
|
+
|
|
151
|
+
if (total === 0) {
|
|
152
|
+
return onError(new Error('No result.'));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (total === undefined) {
|
|
156
|
+
return onError(new Error('Unexpected response.'));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let totalPages = Math.ceil(json.total / limit);
|
|
160
|
+
|
|
161
|
+
if (totalPages > maxPages) {
|
|
162
|
+
totalPages = maxPages;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (let pageNumber = 1; pageNumber <= totalPages; pageNumber += 1) {
|
|
166
|
+
feed.write({ ...data,
|
|
167
|
+
offset: (pageNumber - 1) * limit,
|
|
168
|
+
pageNumber,
|
|
169
|
+
totalPages,
|
|
170
|
+
maxPages,
|
|
171
|
+
limit
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
feed.end();
|
|
176
|
+
} catch (e) {
|
|
177
|
+
onError(e);
|
|
178
|
+
}
|
|
179
|
+
}
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.writeTo = void 0;
|
|
7
|
+
|
|
8
|
+
const writeTo = function writeTo(stream, data, cb) {
|
|
9
|
+
if (!stream.write(data)) {
|
|
10
|
+
stream.once('drain', cb);
|
|
11
|
+
} else {
|
|
12
|
+
process.nextTick(cb);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
exports.writeTo = writeTo;
|
|
17
|
+
var _default = writeTo;
|
|
18
|
+
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezs/basics",
|
|
3
3
|
"description": "Basics statements for EZS",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"author": "Nicolas Thouvenin <nthouvenin@gmail.com>",
|
|
6
6
|
"bugs": "https://github.com/Inist-CNRS/ezs/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"from": "0.1.7",
|
|
16
16
|
"get-stream": "6.0.1",
|
|
17
17
|
"higher-path": "1.0.0",
|
|
18
|
+
"inflection": "2.0.1",
|
|
18
19
|
"lodash.escaperegexp": "4.1.2",
|
|
19
20
|
"lodash.get": "4.4.2",
|
|
20
21
|
"lodash.mapkeys": "4.6.0",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"directories": {
|
|
40
41
|
"test": "test"
|
|
41
42
|
},
|
|
42
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "54e12b40d2cd6ccb6754f06ab5cae566c60bb3a9",
|
|
43
44
|
"homepage": "https://github.com/Inist-CNRS/ezs/tree/master/packages/basics#readme",
|
|
44
45
|
"keywords": [
|
|
45
46
|
"ezs"
|