@twin.org/data-processing-extractors 0.0.2-next.2 → 0.0.2-next.4
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/dist/cjs/index.cjs
CHANGED
|
@@ -16,7 +16,7 @@ class JsonPathExtractorConnector {
|
|
|
16
16
|
/**
|
|
17
17
|
* Runtime name for the class.
|
|
18
18
|
*/
|
|
19
|
-
CLASS_NAME = "JsonPathExtractorConnector";
|
|
19
|
+
static CLASS_NAME = "JsonPathExtractorConnector";
|
|
20
20
|
/**
|
|
21
21
|
* Extracts data from the provided input.
|
|
22
22
|
* @param data The object to extract from.
|
|
@@ -24,8 +24,8 @@ class JsonPathExtractorConnector {
|
|
|
24
24
|
* @returns The extracted data.
|
|
25
25
|
*/
|
|
26
26
|
async extract(data, rules) {
|
|
27
|
-
core.Guards.object(
|
|
28
|
-
core.Guards.array(
|
|
27
|
+
core.Guards.object(JsonPathExtractorConnector.CLASS_NAME, "data", data);
|
|
28
|
+
core.Guards.array(JsonPathExtractorConnector.CLASS_NAME, "rules", rules);
|
|
29
29
|
const outputObject = {};
|
|
30
30
|
for (const extractRule of rules) {
|
|
31
31
|
this.extractValue(data, extractRule, outputObject);
|
|
@@ -42,14 +42,44 @@ class JsonPathExtractorConnector {
|
|
|
42
42
|
extractValue(jsonObject, rule, outputObject) {
|
|
43
43
|
try {
|
|
44
44
|
const jsonNodes = jsonP3.query(rule.source, jsonObject);
|
|
45
|
+
const ruleParts = rule.source.split(".");
|
|
46
|
+
// Group values by their target path to handle multiple results correctly
|
|
47
|
+
const pathToValues = {};
|
|
45
48
|
for (const jsonNode of jsonNodes) {
|
|
46
49
|
const retainPathDepth = rule.retainPathDepth ?? 0;
|
|
47
50
|
const fullTargetPath = `${rule.target}${retainPathDepth > 0 ? `.${jsonNode.location.slice(-retainPathDepth).join(".")}` : ""}`;
|
|
48
|
-
|
|
51
|
+
const coercedValue = core.Coerce.byType(jsonNode.value, rule.coerce);
|
|
52
|
+
const nodeLocation = jsonNode.location;
|
|
53
|
+
// If the last part of the location before the target property is an integer
|
|
54
|
+
// and the corresponding rule part ends with [*], we are dealing with an array
|
|
55
|
+
const isArray = nodeLocation.length > 1 &&
|
|
56
|
+
ruleParts.length > 1 &&
|
|
57
|
+
core.Is.integer(nodeLocation[nodeLocation.length - 2]) &&
|
|
58
|
+
ruleParts[nodeLocation.length - 2].endsWith("[*]");
|
|
59
|
+
if (isArray) {
|
|
60
|
+
// If the value is set and not currently an array, convert it to one
|
|
61
|
+
if (!core.Is.empty(pathToValues[fullTargetPath]) && !core.Is.array(pathToValues[fullTargetPath])) {
|
|
62
|
+
pathToValues[fullTargetPath] = [pathToValues[fullTargetPath]];
|
|
63
|
+
}
|
|
64
|
+
// Make sure the array exists
|
|
65
|
+
pathToValues[fullTargetPath] ??= [];
|
|
66
|
+
// And add the new value
|
|
67
|
+
if (core.Is.array(pathToValues[fullTargetPath])) {
|
|
68
|
+
pathToValues[fullTargetPath].push(coercedValue);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// For single values, just set the value directly
|
|
73
|
+
pathToValues[fullTargetPath] = coercedValue;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Set the values in the output object
|
|
77
|
+
for (const [path, values] of Object.entries(pathToValues)) {
|
|
78
|
+
core.ObjectHelper.propertySet(outputObject, path, values);
|
|
49
79
|
}
|
|
50
80
|
}
|
|
51
81
|
catch (err) {
|
|
52
|
-
throw new core.GeneralError(
|
|
82
|
+
throw new core.GeneralError(JsonPathExtractorConnector.CLASS_NAME, "invalidRule", {
|
|
53
83
|
rule: rule.source,
|
|
54
84
|
reason: core.BaseError.fromError(err).message
|
|
55
85
|
});
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Guards,
|
|
1
|
+
import { Guards, Coerce, Is, ObjectHelper, GeneralError, BaseError } from '@twin.org/core';
|
|
2
2
|
import { query } from 'json-p3';
|
|
3
3
|
|
|
4
4
|
// Copyright 2024 IOTA Stiftung.
|
|
@@ -14,7 +14,7 @@ class JsonPathExtractorConnector {
|
|
|
14
14
|
/**
|
|
15
15
|
* Runtime name for the class.
|
|
16
16
|
*/
|
|
17
|
-
CLASS_NAME = "JsonPathExtractorConnector";
|
|
17
|
+
static CLASS_NAME = "JsonPathExtractorConnector";
|
|
18
18
|
/**
|
|
19
19
|
* Extracts data from the provided input.
|
|
20
20
|
* @param data The object to extract from.
|
|
@@ -22,8 +22,8 @@ class JsonPathExtractorConnector {
|
|
|
22
22
|
* @returns The extracted data.
|
|
23
23
|
*/
|
|
24
24
|
async extract(data, rules) {
|
|
25
|
-
Guards.object(
|
|
26
|
-
Guards.array(
|
|
25
|
+
Guards.object(JsonPathExtractorConnector.CLASS_NAME, "data", data);
|
|
26
|
+
Guards.array(JsonPathExtractorConnector.CLASS_NAME, "rules", rules);
|
|
27
27
|
const outputObject = {};
|
|
28
28
|
for (const extractRule of rules) {
|
|
29
29
|
this.extractValue(data, extractRule, outputObject);
|
|
@@ -40,14 +40,44 @@ class JsonPathExtractorConnector {
|
|
|
40
40
|
extractValue(jsonObject, rule, outputObject) {
|
|
41
41
|
try {
|
|
42
42
|
const jsonNodes = query(rule.source, jsonObject);
|
|
43
|
+
const ruleParts = rule.source.split(".");
|
|
44
|
+
// Group values by their target path to handle multiple results correctly
|
|
45
|
+
const pathToValues = {};
|
|
43
46
|
for (const jsonNode of jsonNodes) {
|
|
44
47
|
const retainPathDepth = rule.retainPathDepth ?? 0;
|
|
45
48
|
const fullTargetPath = `${rule.target}${retainPathDepth > 0 ? `.${jsonNode.location.slice(-retainPathDepth).join(".")}` : ""}`;
|
|
46
|
-
|
|
49
|
+
const coercedValue = Coerce.byType(jsonNode.value, rule.coerce);
|
|
50
|
+
const nodeLocation = jsonNode.location;
|
|
51
|
+
// If the last part of the location before the target property is an integer
|
|
52
|
+
// and the corresponding rule part ends with [*], we are dealing with an array
|
|
53
|
+
const isArray = nodeLocation.length > 1 &&
|
|
54
|
+
ruleParts.length > 1 &&
|
|
55
|
+
Is.integer(nodeLocation[nodeLocation.length - 2]) &&
|
|
56
|
+
ruleParts[nodeLocation.length - 2].endsWith("[*]");
|
|
57
|
+
if (isArray) {
|
|
58
|
+
// If the value is set and not currently an array, convert it to one
|
|
59
|
+
if (!Is.empty(pathToValues[fullTargetPath]) && !Is.array(pathToValues[fullTargetPath])) {
|
|
60
|
+
pathToValues[fullTargetPath] = [pathToValues[fullTargetPath]];
|
|
61
|
+
}
|
|
62
|
+
// Make sure the array exists
|
|
63
|
+
pathToValues[fullTargetPath] ??= [];
|
|
64
|
+
// And add the new value
|
|
65
|
+
if (Is.array(pathToValues[fullTargetPath])) {
|
|
66
|
+
pathToValues[fullTargetPath].push(coercedValue);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// For single values, just set the value directly
|
|
71
|
+
pathToValues[fullTargetPath] = coercedValue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Set the values in the output object
|
|
75
|
+
for (const [path, values] of Object.entries(pathToValues)) {
|
|
76
|
+
ObjectHelper.propertySet(outputObject, path, values);
|
|
47
77
|
}
|
|
48
78
|
}
|
|
49
79
|
catch (err) {
|
|
50
|
-
throw new GeneralError(
|
|
80
|
+
throw new GeneralError(JsonPathExtractorConnector.CLASS_NAME, "invalidRule", {
|
|
51
81
|
rule: rule.source,
|
|
52
82
|
reason: BaseError.fromError(err).message
|
|
53
83
|
});
|
|
@@ -10,7 +10,7 @@ export declare class JsonPathExtractorConnector implements IDataExtractorConnect
|
|
|
10
10
|
/**
|
|
11
11
|
* Runtime name for the class.
|
|
12
12
|
*/
|
|
13
|
-
readonly CLASS_NAME: string;
|
|
13
|
+
static readonly CLASS_NAME: string;
|
|
14
14
|
/**
|
|
15
15
|
* Extracts data from the provided input.
|
|
16
16
|
* @param data The object to extract from.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @twin.org/data-processing-extractors - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.4](https://github.com/twinfoundation/data-processing/compare/data-processing-extractors-v0.0.2-next.3...data-processing-extractors-v0.0.2-next.4) (2025-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* supporting array usage ([#20](https://github.com/twinfoundation/data-processing/issues/20)) ([d2c68cd](https://github.com/twinfoundation/data-processing/commit/d2c68cd3983622586cc073377545d6416b87a827))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/data-processing-models bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
16
|
+
|
|
17
|
+
## [0.0.2-next.3](https://github.com/twinfoundation/data-processing/compare/data-processing-extractors-v0.0.2-next.2...data-processing-extractors-v0.0.2-next.3) (2025-10-09)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add validate-locales ([9af0874](https://github.com/twinfoundation/data-processing/commit/9af0874cd3f44a4cfca514dde8380f002e62337e))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/data-processing-models bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
30
|
+
|
|
3
31
|
## [0.0.2-next.2](https://github.com/twinfoundation/data-processing/compare/data-processing-extractors-v0.0.2-next.1...data-processing-extractors-v0.0.2-next.2) (2025-08-29)
|
|
4
32
|
|
|
5
33
|
|
|
@@ -28,14 +28,10 @@ The namespace supported by the data extractor connector.
|
|
|
28
28
|
|
|
29
29
|
### CLASS\_NAME
|
|
30
30
|
|
|
31
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
31
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
32
32
|
|
|
33
33
|
Runtime name for the class.
|
|
34
34
|
|
|
35
|
-
#### Implementation of
|
|
36
|
-
|
|
37
|
-
`IDataExtractorConnector.CLASS_NAME`
|
|
38
|
-
|
|
39
35
|
## Methods
|
|
40
36
|
|
|
41
37
|
### extract()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/data-processing-extractors",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.4",
|
|
4
4
|
"description": "Data extractor connector implementations",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/core": "next",
|
|
18
|
-
"@twin.org/data-processing-models": "0.0.2-next.
|
|
18
|
+
"@twin.org/data-processing-models": "0.0.2-next.4",
|
|
19
19
|
"@twin.org/nameof": "next",
|
|
20
20
|
"@twin.org/web": "next",
|
|
21
21
|
"json-p3": "2.2.2"
|
|
@@ -37,5 +37,21 @@
|
|
|
37
37
|
"dist/types",
|
|
38
38
|
"locales",
|
|
39
39
|
"docs"
|
|
40
|
-
]
|
|
40
|
+
],
|
|
41
|
+
"keywords": [
|
|
42
|
+
"twin",
|
|
43
|
+
"trade",
|
|
44
|
+
"iota",
|
|
45
|
+
"framework",
|
|
46
|
+
"blockchain",
|
|
47
|
+
"data-processing",
|
|
48
|
+
"data",
|
|
49
|
+
"processing",
|
|
50
|
+
"transformation",
|
|
51
|
+
"conversion"
|
|
52
|
+
],
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "git+https://github.com/twinfoundation/data-processing/issues"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://twindev.org"
|
|
41
57
|
}
|