@contrail/cli 2.2.7 → 2.2.8
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/helpers/types/type-uploader.d.ts +17 -0
- package/dist/helpers/types/type-uploader.js +139 -91
- package/dist/helpers/types/type-uploader.spec.d.ts +1 -0
- package/dist/helpers/types/type-uploader.spec.js +119 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ $ npm install -g @contrail/cli
|
|
|
17
17
|
$ contrail COMMAND
|
|
18
18
|
running command...
|
|
19
19
|
$ contrail (--version)
|
|
20
|
-
@contrail/cli/2.2.
|
|
20
|
+
@contrail/cli/2.2.8 darwin-arm64 node-v18.13.0
|
|
21
21
|
$ contrail --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ contrail COMMAND
|
|
@@ -1 +1,18 @@
|
|
|
1
1
|
export declare function uploadTypes(dir: string): Promise<void>;
|
|
2
|
+
export interface ValueDiff {
|
|
3
|
+
adds: any[];
|
|
4
|
+
updates: any[];
|
|
5
|
+
deletions: any[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* compares the keys between different objects and returns the differences
|
|
9
|
+
* captures in adds, updates, and deletions. Object 1 is considered the
|
|
10
|
+
* original, and object 2 is considered the "edit".
|
|
11
|
+
*
|
|
12
|
+
* An add is a property that exists in object2 but not in 1. An edit
|
|
13
|
+
* is a property that exists in both object 1 and 2, but with different values.
|
|
14
|
+
* A deletion is a property in object 1 but not in object 2.
|
|
15
|
+
* @param object1 any object
|
|
16
|
+
* @param object2 any other object
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractValueDifferences(object1: object, object2: object, keysToIgnore: Array<string>): ValueDiff;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uploadTypes = void 0;
|
|
3
|
+
exports.extractValueDifferences = exports.uploadTypes = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const sdk_1 = require("@contrail/sdk");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -61,6 +61,13 @@ async function uploadReducedTypes(dir) {
|
|
|
61
61
|
for (const type of types) {
|
|
62
62
|
newTypesBySlug[type.slug] = type;
|
|
63
63
|
}
|
|
64
|
+
const optionSets = await new sdk_1.Entities().get({
|
|
65
|
+
entityName: 'type-property-option-set',
|
|
66
|
+
});
|
|
67
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
68
|
+
fs_1.default.writeFileSync('reducedTypes.json', JSON.stringify(types, null, 2));
|
|
69
|
+
fs_1.default.writeFileSync('currentTypes.json', JSON.stringify(currentTypes, null, 2));
|
|
70
|
+
}
|
|
64
71
|
for (const type of types) {
|
|
65
72
|
try {
|
|
66
73
|
const found = currentTypesBySlug[type.slug];
|
|
@@ -81,21 +88,47 @@ async function uploadReducedTypes(dir) {
|
|
|
81
88
|
});
|
|
82
89
|
const newTypeProperties = (await new sdk_1.Types().getType({ id: createdType.id }))
|
|
83
90
|
.typeProperties;
|
|
84
|
-
await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties);
|
|
91
|
+
await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties, optionSets);
|
|
85
92
|
}
|
|
86
93
|
else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const proposedType = {
|
|
95
|
+
slug: type.slug,
|
|
96
|
+
label: type.label,
|
|
97
|
+
typePath: type.typePath,
|
|
98
|
+
isArchived: type.isArchived,
|
|
99
|
+
};
|
|
100
|
+
const differences = extractValueDifferences(found, proposedType, [
|
|
101
|
+
'id',
|
|
102
|
+
'createdOn',
|
|
103
|
+
'updatedOn',
|
|
104
|
+
'createdById',
|
|
105
|
+
'updatedById',
|
|
106
|
+
'orgId',
|
|
107
|
+
'typeRootId',
|
|
108
|
+
'parentId',
|
|
109
|
+
'typePolicyIds',
|
|
110
|
+
'typePolicies',
|
|
111
|
+
'typeProperties',
|
|
112
|
+
'typePropertyPolicies',
|
|
113
|
+
'typeRuleSets',
|
|
114
|
+
'typeOptionSetHierarchyLinks',
|
|
115
|
+
'relations',
|
|
116
|
+
'typeInterfaces',
|
|
117
|
+
]);
|
|
118
|
+
let updatedType = found;
|
|
119
|
+
if (differences.updates.length || differences.adds.length || differences.deletions.length) {
|
|
120
|
+
logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
|
|
121
|
+
logger_1.default.info(`Updating Type: ${type.slug}`);
|
|
122
|
+
updatedType = await new sdk_1.Entities().update({
|
|
123
|
+
entityName: 'type',
|
|
124
|
+
id: found.id,
|
|
125
|
+
object: proposedType,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
logger_1.default.debug(`Skipping empty update of type ${type.slug}`);
|
|
130
|
+
}
|
|
131
|
+
await uploadReducedTypeProperties(updatedType, found.typeProperties, type.typeProperties, optionSets);
|
|
99
132
|
}
|
|
100
133
|
}
|
|
101
134
|
catch (err) {
|
|
@@ -103,7 +136,7 @@ async function uploadReducedTypes(dir) {
|
|
|
103
136
|
}
|
|
104
137
|
}
|
|
105
138
|
}
|
|
106
|
-
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes) {
|
|
139
|
+
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes, optionSets) {
|
|
107
140
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
108
141
|
const currentPropertyTypeBySlug = {};
|
|
109
142
|
for (const currentPropertyType of currentPropertyTypes) {
|
|
@@ -113,9 +146,6 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
113
146
|
for (const newPropertyType of newPropertyTypes) {
|
|
114
147
|
newPropertyTypesBySlug[newPropertyType.slug] = newPropertyType;
|
|
115
148
|
}
|
|
116
|
-
const optionSets = await new sdk_1.Entities().get({
|
|
117
|
-
entityName: 'type-property-option-set',
|
|
118
|
-
});
|
|
119
149
|
const optionSetIdBySlug = {};
|
|
120
150
|
for (const optionSet of optionSets) {
|
|
121
151
|
optionSetIdBySlug[optionSet.slug] = optionSet.id;
|
|
@@ -123,7 +153,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
123
153
|
for (const newPropertyType of newPropertyTypes) {
|
|
124
154
|
try {
|
|
125
155
|
const found = currentPropertyTypeBySlug[newPropertyType.slug];
|
|
126
|
-
if (!found
|
|
156
|
+
if (!found) {
|
|
127
157
|
logger_1.default.info(`Creating Type-Property: ${newPropertyType.slug}`);
|
|
128
158
|
await sdk_1.Request.request(`/types/${type.id}/type-properties`, {
|
|
129
159
|
method: 'POST',
|
|
@@ -154,35 +184,68 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
154
184
|
},
|
|
155
185
|
});
|
|
156
186
|
}
|
|
157
|
-
else if (found
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
else if (found
|
|
188
|
+
// !newPropertyType.inherited &&
|
|
189
|
+
// !typePropertiesEqual(found, newPropertyType, optionSetIdBySlug)
|
|
190
|
+
) {
|
|
191
|
+
const proposedTP = {
|
|
192
|
+
isArchived: (_a = newPropertyType.isArchived) !== null && _a !== void 0 ? _a : null,
|
|
193
|
+
propertyType: (_b = newPropertyType.propertyType) !== null && _b !== void 0 ? _b : null,
|
|
194
|
+
slug: (_c = newPropertyType.slug) !== null && _c !== void 0 ? _c : null,
|
|
195
|
+
label: (_d = newPropertyType.label) !== null && _d !== void 0 ? _d : null,
|
|
196
|
+
editable: (_e = newPropertyType.editable) !== null && _e !== void 0 ? _e : null,
|
|
197
|
+
searchable: (_f = newPropertyType.searchable) !== null && _f !== void 0 ? _f : null,
|
|
198
|
+
core: (_g = newPropertyType.core) !== null && _g !== void 0 ? _g : null,
|
|
199
|
+
typePropertyOptionSetId: (_h = optionSetIdBySlug[newPropertyType.typePropertyOptionSetSlug]) !== null && _h !== void 0 ? _h : null,
|
|
200
|
+
formula: (_j = newPropertyType.formula) !== null && _j !== void 0 ? _j : null,
|
|
201
|
+
referencedTypePath: (_k = newPropertyType.referencedTypePath) !== null && _k !== void 0 ? _k : null,
|
|
202
|
+
carryOverBehavior: (_l = newPropertyType.carryOverBehavior) !== null && _l !== void 0 ? _l : null,
|
|
203
|
+
carryOverDefault: (_m = newPropertyType.carryOverDefault) !== null && _m !== void 0 ? _m : null,
|
|
204
|
+
referencedTypeRootSlug: (_o = newPropertyType.referencedTypeRootSlug) !== null && _o !== void 0 ? _o : null,
|
|
205
|
+
defaultValue: (_p = newPropertyType.defaultValue) !== null && _p !== void 0 ? _p : null,
|
|
206
|
+
propertyLevel: (_q = newPropertyType.propertyLevel) !== null && _q !== void 0 ? _q : null,
|
|
207
|
+
formulaFunction: (_r = newPropertyType.formulaFunction) !== null && _r !== void 0 ? _r : null,
|
|
208
|
+
validationFunction: (_s = newPropertyType.validationFunction) !== null && _s !== void 0 ? _s : null,
|
|
209
|
+
numberFormat: (_t = newPropertyType.numberFormat) !== null && _t !== void 0 ? _t : null,
|
|
210
|
+
sequenceSeedValue: (_u = newPropertyType.sequenceSeedValue) !== null && _u !== void 0 ? _u : null,
|
|
211
|
+
};
|
|
212
|
+
// logger.debug(
|
|
213
|
+
// `found type property option set: ${newPropertyType.typePropertyOptionSetSlug}, ${proposedTP.typePropertyOptionSetId}, `,
|
|
214
|
+
// );
|
|
215
|
+
const differences = extractValueDifferences(found, proposedTP, [
|
|
216
|
+
'id',
|
|
217
|
+
'createdOn',
|
|
218
|
+
'updatedOn',
|
|
219
|
+
'createdById',
|
|
220
|
+
'updatedById',
|
|
221
|
+
'orgId',
|
|
222
|
+
'typePropertyUserListId',
|
|
223
|
+
'referencedTypeRole',
|
|
224
|
+
'referencedTypeFilterProperties',
|
|
225
|
+
'referencedTypeId',
|
|
226
|
+
'description',
|
|
227
|
+
'apiDetails',
|
|
228
|
+
'notes',
|
|
229
|
+
'isFederationProperty',
|
|
230
|
+
'required',
|
|
231
|
+
'optionsSet',
|
|
232
|
+
'options',
|
|
233
|
+
'inherited',
|
|
234
|
+
'used',
|
|
235
|
+
'typePropertyPolicyIds',
|
|
236
|
+
]);
|
|
237
|
+
if (differences.updates.length || differences.adds.length || differences.deletions.length) {
|
|
238
|
+
logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
|
|
239
|
+
logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(proposedTP, null, 2)}`);
|
|
240
|
+
await new sdk_1.Entities().update({
|
|
241
|
+
entityName: 'type-property',
|
|
242
|
+
id: found.id,
|
|
243
|
+
object: proposedTP,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
logger_1.default.debug(`Skipping empty update of type property ${newPropertyType.slug}`);
|
|
248
|
+
}
|
|
186
249
|
}
|
|
187
250
|
}
|
|
188
251
|
catch (err) {
|
|
@@ -208,48 +271,33 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
208
271
|
}
|
|
209
272
|
}
|
|
210
273
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
editable: typeProperty2.editable,
|
|
239
|
-
searchable: typeProperty2.searchable,
|
|
240
|
-
core: typeProperty2.core,
|
|
241
|
-
typePropertyOptionSetId: optionSetIdByIdentifier[typeProperty2.typePropertyOptionSetSlug],
|
|
242
|
-
formula: typeProperty2.formula,
|
|
243
|
-
referencedTypePath: typeProperty2.referencedTypePath,
|
|
244
|
-
referencedTypeRootSlug: typeProperty2.referencedTypeRootSlug,
|
|
245
|
-
defaultValue: typeProperty2.defaultValue,
|
|
246
|
-
propertyLevel: typeProperty2.propertyLevel,
|
|
247
|
-
carryOverBehavior: typeProperty2.carryOverBehavior,
|
|
248
|
-
carryOverDefault: typeProperty2.carryOverDefault,
|
|
249
|
-
formulaFunction: typeProperty2.formulaFunction,
|
|
250
|
-
validationFunction: typeProperty2.validationFunction,
|
|
251
|
-
numberFormat: typeProperty2.numberFormat,
|
|
252
|
-
sequenceSeedValue: typeProperty2.sequenceSeedValue,
|
|
274
|
+
/**
|
|
275
|
+
* compares the keys between different objects and returns the differences
|
|
276
|
+
* captures in adds, updates, and deletions. Object 1 is considered the
|
|
277
|
+
* original, and object 2 is considered the "edit".
|
|
278
|
+
*
|
|
279
|
+
* An add is a property that exists in object2 but not in 1. An edit
|
|
280
|
+
* is a property that exists in both object 1 and 2, but with different values.
|
|
281
|
+
* A deletion is a property in object 1 but not in object 2.
|
|
282
|
+
* @param object1 any object
|
|
283
|
+
* @param object2 any other object
|
|
284
|
+
*/
|
|
285
|
+
function extractValueDifferences(object1, object2, keysToIgnore) {
|
|
286
|
+
const updates = [];
|
|
287
|
+
const object1Keys = Object.keys(object1);
|
|
288
|
+
const object2keys = Object.keys(object2);
|
|
289
|
+
const adds = object2keys.filter((key) => !object1Keys.includes(key) && !keysToIgnore.includes(key));
|
|
290
|
+
const deletions = object1Keys.filter((key) => !object2keys.includes(key) && !keysToIgnore.includes(key));
|
|
291
|
+
const shared = object1Keys.filter((key) => object2keys.includes(key) && !keysToIgnore.includes(key));
|
|
292
|
+
for (const key of shared) {
|
|
293
|
+
if (!_.isEqual(object1[key], object2[key])) {
|
|
294
|
+
updates.push(key);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
adds,
|
|
299
|
+
updates,
|
|
300
|
+
deletions,
|
|
253
301
|
};
|
|
254
|
-
return _.isEqual(reducedProperty1, reducedProperty2);
|
|
255
302
|
}
|
|
303
|
+
exports.extractValueDifferences = extractValueDifferences;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const type_uploader_1 = require("./type-uploader");
|
|
4
|
+
describe('extractValueDifferences', () => {
|
|
5
|
+
it('should return the correct value differences', () => {
|
|
6
|
+
const object1 = {
|
|
7
|
+
name: 'John',
|
|
8
|
+
age: 30,
|
|
9
|
+
city: 'New York',
|
|
10
|
+
};
|
|
11
|
+
const object2 = {
|
|
12
|
+
name: 'John',
|
|
13
|
+
age: 35,
|
|
14
|
+
city: 'Los Angeles',
|
|
15
|
+
country: 'USA',
|
|
16
|
+
};
|
|
17
|
+
const expectedValueDiff = {
|
|
18
|
+
adds: ['country'],
|
|
19
|
+
updates: ['age', 'city'],
|
|
20
|
+
deletions: [],
|
|
21
|
+
};
|
|
22
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, []);
|
|
23
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
24
|
+
});
|
|
25
|
+
it('should handle empty objects', () => {
|
|
26
|
+
const object1 = {};
|
|
27
|
+
const object2 = {};
|
|
28
|
+
const expectedValueDiff = {
|
|
29
|
+
adds: [],
|
|
30
|
+
updates: [],
|
|
31
|
+
deletions: [],
|
|
32
|
+
};
|
|
33
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, []);
|
|
34
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
35
|
+
});
|
|
36
|
+
it('should handle objects with no shared keys', () => {
|
|
37
|
+
const object1 = {
|
|
38
|
+
name: 'John',
|
|
39
|
+
age: 30,
|
|
40
|
+
};
|
|
41
|
+
const object2 = {
|
|
42
|
+
city: 'New York',
|
|
43
|
+
country: 'USA',
|
|
44
|
+
};
|
|
45
|
+
const expectedValueDiff = {
|
|
46
|
+
adds: ['city', 'country'],
|
|
47
|
+
updates: [],
|
|
48
|
+
deletions: ['name', 'age'],
|
|
49
|
+
};
|
|
50
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, []);
|
|
51
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
52
|
+
});
|
|
53
|
+
it('should handle objects with shared keys but no differences', () => {
|
|
54
|
+
const object1 = {
|
|
55
|
+
name: 'John',
|
|
56
|
+
age: 30,
|
|
57
|
+
};
|
|
58
|
+
const object2 = {
|
|
59
|
+
name: 'John',
|
|
60
|
+
age: 30,
|
|
61
|
+
};
|
|
62
|
+
const expectedValueDiff = {
|
|
63
|
+
adds: [],
|
|
64
|
+
updates: [],
|
|
65
|
+
deletions: [],
|
|
66
|
+
};
|
|
67
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, []);
|
|
68
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
69
|
+
});
|
|
70
|
+
it('should handle correctly ignore keys on deletion', () => {
|
|
71
|
+
const object1 = {
|
|
72
|
+
name: 'John',
|
|
73
|
+
age: 30,
|
|
74
|
+
};
|
|
75
|
+
const object2 = {
|
|
76
|
+
name: 'John',
|
|
77
|
+
};
|
|
78
|
+
const expectedValueDiff = {
|
|
79
|
+
adds: [],
|
|
80
|
+
updates: [],
|
|
81
|
+
deletions: [],
|
|
82
|
+
};
|
|
83
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, ['age']);
|
|
84
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
85
|
+
});
|
|
86
|
+
it('should handle correctly ignore keys on updates', () => {
|
|
87
|
+
const object1 = {
|
|
88
|
+
name: 'John',
|
|
89
|
+
age: 30,
|
|
90
|
+
};
|
|
91
|
+
const object2 = {
|
|
92
|
+
name: 'John',
|
|
93
|
+
age: 15,
|
|
94
|
+
};
|
|
95
|
+
const expectedValueDiff = {
|
|
96
|
+
adds: [],
|
|
97
|
+
updates: [],
|
|
98
|
+
deletions: [],
|
|
99
|
+
};
|
|
100
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, ['age']);
|
|
101
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
102
|
+
});
|
|
103
|
+
it('should handle correctly ignore keys on deletion', () => {
|
|
104
|
+
const object1 = {
|
|
105
|
+
name: 'John',
|
|
106
|
+
};
|
|
107
|
+
const object2 = {
|
|
108
|
+
name: 'John',
|
|
109
|
+
age: 30,
|
|
110
|
+
};
|
|
111
|
+
const expectedValueDiff = {
|
|
112
|
+
adds: [],
|
|
113
|
+
updates: [],
|
|
114
|
+
deletions: [],
|
|
115
|
+
};
|
|
116
|
+
const valueDiff = (0, type_uploader_1.extractValueDifferences)(object1, object2, ['age']);
|
|
117
|
+
expect(valueDiff).toEqual(expectedValueDiff);
|
|
118
|
+
});
|
|
119
|
+
});
|
package/oclif.manifest.json
CHANGED