@contrail/cli 2.1.2 → 2.1.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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ $ npm install -g @contrail/cli
15
15
  $ contrail COMMAND
16
16
  running command...
17
17
  $ contrail (--version)
18
- @contrail/cli/2.1.2 darwin-arm64 node-v18.13.0
18
+ @contrail/cli/2.1.4 darwin-arm64 node-v18.13.0
19
19
  $ contrail --help [COMMAND]
20
20
  USAGE
21
21
  $ contrail COMMAND
@@ -75,6 +75,7 @@ To get instructions on how to set up autocomplete for your shell, run `contrail
75
75
  * [`contrail types uploadOptionSets`](#contrail-types-uploadoptionsets)
76
76
  * [`contrail types uploadOptionSetsHierarchyLocalFile FILE NAME`](#contrail-types-uploadoptionsetshierarchylocalfile-file-name)
77
77
  * [`contrail types uploadRuleSets`](#contrail-types-uploadrulesets)
78
+ * [`contrail types uploadTypePolicies`](#contrail-types-uploadtypepolicies)
78
79
  * [`contrail types uploadTypePropertyPolicies`](#contrail-types-uploadtypepropertypolicies)
79
80
  * [`contrail types uploadUsageInfo`](#contrail-types-uploadusageinfo)
80
81
  * [`contrail users export`](#contrail-users-export)
@@ -764,11 +765,11 @@ Get all Types and associated data for your Org
764
765
 
765
766
  ```
766
767
  USAGE
767
- $ contrail types getAll [-d <value>] [--overwrite]
768
+ $ contrail types getAll [-d <value>] [-f]
768
769
 
769
770
  FLAGS
770
771
  -d, --outDir=<value> [default: .] The directory to which to export the type data. Defaults to the current directory
771
- --overwrite Replaces any existing export files in outDir
772
+ -f, --overwrite Replaces any existing export files in outDir
772
773
 
773
774
  DESCRIPTION
774
775
  Get all Types and associated data for your Org
@@ -1047,6 +1048,25 @@ EXAMPLES
1047
1048
  $ contrail types uploadRuleSets
1048
1049
  ```
1049
1050
 
1051
+ ## `contrail types uploadTypePolicies`
1052
+
1053
+ Upload type policies
1054
+
1055
+ ```
1056
+ USAGE
1057
+ $ contrail types uploadTypePolicies [-d <value>]
1058
+
1059
+ FLAGS
1060
+ -d, --dir=<value> [default: .] The directory from which to export the type policy data. Defaults to the current
1061
+ directory. The type policy data will be loaded from $dir/type-policies/*.yml
1062
+
1063
+ DESCRIPTION
1064
+ Upload type policies
1065
+
1066
+ EXAMPLES
1067
+ $ contrail types UploadTypePolicies
1068
+ ```
1069
+
1050
1070
  ## `contrail types uploadTypePropertyPolicies`
1051
1071
 
1052
1072
  Upload type property policies
@@ -1,7 +1,10 @@
1
1
  export declare function getOptionSets(): Promise<any>;
2
2
  export declare function getOptionSetHierarchies(): Promise<any>;
3
+ export declare function getOptionSetHierarchyLinks(): Promise<any>;
3
4
  export declare function getRuleSets(): Promise<any>;
4
5
  export declare function getRuleSetLinks(): Promise<any>;
5
6
  export declare function getUsageInfo(): Promise<any>;
6
7
  export declare function getTypePropertyPolicies(): Promise<any>;
7
8
  export declare function getTypePropertyPolicyLinks(): Promise<any>;
9
+ export declare function getTypePolicies(): Promise<any>;
10
+ export declare function getTypePolicyLinks(): Promise<any>;
package/dist/api/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchies = exports.getOptionSets = void 0;
3
+ exports.getTypePolicyLinks = exports.getTypePolicies = exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchyLinks = exports.getOptionSetHierarchies = exports.getOptionSets = void 0;
4
4
  const sdk_1 = require("@contrail/sdk");
5
5
  async function getOptionSets() {
6
6
  return await new sdk_1.Entities().get({
@@ -15,6 +15,13 @@ async function getOptionSetHierarchies() {
15
15
  });
16
16
  }
17
17
  exports.getOptionSetHierarchies = getOptionSetHierarchies;
18
+ async function getOptionSetHierarchyLinks() {
19
+ const entitiesClient = new sdk_1.Entities();
20
+ return await entitiesClient.get({
21
+ entityName: 'type-option-set-hierarchy-link',
22
+ });
23
+ }
24
+ exports.getOptionSetHierarchyLinks = getOptionSetHierarchyLinks;
18
25
  async function getRuleSets() {
19
26
  const entitiesClient = new sdk_1.Entities();
20
27
  return await entitiesClient.get({
@@ -50,3 +57,17 @@ async function getTypePropertyPolicyLinks() {
50
57
  });
51
58
  }
52
59
  exports.getTypePropertyPolicyLinks = getTypePropertyPolicyLinks;
60
+ async function getTypePolicies() {
61
+ const entitiesClient = new sdk_1.Entities();
62
+ return await entitiesClient.get({
63
+ entityName: 'type-policy',
64
+ });
65
+ }
66
+ exports.getTypePolicies = getTypePolicies;
67
+ async function getTypePolicyLinks() {
68
+ const entitiesClient = new sdk_1.Entities();
69
+ return await entitiesClient.get({
70
+ entityName: 'type-policy-link',
71
+ });
72
+ }
73
+ exports.getTypePolicyLinks = getTypePolicyLinks;
@@ -7,6 +7,7 @@ const loadAll_1 = require("../types/loadAll");
7
7
  const upload_1 = require("../users/upload");
8
8
  const upload_2 = require("../groups/upload");
9
9
  const uploadTypePropertyPolicies_1 = require("../types/uploadTypePropertyPolicies");
10
+ const uploadTypePolicies_1 = require("../types/uploadTypePolicies");
10
11
  class ImportInstance extends core_1.Command {
11
12
  async run() {
12
13
  const { flags } = await this.parse(ImportInstance);
@@ -14,6 +15,7 @@ class ImportInstance extends core_1.Command {
14
15
  await (0, upload_1.uploadUsers)(path.join(flags.dir, 'users.yml'));
15
16
  await (0, upload_2.uploadGroups)(path.join(flags.dir, 'groups.yml'));
16
17
  await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(flags.dir);
18
+ await (0, uploadTypePolicies_1.uploadTypePolicies)(flags.dir);
17
19
  }
18
20
  }
19
21
  exports.default = ImportInstance;
@@ -3,21 +3,27 @@ export interface DataHolder {
3
3
  types: any[];
4
4
  optionSets: any[];
5
5
  optionSetHierarchies: any[];
6
+ optionSetHierarchyLinks: any[];
6
7
  ruleSets: any[];
7
8
  ruleSetLinks: any[];
8
9
  usageInfo: any[];
9
10
  typePropertyPolicies: any[];
10
11
  typePropertyPolicyLinks: any[];
12
+ typePolicies: any[];
13
+ typePolicyLinks: any[];
11
14
  }
12
15
  export interface ReducedDataHolder {
13
16
  reducedTypes: any[];
14
17
  reducedOptionSets: any[];
15
18
  reducedOptionSetHierarchies: any[];
19
+ reducedOptionSetHierarchyLinks: any[];
16
20
  reducedRuleSets: any[];
17
21
  reducedRuleSetLinks: any[];
18
22
  reducedUsageInfo: any[];
19
23
  reducedTypePropertyPolicies: any[];
20
24
  reducedTypePropertyPolicyLinks: any[];
25
+ reducedTypePolicies: any[];
26
+ reducedTypePolicyLinks: any[];
21
27
  }
22
28
  export default class GetAllTypes extends Command {
23
29
  static description: string;
@@ -26,7 +26,7 @@ GetAllTypes.examples = [
26
26
  ];
27
27
  GetAllTypes.flags = {
28
28
  outDir: core_1.Flags.string({ char: 'd', description: 'The directory to which to export the type data. Defaults to the current directory', required: false, default: '.' }),
29
- overwrite: core_1.Flags.boolean({ description: 'Replaces any existing export files in outDir', required: false, default: false })
29
+ overwrite: core_1.Flags.boolean({ char: 'f', description: 'Replaces any existing export files in outDir', required: false, default: false })
30
30
  };
31
31
  async function getAll(outDir, overwrite) {
32
32
  try {
@@ -40,11 +40,14 @@ async function getAll(outDir, overwrite) {
40
40
  types: await (0, type_extractor_1.getTypes)(),
41
41
  optionSets: await (0, types_1.getOptionSets)(),
42
42
  optionSetHierarchies: await (0, types_1.getOptionSetHierarchies)(),
43
+ optionSetHierarchyLinks: await (0, types_1.getOptionSetHierarchyLinks)(),
43
44
  ruleSets: await (0, types_1.getRuleSets)(),
44
45
  ruleSetLinks: await (0, types_1.getRuleSetLinks)(),
45
46
  usageInfo: await (0, types_1.getUsageInfo)(),
46
47
  typePropertyPolicies: await (0, types_1.getTypePropertyPolicies)(),
47
48
  typePropertyPolicyLinks: await (0, types_1.getTypePropertyPolicyLinks)(),
49
+ typePolicies: await (0, types_1.getTypePolicies)(),
50
+ typePolicyLinks: await (0, types_1.getTypePolicyLinks)(),
48
51
  };
49
52
  const reducedData = await reduceData(data);
50
53
  await saveData(reducedData, outDir, overwrite);
@@ -101,11 +104,80 @@ async function reduceTypePropertyPolicies(data) {
101
104
  function reduceTypePropertyPolicyLinks(data) {
102
105
  var _a, _b;
103
106
  const typeProperties = (_a = data === null || data === void 0 ? void 0 : data.types) === null || _a === void 0 ? void 0 : _a.map(x => x.typeProperties).reduce((x, y) => x.concat(y));
107
+ // make a map of all type properties to their type ids
108
+ const typePropertyIdToTypeSlugMap = data.types.reduce((map, obj) => {
109
+ for (const tp of obj.typeProperties) {
110
+ map[tp.id] = obj.slug;
111
+ }
112
+ return map;
113
+ }, {});
104
114
  return (_b = data === null || data === void 0 ? void 0 : data.typePropertyPolicyLinks) === null || _b === void 0 ? void 0 : _b.map(x => {
115
+ var _a, _b;
116
+ const typeSlug = typePropertyIdToTypeSlugMap[x.typePropertyId];
117
+ const typePropertySlug = (_a = typeProperties.find(y => y.id === x.typePropertyId)) === null || _a === void 0 ? void 0 : _a.slug;
118
+ const typePropertyPolicyLabel = (_b = data.typePropertyPolicies.find(y => y.id === x.typePropertyPolicyId)) === null || _b === void 0 ? void 0 : _b.label;
119
+ if (!typeSlug ||
120
+ !typePropertySlug ||
121
+ !typePropertyPolicyLabel) {
122
+ console.warn('Could not reduce bad type property policy link... skipping', x);
123
+ return null;
124
+ }
125
+ return {
126
+ typeSlug,
127
+ typePropertySlug,
128
+ typePropertyPolicyLabel,
129
+ };
130
+ }).filter(x => !!x);
131
+ }
132
+ async function reduceTypePolicies(data) {
133
+ var _a;
134
+ const orgUsers = await (0, users_1.getUserOrgs)();
135
+ const groups = await (0, users_1.getGroups)();
136
+ function reducePrincipal(statement) {
137
+ var _a, _b;
138
+ if (!(statement === null || statement === void 0 ? void 0 : statement.principal)) {
139
+ return statement;
140
+ }
141
+ const [type, id] = statement.principal.split(':');
142
+ if (!type || !id) {
143
+ return statement;
144
+ }
145
+ if (type === 'group') {
146
+ const groupName = (_a = groups.find(x => x.id === id)) === null || _a === void 0 ? void 0 : _a.name;
147
+ if (!groupName) {
148
+ console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
149
+ return statement;
150
+ }
151
+ statement.principal = `group:${groupName}`;
152
+ }
153
+ else if (type === 'user') {
154
+ const userEmail = (_b = orgUsers.find(x => x.user.id === id)) === null || _b === void 0 ? void 0 : _b.email;
155
+ if (!userEmail) {
156
+ console.log(`Could not find group for statement. skipping invalid policy conversion ${id}`);
157
+ return statement;
158
+ }
159
+ statement.principal = `user:${userEmail}`;
160
+ }
161
+ return statement;
162
+ }
163
+ return (_a = data === null || data === void 0 ? void 0 : data.typePolicies) === null || _a === void 0 ? void 0 : _a.map(x => {
164
+ return {
165
+ label: x.label,
166
+ policy: {
167
+ version: x.policy.version,
168
+ statements: x.policy.statements.map(x => reducePrincipal(x)),
169
+ }
170
+ };
171
+ });
172
+ }
173
+ function reduceTypePolicyLinks(data) {
174
+ var _a;
175
+ const types = data === null || data === void 0 ? void 0 : data.types;
176
+ return (_a = data === null || data === void 0 ? void 0 : data.typePolicyLinks) === null || _a === void 0 ? void 0 : _a.map(x => {
105
177
  var _a, _b;
106
178
  return {
107
- typePropertySlug: (_a = typeProperties.find(y => y.id === x.typePropertyId)) === null || _a === void 0 ? void 0 : _a.slug,
108
- typePropertyPolicyLabel: (_b = data.typePropertyPolicies.find(y => y.id === x.typePropertyPolicyId)) === null || _b === void 0 ? void 0 : _b.label,
179
+ typeSlug: (_a = types.find(y => y.id === x.typeId)) === null || _a === void 0 ? void 0 : _a.slug,
180
+ typePolicyLabel: (_b = data.typePolicies.find(y => y.id === x.typePolicyId)) === null || _b === void 0 ? void 0 : _b.label,
109
181
  };
110
182
  });
111
183
  }
@@ -176,6 +248,36 @@ function reduceOptionSetHierarchies(data) {
176
248
  };
177
249
  });
178
250
  }
251
+ function reduceOptionSetHierarchyLinks(data) {
252
+ var _a;
253
+ return (_a = data.optionSetHierarchyLinks) === null || _a === void 0 ? void 0 : _a.map(x => {
254
+ var _a;
255
+ const osh = data.optionSetHierarchies.find(y => y.id === x.optionSetHierarchyId);
256
+ if (!osh) {
257
+ console.log('OSH Link: could not find option set hierarchy', x.optionSetHierarchyId, 'skipping...');
258
+ return null;
259
+ }
260
+ const type = data.types.find(y => y.id === x.typeId);
261
+ if (!type) {
262
+ console.log('OSH Link: could not find type', x.typeId, 'skipping...');
263
+ return null;
264
+ }
265
+ const typePropertySlugs = [];
266
+ for (const tpId of x.hierarchyTypePropertyIds) {
267
+ const typePropertySlug = (_a = type.typeProperties.find(y => y.id === tpId)) === null || _a === void 0 ? void 0 : _a.slug;
268
+ if (!typePropertySlug) {
269
+ console.log('OSH Link: could not find type property', tpId, 'skipping...');
270
+ return null;
271
+ }
272
+ typePropertySlugs.push(typePropertySlug);
273
+ }
274
+ return {
275
+ optionSetHierarchyName: osh.name,
276
+ typeSlug: type.slug,
277
+ typePropertySlugs,
278
+ };
279
+ }).filter(x => !!x);
280
+ }
179
281
  function reduceTypes(dataHolder) {
180
282
  console.log('Found types: ', dataHolder.types.length);
181
283
  let reducedTypes = [];
@@ -197,6 +299,7 @@ function reduceTypes(dataHolder) {
197
299
  core: typeProperty.core,
198
300
  typePropertyOptionSetName: optionSetNameById[typeProperty.typePropertyOptionSetId],
199
301
  formula: typeProperty.formula,
302
+ referencedTypePath: typeProperty.referencedTypePath,
200
303
  referencedTypeRootSlug: typeProperty.referencedTypeRootSlug,
201
304
  defaultValue: typeProperty.defaultValue,
202
305
  propertyLevel: typeProperty.propertyLevel,
@@ -230,11 +333,14 @@ async function reduceData(data) {
230
333
  reducedTypes: reduceTypes(data),
231
334
  reducedOptionSets: reduceOptionSets(data),
232
335
  reducedOptionSetHierarchies: reduceOptionSetHierarchies(data),
336
+ reducedOptionSetHierarchyLinks: reduceOptionSetHierarchyLinks(data),
233
337
  reducedRuleSets: reduceRuleSets(data),
234
338
  reducedRuleSetLinks: reduceRuleSetLinks(data),
235
339
  reducedUsageInfo: reduceUsageInfo(data),
236
340
  reducedTypePropertyPolicies: await reduceTypePropertyPolicies(data),
237
341
  reducedTypePropertyPolicyLinks: reduceTypePropertyPolicyLinks(data),
342
+ reducedTypePolicies: await reduceTypePolicies(data),
343
+ reducedTypePolicyLinks: reduceTypePolicyLinks(data),
238
344
  };
239
345
  }
240
346
  exports.reduceData = reduceData;
@@ -276,11 +382,14 @@ async function saveData(reducedData, dir, overwrite) {
276
382
  reducedTypes: { filename: 'types', split: false, fileLabel: 'slug', saveFunction: saveTypesFunction },
277
383
  reducedOptionSets: { filename: 'option-sets', split: true, fileLabel: 'name' },
278
384
  reducedOptionSetHierarchies: { filename: 'option-set-hierarchies', split: true, fileLabel: 'name' },
385
+ reducedOptionSetHierarchyLinks: { filename: 'type-option-set-hierarchy-links', split: false, fileLabel: '' },
279
386
  reducedRuleSets: { filename: 'rule-sets', split: true, fileLabel: 'name' },
280
387
  reducedRuleSetLinks: { filename: 'rule-set-links', split: false, fileLabel: '' },
281
388
  reducedUsageInfo: { filename: 'usage-info', split: false, fileLabel: '' },
282
389
  reducedTypePropertyPolicies: { filename: 'type-property-policies', split: true, fileLabel: 'label' },
283
390
  reducedTypePropertyPolicyLinks: { filename: 'type-property-policy-links', split: false, fileLabel: '' },
391
+ reducedTypePolicies: { filename: 'type-policies', split: true, fileLabel: 'label' },
392
+ reducedTypePolicyLinks: { filename: 'type-policy-links', split: false, fileLabel: '' },
284
393
  };
285
394
  for (const [key, folder] of Object.entries(propertyToFolderMap)) {
286
395
  const CURRENT_DIR = process.cwd();
@@ -11,6 +11,7 @@ const uploadUsageInfo_1 = require("./uploadUsageInfo");
11
11
  const uploadRuleSets_1 = require("./uploadRuleSets");
12
12
  const uploadTypePropertyPolicies_1 = require("./uploadTypePropertyPolicies");
13
13
  const type_uploader_1 = require("../../helpers/types/type-uploader");
14
+ const uploadTypePolicies_1 = require("./uploadTypePolicies");
14
15
  class LoadAllTypes extends core_1.Command {
15
16
  async run() {
16
17
  const { flags } = await this.parse(LoadAllTypes);
@@ -30,12 +31,13 @@ async function loadAll(dir, skipPolicies = false) {
30
31
  try {
31
32
  await (0, login_1.authUser)();
32
33
  await (0, uploadOptionSets_1.uploadOptionSets)(dir);
33
- await (0, uploadOptionSetHierarchies_1.uploadOptionSetHierarchies)(dir);
34
34
  await (0, type_uploader_1.uploadTypes)(dir);
35
+ await (0, uploadOptionSetHierarchies_1.uploadOptionSetHierarchies)(dir);
35
36
  await (0, uploadUsageInfo_1.uploadUsageInfo)(dir);
36
37
  await (0, uploadRuleSets_1.uploadRuleSets)(dir);
37
38
  if (!skipPolicies) {
38
39
  await (0, uploadTypePropertyPolicies_1.uploadTypePropertyPolicies)(dir);
40
+ await (0, uploadTypePolicies_1.uploadTypePolicies)(dir);
39
41
  }
40
42
  }
41
43
  catch (e) {
@@ -58,11 +58,14 @@ async function mergeTypeProperties(fileLocation, typePaths) {
58
58
  types: await (0, type_extractor_1.getTypes)(),
59
59
  optionSets: await (0, types_1.getOptionSets)(),
60
60
  optionSetHierarchies: [],
61
+ optionSetHierarchyLinks: [],
61
62
  ruleSets: [],
62
63
  ruleSetLinks: [],
63
64
  usageInfo: [],
64
65
  typePropertyPolicies: [],
65
66
  typePropertyPolicyLinks: [],
67
+ typePolicies: [],
68
+ typePolicyLinks: [],
66
69
  };
67
70
  const reducedData = await (0, getAll_1.reduceData)(data);
68
71
  for (const typePath of typePaths) {
@@ -8,6 +8,7 @@ const path = tslib_1.__importStar(require("path"));
8
8
  const login_1 = require("../../auth/login");
9
9
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
10
10
  const core_1 = require("@oclif/core");
11
+ const type_extractor_1 = require("../../helpers/types/type-extractor");
11
12
  const yaml = require('js-yaml');
12
13
  class UploadOptionSetHierarchies extends core_1.Command {
13
14
  async run() {
@@ -30,6 +31,8 @@ async function uploadOptionSetHierarchies(dir) {
30
31
  console.log('%s Uploading', chalk_1.default.yellow.bold('OPTION SET HIERARCHIES'));
31
32
  const optionSetHierarchies = await loadOptionSetHierarchies(dir);
32
33
  await uploadOSH(optionSetHierarchies);
34
+ const optionSetHierarchyLinks = await loadOptionSetHierarchyLinks(dir);
35
+ await uploadOSHLinks(optionSetHierarchyLinks);
33
36
  console.log('%s Uploaded', chalk_1.default.yellow.bold('OPTION SET HIERARCHIES'));
34
37
  }
35
38
  catch (e) {
@@ -53,6 +56,14 @@ function loadOptionSetHierarchies(fromDir) {
53
56
  throw new Error(`ERROR PARSING YAML: ${e}`);
54
57
  }
55
58
  }
59
+ function loadOptionSetHierarchyLinks(fromDir) {
60
+ try {
61
+ return yaml.load(fs_1.default.readFileSync(path.join(fromDir, 'type-option-set-hierarchy-links.yml'), 'utf8'));
62
+ }
63
+ catch (e) {
64
+ throw new Error(`ERROR PARSING YAML: ${e}`);
65
+ }
66
+ }
56
67
  async function uploadOSH(loadedOSHs) {
57
68
  const optionSets = await new sdk_1.Entities().get({
58
69
  entityName: 'type-property-option-set',
@@ -132,3 +143,96 @@ function transformOSHNameToID(hierarchy, optionSets) {
132
143
  }
133
144
  return true;
134
145
  }
146
+ async function uploadOSHLinks(reducedOSHLinks) {
147
+ const typesWithProperties = await (0, type_extractor_1.getTypes)();
148
+ const typeProperties = [];
149
+ typesWithProperties.forEach(type => {
150
+ if (type.typeProperties) {
151
+ for (const tp of type.typeProperties) {
152
+ tp.typeId = type.id;
153
+ tp.typeSlug = type.slug;
154
+ typeProperties.push(tp);
155
+ }
156
+ }
157
+ });
158
+ const currentOSHs = await new sdk_1.Entities().get({
159
+ entityName: 'option-set-hierarchy',
160
+ });
161
+ const currentOSHLinks = await new sdk_1.Entities().get({
162
+ entityName: 'type-option-set-hierarchy-link',
163
+ });
164
+ const currentOSHLinkHashes = {};
165
+ for (const currentLink of currentOSHLinks) {
166
+ const foundType = typesWithProperties.find(x => x.id === currentLink.typeId);
167
+ const foundOSH = currentOSHs.find(osh => osh.id === currentLink.optionSetHierarchyId);
168
+ const foundTPSlugs = typeProperties.filter(x => { var _a; return (_a = currentLink === null || currentLink === void 0 ? void 0 : currentLink.hierarchyTypePropertyIds) === null || _a === void 0 ? void 0 : _a.includes(x.id); }).map(x => x.slug);
169
+ if (!foundType || !foundOSH || (foundTPSlugs.length !== currentLink.hierarchyTypePropertyIds.length)) {
170
+ console.log('skipping unhashable, invalid type option set hierarchy link:', currentLink);
171
+ }
172
+ const hash = `${foundType.slug}|${foundOSH.name}|${foundTPSlugs.sort().join('|')}`;
173
+ currentOSHLinkHashes[hash] = currentLink;
174
+ }
175
+ const reducedLinksByHashes = {};
176
+ for (const loadedLink of reducedOSHLinks) {
177
+ const hash = `${loadedLink.typeSlug}|${loadedLink.optionSetHierarchyName}|${loadedLink.typePropertySlugs.sort().join('|')}}`;
178
+ reducedLinksByHashes[hash] = loadedLink;
179
+ }
180
+ for (const loadedLink of reducedOSHLinks) {
181
+ try {
182
+ const found = currentOSHLinkHashes[`${loadedLink.typeSlug}|${loadedLink.optionSetHierarchyName}|${loadedLink.typePropertySlugs.sort().join('|')}`];
183
+ if (!found) {
184
+ if (!transformReducedLink(loadedLink, typesWithProperties, currentOSHs)) {
185
+ continue;
186
+ }
187
+ await new sdk_1.Entities().create({
188
+ entityName: 'type-option-set-hierarchy-link',
189
+ object: {
190
+ hierarchyTypePropertyIds: loadedLink.hierarchyTypePropertyIds,
191
+ optionSetHierarchyId: loadedLink.optionSetHierarchyId,
192
+ typeId: loadedLink.typeId,
193
+ },
194
+ });
195
+ }
196
+ }
197
+ catch (err) {
198
+ throw new Error(`Error uploading type option set hierarchy links: ${err}`);
199
+ }
200
+ }
201
+ for (const [currentLinkHash, currentLink] of Object.entries(currentOSHLinkHashes)) {
202
+ try {
203
+ const found = reducedLinksByHashes[currentLinkHash];
204
+ if (!found) {
205
+ console.log('Deleting: ', currentLinkHash);
206
+ await new sdk_1.Entities().delete({
207
+ entityName: 'type-option-set-hierarchy-link',
208
+ id: currentLink['id'],
209
+ });
210
+ }
211
+ }
212
+ catch (err) {
213
+ throw new Error(`Error Deleting rule set link: ${err}`);
214
+ }
215
+ }
216
+ }
217
+ function transformReducedLink(OSHLink, typesWithProperties, OSHs) {
218
+ var _a, _b;
219
+ const foundType = typesWithProperties.find(x => x.slug === OSHLink.typeSlug);
220
+ if (!foundType) {
221
+ console.error('OSH Links: Could not find type with slug', OSHLink.typeSlug);
222
+ return false;
223
+ }
224
+ OSHLink.typeId = foundType.id;
225
+ const foundTPs = (_b = (_a = foundType === null || foundType === void 0 ? void 0 : foundType.typeProperties) === null || _a === void 0 ? void 0 : _a.filter(x => OSHLink.typePropertySlugs.includes(x.slug))) !== null && _b !== void 0 ? _b : [];
226
+ if (foundTPs.length !== OSHLink.typePropertySlugs.length) {
227
+ console.error('OSH Links: Could not find all type properties with slugs', OSHLink.typePropertySlugs);
228
+ return false;
229
+ }
230
+ OSHLink.hierarchyTypePropertyIds = foundTPs.map(x => x.id);
231
+ const foundOSH = OSHs.find(x => x.name === OSHLink.optionSetHierarchyName);
232
+ if (!foundOSH) {
233
+ console.error('OSH Links: Could not find option set hierarchy with name', OSHLink.optionSetHierarchyName);
234
+ return false;
235
+ }
236
+ OSHLink.optionSetHierarchyId = foundOSH.id;
237
+ return true;
238
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class UploadTypePolicies extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ dir: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ export declare function uploadTypePolicies(dir: string): Promise<void>;
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uploadTypePolicies = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const sdk_1 = require("@contrail/sdk");
6
+ const fs_1 = tslib_1.__importDefault(require("fs"));
7
+ const path = tslib_1.__importStar(require("path"));
8
+ const login_1 = require("../../auth/login");
9
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
10
+ const core_1 = require("@oclif/core");
11
+ const type_extractor_1 = require("../../helpers/types/type-extractor");
12
+ const users_1 = require("../../api/users");
13
+ const yaml = require('js-yaml');
14
+ class UploadTypePolicies extends core_1.Command {
15
+ async run() {
16
+ const { flags } = await this.parse(UploadTypePolicies);
17
+ return await uploadTypePolicies(flags.dir);
18
+ }
19
+ }
20
+ exports.default = UploadTypePolicies;
21
+ UploadTypePolicies.description = 'Upload type policies';
22
+ UploadTypePolicies.examples = [
23
+ `$ contrail types UploadTypePolicies
24
+ `,
25
+ ];
26
+ UploadTypePolicies.flags = {
27
+ dir: core_1.Flags.string({ char: 'd', description: 'The directory from which to export the type policy data. Defaults to the current directory. The type policy data will be loaded from $dir/type-policies/*.yml', required: false, default: '.' }),
28
+ };
29
+ async function uploadTypePolicies(dir) {
30
+ try {
31
+ await (0, login_1.authUser)();
32
+ console.log('%s Uploading', chalk_1.default.yellow.bold('TYPE POLICY'));
33
+ const [reducedTypePolicies, reducedTypePolicyLinks] = await loadTypePolicies(dir);
34
+ await uploadTypePolicyObjects(reducedTypePolicies);
35
+ await uploadTypePolicyLinks(reducedTypePolicyLinks);
36
+ console.log('%s Uploaded', chalk_1.default.yellow.bold('TYPE POLICY'));
37
+ }
38
+ catch (e) {
39
+ console.log(`%s Type Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
40
+ return;
41
+ }
42
+ console.log('%s Type Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
43
+ }
44
+ exports.uploadTypePolicies = uploadTypePolicies;
45
+ function loadTypePolicies(fromDir) {
46
+ const tps = [];
47
+ let tpLinks = [];
48
+ const dir = path.join(fromDir, 'type-policies');
49
+ try {
50
+ const files = fs_1.default.readdirSync(dir);
51
+ for (const file of files) {
52
+ tps.push(yaml.load(fs_1.default.readFileSync(path.join(dir, file), 'utf8')));
53
+ }
54
+ tpLinks = yaml.load(fs_1.default.readFileSync(path.join(fromDir, 'type-policy-links.yml'), 'utf8'));
55
+ return [tps, tpLinks];
56
+ }
57
+ catch (e) {
58
+ throw new Error(`ERROR PARSING YAML: ${e}`);
59
+ }
60
+ }
61
+ async function uploadTypePolicyObjects(reducedTypePolicies) {
62
+ const orgUsers = await (0, users_1.getUserOrgs)();
63
+ const groups = await (0, users_1.getGroups)();
64
+ function fillPrincipal(statement) {
65
+ const principal = statement === null || statement === void 0 ? void 0 : statement.principal;
66
+ if (!principal) {
67
+ console.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
68
+ return statement;
69
+ }
70
+ const [type, identifier] = principal.split(':');
71
+ if (!type || !identifier) {
72
+ console.warn(`skipping bad statement principal ${statement === null || statement === void 0 ? void 0 : statement.principal}`);
73
+ return statement;
74
+ }
75
+ if (type === 'group') {
76
+ const group = groups.find(x => x.name === identifier);
77
+ if (!group) {
78
+ console.log(`Could not find group ${identifier}`);
79
+ }
80
+ else {
81
+ statement.principal = `group:${group.id}`;
82
+ }
83
+ }
84
+ else if (type === 'user') {
85
+ const orgUser = orgUsers.find(x => x.user.email === identifier);
86
+ if (!orgUser) {
87
+ console.log(`Could not find user ${identifier}`);
88
+ }
89
+ else {
90
+ statement.principal = `user:${orgUser.user.id}`;
91
+ }
92
+ }
93
+ return statement;
94
+ }
95
+ reducedTypePolicies.forEach(policy => {
96
+ policy.policy.statements = policy.policy.statements.map(x => fillPrincipal(x));
97
+ });
98
+ const currentTypePolicies = await new sdk_1.Entities().get({
99
+ entityName: 'type-policy',
100
+ });
101
+ const currentTypePolicyByLabel = {};
102
+ for (const currentTypePolicy of currentTypePolicies) {
103
+ currentTypePolicyByLabel[currentTypePolicy.label] = currentTypePolicy;
104
+ }
105
+ const loadedTypePolicyByName = {};
106
+ for (const loadedTPP of reducedTypePolicies) {
107
+ loadedTypePolicyByName[loadedTPP.label] = loadedTPP;
108
+ }
109
+ for (const [label, loadedTPP] of Object.entries(loadedTypePolicyByName)) {
110
+ try {
111
+ const found = currentTypePolicyByLabel[label];
112
+ if (!found) {
113
+ console.log('Creating: ', label);
114
+ await new sdk_1.Entities().create({
115
+ entityName: 'type-policy',
116
+ object: loadedTPP
117
+ });
118
+ }
119
+ else {
120
+ console.log('Updating: ', label);
121
+ await new sdk_1.Entities().update({
122
+ entityName: 'type-policy',
123
+ id: found.id,
124
+ object: loadedTPP,
125
+ });
126
+ }
127
+ }
128
+ catch (err) {
129
+ throw new Error(`Error Uploading Type Policy: ${err}`);
130
+ }
131
+ }
132
+ for (const [label, currentTPP] of Object.entries(currentTypePolicyByLabel)) {
133
+ try {
134
+ const found = loadedTypePolicyByName[label];
135
+ if (!found) {
136
+ console.log('Deleting: ', label);
137
+ await new sdk_1.Entities().delete({
138
+ entityName: 'type-policy',
139
+ id: currentTPP['id'],
140
+ });
141
+ }
142
+ }
143
+ catch (err) {
144
+ throw new Error(`Error Type Policy: ${err}`);
145
+ }
146
+ }
147
+ }
148
+ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
149
+ const types = await (0, type_extractor_1.getTypes)();
150
+ const currentTypePolicies = await new sdk_1.Entities().get({
151
+ entityName: 'type-policy',
152
+ });
153
+ const currentTypePolicyLinks = await new sdk_1.Entities().get({
154
+ entityName: 'type-policy-link',
155
+ });
156
+ const currentLinksHashes = {};
157
+ for (const currentLink of currentTypePolicyLinks) {
158
+ const foundType = types.find(type => type.id === currentLink.typeId);
159
+ const foundTypePolicy = currentTypePolicies.find(tp => tp.id === currentLink.typePolicyId);
160
+ if (!foundType || !foundTypePolicy) {
161
+ console.log('skipping unhashable, invalid policy link:', currentLink);
162
+ }
163
+ const hash = `${foundType.slug}|${foundTypePolicy.label}`;
164
+ currentLinksHashes[hash] = currentLink;
165
+ }
166
+ const reducedLinksByHashes = {};
167
+ for (const loadedLink of reducedTypePolicyLinks) {
168
+ const hash = `${loadedLink.typeSlug}|${loadedLink.typePolicyLabel}`;
169
+ reducedLinksByHashes[hash] = loadedLink;
170
+ }
171
+ for (const loadedTPLink of reducedTypePolicyLinks) {
172
+ try {
173
+ const found = currentLinksHashes[`${loadedTPLink.typeSlug}|${loadedTPLink.typePolicyLabel}`];
174
+ if (!found) {
175
+ if (!transformReducedLink(loadedTPLink, types, currentTypePolicies)) {
176
+ continue;
177
+ }
178
+ await new sdk_1.Entities().create({
179
+ entityName: 'type-policy-link',
180
+ object: {
181
+ typePolicyId: loadedTPLink.typePolicyId,
182
+ typeId: loadedTPLink.typeId,
183
+ },
184
+ });
185
+ }
186
+ else {
187
+ if (!transformReducedLink(loadedTPLink, types, currentTypePolicies)) {
188
+ continue;
189
+ }
190
+ }
191
+ }
192
+ catch (err) {
193
+ throw new Error(`Error Uploading type policy links: ${err}`);
194
+ }
195
+ }
196
+ for (const [currentLinkHash, currentLink] of Object.entries(currentLinksHashes)) {
197
+ try {
198
+ const found = reducedLinksByHashes[currentLinkHash];
199
+ if (!found) {
200
+ console.log('Deleting: ', currentLinkHash);
201
+ await new sdk_1.Entities().delete({
202
+ entityName: 'type-policy-link',
203
+ id: currentLink['id'],
204
+ });
205
+ }
206
+ }
207
+ catch (err) {
208
+ throw new Error(`Error Deleting rule set link: ${err}`);
209
+ }
210
+ }
211
+ }
212
+ function transformReducedLink(typePolicyLink, types, typePolicies) {
213
+ const foundType = types.find(type => type.slug === typePolicyLink.typeSlug);
214
+ if (!foundType) {
215
+ console.error('Could not find type with slug', typePolicyLink.typeSlug);
216
+ return false;
217
+ }
218
+ typePolicyLink.typeId = foundType.id;
219
+ const foundTypePolicy = typePolicies.find(tpp => tpp.label === typePolicyLink.typePolicyLabel);
220
+ if (!foundTypePolicy) {
221
+ console.error('Could not find type policy with label', typePolicyLink.typePolicyLabel);
222
+ return false;
223
+ }
224
+ typePolicyLink.typePolicyId = foundTypePolicy.id;
225
+ return true;
226
+ }
@@ -37,6 +37,8 @@ async function uploadTypePropertyPolicies(dir) {
37
37
  }
38
38
  catch (e) {
39
39
  console.log(`%s Type Property Policy Upload Failed. ${e}`, chalk_1.default.red.bold('FAIL'));
40
+ //TODO make this only print if a debug flag is set
41
+ console.trace(e);
40
42
  return;
41
43
  }
42
44
  console.log('%s Type Property Policy Upload Complete.', chalk_1.default.green.bold('COMPLETE'));
@@ -147,10 +149,16 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
147
149
  }
148
150
  async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
149
151
  const typesWithProperties = await (0, type_extractor_1.getTypes)();
150
- const typeProperties = typesWithProperties
151
- .filter(t => !!t.typeProperties)
152
- .map(t => t.typeProperties)
153
- .reduce((a, b) => a.concat(b));
152
+ const typeProperties = [];
153
+ typesWithProperties.forEach(type => {
154
+ if (type.typeProperties) {
155
+ for (const tp of type.typeProperties) {
156
+ tp.typeId = type.id;
157
+ tp.typeSlug = type.slug;
158
+ typeProperties.push(tp);
159
+ }
160
+ }
161
+ });
154
162
  const currentTPPs = await new sdk_1.Entities().get({
155
163
  entityName: 'type-property-policy',
156
164
  });
@@ -164,17 +172,17 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
164
172
  if (!foundTypeProperty || !foundTPP) {
165
173
  console.log('skipping unhashable, invalid policy link:', currentLink);
166
174
  }
167
- const hash = `${foundTypeProperty.slug}|${foundTPP.label}`;
175
+ const hash = `${foundTypeProperty.typeSlug}${foundTypeProperty.slug}|${foundTPP.label}`;
168
176
  currentLinksHashes[hash] = currentLink;
169
177
  }
170
178
  const reducedLinksByHashes = {};
171
179
  for (const loadedLink of reducedTypePropertyPolicyLinks) {
172
- const hash = `${loadedLink.typePropertySlug}|${loadedLink.typePropertyPolicyLabel}`;
180
+ const hash = `${loadedLink.typeSlug}|${loadedLink.typePropertySlug}|${loadedLink.typePropertyPolicyLabel}`;
173
181
  reducedLinksByHashes[hash] = loadedLink;
174
182
  }
175
183
  for (const loadedTPPLink of reducedTypePropertyPolicyLinks) {
176
184
  try {
177
- const found = currentLinksHashes[`${loadedTPPLink.typePropertySlug}|${loadedTPPLink.typePropertyPolicyLabel}`];
185
+ const found = currentLinksHashes[`${loadedTPPLink.typeSlug}|${loadedTPPLink.typePropertySlug}|${loadedTPPLink.typePropertyPolicyLabel}`];
178
186
  if (!found) {
179
187
  if (!transformReducedLink(loadedTPPLink, typeProperties, currentTPPs)) {
180
188
  continue;
@@ -209,12 +217,12 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
209
217
  }
210
218
  }
211
219
  catch (err) {
212
- throw new Error(`Error Deleting rule set link: ${err}`);
220
+ throw new Error(`Error Deleting type property policy link: ${err}`);
213
221
  }
214
222
  }
215
223
  }
216
224
  function transformReducedLink(TPPLink, typeProperties, typePropertyPolicies) {
217
- const foundTP = typeProperties.find(tp => tp.slug === TPPLink.typePropertySlug);
225
+ const foundTP = typeProperties.find(tp => tp.slug === TPPLink.typePropertySlug && tp.typeSlug === TPPLink.typeSlug);
218
226
  if (!foundTP) {
219
227
  console.error('Could not find type property with label', TPPLink.typePropertySlug);
220
228
  return false;
@@ -52,13 +52,6 @@ class AppDeployer {
52
52
  if (appDeclaration === null || appDeclaration === void 0 ? void 0 : appDeclaration.triggers) {
53
53
  triggerKeyDefinitions = app_template_parsers_1.TriggerKeyDefinitionParser.buildTriggersArray(appDeclaration);
54
54
  }
55
- // does appDeclaration have dockerImageRef
56
- const isDocker = Object.hasOwnProperty.call(appDeclaration, 'dockerImageRef');
57
- let appCodePackageId;
58
- if (!isDocker) { // this is the expected default behavior
59
- const appCodePackage = await createNodePackage(appDeclaration.appIdentifier, this.debug, this.dryRun);
60
- appCodePackageId = appCodePackage.id;
61
- }
62
55
  const newApp = {
63
56
  identifier: appDeclaration.appIdentifier,
64
57
  name: appDeclaration.appName,
@@ -72,7 +65,6 @@ class AppDeployer {
72
65
  configProperties,
73
66
  triggerKeyDefinitions,
74
67
  dockerImageRef: (_a = appDeclaration.dockerImageRef) !== null && _a !== void 0 ? _a : null,
75
- appCodePackageId: appCodePackageId !== null && appCodePackageId !== void 0 ? appCodePackageId : null,
76
68
  frameworkVersion: 2,
77
69
  };
78
70
  if (this.dryRun) {
@@ -81,6 +73,13 @@ class AppDeployer {
81
73
  }
82
74
  const app = await new sdk_1.Entities().create({ entityName: 'app', object: newApp });
83
75
  console.log(`%s Created new app: ${app.name}`, chalk_1.default.yellow.bold('APP'));
76
+ const isDocker = Object.hasOwnProperty.call(appDeclaration, 'dockerImageRef');
77
+ if (!isDocker) { // this is the expected default behavior
78
+ const appCodePackage = await createNodePackage(appDeclaration.appIdentifier, this.debug, this.dryRun);
79
+ app.appCodePackageId = appCodePackage.id;
80
+ await new sdk_1.Entities().update({ entityName: 'app', object: app });
81
+ console.log(`%s Updated app with code package: ${app.name}`, chalk_1.default.yellow.bold('APP'));
82
+ }
84
83
  return app;
85
84
  }
86
85
  async updateExistingApp(appDeclaration, existingApp) {
@@ -159,6 +158,9 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
159
158
  console.log('Building package...');
160
159
  child_process.execSync('npx tsc --outDir tmp/dist');
161
160
  console.log('Building package done.');
161
+ console.log('Copying Assets...');
162
+ child_process.execSync('npx copyfiles assets/**/* tmp/dist/');
163
+ console.log('Copying Assets done.');
162
164
  // including the app.yml file in the package at the dist level
163
165
  fs.cpSync('app.yml', 'tmp/dist/app.yml');
164
166
  console.log('Zipping package...');
@@ -1 +1 @@
1
- export declare function getTypes(): Promise<any[]>;
1
+ export declare function getTypes(withTypeProperties?: boolean): Promise<any>;
@@ -6,13 +6,16 @@ const sdk_1 = require("@contrail/sdk");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const p_limit_1 = tslib_1.__importDefault(require("p-limit"));
8
8
  const limit = (0, p_limit_1.default)(30);
9
- async function getTypes() {
9
+ async function getTypes(withTypeProperties = true) {
10
10
  console.log('%s Retrieving', chalk_1.default.yellow.bold('TYPES'));
11
11
  const entitiesClient = new sdk_1.Entities();
12
12
  const types = await entitiesClient.get({
13
13
  entityName: 'type',
14
14
  });
15
15
  console.log(`${chalk_1.default.yellow.bold('TYPES')} Found ${types.length} types`);
16
+ if (!withTypeProperties) {
17
+ return types;
18
+ }
16
19
  const typesWithProperties = [];
17
20
  const promises = [];
18
21
  for (const type of types) {
@@ -78,7 +78,8 @@ async function uploadReducedTypes(dir) {
78
78
  isArchived: type.isArchived,
79
79
  },
80
80
  });
81
- await uploadReducedTypeProperties(createdType, [], type.typeProperties);
81
+ const newTypeProperties = (await new sdk_1.Types().getType({ id: createdType.id })).typeProperties;
82
+ await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties);
82
83
  }
83
84
  else {
84
85
  console.log('Updating Type: ', type.slug);
@@ -148,11 +149,13 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
148
149
  core: newPropertyType.core,
149
150
  typePropertyOptionSetId: optionSetIdByName[newPropertyType.typePropertyOptionSetName],
150
151
  formula: newPropertyType.formula,
152
+ referencedTypePath: newPropertyType.referencedTypePath,
151
153
  referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug,
152
154
  defaultValue: newPropertyType.defaultValue,
153
155
  propertyLevel: newPropertyType.propertyLevel,
154
156
  formulaFunction: newPropertyType.formulaFunction,
155
157
  validationFunction: newPropertyType.validationFunction,
158
+ numberFormat: newPropertyType.numberFormat,
156
159
  }),
157
160
  headers: {
158
161
  Accept: 'application/json',
@@ -175,11 +178,13 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
175
178
  core: newPropertyType.core,
176
179
  typePropertyOptionSetId: optionSetIdByName[newPropertyType.typePropertyOptionSetName],
177
180
  formula: newPropertyType.formula,
181
+ referencedTypePath: newPropertyType.referencedTypePath,
178
182
  referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug,
179
183
  defaultValue: newPropertyType.defaultValue,
180
184
  propertyLevel: newPropertyType.propertyLevel,
181
185
  formulaFunction: newPropertyType.formulaFunction,
182
186
  validationFunction: newPropertyType.validationFunction,
187
+ numberFormat: newPropertyType.numberFormat,
183
188
  },
184
189
  });
185
190
  }
@@ -218,11 +223,13 @@ function typePropertiesEqual(typeProperty1, typeProperty2, optionSetIdByName) {
218
223
  core: typeProperty1.core,
219
224
  typePropertyOptionSetId: optionSetIdByName[typeProperty1.typePropertyOptionSetName],
220
225
  formula: typeProperty1.formula,
226
+ referencedTypePath: typeProperty1.referencedTypePath,
221
227
  referencedTypeRootSlug: typeProperty1.referencedTypeRootSlug,
222
228
  defaultValue: typeProperty1.defaultValue,
223
229
  propertyLevel: typeProperty1.propertyLevel,
224
230
  formulaFunction: typeProperty1.formulaFunction,
225
231
  validationFunction: typeProperty1.validationFunction,
232
+ numberFormat: typeProperty1.numberFormat,
226
233
  };
227
234
  const reducedProperty2 = {
228
235
  isArchived: typeProperty2.isArchived,
@@ -234,11 +241,13 @@ function typePropertiesEqual(typeProperty1, typeProperty2, optionSetIdByName) {
234
241
  core: typeProperty2.core,
235
242
  typePropertyOptionSetId: optionSetIdByName[typeProperty2.typePropertyOptionSetName],
236
243
  formula: typeProperty2.formula,
244
+ referencedTypePath: typeProperty2.referencedTypePath,
237
245
  referencedTypeRootSlug: typeProperty2.referencedTypeRootSlug,
238
246
  defaultValue: typeProperty2.defaultValue,
239
247
  propertyLevel: typeProperty2.propertyLevel,
240
248
  formulaFunction: typeProperty2.formulaFunction,
241
249
  validationFunction: typeProperty2.validationFunction,
250
+ numberFormat: typeProperty2.numberFormat,
242
251
  };
243
252
  return _.isEqual(reducedProperty1, reducedProperty2);
244
253
  }
@@ -301,6 +301,7 @@ export interface ReducedTypeProperty {
301
301
  core: boolean;
302
302
  typePropertyOptionSetName: string;
303
303
  formula: string;
304
+ referencedTypePath: string;
304
305
  referencedTypeRootSlug: string;
305
306
  defaultValue: string;
306
307
  propertyLevel: string;
@@ -0,0 +1,3 @@
1
+ {
2
+ "foo": "bar"
3
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.1.2",
2
+ "version": "2.1.4",
3
3
  "commands": {
4
4
  "app:create": {
5
5
  "id": "app:create",
@@ -556,6 +556,7 @@
556
556
  "overwrite": {
557
557
  "name": "overwrite",
558
558
  "type": "boolean",
559
+ "char": "f",
559
560
  "description": "Replaces any existing export files in outDir",
560
561
  "required": false,
561
562
  "allowNo": false
@@ -890,6 +891,30 @@
890
891
  },
891
892
  "args": {}
892
893
  },
894
+ "types:uploadTypePolicies": {
895
+ "id": "types:uploadTypePolicies",
896
+ "description": "Upload type policies",
897
+ "strict": true,
898
+ "pluginName": "@contrail/cli",
899
+ "pluginAlias": "@contrail/cli",
900
+ "pluginType": "core",
901
+ "aliases": [],
902
+ "examples": [
903
+ "$ contrail types UploadTypePolicies\n"
904
+ ],
905
+ "flags": {
906
+ "dir": {
907
+ "name": "dir",
908
+ "type": "option",
909
+ "char": "d",
910
+ "description": "The directory from which to export the type policy data. Defaults to the current directory. The type policy data will be loaded from $dir/type-policies/*.yml",
911
+ "required": false,
912
+ "multiple": false,
913
+ "default": "."
914
+ }
915
+ },
916
+ "args": {}
917
+ },
893
918
  "types:uploadTypePropertyPolicies": {
894
919
  "id": "types:uploadTypePropertyPolicies",
895
920
  "description": "Upload type property policies",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "bin": {
6
6
  "contrail-cli": "./bin/run",
@@ -22,7 +22,7 @@
22
22
  "/oclif.manifest.json"
23
23
  ],
24
24
  "dependencies": {
25
- "@contrail/sdk": "^1.2.0",
25
+ "@contrail/sdk": "^1.2.3",
26
26
  "@contrail/types": "^3.0.20",
27
27
  "@contrail/util": "^1.0.17",
28
28
  "@oclif/core": "^2",