@contrail/transform-data 1.3.0-alpha.0 → 1.3.0-alpha.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/.claude/settings.local.json +1 -4
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.js +17 -0
- package/lib/common/object-path-util.d.ts +24 -0
- package/lib/common/object-path-util.js +136 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/rekey/rekey-transformer.d.ts +0 -8
- package/lib/rekey/rekey-transformer.js +20 -139
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './object-path-util';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./object-path-util"), exports);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class ObjectPathUtil {
|
|
2
|
+
static parseKeyParts(key: string, nestedDelimiter: string | undefined): string[];
|
|
3
|
+
static getValueAtPath({ obj, pathParts, nestedDelimiter, }: {
|
|
4
|
+
obj: Record<string, unknown>;
|
|
5
|
+
pathParts: string[];
|
|
6
|
+
nestedDelimiter: string | undefined;
|
|
7
|
+
}): {
|
|
8
|
+
value: unknown;
|
|
9
|
+
isExistingPath: boolean;
|
|
10
|
+
};
|
|
11
|
+
static setValueAtPath({ obj, pathParts, value, options, }: {
|
|
12
|
+
obj: Record<string, unknown>;
|
|
13
|
+
pathParts: string[];
|
|
14
|
+
value: unknown;
|
|
15
|
+
options: {
|
|
16
|
+
shouldOverwrite: boolean;
|
|
17
|
+
};
|
|
18
|
+
}): void;
|
|
19
|
+
private static expandArraySegments;
|
|
20
|
+
static isArrayIndexPart(part: string): boolean;
|
|
21
|
+
static getArrayIndex(part: string): number;
|
|
22
|
+
private static ensureArrayFilledTo;
|
|
23
|
+
static traversePath(obj: any, parts: string[]): any;
|
|
24
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectPathUtil = void 0;
|
|
4
|
+
class ObjectPathUtil {
|
|
5
|
+
static parseKeyParts(key, nestedDelimiter) {
|
|
6
|
+
if (!nestedDelimiter || !key.includes(nestedDelimiter)) {
|
|
7
|
+
return ObjectPathUtil.expandArraySegments(key);
|
|
8
|
+
}
|
|
9
|
+
const parts = key.split(nestedDelimiter);
|
|
10
|
+
const expanded = [];
|
|
11
|
+
for (const part of parts) {
|
|
12
|
+
expanded.push(...ObjectPathUtil.expandArraySegments(part));
|
|
13
|
+
}
|
|
14
|
+
return expanded;
|
|
15
|
+
}
|
|
16
|
+
static getValueAtPath({ obj, pathParts, nestedDelimiter, }) {
|
|
17
|
+
if (!nestedDelimiter || pathParts.length === 1) {
|
|
18
|
+
const propertyKey = pathParts[0];
|
|
19
|
+
return { value: obj[propertyKey], isExistingPath: obj.hasOwnProperty(propertyKey) };
|
|
20
|
+
}
|
|
21
|
+
let current = obj;
|
|
22
|
+
for (const key of pathParts) {
|
|
23
|
+
const isPathBroken = current == null || typeof current !== 'object';
|
|
24
|
+
if (isPathBroken) {
|
|
25
|
+
return { value: undefined, isExistingPath: false };
|
|
26
|
+
}
|
|
27
|
+
const isArrayIndex = ObjectPathUtil.isArrayIndexPart(key);
|
|
28
|
+
if (isArrayIndex) {
|
|
29
|
+
const idx = ObjectPathUtil.getArrayIndex(key);
|
|
30
|
+
const isIndexOutOfBounds = !Array.isArray(current) || idx >= current.length;
|
|
31
|
+
if (isIndexOutOfBounds) {
|
|
32
|
+
return { value: undefined, isExistingPath: false };
|
|
33
|
+
}
|
|
34
|
+
current = current[idx];
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const isPropertyMissing = !Object.prototype.hasOwnProperty.call(current, key);
|
|
38
|
+
if (isPropertyMissing) {
|
|
39
|
+
return { value: undefined, isExistingPath: false };
|
|
40
|
+
}
|
|
41
|
+
current = current[key];
|
|
42
|
+
}
|
|
43
|
+
return { value: current, isExistingPath: true };
|
|
44
|
+
}
|
|
45
|
+
static setValueAtPath({ obj, pathParts, value, options, }) {
|
|
46
|
+
let current = obj;
|
|
47
|
+
let pathHasArrayIndex = false;
|
|
48
|
+
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
49
|
+
const key = pathParts[i];
|
|
50
|
+
const isCurrentPartArrayIndex = ObjectPathUtil.isArrayIndexPart(key);
|
|
51
|
+
if (isCurrentPartArrayIndex) {
|
|
52
|
+
pathHasArrayIndex = true;
|
|
53
|
+
const idx = ObjectPathUtil.getArrayIndex(key);
|
|
54
|
+
ObjectPathUtil.ensureArrayFilledTo(current, idx);
|
|
55
|
+
current = current[idx];
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const isNextPartArrayIndex = ObjectPathUtil.isArrayIndexPart(pathParts[i + 1]);
|
|
59
|
+
const needsInitialization = current[key] == null || typeof current[key] !== 'object';
|
|
60
|
+
const needsArrayConversion = isNextPartArrayIndex && !Array.isArray(current[key]);
|
|
61
|
+
if (needsInitialization || needsArrayConversion) {
|
|
62
|
+
current[key] = isNextPartArrayIndex ? [] : {};
|
|
63
|
+
}
|
|
64
|
+
current = current[key];
|
|
65
|
+
}
|
|
66
|
+
const finalKey = pathParts[pathParts.length - 1];
|
|
67
|
+
const isFinalKeyArrayIndex = ObjectPathUtil.isArrayIndexPart(finalKey);
|
|
68
|
+
if (isFinalKeyArrayIndex) {
|
|
69
|
+
const idx = ObjectPathUtil.getArrayIndex(finalKey);
|
|
70
|
+
ObjectPathUtil.ensureArrayFilledTo(current, idx);
|
|
71
|
+
current[idx] = value;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const shouldWriteProperty = pathHasArrayIndex || !Object.prototype.hasOwnProperty.call(current, finalKey);
|
|
75
|
+
if (shouldWriteProperty || options.shouldOverwrite) {
|
|
76
|
+
current[finalKey] = value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
static expandArraySegments(segment) {
|
|
80
|
+
const results = [];
|
|
81
|
+
const regex = /\[(\d+)\]/g;
|
|
82
|
+
let lastIndex = 0;
|
|
83
|
+
let match;
|
|
84
|
+
while ((match = regex.exec(segment)) !== null) {
|
|
85
|
+
if (match.index > lastIndex) {
|
|
86
|
+
results.push(segment.slice(lastIndex, match.index));
|
|
87
|
+
}
|
|
88
|
+
results.push(`[${match[1]}]`);
|
|
89
|
+
lastIndex = regex.lastIndex;
|
|
90
|
+
}
|
|
91
|
+
if (lastIndex === 0) {
|
|
92
|
+
return [segment];
|
|
93
|
+
}
|
|
94
|
+
if (lastIndex < segment.length) {
|
|
95
|
+
results.push(segment.slice(lastIndex));
|
|
96
|
+
}
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
static isArrayIndexPart(part) {
|
|
100
|
+
return /^\[\d+\]$/.test(part);
|
|
101
|
+
}
|
|
102
|
+
static getArrayIndex(part) {
|
|
103
|
+
return parseInt(part.slice(1, -1), 10);
|
|
104
|
+
}
|
|
105
|
+
static ensureArrayFilledTo(arr, index) {
|
|
106
|
+
while (arr.length <= index) {
|
|
107
|
+
arr.push({});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
static traversePath(obj, parts) {
|
|
111
|
+
let current = obj;
|
|
112
|
+
for (const part of parts) {
|
|
113
|
+
const isPathBroken = current == null || typeof current !== 'object';
|
|
114
|
+
if (isPathBroken) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const isArrayIndex = ObjectPathUtil.isArrayIndexPart(part);
|
|
118
|
+
if (isArrayIndex) {
|
|
119
|
+
const idx = ObjectPathUtil.getArrayIndex(part);
|
|
120
|
+
const isIndexOutOfBounds = !Array.isArray(current) || idx >= current.length;
|
|
121
|
+
if (isIndexOutOfBounds) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
current = current[idx];
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const isPropertyMissing = !(part in current);
|
|
128
|
+
if (isPropertyMissing) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
current = current[part];
|
|
132
|
+
}
|
|
133
|
+
return current;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.ObjectPathUtil = ObjectPathUtil;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
export declare class RekeyTransformer {
|
|
2
2
|
static transformData(csvJSON: any[], federatedMappings: Record<string, string>, deleteOldKey?: boolean, rekeyKeepMissingValues?: boolean, nestedDelimiter?: string | undefined): void;
|
|
3
3
|
static transformObject(row: any, federatedMappings: Record<string, string>, deleteOldKey?: boolean, rekeyKeepMissingValues?: boolean, nestedDelimiter?: string | undefined): void;
|
|
4
|
-
private static parseKeyParts;
|
|
5
|
-
private static setValueAtPath;
|
|
6
|
-
private static getValueAtPath;
|
|
7
|
-
private static expandArraySegments;
|
|
8
|
-
private static isArrayIndexPart;
|
|
9
|
-
private static getArrayIndex;
|
|
10
|
-
private static ensureArrayFilledTo;
|
|
11
|
-
private static traversePath;
|
|
12
4
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RekeyTransformer = void 0;
|
|
4
|
+
const object_path_util_1 = require("../common/object-path-util");
|
|
4
5
|
class RekeyTransformer {
|
|
5
6
|
static transformData(csvJSON, federatedMappings, deleteOldKey = false, rekeyKeepMissingValues = false, nestedDelimiter = undefined) {
|
|
6
7
|
for (const row of csvJSON) {
|
|
@@ -9,37 +10,47 @@ class RekeyTransformer {
|
|
|
9
10
|
}
|
|
10
11
|
static transformObject(row, federatedMappings, deleteOldKey = false, rekeyKeepMissingValues = false, nestedDelimiter = undefined) {
|
|
11
12
|
for (const [newKey, oldKey] of Object.entries(federatedMappings)) {
|
|
12
|
-
const newKeyParts =
|
|
13
|
-
const oldKeyParts =
|
|
14
|
-
const { value: oldValue, isExistingPath: doesOldKeyExist } =
|
|
13
|
+
const newKeyParts = object_path_util_1.ObjectPathUtil.parseKeyParts(newKey, nestedDelimiter);
|
|
14
|
+
const oldKeyParts = object_path_util_1.ObjectPathUtil.parseKeyParts(oldKey, nestedDelimiter);
|
|
15
|
+
const { value: oldValue, isExistingPath: doesOldKeyExist } = object_path_util_1.ObjectPathUtil.getValueAtPath({
|
|
15
16
|
obj: row,
|
|
16
17
|
pathParts: oldKeyParts,
|
|
17
18
|
nestedDelimiter,
|
|
18
19
|
});
|
|
19
20
|
if (doesOldKeyExist) {
|
|
20
|
-
|
|
21
|
+
object_path_util_1.ObjectPathUtil.setValueAtPath({
|
|
22
|
+
obj: row,
|
|
23
|
+
pathParts: newKeyParts,
|
|
24
|
+
value: oldValue,
|
|
25
|
+
options: { shouldOverwrite: false },
|
|
26
|
+
});
|
|
21
27
|
}
|
|
22
28
|
else if (rekeyKeepMissingValues) {
|
|
23
|
-
|
|
29
|
+
object_path_util_1.ObjectPathUtil.setValueAtPath({
|
|
30
|
+
obj: row,
|
|
31
|
+
pathParts: newKeyParts,
|
|
32
|
+
value: undefined,
|
|
33
|
+
options: { shouldOverwrite: false },
|
|
34
|
+
});
|
|
24
35
|
}
|
|
25
36
|
}
|
|
26
37
|
if (deleteOldKey) {
|
|
27
38
|
for (const oldKey of Object.values(federatedMappings)) {
|
|
28
|
-
const oldKeyParts =
|
|
39
|
+
const oldKeyParts = object_path_util_1.ObjectPathUtil.parseKeyParts(oldKey, nestedDelimiter);
|
|
29
40
|
const isNestedPath = oldKeyParts.length > 1;
|
|
30
41
|
if (!isNestedPath) {
|
|
31
42
|
delete row[oldKey];
|
|
32
43
|
continue;
|
|
33
44
|
}
|
|
34
|
-
let current =
|
|
45
|
+
let current = object_path_util_1.ObjectPathUtil.traversePath(row, oldKeyParts.slice(0, -1));
|
|
35
46
|
const isPathNonExistent = current == null || typeof current !== 'object';
|
|
36
47
|
if (isPathNonExistent) {
|
|
37
48
|
continue;
|
|
38
49
|
}
|
|
39
50
|
const finalPart = oldKeyParts[oldKeyParts.length - 1];
|
|
40
|
-
const isFinalPartArrayIndex =
|
|
51
|
+
const isFinalPartArrayIndex = object_path_util_1.ObjectPathUtil.isArrayIndexPart(finalPart);
|
|
41
52
|
if (isFinalPartArrayIndex) {
|
|
42
|
-
const idx =
|
|
53
|
+
const idx = object_path_util_1.ObjectPathUtil.getArrayIndex(finalPart);
|
|
43
54
|
if (Array.isArray(current) && idx < current.length) {
|
|
44
55
|
current[idx] = undefined;
|
|
45
56
|
}
|
|
@@ -51,135 +62,5 @@ class RekeyTransformer {
|
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
}
|
|
54
|
-
static parseKeyParts(key, nestedDelimiter) {
|
|
55
|
-
if (!nestedDelimiter || !key.includes(nestedDelimiter)) {
|
|
56
|
-
return RekeyTransformer.expandArraySegments(key);
|
|
57
|
-
}
|
|
58
|
-
const parts = key.split(nestedDelimiter);
|
|
59
|
-
const expanded = [];
|
|
60
|
-
for (const part of parts) {
|
|
61
|
-
expanded.push(...RekeyTransformer.expandArraySegments(part));
|
|
62
|
-
}
|
|
63
|
-
return expanded;
|
|
64
|
-
}
|
|
65
|
-
static setValueAtPath({ obj, pathParts, value, }) {
|
|
66
|
-
let current = obj;
|
|
67
|
-
let pathHasArrayIndex = false;
|
|
68
|
-
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
69
|
-
const key = pathParts[i];
|
|
70
|
-
const isCurrentPartArrayIndex = RekeyTransformer.isArrayIndexPart(key);
|
|
71
|
-
if (isCurrentPartArrayIndex) {
|
|
72
|
-
pathHasArrayIndex = true;
|
|
73
|
-
const idx = RekeyTransformer.getArrayIndex(key);
|
|
74
|
-
RekeyTransformer.ensureArrayFilledTo(current, idx);
|
|
75
|
-
current = current[idx];
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
const isNextPartArrayIndex = RekeyTransformer.isArrayIndexPart(pathParts[i + 1]);
|
|
79
|
-
const needsInitialization = current[key] == null || typeof current[key] !== 'object';
|
|
80
|
-
const needsArrayConversion = isNextPartArrayIndex && !Array.isArray(current[key]);
|
|
81
|
-
if (needsInitialization || needsArrayConversion) {
|
|
82
|
-
current[key] = isNextPartArrayIndex ? [] : {};
|
|
83
|
-
}
|
|
84
|
-
current = current[key];
|
|
85
|
-
}
|
|
86
|
-
const finalKey = pathParts[pathParts.length - 1];
|
|
87
|
-
const isFinalKeyArrayIndex = RekeyTransformer.isArrayIndexPart(finalKey);
|
|
88
|
-
if (isFinalKeyArrayIndex) {
|
|
89
|
-
const idx = RekeyTransformer.getArrayIndex(finalKey);
|
|
90
|
-
RekeyTransformer.ensureArrayFilledTo(current, idx);
|
|
91
|
-
current[idx] = value;
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const shouldWriteProperty = pathHasArrayIndex || !Object.prototype.hasOwnProperty.call(current, finalKey);
|
|
95
|
-
if (shouldWriteProperty) {
|
|
96
|
-
current[finalKey] = value;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
static getValueAtPath({ obj, pathParts, nestedDelimiter, }) {
|
|
100
|
-
if (!nestedDelimiter || pathParts.length === 1) {
|
|
101
|
-
const propertyKey = pathParts[0];
|
|
102
|
-
return { value: obj[propertyKey], isExistingPath: obj.hasOwnProperty(propertyKey) };
|
|
103
|
-
}
|
|
104
|
-
let current = obj;
|
|
105
|
-
for (const key of pathParts) {
|
|
106
|
-
const isPathBroken = current == null || typeof current !== 'object';
|
|
107
|
-
if (isPathBroken) {
|
|
108
|
-
return { value: undefined, isExistingPath: false };
|
|
109
|
-
}
|
|
110
|
-
const isArrayIndex = RekeyTransformer.isArrayIndexPart(key);
|
|
111
|
-
if (isArrayIndex) {
|
|
112
|
-
const idx = RekeyTransformer.getArrayIndex(key);
|
|
113
|
-
const isIndexOutOfBounds = !Array.isArray(current) || idx >= current.length;
|
|
114
|
-
if (isIndexOutOfBounds) {
|
|
115
|
-
return { value: undefined, isExistingPath: false };
|
|
116
|
-
}
|
|
117
|
-
current = current[idx];
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
const isPropertyMissing = !Object.prototype.hasOwnProperty.call(current, key);
|
|
121
|
-
if (isPropertyMissing) {
|
|
122
|
-
return { value: undefined, isExistingPath: false };
|
|
123
|
-
}
|
|
124
|
-
current = current[key];
|
|
125
|
-
}
|
|
126
|
-
return { value: current, isExistingPath: true };
|
|
127
|
-
}
|
|
128
|
-
static expandArraySegments(segment) {
|
|
129
|
-
const results = [];
|
|
130
|
-
const regex = /\[(\d+)\]/g;
|
|
131
|
-
let lastIndex = 0;
|
|
132
|
-
let match;
|
|
133
|
-
while ((match = regex.exec(segment)) !== null) {
|
|
134
|
-
if (match.index > lastIndex) {
|
|
135
|
-
results.push(segment.slice(lastIndex, match.index));
|
|
136
|
-
}
|
|
137
|
-
results.push(`[${match[1]}]`);
|
|
138
|
-
lastIndex = regex.lastIndex;
|
|
139
|
-
}
|
|
140
|
-
if (lastIndex === 0) {
|
|
141
|
-
return [segment];
|
|
142
|
-
}
|
|
143
|
-
if (lastIndex < segment.length) {
|
|
144
|
-
results.push(segment.slice(lastIndex));
|
|
145
|
-
}
|
|
146
|
-
return results;
|
|
147
|
-
}
|
|
148
|
-
static isArrayIndexPart(part) {
|
|
149
|
-
return /^\[\d+\]$/.test(part);
|
|
150
|
-
}
|
|
151
|
-
static getArrayIndex(part) {
|
|
152
|
-
return parseInt(part.slice(1, -1), 10);
|
|
153
|
-
}
|
|
154
|
-
static ensureArrayFilledTo(arr, index) {
|
|
155
|
-
while (arr.length <= index) {
|
|
156
|
-
arr.push({});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
static traversePath(obj, parts) {
|
|
160
|
-
let current = obj;
|
|
161
|
-
for (const part of parts) {
|
|
162
|
-
const isPathBroken = current == null || typeof current !== 'object';
|
|
163
|
-
if (isPathBroken) {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
const isArrayIndex = RekeyTransformer.isArrayIndexPart(part);
|
|
167
|
-
if (isArrayIndex) {
|
|
168
|
-
const idx = RekeyTransformer.getArrayIndex(part);
|
|
169
|
-
const isIndexOutOfBounds = !Array.isArray(current) || idx >= current.length;
|
|
170
|
-
if (isIndexOutOfBounds) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
current = current[idx];
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
const isPropertyMissing = !(part in current);
|
|
177
|
-
if (isPropertyMissing) {
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
current = current[part];
|
|
181
|
-
}
|
|
182
|
-
return current;
|
|
183
|
-
}
|
|
184
65
|
}
|
|
185
66
|
exports.RekeyTransformer = RekeyTransformer;
|