@twin.org/data-processing-extractors 0.0.2-next.4 → 0.0.3-next.2
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 +1 -1
- package/dist/{esm/index.mjs → es/extractors/jsonPathExtractorConnector.js} +14 -10
- package/dist/es/extractors/jsonPathExtractorConnector.js.map +1 -0
- package/dist/es/index.js +4 -0
- package/dist/es/index.js.map +1 -0
- package/dist/types/extractors/jsonPathExtractorConnector.d.ts +5 -0
- package/dist/types/index.d.ts +1 -1
- package/docs/changelog.md +64 -25
- package/docs/examples.md +69 -1
- package/docs/reference/classes/JsonPathExtractorConnector.md +21 -3
- package/locales/en.json +1 -1
- package/package.json +11 -13
- package/dist/cjs/index.cjs +0 -90
package/README.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { Guards, Coerce, Is, ObjectHelper, GeneralError, BaseError } from '@twin.org/core';
|
|
2
|
-
import { query } from 'json-p3';
|
|
3
|
-
|
|
4
1
|
// Copyright 2024 IOTA Stiftung.
|
|
5
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { BaseError, Coerce, GeneralError, Guards, Is, ObjectHelper } from "@twin.org/core";
|
|
4
|
+
import { JsonPathHelper } from "@twin.org/data-json-path";
|
|
6
5
|
/**
|
|
7
6
|
* Class for extracting data from a JSON source.
|
|
8
7
|
*/
|
|
9
|
-
class JsonPathExtractorConnector {
|
|
8
|
+
export class JsonPathExtractorConnector {
|
|
10
9
|
/**
|
|
11
10
|
* The namespace supported by the data extractor connector.
|
|
12
11
|
*/
|
|
@@ -15,6 +14,13 @@ class JsonPathExtractorConnector {
|
|
|
15
14
|
* Runtime name for the class.
|
|
16
15
|
*/
|
|
17
16
|
static CLASS_NAME = "JsonPathExtractorConnector";
|
|
17
|
+
/**
|
|
18
|
+
* Returns the class name of the component.
|
|
19
|
+
* @returns The class name of the component.
|
|
20
|
+
*/
|
|
21
|
+
className() {
|
|
22
|
+
return JsonPathExtractorConnector.CLASS_NAME;
|
|
23
|
+
}
|
|
18
24
|
/**
|
|
19
25
|
* Extracts data from the provided input.
|
|
20
26
|
* @param data The object to extract from.
|
|
@@ -39,7 +45,7 @@ class JsonPathExtractorConnector {
|
|
|
39
45
|
*/
|
|
40
46
|
extractValue(jsonObject, rule, outputObject) {
|
|
41
47
|
try {
|
|
42
|
-
const jsonNodes = query(rule.source, jsonObject);
|
|
48
|
+
const jsonNodes = JsonPathHelper.query(rule.source, jsonObject);
|
|
43
49
|
const ruleParts = rule.source.split(".");
|
|
44
50
|
// Group values by their target path to handle multiple results correctly
|
|
45
51
|
const pathToValues = {};
|
|
@@ -78,11 +84,9 @@ class JsonPathExtractorConnector {
|
|
|
78
84
|
}
|
|
79
85
|
catch (err) {
|
|
80
86
|
throw new GeneralError(JsonPathExtractorConnector.CLASS_NAME, "invalidRule", {
|
|
81
|
-
rule: rule.source
|
|
82
|
-
|
|
83
|
-
});
|
|
87
|
+
rule: rule.source
|
|
88
|
+
}, BaseError.fromError(err));
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
|
-
|
|
88
|
-
export { JsonPathExtractorConnector };
|
|
92
|
+
//# sourceMappingURL=jsonPathExtractorConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonPathExtractorConnector.js","sourceRoot":"","sources":["../../../src/extractors/jsonPathExtractorConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { BaseError, Coerce, GeneralError, Guards, Is, ObjectHelper } from \"@twin.org/core\";\nimport { JsonPathHelper } from \"@twin.org/data-json-path\";\nimport type { IDataExtractorConnector, IRule } from \"@twin.org/data-processing-models\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Class for extracting data from a JSON source.\n */\nexport class JsonPathExtractorConnector implements IDataExtractorConnector {\n\t/**\n\t * The namespace supported by the data extractor connector.\n\t */\n\tpublic static readonly NAMESPACE: string = \"json-path\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<JsonPathExtractorConnector>();\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn JsonPathExtractorConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Extracts data from the provided input.\n\t * @param data The object to extract from.\n\t * @param rules The rules to use to extract the data.\n\t * @returns The extracted data.\n\t */\n\tpublic async extract(data: unknown, rules: IRule[]): Promise<unknown> {\n\t\tGuards.object(JsonPathExtractorConnector.CLASS_NAME, nameof(data), data);\n\t\tGuards.array(JsonPathExtractorConnector.CLASS_NAME, nameof(rules), rules);\n\n\t\tconst outputObject: unknown = {};\n\n\t\tfor (const extractRule of rules) {\n\t\t\tthis.extractValue(data, extractRule, outputObject);\n\t\t}\n\n\t\treturn outputObject;\n\t}\n\n\t/**\n\t * Extracts the value from the JSON object.\n\t * @param jsonObject The JSON object to extract from.\n\t * @param rule The rule to use to extract the data.\n\t * @param outputObject The object to output the extracted data to.\n\t * @internal\n\t */\n\tprivate extractValue(jsonObject: unknown, rule: IRule, outputObject: unknown): void {\n\t\ttry {\n\t\t\tconst jsonNodes = JsonPathHelper.query(rule.source, jsonObject);\n\n\t\t\tconst ruleParts = rule.source.split(\".\");\n\n\t\t\t// Group values by their target path to handle multiple results correctly\n\t\t\tconst pathToValues: { [id: string]: unknown } = {};\n\n\t\t\tfor (const jsonNode of jsonNodes) {\n\t\t\t\tconst retainPathDepth = rule.retainPathDepth ?? 0;\n\t\t\t\tconst fullTargetPath = `${rule.target}${retainPathDepth > 0 ? `.${jsonNode.location.slice(-retainPathDepth).join(\".\")}` : \"\"}`;\n\t\t\t\tconst coercedValue = Coerce.byType(jsonNode.value, rule.coerce);\n\n\t\t\t\tconst nodeLocation = jsonNode.location;\n\n\t\t\t\t// If the last part of the location before the target property is an integer\n\t\t\t\t// and the corresponding rule part ends with [*], we are dealing with an array\n\t\t\t\tconst isArray =\n\t\t\t\t\tnodeLocation.length > 1 &&\n\t\t\t\t\truleParts.length > 1 &&\n\t\t\t\t\tIs.integer(nodeLocation[nodeLocation.length - 2]) &&\n\t\t\t\t\truleParts[nodeLocation.length - 2].endsWith(\"[*]\");\n\n\t\t\t\tif (isArray) {\n\t\t\t\t\t// If the value is set and not currently an array, convert it to one\n\t\t\t\t\tif (!Is.empty(pathToValues[fullTargetPath]) && !Is.array(pathToValues[fullTargetPath])) {\n\t\t\t\t\t\tpathToValues[fullTargetPath] = [pathToValues[fullTargetPath]];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Make sure the array exists\n\t\t\t\t\tpathToValues[fullTargetPath] ??= [];\n\t\t\t\t\t// And add the new value\n\t\t\t\t\tif (Is.array(pathToValues[fullTargetPath])) {\n\t\t\t\t\t\tpathToValues[fullTargetPath].push(coercedValue);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// For single values, just set the value directly\n\t\t\t\t\tpathToValues[fullTargetPath] = coercedValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the values in the output object\n\t\t\tfor (const [path, values] of Object.entries(pathToValues)) {\n\t\t\t\tObjectHelper.propertySet(outputObject, path, values);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tJsonPathExtractorConnector.CLASS_NAME,\n\t\t\t\t\"invalidRule\",\n\t\t\t\t{\n\t\t\t\t\trule: rule.source\n\t\t\t\t},\n\t\t\t\tBaseError.fromError(err)\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,4CAA4C,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./extractors/jsonPathExtractorConnector.js\";\n"]}
|
|
@@ -11,6 +11,11 @@ export declare class JsonPathExtractorConnector implements IDataExtractorConnect
|
|
|
11
11
|
* Runtime name for the class.
|
|
12
12
|
*/
|
|
13
13
|
static readonly CLASS_NAME: string;
|
|
14
|
+
/**
|
|
15
|
+
* Returns the class name of the component.
|
|
16
|
+
* @returns The class name of the component.
|
|
17
|
+
*/
|
|
18
|
+
className(): string;
|
|
14
19
|
/**
|
|
15
20
|
* Extracts data from the provided input.
|
|
16
21
|
* @param data The object to extract from.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./extractors/jsonPathExtractorConnector";
|
|
1
|
+
export * from "./extractors/jsonPathExtractorConnector.js";
|
package/docs/changelog.md
CHANGED
|
@@ -1,11 +1,50 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.0.
|
|
3
|
+
## [0.0.3-next.2](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.3-next.1...data-processing-extractors-v0.0.3-next.2) (2026-05-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* typescript 6 update ([b67debb](https://github.com/iotaledger/twin-data-processing/commit/b67debb8aff83c0f3b179c6db038ed733f7308b1))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/data-processing-models bumped from 0.0.3-next.1 to 0.0.3-next.2
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.1](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.3-next.0...data-processing-extractors-v0.0.3-next.1) (2025-11-11)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add context id features ([#25](https://github.com/iotaledger/twin-data-processing/issues/25)) ([2a2a955](https://github.com/iotaledger/twin-data-processing/commit/2a2a9559d54e8c703e97e2c05996e678416ef560))
|
|
23
|
+
* Add rule group query functionality ([#2](https://github.com/iotaledger/twin-data-processing/issues/2)) ([0fbbfb0](https://github.com/iotaledger/twin-data-processing/commit/0fbbfb065b6ecc293920b25f97ba011743105486))
|
|
24
|
+
* add validate-locales ([9af0874](https://github.com/iotaledger/twin-data-processing/commit/9af0874cd3f44a4cfca514dde8380f002e62337e))
|
|
25
|
+
* eslint migration to flat config ([a8138b0](https://github.com/iotaledger/twin-data-processing/commit/a8138b020ed58baeff162a822d4df207a6aeadc4))
|
|
26
|
+
* update dependencies ([21b8e80](https://github.com/iotaledger/twin-data-processing/commit/21b8e8007c87136a09f0a8e35ffde13a07ff4711))
|
|
27
|
+
* update framework core ([96f6e80](https://github.com/iotaledger/twin-data-processing/commit/96f6e8016a4ef0fb873f6775e750b4ab42e9f491))
|
|
28
|
+
* use shared store mechanism ([#6](https://github.com/iotaledger/twin-data-processing/issues/6)) ([6009228](https://github.com/iotaledger/twin-data-processing/commit/600922880acef07cc2f818dee7645c342929108b))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* supporting array usage ([#20](https://github.com/iotaledger/twin-data-processing/issues/20)) ([d2c68cd](https://github.com/iotaledger/twin-data-processing/commit/d2c68cd3983622586cc073377545d6416b87a827))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Dependencies
|
|
37
|
+
|
|
38
|
+
* The following workspace dependencies were updated
|
|
39
|
+
* dependencies
|
|
40
|
+
* @twin.org/data-processing-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
41
|
+
|
|
42
|
+
## [0.0.2-next.4](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.2-next.3...data-processing-extractors-v0.0.2-next.4) (2025-10-22)
|
|
4
43
|
|
|
5
44
|
|
|
6
45
|
### Bug Fixes
|
|
7
46
|
|
|
8
|
-
* supporting array usage ([#20](https://github.com/
|
|
47
|
+
* supporting array usage ([#20](https://github.com/iotaledger/twin-data-processing/issues/20)) ([d2c68cd](https://github.com/iotaledger/twin-data-processing/commit/d2c68cd3983622586cc073377545d6416b87a827))
|
|
9
48
|
|
|
10
49
|
|
|
11
50
|
### Dependencies
|
|
@@ -14,12 +53,12 @@
|
|
|
14
53
|
* dependencies
|
|
15
54
|
* @twin.org/data-processing-models bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
16
55
|
|
|
17
|
-
## [0.0.2-next.3](https://github.com/
|
|
56
|
+
## [0.0.2-next.3](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.2-next.2...data-processing-extractors-v0.0.2-next.3) (2025-10-09)
|
|
18
57
|
|
|
19
58
|
|
|
20
59
|
### Features
|
|
21
60
|
|
|
22
|
-
* add validate-locales ([9af0874](https://github.com/
|
|
61
|
+
* add validate-locales ([9af0874](https://github.com/iotaledger/twin-data-processing/commit/9af0874cd3f44a4cfca514dde8380f002e62337e))
|
|
23
62
|
|
|
24
63
|
|
|
25
64
|
### Dependencies
|
|
@@ -28,12 +67,12 @@
|
|
|
28
67
|
* dependencies
|
|
29
68
|
* @twin.org/data-processing-models bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
30
69
|
|
|
31
|
-
## [0.0.2-next.2](https://github.com/
|
|
70
|
+
## [0.0.2-next.2](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.2-next.1...data-processing-extractors-v0.0.2-next.2) (2025-08-29)
|
|
32
71
|
|
|
33
72
|
|
|
34
73
|
### Features
|
|
35
74
|
|
|
36
|
-
* eslint migration to flat config ([a8138b0](https://github.com/
|
|
75
|
+
* eslint migration to flat config ([a8138b0](https://github.com/iotaledger/twin-data-processing/commit/a8138b020ed58baeff162a822d4df207a6aeadc4))
|
|
37
76
|
|
|
38
77
|
|
|
39
78
|
### Dependencies
|
|
@@ -42,15 +81,15 @@
|
|
|
42
81
|
* dependencies
|
|
43
82
|
* @twin.org/data-processing-models bumped from 0.0.2-next.1 to 0.0.2-next.2
|
|
44
83
|
|
|
45
|
-
## [0.0.2-next.1](https://github.com/
|
|
84
|
+
## [0.0.2-next.1](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.2-next.0...data-processing-extractors-v0.0.2-next.1) (2025-08-20)
|
|
46
85
|
|
|
47
86
|
|
|
48
87
|
### Features
|
|
49
88
|
|
|
50
|
-
* Add rule group query functionality ([#2](https://github.com/
|
|
51
|
-
* update dependencies ([21b8e80](https://github.com/
|
|
52
|
-
* update framework core ([96f6e80](https://github.com/
|
|
53
|
-
* use shared store mechanism ([#6](https://github.com/
|
|
89
|
+
* Add rule group query functionality ([#2](https://github.com/iotaledger/twin-data-processing/issues/2)) ([0fbbfb0](https://github.com/iotaledger/twin-data-processing/commit/0fbbfb065b6ecc293920b25f97ba011743105486))
|
|
90
|
+
* update dependencies ([21b8e80](https://github.com/iotaledger/twin-data-processing/commit/21b8e8007c87136a09f0a8e35ffde13a07ff4711))
|
|
91
|
+
* update framework core ([96f6e80](https://github.com/iotaledger/twin-data-processing/commit/96f6e8016a4ef0fb873f6775e750b4ab42e9f491))
|
|
92
|
+
* use shared store mechanism ([#6](https://github.com/iotaledger/twin-data-processing/issues/6)) ([6009228](https://github.com/iotaledger/twin-data-processing/commit/600922880acef07cc2f818dee7645c342929108b))
|
|
54
93
|
|
|
55
94
|
|
|
56
95
|
### Dependencies
|
|
@@ -64,10 +103,10 @@
|
|
|
64
103
|
|
|
65
104
|
### Features
|
|
66
105
|
|
|
67
|
-
* Add rule group query functionality ([#2](https://github.com/
|
|
68
|
-
* release to production ([531ba89](https://github.com/
|
|
69
|
-
* update dependencies ([21b8e80](https://github.com/
|
|
70
|
-
* use shared store mechanism ([#6](https://github.com/
|
|
106
|
+
* Add rule group query functionality ([#2](https://github.com/iotaledger/twin-data-processing/issues/2)) ([0fbbfb0](https://github.com/iotaledger/twin-data-processing/commit/0fbbfb065b6ecc293920b25f97ba011743105486))
|
|
107
|
+
* release to production ([531ba89](https://github.com/iotaledger/twin-data-processing/commit/531ba89dea2deb2810870b72851dca3081f9d2ce))
|
|
108
|
+
* update dependencies ([21b8e80](https://github.com/iotaledger/twin-data-processing/commit/21b8e8007c87136a09f0a8e35ffde13a07ff4711))
|
|
109
|
+
* use shared store mechanism ([#6](https://github.com/iotaledger/twin-data-processing/issues/6)) ([6009228](https://github.com/iotaledger/twin-data-processing/commit/600922880acef07cc2f818dee7645c342929108b))
|
|
71
110
|
|
|
72
111
|
|
|
73
112
|
### Dependencies
|
|
@@ -76,7 +115,7 @@
|
|
|
76
115
|
* dependencies
|
|
77
116
|
* @twin.org/data-processing-models bumped from ^0.0.0 to ^0.0.1
|
|
78
117
|
|
|
79
|
-
## [0.0.1-next.16](https://github.com/
|
|
118
|
+
## [0.0.1-next.16](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.15...data-processing-extractors-v0.0.1-next.16) (2025-06-20)
|
|
80
119
|
|
|
81
120
|
|
|
82
121
|
### Miscellaneous Chores
|
|
@@ -90,12 +129,12 @@
|
|
|
90
129
|
* dependencies
|
|
91
130
|
* @twin.org/data-processing-models bumped from 0.0.1-next.15 to 0.0.1-next.16
|
|
92
131
|
|
|
93
|
-
## [0.0.1-next.15](https://github.com/
|
|
132
|
+
## [0.0.1-next.15](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.14...data-processing-extractors-v0.0.1-next.15) (2025-06-12)
|
|
94
133
|
|
|
95
134
|
|
|
96
135
|
### Features
|
|
97
136
|
|
|
98
|
-
* update dependencies ([21b8e80](https://github.com/
|
|
137
|
+
* update dependencies ([21b8e80](https://github.com/iotaledger/twin-data-processing/commit/21b8e8007c87136a09f0a8e35ffde13a07ff4711))
|
|
99
138
|
|
|
100
139
|
|
|
101
140
|
### Dependencies
|
|
@@ -104,7 +143,7 @@
|
|
|
104
143
|
* dependencies
|
|
105
144
|
* @twin.org/data-processing-models bumped from 0.0.1-next.14 to 0.0.1-next.15
|
|
106
145
|
|
|
107
|
-
## [0.0.1-next.14](https://github.com/
|
|
146
|
+
## [0.0.1-next.14](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.13...data-processing-extractors-v0.0.1-next.14) (2025-04-28)
|
|
108
147
|
|
|
109
148
|
|
|
110
149
|
### Miscellaneous Chores
|
|
@@ -118,7 +157,7 @@
|
|
|
118
157
|
* dependencies
|
|
119
158
|
* @twin.org/data-processing-models bumped from 0.0.1-next.13 to 0.0.1-next.14
|
|
120
159
|
|
|
121
|
-
## [0.0.1-next.13](https://github.com/
|
|
160
|
+
## [0.0.1-next.13](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.12...data-processing-extractors-v0.0.1-next.13) (2025-04-24)
|
|
122
161
|
|
|
123
162
|
|
|
124
163
|
### Miscellaneous Chores
|
|
@@ -132,12 +171,12 @@
|
|
|
132
171
|
* dependencies
|
|
133
172
|
* @twin.org/data-processing-models bumped from 0.0.1-next.12 to 0.0.1-next.13
|
|
134
173
|
|
|
135
|
-
## [0.0.1-next.12](https://github.com/
|
|
174
|
+
## [0.0.1-next.12](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.11...data-processing-extractors-v0.0.1-next.12) (2025-04-17)
|
|
136
175
|
|
|
137
176
|
|
|
138
177
|
### Features
|
|
139
178
|
|
|
140
|
-
* use shared store mechanism ([#6](https://github.com/
|
|
179
|
+
* use shared store mechanism ([#6](https://github.com/iotaledger/twin-data-processing/issues/6)) ([6009228](https://github.com/iotaledger/twin-data-processing/commit/600922880acef07cc2f818dee7645c342929108b))
|
|
141
180
|
|
|
142
181
|
|
|
143
182
|
### Dependencies
|
|
@@ -146,12 +185,12 @@
|
|
|
146
185
|
* dependencies
|
|
147
186
|
* @twin.org/data-processing-models bumped from 0.0.1-next.11 to 0.0.1-next.12
|
|
148
187
|
|
|
149
|
-
## [0.0.1-next.11](https://github.com/
|
|
188
|
+
## [0.0.1-next.11](https://github.com/iotaledger/twin-data-processing/compare/data-processing-extractors-v0.0.1-next.10...data-processing-extractors-v0.0.1-next.11) (2025-03-28)
|
|
150
189
|
|
|
151
190
|
|
|
152
191
|
### Features
|
|
153
192
|
|
|
154
|
-
* Add rule group query functionality ([#2](https://github.com/
|
|
193
|
+
* Add rule group query functionality ([#2](https://github.com/iotaledger/twin-data-processing/issues/2)) ([0fbbfb0](https://github.com/iotaledger/twin-data-processing/commit/0fbbfb065b6ecc293920b25f97ba011743105486))
|
|
155
194
|
|
|
156
195
|
|
|
157
196
|
### Dependencies
|
package/docs/examples.md
CHANGED
|
@@ -1 +1,69 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Data Processing Extractors Examples
|
|
2
|
+
|
|
3
|
+
Use these snippets to map nested JSON data into flatter, application-focused shapes with JSONPath rules.
|
|
4
|
+
|
|
5
|
+
## JsonPathExtractorConnector
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { JsonPathExtractorConnector } from '@twin.org/data-processing-extractors';
|
|
9
|
+
|
|
10
|
+
const extractor = new JsonPathExtractorConnector();
|
|
11
|
+
|
|
12
|
+
console.log(extractor.className()); // jsonPathExtractorConnector
|
|
13
|
+
|
|
14
|
+
const sourceData = {
|
|
15
|
+
users: [
|
|
16
|
+
{ firstName: 'John', lastName: 'Doe', age: 30 },
|
|
17
|
+
{ firstName: 'Jane', lastName: 'Doe', age: 25 }
|
|
18
|
+
]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const extracted = await extractor.extract(sourceData, [
|
|
22
|
+
{ source: '$.users[0].firstName', target: 'profile.givenName' },
|
|
23
|
+
{ source: '$.users[1].lastName', target: 'profile.familyName' }
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
console.log(extracted); // { profile: { givenName: 'John', familyName: 'Doe' } }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { JsonPathExtractorConnector } from '@twin.org/data-processing-extractors';
|
|
31
|
+
|
|
32
|
+
const extractor = new JsonPathExtractorConnector();
|
|
33
|
+
|
|
34
|
+
const extracted = await extractor.extract(
|
|
35
|
+
{
|
|
36
|
+
store: {
|
|
37
|
+
books: [
|
|
38
|
+
{ title: 'The Hobbit', author: 'J.R.R. Tolkien' },
|
|
39
|
+
{ title: '1984', author: 'George Orwell' },
|
|
40
|
+
{ title: 'Dune', author: 'Frank Herbert' }
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
[{ source: '$.store.books[*].title', target: 'bookTitles' }]
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
console.log(extracted); // { bookTitles: ['The Hobbit', '1984', 'Dune'] }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { JsonPathExtractorConnector } from '@twin.org/data-processing-extractors';
|
|
52
|
+
|
|
53
|
+
const extractor = new JsonPathExtractorConnector();
|
|
54
|
+
|
|
55
|
+
const extracted = await extractor.extract(
|
|
56
|
+
{
|
|
57
|
+
users: {
|
|
58
|
+
user1: { firstName: 'John', lastName: 'Doe', age: 30 },
|
|
59
|
+
user2: { firstName: 'Jane', lastName: 'Doe', age: 25 }
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
[
|
|
63
|
+
{ source: '$.users.*.firstName', target: 'selected', retainPathDepth: 2 },
|
|
64
|
+
{ source: '$.users.*.lastName', target: 'selected', retainPathDepth: 2 }
|
|
65
|
+
]
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
console.log(extracted); // { selected: { user1: { firstName: 'John', lastName: 'Doe' }, user2: { firstName: 'Jane', lastName: 'Doe' } } }
|
|
69
|
+
```
|
|
@@ -18,7 +18,7 @@ Class for extracting data from a JSON source.
|
|
|
18
18
|
|
|
19
19
|
## Properties
|
|
20
20
|
|
|
21
|
-
### NAMESPACE
|
|
21
|
+
### NAMESPACE {#namespace}
|
|
22
22
|
|
|
23
23
|
> `readonly` `static` **NAMESPACE**: `string` = `"json-path"`
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ The namespace supported by the data extractor connector.
|
|
|
26
26
|
|
|
27
27
|
***
|
|
28
28
|
|
|
29
|
-
### CLASS\_NAME
|
|
29
|
+
### CLASS\_NAME {#class_name}
|
|
30
30
|
|
|
31
31
|
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
32
32
|
|
|
@@ -34,7 +34,25 @@ Runtime name for the class.
|
|
|
34
34
|
|
|
35
35
|
## Methods
|
|
36
36
|
|
|
37
|
-
###
|
|
37
|
+
### className() {#classname}
|
|
38
|
+
|
|
39
|
+
> **className**(): `string`
|
|
40
|
+
|
|
41
|
+
Returns the class name of the component.
|
|
42
|
+
|
|
43
|
+
#### Returns
|
|
44
|
+
|
|
45
|
+
`string`
|
|
46
|
+
|
|
47
|
+
The class name of the component.
|
|
48
|
+
|
|
49
|
+
#### Implementation of
|
|
50
|
+
|
|
51
|
+
`IDataExtractorConnector.className`
|
|
52
|
+
|
|
53
|
+
***
|
|
54
|
+
|
|
55
|
+
### extract() {#extract}
|
|
38
56
|
|
|
39
57
|
> **extract**(`data`, `rules`): `Promise`\<`unknown`\>
|
|
40
58
|
|
package/locales/en.json
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/data-processing-extractors",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.3-next.2",
|
|
4
|
+
"description": "Connector implementations that extract data from external systems for processing",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/
|
|
7
|
+
"url": "git+https://github.com/iotaledger/data-processing.git",
|
|
8
8
|
"directory": "packages/data-processing-extractors"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
@@ -15,25 +15,23 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/core": "next",
|
|
18
|
-
"@twin.org/data-
|
|
18
|
+
"@twin.org/data-json-path": "next",
|
|
19
|
+
"@twin.org/data-processing-models": "0.0.3-next.2",
|
|
19
20
|
"@twin.org/nameof": "next",
|
|
20
|
-
"@twin.org/web": "next"
|
|
21
|
-
"json-p3": "2.2.2"
|
|
21
|
+
"@twin.org/web": "next"
|
|
22
22
|
},
|
|
23
|
-
"main": "./dist/
|
|
24
|
-
"module": "./dist/esm/index.mjs",
|
|
23
|
+
"main": "./dist/es/index.js",
|
|
25
24
|
"types": "./dist/types/index.d.ts",
|
|
26
25
|
"exports": {
|
|
27
26
|
".": {
|
|
28
27
|
"types": "./dist/types/index.d.ts",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
28
|
+
"import": "./dist/es/index.js",
|
|
29
|
+
"default": "./dist/es/index.js"
|
|
31
30
|
},
|
|
32
31
|
"./locales/*.json": "./locales/*.json"
|
|
33
32
|
},
|
|
34
33
|
"files": [
|
|
35
|
-
"dist/
|
|
36
|
-
"dist/esm",
|
|
34
|
+
"dist/es",
|
|
37
35
|
"dist/types",
|
|
38
36
|
"locales",
|
|
39
37
|
"docs"
|
|
@@ -51,7 +49,7 @@
|
|
|
51
49
|
"conversion"
|
|
52
50
|
],
|
|
53
51
|
"bugs": {
|
|
54
|
-
"url": "git+https://github.com/
|
|
52
|
+
"url": "git+https://github.com/iotaledger/data-processing/issues"
|
|
55
53
|
},
|
|
56
54
|
"homepage": "https://twindev.org"
|
|
57
55
|
}
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var core = require('@twin.org/core');
|
|
4
|
-
var jsonP3 = require('json-p3');
|
|
5
|
-
|
|
6
|
-
// Copyright 2024 IOTA Stiftung.
|
|
7
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
8
|
-
/**
|
|
9
|
-
* Class for extracting data from a JSON source.
|
|
10
|
-
*/
|
|
11
|
-
class JsonPathExtractorConnector {
|
|
12
|
-
/**
|
|
13
|
-
* The namespace supported by the data extractor connector.
|
|
14
|
-
*/
|
|
15
|
-
static NAMESPACE = "json-path";
|
|
16
|
-
/**
|
|
17
|
-
* Runtime name for the class.
|
|
18
|
-
*/
|
|
19
|
-
static CLASS_NAME = "JsonPathExtractorConnector";
|
|
20
|
-
/**
|
|
21
|
-
* Extracts data from the provided input.
|
|
22
|
-
* @param data The object to extract from.
|
|
23
|
-
* @param rules The rules to use to extract the data.
|
|
24
|
-
* @returns The extracted data.
|
|
25
|
-
*/
|
|
26
|
-
async extract(data, rules) {
|
|
27
|
-
core.Guards.object(JsonPathExtractorConnector.CLASS_NAME, "data", data);
|
|
28
|
-
core.Guards.array(JsonPathExtractorConnector.CLASS_NAME, "rules", rules);
|
|
29
|
-
const outputObject = {};
|
|
30
|
-
for (const extractRule of rules) {
|
|
31
|
-
this.extractValue(data, extractRule, outputObject);
|
|
32
|
-
}
|
|
33
|
-
return outputObject;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Extracts the value from the JSON object.
|
|
37
|
-
* @param jsonObject The JSON object to extract from.
|
|
38
|
-
* @param rule The rule to use to extract the data.
|
|
39
|
-
* @param outputObject The object to output the extracted data to.
|
|
40
|
-
* @internal
|
|
41
|
-
*/
|
|
42
|
-
extractValue(jsonObject, rule, outputObject) {
|
|
43
|
-
try {
|
|
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 = {};
|
|
48
|
-
for (const jsonNode of jsonNodes) {
|
|
49
|
-
const retainPathDepth = rule.retainPathDepth ?? 0;
|
|
50
|
-
const fullTargetPath = `${rule.target}${retainPathDepth > 0 ? `.${jsonNode.location.slice(-retainPathDepth).join(".")}` : ""}`;
|
|
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);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch (err) {
|
|
82
|
-
throw new core.GeneralError(JsonPathExtractorConnector.CLASS_NAME, "invalidRule", {
|
|
83
|
-
rule: rule.source,
|
|
84
|
-
reason: core.BaseError.fromError(err).message
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
exports.JsonPathExtractorConnector = JsonPathExtractorConnector;
|