@karmaniverous/jsonmap 0.2.2 → 0.2.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.
@@ -9,16 +9,42 @@ var _lodash2 = _interopRequireDefault(require("lodash.clonedeepwith"));
9
9
  var _lodash3 = _interopRequireDefault(require("lodash.get"));
10
10
  var _lodash4 = _interopRequireDefault(require("lodash.invoke"));
11
11
  var _lodash5 = _interopRequireDefault(require("lodash.isarray"));
12
- var _lodash6 = _interopRequireDefault(require("lodash.isobject"));
13
- var _lodash7 = _interopRequireDefault(require("lodash.isplainobject"));
14
- var _lodash8 = _interopRequireDefault(require("lodash.isstring"));
15
- var _lodash9 = _interopRequireDefault(require("lodash.mapvalues"));
16
- var _lodash10 = _interopRequireDefault(require("lodash.pickby"));
17
- var _lodash11 = _interopRequireDefault(require("lodash.set"));
18
- var _lodash12 = _interopRequireDefault(require("lodash.size"));
12
+ var _lodash6 = _interopRequireDefault(require("lodash.isarraylikeobject"));
13
+ var _lodash7 = _interopRequireDefault(require("lodash.isobject"));
14
+ var _lodash8 = _interopRequireDefault(require("lodash.isplainobject"));
15
+ var _lodash9 = _interopRequireDefault(require("lodash.isstring"));
16
+ var _lodash10 = _interopRequireDefault(require("lodash.isundefined"));
17
+ var _lodash11 = _interopRequireDefault(require("lodash.mapvalues"));
18
+ var _lodash12 = _interopRequireDefault(require("lodash.pickby"));
19
+ var _lodash13 = _interopRequireDefault(require("lodash.set"));
20
+ var _lodash14 = _interopRequireDefault(require("lodash.size"));
21
+ var _nanoid = require("nanoid");
19
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
23
  // npm imports
21
24
 
25
+ const getJsonFns = () => {
26
+ const seen = new WeakSet();
27
+ const undefinedToken = (0, _nanoid.nanoid)();
28
+ const replacer = (key, value) => {
29
+ if (typeof value === 'object' && value !== null) {
30
+ if (seen.has(value)) {
31
+ return 'CIRCULAR REFERENCE';
32
+ }
33
+ seen.add(value);
34
+ if (!(0, _lodash6.default)(value)) return Object.getOwnPropertyNames(value).reduce((v, p) => ({
35
+ ...v,
36
+ [p]: value[p]
37
+ }), {});
38
+ }
39
+ return (0, _lodash10.default)(value) ? undefinedToken : value;
40
+ };
41
+ const reviver = (key, value) => value === undefinedToken ? undefined : value;
42
+ return {
43
+ replacer,
44
+ reviver
45
+ };
46
+ };
47
+
22
48
  /**
23
49
  * JsonMap class to apply transformations to a JSON object
24
50
  */
@@ -47,11 +73,15 @@ class JsonMap {
47
73
  this.input = input;
48
74
  this.output = {};
49
75
 
50
- // Calls the #transform method to perform the transformation
51
- const result = await this.#transform(this.map, this.input, this.output);
76
+ // Perform transformation & eliminate recursion from result.
77
+ const {
78
+ replacer,
79
+ reviver
80
+ } = getJsonFns();
81
+ const result = JSON.parse(JSON.stringify(await this.#transform(this.map, this.input, this.output), replacer), reviver);
52
82
 
53
83
  // Recursively eliminate non-string keys & string keys starting with $.
54
- const deep = value => (0, _lodash7.default)(value) ? (0, _lodash9.default)((0, _lodash10.default)(value, (v, k) => (0, _lodash8.default)(k) && /^[^$]/.test(k)), value => (0, _lodash2.default)(value, deep)) : undefined;
84
+ const deep = value => (0, _lodash8.default)(value) ? (0, _lodash11.default)((0, _lodash12.default)(value, (v, k) => /^[^$]/.test(k)), value => (0, _lodash2.default)(value, deep)) : undefined;
55
85
  return (0, _lodash2.default)(result, deep);
56
86
  }
57
87
 
@@ -68,7 +98,7 @@ class JsonMap {
68
98
  async #transform(node, input, output) {
69
99
  let path = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
70
100
  // Checks if the current node is an object and has a '$' key
71
- if ((0, _lodash7.default)(node) && (0, _lodash12.default)(node) === 1 && '$' in node) {
101
+ if ((0, _lodash8.default)(node) && (0, _lodash14.default)(node) === 1 && '$' in node) {
72
102
  // Retrieves the transformations to be applied (can be an array or a single object)
73
103
  const transformations = (0, _lodash.default)(node['$']);
74
104
 
@@ -84,13 +114,13 @@ class JsonMap {
84
114
  } = this.#resolvePath(transformation.method, results);
85
115
 
86
116
  // Resolves the parameter paths for the transformation
87
- const params = await Promise.all((0, _lodash.default)(transformation.params).map(param => {
117
+ const params = (0, _lodash.default)(transformation.params).map(param => {
88
118
  const {
89
119
  obj: paramObj,
90
120
  path: paramPath
91
121
  } = this.#resolvePath(param, results);
92
122
  return paramObj ? paramPath ? (0, _lodash3.default)(paramObj, paramPath) : paramObj : paramPath;
93
- }));
123
+ });
94
124
 
95
125
  // Calls the specified method on the resolved object with the resolved parameters
96
126
  const result = await (0, _lodash4.default)(methodObj, methodPath, ...params);
@@ -100,12 +130,12 @@ class JsonMap {
100
130
  }
101
131
 
102
132
  // Sets the output at the specified path to the last result of the transformations & returns.
103
- (0, _lodash11.default)(output, path, results[0]);
133
+ (0, _lodash13.default)(output, path, results[0]);
104
134
  return results[0];
105
135
  }
106
136
 
107
137
  // Checks if the current node is an object
108
- if ((0, _lodash6.default)(node)) {
138
+ if ((0, _lodash7.default)(node)) {
109
139
  // Creates an empty array or object based on whether the current node is an array or not
110
140
  const transformedNode = (0, _lodash5.default)(node) ? [] : {};
111
141
 
@@ -120,12 +150,12 @@ class JsonMap {
120
150
  }
121
151
 
122
152
  // Sets the output at the specified path to the transformedNode & returnsd.
123
- (0, _lodash11.default)(output, path, transformedNode);
153
+ (0, _lodash13.default)(output, path, transformedNode);
124
154
  return transformedNode;
125
155
  }
126
156
 
127
157
  // Sets the output at the specified path to the current node & returns.
128
- (0, _lodash11.default)(output, path, node);
158
+ (0, _lodash13.default)(output, path, node);
129
159
  return node;
130
160
  }
131
161
 
@@ -146,8 +176,10 @@ class JsonMap {
146
176
  */
147
177
  #resolvePath(path, results) {
148
178
  // If the path is not a string, return it as is
149
- if (!(0, _lodash8.default)(path)) {
150
- return path;
179
+ if (!(0, _lodash9.default)(path)) {
180
+ return {
181
+ path
182
+ };
151
183
  }
152
184
 
153
185
  // Defines special patterns and their corresponding resolution functions
@@ -4,13 +4,42 @@ import cloneDeepWith from 'lodash.clonedeepwith';
4
4
  import get from 'lodash.get';
5
5
  import invoke from 'lodash.invoke';
6
6
  import isArray from 'lodash.isarray';
7
+ import isArrayLikeObject from 'lodash.isarraylikeobject';
7
8
  import isObject from 'lodash.isobject';
8
9
  import isPlainObject from 'lodash.isplainobject';
9
10
  import isString from 'lodash.isstring';
11
+ import isUndefined from 'lodash.isundefined';
10
12
  import mapValues from 'lodash.mapvalues';
11
13
  import pickBy from 'lodash.pickby';
12
14
  import set from 'lodash.set';
13
15
  import size from 'lodash.size';
16
+ import { nanoid } from 'nanoid';
17
+
18
+ const getJsonFns = () => {
19
+ const seen = new WeakSet();
20
+ const undefinedToken = nanoid();
21
+
22
+ const replacer = (key, value) => {
23
+ if (typeof value === 'object' && value !== null) {
24
+ if (seen.has(value)) {
25
+ return 'CIRCULAR REFERENCE';
26
+ }
27
+ seen.add(value);
28
+
29
+ if (!isArrayLikeObject(value))
30
+ return Object.getOwnPropertyNames(value).reduce(
31
+ (v, p) => ({ ...v, [p]: value[p] }),
32
+ {}
33
+ );
34
+ }
35
+ return isUndefined(value) ? undefinedToken : value;
36
+ };
37
+
38
+ const reviver = (key, value) =>
39
+ value === undefinedToken ? undefined : value;
40
+
41
+ return { replacer, reviver };
42
+ };
14
43
 
15
44
  /**
16
45
  * JsonMap class to apply transformations to a JSON object
@@ -38,14 +67,21 @@ class JsonMap {
38
67
  this.input = input;
39
68
  this.output = {};
40
69
 
41
- // Calls the #transform method to perform the transformation
42
- const result = await this.#transform(this.map, this.input, this.output);
70
+ // Perform transformation & eliminate recursion from result.
71
+ const { replacer, reviver } = getJsonFns();
72
+ const result = JSON.parse(
73
+ JSON.stringify(
74
+ await this.#transform(this.map, this.input, this.output),
75
+ replacer
76
+ ),
77
+ reviver
78
+ );
43
79
 
44
80
  // Recursively eliminate non-string keys & string keys starting with $.
45
81
  const deep = (value) =>
46
82
  isPlainObject(value)
47
83
  ? mapValues(
48
- pickBy(value, (v, k) => isString(k) && /^[^$]/.test(k)),
84
+ pickBy(value, (v, k) => /^[^$]/.test(k)),
49
85
  (value) => cloneDeepWith(value, deep)
50
86
  )
51
87
  : undefined;
@@ -81,19 +117,17 @@ class JsonMap {
81
117
  );
82
118
 
83
119
  // Resolves the parameter paths for the transformation
84
- const params = await Promise.all(
85
- castArray(transformation.params).map((param) => {
86
- const { obj: paramObj, path: paramPath } = this.#resolvePath(
87
- param,
88
- results
89
- );
90
- return paramObj
91
- ? paramPath
92
- ? get(paramObj, paramPath)
93
- : paramObj
94
- : paramPath;
95
- })
96
- );
120
+ const params = castArray(transformation.params).map((param) => {
121
+ const { obj: paramObj, path: paramPath } = this.#resolvePath(
122
+ param,
123
+ results
124
+ );
125
+ return paramObj
126
+ ? paramPath
127
+ ? get(paramObj, paramPath)
128
+ : paramObj
129
+ : paramPath;
130
+ });
97
131
 
98
132
  // Calls the specified method on the resolved object with the resolved parameters
99
133
  const result = await invoke(methodObj, methodPath, ...params);
@@ -155,7 +189,7 @@ class JsonMap {
155
189
  #resolvePath(path, results) {
156
190
  // If the path is not a string, return it as is
157
191
  if (!isString(path)) {
158
- return path;
192
+ return { path };
159
193
  }
160
194
 
161
195
  // Defines special patterns and their corresponding resolution functions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karmaniverous/jsonmap",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -27,13 +27,16 @@
27
27
  "lodash.get": "^4.4.2",
28
28
  "lodash.invoke": "^4.5.2",
29
29
  "lodash.isarray": "^4.0.0",
30
+ "lodash.isarraylikeobject": "^4.2.0",
30
31
  "lodash.isobject": "^3.0.2",
31
32
  "lodash.isplainobject": "^4.0.6",
32
33
  "lodash.isstring": "^4.0.1",
34
+ "lodash.isundefined": "^3.0.1",
33
35
  "lodash.mapvalues": "^4.6.0",
34
36
  "lodash.pickby": "^4.6.0",
35
37
  "lodash.set": "^4.3.2",
36
- "lodash.size": "^4.2.0"
38
+ "lodash.size": "^4.2.0",
39
+ "nanoid": "^4.0.2"
37
40
  },
38
41
  "devDependencies": {
39
42
  "@babel/cli": "^7.22.10",