@contrail/cli 2.2.7 → 2.3.0
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 +135 -367
- package/dist/api/apps.js +1 -2
- package/dist/auth/auth.js +1 -0
- package/dist/basecommand.js +16 -19
- package/dist/commands/app/create.js +5 -5
- package/dist/commands/app/delete.js +7 -7
- package/dist/commands/app/getApiKey.js +8 -8
- package/dist/commands/app/init.js +5 -5
- package/dist/commands/app/install.js +24 -24
- package/dist/commands/app/publish.js +24 -24
- package/dist/commands/app/uninstall.js +14 -14
- package/dist/commands/app/upgrade.js +19 -19
- package/dist/commands/app/version/major.js +6 -9
- package/dist/commands/app/version/minor.js +6 -9
- package/dist/commands/app/version/patch.js +6 -9
- package/dist/commands/colors/deleteAll.js +5 -5
- package/dist/commands/colors/load.js +5 -5
- package/dist/commands/config/environments/list.js +6 -9
- package/dist/commands/config/environments/remove.js +12 -15
- package/dist/commands/config/environments/set.js +11 -14
- package/dist/commands/config/list.js +6 -9
- package/dist/commands/config/remove.js +16 -19
- package/dist/commands/config/set.js +22 -25
- package/dist/commands/groups/export.js +21 -22
- package/dist/commands/groups/upload.js +10 -11
- package/dist/commands/instance/export.js +19 -19
- package/dist/commands/instance/import.js +13 -13
- package/dist/commands/loader-process/load.js +12 -12
- package/dist/commands/loader-process/upload-and-load.js +17 -17
- package/dist/commands/projects/export.js +9 -9
- package/dist/commands/projects/list.js +5 -5
- package/dist/commands/projects/load.js +16 -17
- package/dist/commands/types/exportOptionSetHierarchies.js +5 -5
- package/dist/commands/types/getAll.js +73 -72
- package/dist/commands/types/loadAll.js +13 -13
- package/dist/commands/types/mergeOptionSets.js +9 -10
- package/dist/commands/types/mergeTypeProperties.js +11 -11
- package/dist/commands/types/parseOptionSetsHierarchyLocalFile.js +9 -9
- package/dist/commands/types/parseOptionSetsHierarchyValuesToKeysLocalFile.js +9 -9
- package/dist/commands/types/parseOptionSetsLocalFiles.d.ts +21 -0
- package/dist/commands/types/parseOptionSetsLocalFiles.js +95 -17
- package/dist/commands/types/parseOptionSetsToFolderStructure.d.ts +0 -1
- package/dist/commands/types/parseOptionSetsToFolderStructure.js +5 -41
- package/dist/commands/types/parseTypesFromFiles.js +13 -13
- package/dist/commands/types/parseTypesFromLocalFiles.js +10 -10
- package/dist/commands/types/parseTypesFromTemplateAndDataFromLocalFiles.js +10 -10
- package/dist/commands/types/parseTypesFromTemplateFromLocalFiles.js +9 -9
- package/dist/commands/types/uploadOptionSetHierarchies.js +15 -16
- package/dist/commands/types/uploadOptionSets.js +15 -13
- package/dist/commands/types/uploadOptionSetsHierarchyLocalFile.js +13 -13
- package/dist/commands/types/uploadRuleSets.js +13 -13
- package/dist/commands/types/uploadTypePolicies.js +16 -16
- package/dist/commands/types/uploadTypePropertyPolicies.js +16 -16
- package/dist/commands/types/uploadTypes.js +13 -13
- package/dist/commands/types/uploadUsageInfo.js +13 -13
- package/dist/commands/users/export.js +19 -20
- package/dist/commands/users/upload.js +8 -8
- package/dist/commands/webhooks/create.js +5 -5
- package/dist/commands/webhooks/delete.js +11 -11
- package/dist/commands/webhooks/getWebhookTrigger.js +5 -5
- package/dist/commands/webhooks/list.js +11 -11
- package/dist/commands/workflow-template-definitions/install.js +5 -5
- package/dist/commands/workflow-template-definitions/list.js +5 -5
- package/dist/commands/workflow-templates/delete.js +5 -5
- package/dist/commands/workflow-templates/export.js +19 -20
- package/dist/commands/workflow-templates/list.js +5 -5
- package/dist/commands/workflow-templates/load.js +11 -11
- package/dist/helpers/app/actions-deployer.js +4 -4
- package/dist/helpers/app/app-deployer.js +9 -9
- package/dist/helpers/app/app-template-parsers.js +1 -1
- package/dist/helpers/app/extensions-deployer.js +5 -6
- package/dist/helpers/app/load-app-config.js +1 -1
- package/dist/helpers/loader-process/helpers.js +3 -3
- package/dist/helpers/projects/helpers.js +5 -5
- package/dist/helpers/types/type-parser.js +8 -8
- package/dist/helpers/types/type-uploader.d.ts +17 -0
- package/dist/helpers/types/type-uploader.js +139 -92
- package/dist/helpers/types/type-uploader.spec.d.ts +1 -0
- package/dist/helpers/types/type-uploader.spec.js +119 -0
- package/dist/helpers/workflow-template-definitions/workflow-template-definition-deployer.js +3 -4
- package/dist/helpers/workflow-templates/helper.js +11 -16
- package/dist/interface-converters.js +1 -2
- package/dist/interfaces.js +79 -0
- package/dist/logger.js +7 -6
- package/oclif.manifest.json +60 -1422
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ function loadAppConfig(config = { skipValidation: false }) {
|
|
|
10
10
|
const TARGET_DIR = process.cwd();
|
|
11
11
|
try {
|
|
12
12
|
const doc = js_yaml_1.default.load(fs_1.default.readFileSync(path.resolve(path.join(TARGET_DIR, 'app.yml')), 'utf8'));
|
|
13
|
-
if (!
|
|
13
|
+
if (!config?.skipValidation) {
|
|
14
14
|
(0, app_config_validators_1.validateAppConfig)(doc);
|
|
15
15
|
}
|
|
16
16
|
return doc;
|
|
@@ -91,9 +91,9 @@ async function loadLocalFile(configFileName) {
|
|
|
91
91
|
exports.loadLocalFile = loadLocalFile;
|
|
92
92
|
function getFileExtension(fileName) {
|
|
93
93
|
let ext = '';
|
|
94
|
-
const parts = fileName
|
|
95
|
-
if (
|
|
96
|
-
ext = `.${parts[
|
|
94
|
+
const parts = fileName?.split('.');
|
|
95
|
+
if (parts?.length > 1) {
|
|
96
|
+
ext = `.${parts[parts?.length - 1]}`;
|
|
97
97
|
}
|
|
98
98
|
return ext;
|
|
99
99
|
}
|
|
@@ -53,7 +53,7 @@ async function getAssortmentsAndSubFolders(parentId, assortments, subFolders, al
|
|
|
53
53
|
},
|
|
54
54
|
});
|
|
55
55
|
const integrationAssortments = workspaceAssortments; //?.filter(a => a.assortmentType === 'INTEGRATION');
|
|
56
|
-
if (
|
|
56
|
+
if (integrationAssortments?.length > 0) {
|
|
57
57
|
allAssortments.push(...integrationAssortments);
|
|
58
58
|
for (const a of integrationAssortments) {
|
|
59
59
|
const integrationAssortmentsCopy = util_1.ObjectUtil.cloneDeep(a);
|
|
@@ -81,8 +81,8 @@ async function getAssortmentsAndSubFolders(parentId, assortments, subFolders, al
|
|
|
81
81
|
},
|
|
82
82
|
relations: ['entity'],
|
|
83
83
|
});
|
|
84
|
-
const workspaceFolders = workspaceFolderLinks
|
|
85
|
-
if (
|
|
84
|
+
const workspaceFolders = workspaceFolderLinks?.map((wfl) => wfl.entity);
|
|
85
|
+
if (workspaceFolders?.length > 0) {
|
|
86
86
|
for (const folder of workspaceFolders) {
|
|
87
87
|
const converted = {
|
|
88
88
|
identifier: folder.identifier,
|
|
@@ -112,11 +112,11 @@ function convertRelationshipsToIdentifiers(assortments, allAssortments) {
|
|
|
112
112
|
}
|
|
113
113
|
for (const assortment of assortments) {
|
|
114
114
|
if (assortment.sourceAssortmentIds) {
|
|
115
|
-
assortment.sourceAssortmentIdentifier = assortment.sourceAssortmentIds.map((id) =>
|
|
115
|
+
assortment.sourceAssortmentIdentifier = assortment.sourceAssortmentIds.map((id) => allAssortments.find((a) => a.id === id)?.identifier);
|
|
116
116
|
}
|
|
117
117
|
delete assortment.sourceAssortmentIds;
|
|
118
118
|
if (assortment.composedFromAssortmentIds) {
|
|
119
|
-
assortment.composedFromAssortmentIdentifiers = assortment.composedFromAssortmentIds.map((id) =>
|
|
119
|
+
assortment.composedFromAssortmentIdentifiers = assortment.composedFromAssortmentIds.map((id) => allAssortments.find((a) => a.id === id)?.identifier);
|
|
120
120
|
}
|
|
121
121
|
delete assortment.composedFromAssortmentIds;
|
|
122
122
|
}
|
|
@@ -27,7 +27,7 @@ async function parseTypesFromLocalFiles(fileLocations) {
|
|
|
27
27
|
try {
|
|
28
28
|
logger_1.default.info(`Getting data for fileLocation: ${fileLocation}`);
|
|
29
29
|
const csvData = await loadDataFromLocalCSV(fileLocation);
|
|
30
|
-
logger_1.default.info(`CSV import was successful. ${csvData
|
|
30
|
+
logger_1.default.info(`CSV import was successful. ${csvData?.length} rows found. Adding to total rows.`);
|
|
31
31
|
csvJSONData.push(...csvData);
|
|
32
32
|
}
|
|
33
33
|
catch (e) {
|
|
@@ -35,7 +35,7 @@ async function parseTypesFromLocalFiles(fileLocations) {
|
|
|
35
35
|
throw e;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
logger_1.default.info(`CSV imports were successful. ${csvJSONData
|
|
38
|
+
logger_1.default.info(`CSV imports were successful. ${csvJSONData?.length} total rows found.`);
|
|
39
39
|
const suggestions = (0, types_1.GetSuggestedTypes)(csvJSONData);
|
|
40
40
|
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
41
41
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
@@ -47,10 +47,10 @@ async function parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFi
|
|
|
47
47
|
try {
|
|
48
48
|
logger_1.default.info(`Getting template from fileLocation: ${templateFileLocation}`);
|
|
49
49
|
templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
|
|
50
|
-
logger_1.default.info(`CSV import was successful. ${templateCSVData
|
|
50
|
+
logger_1.default.info(`CSV import was successful. ${templateCSVData?.length} rows found.`);
|
|
51
51
|
logger_1.default.info(`Getting data from fileLocation: ${dataFileLocation}`);
|
|
52
52
|
dataCSVData = await loadDataFromLocalCSV(dataFileLocation);
|
|
53
|
-
logger_1.default.info(`CSV import was successful. ${dataCSVData
|
|
53
|
+
logger_1.default.info(`CSV import was successful. ${dataCSVData?.length} rows found.`);
|
|
54
54
|
}
|
|
55
55
|
catch (e) {
|
|
56
56
|
logger_1.default.info(`Error importing csv data. ${e}`);
|
|
@@ -66,7 +66,7 @@ async function parseTypesFromTemplateAndDataFromLocalFiles(templateFileLocation,
|
|
|
66
66
|
try {
|
|
67
67
|
logger_1.default.info(`Getting template from fileLocation: ${templateFileLocation}`);
|
|
68
68
|
templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
|
|
69
|
-
logger_1.default.info(`CSV import was successful. ${templateCSVData
|
|
69
|
+
logger_1.default.info(`CSV import was successful. ${templateCSVData?.length} rows found.`);
|
|
70
70
|
}
|
|
71
71
|
catch (e) {
|
|
72
72
|
logger_1.default.info(`Error importing csv data. ${e}`);
|
|
@@ -77,7 +77,7 @@ async function parseTypesFromTemplateAndDataFromLocalFiles(templateFileLocation,
|
|
|
77
77
|
try {
|
|
78
78
|
logger_1.default.info(`Getting data for dataFileLocation: ${dataFileLocation}`);
|
|
79
79
|
const csvData = await loadDataFromLocalCSV(dataFileLocation);
|
|
80
|
-
logger_1.default.info(`CSV import was successful. ${csvData
|
|
80
|
+
logger_1.default.info(`CSV import was successful. ${csvData?.length} rows found. Adding to total rows.`);
|
|
81
81
|
dataCSVData.push(...csvData);
|
|
82
82
|
}
|
|
83
83
|
catch (e) {
|
|
@@ -98,7 +98,7 @@ async function parseTypesFromFiles(fileIds) {
|
|
|
98
98
|
try {
|
|
99
99
|
logger_1.default.info(`Getting data for fileId: ${loadFileId}`);
|
|
100
100
|
const csvJSON = await (0, csv_parser_1.getCSVFromFile)(loadFileId);
|
|
101
|
-
logger_1.default.info(`CSV download was successful. ${csvJSON
|
|
101
|
+
logger_1.default.info(`CSV download was successful. ${csvJSON?.length} rows found. Adding to total rows`);
|
|
102
102
|
csvJSONData.push(...csvJSON);
|
|
103
103
|
}
|
|
104
104
|
catch (e) {
|
|
@@ -106,7 +106,7 @@ async function parseTypesFromFiles(fileIds) {
|
|
|
106
106
|
throw e;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
logger_1.default.info(`CSV downloads were successful. ${csvJSONData
|
|
109
|
+
logger_1.default.info(`CSV downloads were successful. ${csvJSONData?.length} total rows found.`);
|
|
110
110
|
const suggestions = (0, types_1.GetSuggestedTypes)(csvJSONData);
|
|
111
111
|
saveData(suggestions.OptionSets, 'parsed_optionSets.yml');
|
|
112
112
|
saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
|
|
@@ -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,8 +136,7 @@ async function uploadReducedTypes(dir) {
|
|
|
103
136
|
}
|
|
104
137
|
}
|
|
105
138
|
}
|
|
106
|
-
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes) {
|
|
107
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
139
|
+
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes, optionSets) {
|
|
108
140
|
const currentPropertyTypeBySlug = {};
|
|
109
141
|
for (const currentPropertyType of currentPropertyTypes) {
|
|
110
142
|
currentPropertyTypeBySlug[currentPropertyType.slug] = currentPropertyType;
|
|
@@ -113,9 +145,6 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
113
145
|
for (const newPropertyType of newPropertyTypes) {
|
|
114
146
|
newPropertyTypesBySlug[newPropertyType.slug] = newPropertyType;
|
|
115
147
|
}
|
|
116
|
-
const optionSets = await new sdk_1.Entities().get({
|
|
117
|
-
entityName: 'type-property-option-set',
|
|
118
|
-
});
|
|
119
148
|
const optionSetIdBySlug = {};
|
|
120
149
|
for (const optionSet of optionSets) {
|
|
121
150
|
optionSetIdBySlug[optionSet.slug] = optionSet.id;
|
|
@@ -123,7 +152,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
123
152
|
for (const newPropertyType of newPropertyTypes) {
|
|
124
153
|
try {
|
|
125
154
|
const found = currentPropertyTypeBySlug[newPropertyType.slug];
|
|
126
|
-
if (!found
|
|
155
|
+
if (!found) {
|
|
127
156
|
logger_1.default.info(`Creating Type-Property: ${newPropertyType.slug}`);
|
|
128
157
|
await sdk_1.Request.request(`/types/${type.id}/type-properties`, {
|
|
129
158
|
method: 'POST',
|
|
@@ -154,35 +183,68 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
154
183
|
},
|
|
155
184
|
});
|
|
156
185
|
}
|
|
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
|
-
|
|
186
|
+
else if (found
|
|
187
|
+
// !newPropertyType.inherited &&
|
|
188
|
+
// !typePropertiesEqual(found, newPropertyType, optionSetIdBySlug)
|
|
189
|
+
) {
|
|
190
|
+
const proposedTP = {
|
|
191
|
+
isArchived: newPropertyType.isArchived ?? null,
|
|
192
|
+
propertyType: newPropertyType.propertyType ?? null,
|
|
193
|
+
slug: newPropertyType.slug ?? null,
|
|
194
|
+
label: newPropertyType.label ?? null,
|
|
195
|
+
editable: newPropertyType.editable ?? null,
|
|
196
|
+
searchable: newPropertyType.searchable ?? null,
|
|
197
|
+
core: newPropertyType.core ?? null,
|
|
198
|
+
typePropertyOptionSetId: optionSetIdBySlug[newPropertyType.typePropertyOptionSetSlug] ?? null,
|
|
199
|
+
formula: newPropertyType.formula ?? null,
|
|
200
|
+
referencedTypePath: newPropertyType.referencedTypePath ?? null,
|
|
201
|
+
carryOverBehavior: newPropertyType.carryOverBehavior ?? null,
|
|
202
|
+
carryOverDefault: newPropertyType.carryOverDefault ?? null,
|
|
203
|
+
referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug ?? null,
|
|
204
|
+
defaultValue: newPropertyType.defaultValue ?? null,
|
|
205
|
+
propertyLevel: newPropertyType.propertyLevel ?? null,
|
|
206
|
+
formulaFunction: newPropertyType.formulaFunction ?? null,
|
|
207
|
+
validationFunction: newPropertyType.validationFunction ?? null,
|
|
208
|
+
numberFormat: newPropertyType.numberFormat ?? null,
|
|
209
|
+
sequenceSeedValue: newPropertyType.sequenceSeedValue ?? null,
|
|
210
|
+
};
|
|
211
|
+
// logger.debug(
|
|
212
|
+
// `found type property option set: ${newPropertyType.typePropertyOptionSetSlug}, ${proposedTP.typePropertyOptionSetId}, `,
|
|
213
|
+
// );
|
|
214
|
+
const differences = extractValueDifferences(found, proposedTP, [
|
|
215
|
+
'id',
|
|
216
|
+
'createdOn',
|
|
217
|
+
'updatedOn',
|
|
218
|
+
'createdById',
|
|
219
|
+
'updatedById',
|
|
220
|
+
'orgId',
|
|
221
|
+
'typePropertyUserListId',
|
|
222
|
+
'referencedTypeRole',
|
|
223
|
+
'referencedTypeFilterProperties',
|
|
224
|
+
'referencedTypeId',
|
|
225
|
+
'description',
|
|
226
|
+
'apiDetails',
|
|
227
|
+
'notes',
|
|
228
|
+
'isFederationProperty',
|
|
229
|
+
'required',
|
|
230
|
+
'optionsSet',
|
|
231
|
+
'options',
|
|
232
|
+
'inherited',
|
|
233
|
+
'used',
|
|
234
|
+
'typePropertyPolicyIds',
|
|
235
|
+
]);
|
|
236
|
+
if (differences.updates.length || differences.adds.length || differences.deletions.length) {
|
|
237
|
+
logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
|
|
238
|
+
logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(proposedTP, null, 2)}`);
|
|
239
|
+
await new sdk_1.Entities().update({
|
|
240
|
+
entityName: 'type-property',
|
|
241
|
+
id: found.id,
|
|
242
|
+
object: proposedTP,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
logger_1.default.debug(`Skipping empty update of type property ${newPropertyType.slug}`);
|
|
247
|
+
}
|
|
186
248
|
}
|
|
187
249
|
}
|
|
188
250
|
catch (err) {
|
|
@@ -208,48 +270,33 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
208
270
|
}
|
|
209
271
|
}
|
|
210
272
|
}
|
|
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,
|
|
273
|
+
/**
|
|
274
|
+
* compares the keys between different objects and returns the differences
|
|
275
|
+
* captures in adds, updates, and deletions. Object 1 is considered the
|
|
276
|
+
* original, and object 2 is considered the "edit".
|
|
277
|
+
*
|
|
278
|
+
* An add is a property that exists in object2 but not in 1. An edit
|
|
279
|
+
* is a property that exists in both object 1 and 2, but with different values.
|
|
280
|
+
* A deletion is a property in object 1 but not in object 2.
|
|
281
|
+
* @param object1 any object
|
|
282
|
+
* @param object2 any other object
|
|
283
|
+
*/
|
|
284
|
+
function extractValueDifferences(object1, object2, keysToIgnore) {
|
|
285
|
+
const updates = [];
|
|
286
|
+
const object1Keys = Object.keys(object1);
|
|
287
|
+
const object2keys = Object.keys(object2);
|
|
288
|
+
const adds = object2keys.filter((key) => !object1Keys.includes(key) && !keysToIgnore.includes(key));
|
|
289
|
+
const deletions = object1Keys.filter((key) => !object2keys.includes(key) && !keysToIgnore.includes(key));
|
|
290
|
+
const shared = object1Keys.filter((key) => object2keys.includes(key) && !keysToIgnore.includes(key));
|
|
291
|
+
for (const key of shared) {
|
|
292
|
+
if (!_.isEqual(object1[key], object2[key])) {
|
|
293
|
+
updates.push(key);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
adds,
|
|
298
|
+
updates,
|
|
299
|
+
deletions,
|
|
253
300
|
};
|
|
254
|
-
return _.isEqual(reducedProperty1, reducedProperty2);
|
|
255
301
|
}
|
|
302
|
+
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
|
+
});
|
|
@@ -95,7 +95,7 @@ class WorkflowTemplateDefinitionDeployer {
|
|
|
95
95
|
logger_1.default.info('WORKFLOW DEFINITION \tDeploying workflow definitions.');
|
|
96
96
|
if (appDeclaration.workflows) {
|
|
97
97
|
const localWorkflows = Object.keys(appDeclaration.workflows);
|
|
98
|
-
if (
|
|
98
|
+
if (localWorkflows?.length > 0) {
|
|
99
99
|
for (const workflowKey of localWorkflows) {
|
|
100
100
|
await this.deployWorkflow(workflowKey, appDeclaration.workflows[workflowKey], app, existingWorkflows);
|
|
101
101
|
}
|
|
@@ -131,13 +131,12 @@ class WorkflowTemplateDefinitionDeployer {
|
|
|
131
131
|
return workflowTemplate;
|
|
132
132
|
}
|
|
133
133
|
async populateActionIds(workflowDefinition, app) {
|
|
134
|
-
var _a;
|
|
135
134
|
const availableAppActions = await (0, actions_deployer_1.getActionsForAppVersion)(app);
|
|
136
|
-
if (!
|
|
135
|
+
if (!workflowDefinition.workflowDefinition?.paths) {
|
|
137
136
|
return;
|
|
138
137
|
}
|
|
139
138
|
for (const path of workflowDefinition.workflowDefinition.paths) {
|
|
140
|
-
if (!
|
|
139
|
+
if (!path?.actionDefinitionConfigs) {
|
|
141
140
|
continue;
|
|
142
141
|
}
|
|
143
142
|
for (const actionConfiguration of path.actionDefinitionConfigs) {
|