@contrail/cli 2.2.1 → 2.2.3

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
@@ -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.1 darwin-arm64 node-v18.13.0
20
+ @contrail/cli/2.2.3 darwin-arm64 node-v18.13.0
21
21
  $ contrail --help [COMMAND]
22
22
  USAGE
23
23
  $ contrail COMMAND
@@ -52,6 +52,7 @@ class CreateApp extends basecommand_1.BaseCommand {
52
52
  }
53
53
  const newApp = {
54
54
  identifier: sanitizedIdentifier,
55
+ version: '1.0.0',
55
56
  name: answers.appName,
56
57
  publisher: answers.appPublisher,
57
58
  public: false,
@@ -13,7 +13,7 @@ class DeleteApp extends basecommand_1.BaseCommand {
13
13
  appDeclaration = (0, load_app_config_1.loadAppConfig)();
14
14
  }
15
15
  catch (e) {
16
- this.error(`%s Application Removal Failed. ${e}`);
16
+ logger_1.default.error(`%s Application Removal Failed. ${e}`);
17
17
  return;
18
18
  }
19
19
  logger_1.default.info(`Removing Application. ${appDeclaration.appIdentifier}`);
@@ -14,7 +14,7 @@ class AppMajorVersionUpgrade extends basecommand_1.BaseCommand {
14
14
  async run() {
15
15
  let appDeclaration;
16
16
  try {
17
- appDeclaration = (0, load_app_config_1.loadAppConfig)();
17
+ appDeclaration = (0, load_app_config_1.loadAppConfig)({ skipValidation: true });
18
18
  }
19
19
  catch (e) {
20
20
  logger_1.default.error(`Application Load Configuration Failed: ${e}`);
@@ -14,7 +14,7 @@ class AppMinorVersionUpgrade extends basecommand_1.BaseCommand {
14
14
  async run() {
15
15
  let appDeclaration;
16
16
  try {
17
- appDeclaration = (0, load_app_config_1.loadAppConfig)();
17
+ appDeclaration = (0, load_app_config_1.loadAppConfig)({ skipValidation: true });
18
18
  }
19
19
  catch (e) {
20
20
  logger_1.default.error(`Application Load Configuration Failed: ${e}`);
@@ -14,7 +14,7 @@ class AppPatchVersionUpgrade extends basecommand_1.BaseCommand {
14
14
  async run() {
15
15
  let appDeclaration;
16
16
  try {
17
- appDeclaration = (0, load_app_config_1.loadAppConfig)();
17
+ appDeclaration = (0, load_app_config_1.loadAppConfig)({ skipValidation: true });
18
18
  }
19
19
  catch (e) {
20
20
  logger_1.default.error(`Application Load Configuration Failed: ${e}`);
@@ -99,7 +99,7 @@ async function uploadOSH(loadedOSHs) {
99
99
  if (!transformOSHNameToID(osh.hierarchy, optionSets)) {
100
100
  continue;
101
101
  }
102
- logger_1.default.debug(`Creating: ': ${JSON.stringify(osh)}`);
102
+ logger_1.default.debug(`Creating: ${JSON.stringify(osh)}`);
103
103
  await new sdk_1.Entities().create({
104
104
  entityName: 'option-set-hierarchy',
105
105
  object: osh,
@@ -201,7 +201,7 @@ async function uploadOSHLinks(reducedOSHLinks) {
201
201
  if (!transformReducedLink(loadedLink, typesWithProperties, currentOSHs)) {
202
202
  continue;
203
203
  }
204
- logger_1.default.debug(`Creating: ': ${JSON.stringify(loadedLink)}`);
204
+ logger_1.default.debug(`Creating: ${JSON.stringify(loadedLink)}`);
205
205
  await new sdk_1.Entities().create({
206
206
  entityName: 'type-option-set-hierarchy-link',
207
207
  object: {
@@ -101,7 +101,7 @@ async function uploadOptionSetHierarchiesLocalFile(fileLocation, name) {
101
101
  });
102
102
  const existing = currentOptionSetHierarchies.find((osh) => osh.name === name);
103
103
  if (existing) {
104
- logger_1.default.info(`Updating: ': ${optionSetHierarchy.name}`);
104
+ logger_1.default.info(`Updating: ${optionSetHierarchy.name}`);
105
105
  await new sdk_1.Entities().update({
106
106
  entityName: 'option-set-hierarchy',
107
107
  id: existing.id,
@@ -109,7 +109,7 @@ async function uploadOptionSetHierarchiesLocalFile(fileLocation, name) {
109
109
  });
110
110
  }
111
111
  else {
112
- logger_1.default.info(`Creating: ': ${optionSetHierarchy.name}`);
112
+ logger_1.default.info(`Creating: ${optionSetHierarchy.name}`);
113
113
  await new sdk_1.Entities().create({
114
114
  entityName: 'option-set-hierarchy',
115
115
  object: optionSetHierarchy,
@@ -117,14 +117,14 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
117
117
  try {
118
118
  const found = currentTypePolicyByIdentifier[identifier];
119
119
  if (!found) {
120
- logger_1.default.info(`Creating: ': ${identifier}`);
120
+ logger_1.default.info(`Creating: ${identifier}`);
121
121
  await new sdk_1.Entities().create({
122
122
  entityName: 'type-policy',
123
123
  object: loadedTPP,
124
124
  });
125
125
  }
126
126
  else {
127
- logger_1.default.info(`Updating: ': ${identifier}`);
127
+ logger_1.default.info(`Updating: ${identifier}`);
128
128
  await new sdk_1.Entities().update({
129
129
  entityName: 'type-policy',
130
130
  id: found.id,
@@ -140,7 +140,7 @@ async function uploadTypePolicyObjects(reducedTypePolicies) {
140
140
  try {
141
141
  const found = loadedTypePolicyByIdentifier[identifier];
142
142
  if (!found) {
143
- logger_1.default.info(`Deleting: ': ${identifier}`);
143
+ logger_1.default.info(`Deleting: ${identifier}`);
144
144
  await new sdk_1.Entities().delete({
145
145
  entityName: 'type-policy',
146
146
  id: currentTPP['id'],
@@ -165,7 +165,7 @@ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
165
165
  const foundType = types.find((type) => type.id === currentLink.typeId);
166
166
  const foundTypePolicy = currentTypePolicies.find((tp) => tp.id === currentLink.typePolicyId);
167
167
  if (!foundType || !foundTypePolicy) {
168
- logger_1.default.info(`skipping unhashable, invalid policy link:': ${currentLink}`);
168
+ logger_1.default.info(`skipping unhashable, invalid policy link: ${currentLink}`);
169
169
  }
170
170
  const hash = `${foundType.slug}|${foundTypePolicy.identifier}`;
171
171
  currentLinksHashes[hash] = currentLink;
@@ -204,7 +204,7 @@ async function uploadTypePolicyLinks(reducedTypePolicyLinks) {
204
204
  try {
205
205
  const found = reducedLinksByHashes[currentLinkHash];
206
206
  if (!found) {
207
- logger_1.default.info(`Deleting: ': ${currentLinkHash}`);
207
+ logger_1.default.info(`Deleting: ${currentLinkHash}`);
208
208
  await new sdk_1.Entities().delete({
209
209
  entityName: 'type-policy-link',
210
210
  id: currentLink['id'],
@@ -119,14 +119,14 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
119
119
  try {
120
120
  const found = currentTPPByLabel[label];
121
121
  if (!found) {
122
- logger_1.default.info(`Creating: ': ${label}`);
122
+ logger_1.default.info(`Creating: ${label}`);
123
123
  await new sdk_1.Entities().create({
124
124
  entityName: 'type-property-policy',
125
125
  object: loadedTPP,
126
126
  });
127
127
  }
128
128
  else {
129
- logger_1.default.info(`Updating: ': ${label}`);
129
+ logger_1.default.info(`Updating: ${label}`);
130
130
  await new sdk_1.Entities().update({
131
131
  entityName: 'type-property-policy',
132
132
  id: found.id,
@@ -142,7 +142,7 @@ async function uploadTPPolicyObjects(reducedTypePropertyPolicies) {
142
142
  try {
143
143
  const found = loadedTPPByName[label];
144
144
  if (!found) {
145
- logger_1.default.info(`Deleting: ': ${label}`);
145
+ logger_1.default.info(`Deleting: ${label}`);
146
146
  await new sdk_1.Entities().delete({
147
147
  entityName: 'type-property-policy',
148
148
  id: currentTPP['id'],
@@ -177,7 +177,7 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
177
177
  const foundTypeProperty = typeProperties.find((tp) => tp.id === currentLink.typePropertyId);
178
178
  const foundTPP = currentTPPs.find((tpp) => tpp.id === currentLink.typePropertyPolicyId);
179
179
  if (!foundTypeProperty || !foundTPP) {
180
- logger_1.default.info(`skipping unhashable, invalid policy link:': ${currentLink}`);
180
+ logger_1.default.info(`skipping unhashable, invalid policy link: ${currentLink}`);
181
181
  }
182
182
  const hash = `${foundTypeProperty.typeSlug}${foundTypeProperty.slug}|${foundTPP.identifier}`;
183
183
  currentLinksHashes[hash] = currentLink;
@@ -216,7 +216,7 @@ async function uploadTypePropertyPolicyLinks(reducedTypePropertyPolicyLinks) {
216
216
  try {
217
217
  const found = reducedLinksByHashes[currentLinkHash];
218
218
  if (!found) {
219
- logger_1.default.info(`Deleting: ': ${currentLinkHash}`);
219
+ logger_1.default.info(`Deleting: ${currentLinkHash}`);
220
220
  await new sdk_1.Entities().delete({
221
221
  entityName: 'type-property-policy-link',
222
222
  id: currentLink['id'],
@@ -70,7 +70,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
70
70
  const foundType = typesWithProperties.find((t) => t.id === currentUI.typeId);
71
71
  const foundTypeProperty = typeProperties.find((tp) => tp.id === currentUI.typePropertyId);
72
72
  if (!foundType || !foundTypeProperty) {
73
- logger_1.default.info(`skipping unhashable, invalid usage info:': ${currentUI}`);
73
+ logger_1.default.info(`skipping unhashable, invalid usage info: ${currentUI}`);
74
74
  continue;
75
75
  }
76
76
  const hash = `${foundType.slug}|${foundTypeProperty.slug}`;
@@ -81,7 +81,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
81
81
  const hash = `${loadedUI.typeSlug}|${loadedUI.typePropertySlug}`;
82
82
  reducedUsageInfoHashes[hash] = loadedUI;
83
83
  }
84
- logger_1.default.debug(`current usage info:': ${currentUsageInfo}`);
84
+ logger_1.default.debug(`current usage info: ${currentUsageInfo}`);
85
85
  logger_1.default.debug('loaded usage info:', loadedUsageInfo);
86
86
  for (const loadedUI of loadedUsageInfo) {
87
87
  try {
@@ -90,7 +90,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
90
90
  if (!transformReducedUI(loadedUI, typesWithProperties, typeProperties)) {
91
91
  continue;
92
92
  }
93
- logger_1.default.debug(`Creating: ': ${loadedUI}`);
93
+ logger_1.default.debug(`Creating: ${loadedUI}`);
94
94
  await new sdk_1.Entities().create({
95
95
  entityName: 'type-property-usage-info',
96
96
  object: {
@@ -110,7 +110,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
110
110
  if (!transformReducedUI(loadedUI, typesWithProperties, typeProperties)) {
111
111
  continue;
112
112
  }
113
- logger_1.default.info(`Updating: ': ${loadedUI}`);
113
+ logger_1.default.info(`Updating: ${loadedUI}`);
114
114
  await new sdk_1.Entities().update({
115
115
  entityName: 'type-property-usage-info',
116
116
  id: found.id,
@@ -129,7 +129,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
129
129
  try {
130
130
  const found = reducedUsageInfoHashes[hash];
131
131
  if (!found) {
132
- logger_1.default.debug(`Creating: ': ${hash}`);
132
+ logger_1.default.debug(`Creating: ${hash}`);
133
133
  await new sdk_1.Entities().delete({
134
134
  entityName: 'type-property-usage-info',
135
135
  id: currentUI['id'],
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const login_1 = require("../../auth/login");
5
4
  const webhooks_1 = require("../../api/webhooks");
5
+ const login_1 = require("../../auth/login");
6
6
  const basecommand_1 = require("../../basecommand");
7
7
  class ListWebhooks extends basecommand_1.BaseCommand {
8
8
  async run() {
@@ -0,0 +1,7 @@
1
+ import { AppDeclaration } from '../../interfaces';
2
+ export interface AppConfigValidationError {
3
+ error: string;
4
+ }
5
+ export declare function validateAppConfig(appConfig: AppDeclaration): void;
6
+ export declare function appVersionValidator(appDeclaration: AppDeclaration): AppConfigValidationError;
7
+ export declare function visibilityValidator(appDeclaration: AppDeclaration): AppConfigValidationError;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.visibilityValidator = exports.appVersionValidator = exports.validateAppConfig = void 0;
4
+ const VALIDATORS = [appVersionValidator, visibilityValidator];
5
+ function validateAppConfig(appConfig) {
6
+ const errors = [];
7
+ for (const validator of VALIDATORS) {
8
+ const error = validator(appConfig);
9
+ if (error) {
10
+ errors.push(error);
11
+ }
12
+ }
13
+ if (errors.length) {
14
+ throw new Error(`Invalid app config: \n ${errors.map((x) => x.error).join('\n')}`);
15
+ }
16
+ }
17
+ exports.validateAppConfig = validateAppConfig;
18
+ function appVersionValidator(appDeclaration) {
19
+ if (!appDeclaration.version) {
20
+ return {
21
+ error: 'Missing "version" field". Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
22
+ };
23
+ }
24
+ if (typeof appDeclaration.version !== 'string') {
25
+ return {
26
+ error: '"version" field is not a string. Expecting a version like "1.0.0". Manually update the "version" field to be a string in the app.yml file.',
27
+ };
28
+ }
29
+ const parts = appDeclaration.version.split('.');
30
+ if (parts.length !== 3) {
31
+ return {
32
+ error: 'Invalid app version. Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
33
+ };
34
+ }
35
+ }
36
+ exports.appVersionValidator = appVersionValidator;
37
+ function visibilityValidator(appDeclaration) {
38
+ if (!['public', 'private'].includes(appDeclaration.visibility)) {
39
+ return {
40
+ error: 'Invalid visibility. Visibility must be "public" or "private".',
41
+ };
42
+ }
43
+ if (appDeclaration.visibility === 'private' && appDeclaration.hidden !== true) {
44
+ return {
45
+ error: 'Apps can not be private and hidden.',
46
+ };
47
+ }
48
+ }
49
+ exports.visibilityValidator = visibilityValidator;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const app_config_validators_1 = require("./app-config-validators");
4
+ describe('appVersionValidator', () => {
5
+ it('should return an error if "version" field is missing', () => {
6
+ const appDeclaration = {};
7
+ const expectedError = {
8
+ error: 'Missing "version" field". Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
9
+ };
10
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
11
+ expect(validationResult).toEqual(expectedError);
12
+ });
13
+ it('should return an error if app version is invalid', () => {
14
+ const appDeclaration = {
15
+ version: 'invalidVersion',
16
+ };
17
+ const expectedError = {
18
+ error: 'Invalid app version. Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
19
+ };
20
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
21
+ expect(validationResult).toEqual(expectedError);
22
+ });
23
+ it('should not return an error if app version is valid', () => {
24
+ const appDeclaration = {
25
+ version: '1.0.0',
26
+ };
27
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
28
+ expect(validationResult).toBeUndefined();
29
+ });
30
+ it('should gracefully handle bad versions', () => {
31
+ const appDeclaration = {
32
+ version: '1',
33
+ };
34
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
35
+ expect(validationResult.error).toEqual('Invalid app version. Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.');
36
+ });
37
+ });
38
+ it('should return an error if "version" field is not a string', () => {
39
+ const appDeclaration = {
40
+ version: 123,
41
+ };
42
+ const expectedError = {
43
+ error: '"version" field is not a string. Expecting a version like "1.0.0". Manually update the "version" field to be a string in the app.yml file.',
44
+ };
45
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
46
+ expect(validationResult).toEqual(expectedError);
47
+ });
48
+ it('should return an error if "version" field is empty', () => {
49
+ const appDeclaration = {
50
+ version: '',
51
+ };
52
+ const expectedError = {
53
+ error: 'Missing "version" field". Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
54
+ };
55
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
56
+ expect(validationResult).toEqual(expectedError);
57
+ });
58
+ it('should return an error if app version has invalid format', () => {
59
+ const appDeclaration = {
60
+ version: '1.0',
61
+ };
62
+ const expectedError = {
63
+ error: 'Invalid app version. Semantic App Version looks like "1.0.0". Use "contrail app version [patch|minor|major]" to update the app version.',
64
+ };
65
+ const validationResult = (0, app_config_validators_1.appVersionValidator)(appDeclaration);
66
+ expect(validationResult).toEqual(expectedError);
67
+ });
@@ -61,6 +61,7 @@ class AppDeployer {
61
61
  const newApp = {
62
62
  identifier: appDeclaration.appIdentifier,
63
63
  name: appDeclaration.appName,
64
+ version: appDeclaration.version,
64
65
  public: appDeclaration.visibility === 'public',
65
66
  hidden: appDeclaration.hidden,
66
67
  description: appDeclaration.appDescription,
@@ -113,6 +114,7 @@ class AppDeployer {
113
114
  : [];
114
115
  const updates = {
115
116
  name: appDeclaration.appName,
117
+ version: appDeclaration.version,
116
118
  public: appDeclaration.visibility === 'public',
117
119
  hidden: appDeclaration.hidden,
118
120
  description: appDeclaration.appDescription,
@@ -127,6 +129,7 @@ class AppDeployer {
127
129
  appCodePackageId: appCodePackageId !== null && appCodePackageId !== void 0 ? appCodePackageId : null,
128
130
  frameworkVersion: 2,
129
131
  };
132
+ logger_1.default.debug(`app update: ${JSON.stringify(updates, null, 2)}`);
130
133
  if (this.dryRun) {
131
134
  logger_1.default.info('Dry run, not creating app');
132
135
  return {};
@@ -1,2 +1,4 @@
1
1
  import { AppDeclaration } from '../../interfaces';
2
- export declare function loadAppConfig(): AppDeclaration;
2
+ export declare function loadAppConfig(config?: {
3
+ skipValidation: boolean;
4
+ }): AppDeclaration;
@@ -5,10 +5,14 @@ const tslib_1 = require("tslib");
5
5
  const path = tslib_1.__importStar(require("path"));
6
6
  const fs_1 = tslib_1.__importDefault(require("fs"));
7
7
  const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
8
- function loadAppConfig() {
8
+ const app_config_validators_1 = require("./app-config-validators");
9
+ function loadAppConfig(config = { skipValidation: false }) {
9
10
  const TARGET_DIR = process.cwd();
10
11
  try {
11
12
  const doc = js_yaml_1.default.load(fs_1.default.readFileSync(path.resolve(path.join(TARGET_DIR, 'app.yml')), 'utf8'));
13
+ if (!(config === null || config === void 0 ? void 0 : config.skipValidation)) {
14
+ (0, app_config_validators_1.validateAppConfig)(doc);
15
+ }
12
16
  return doc;
13
17
  }
14
18
  catch (e) {
@@ -69,7 +69,7 @@ async function uploadReducedTypes(dir) {
69
69
  logger_1.default.info(`Cannot create a base type. Skipping: ${type.slug}`);
70
70
  continue;
71
71
  }
72
- logger_1.default.info(`Creating Type: ': ${type.slug}`);
72
+ logger_1.default.info(`Creating Type: ${type.slug}`);
73
73
  const createdType = await new sdk_1.Entities().create({
74
74
  entityName: 'type',
75
75
  object: {
@@ -84,7 +84,7 @@ async function uploadReducedTypes(dir) {
84
84
  await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties);
85
85
  }
86
86
  else {
87
- logger_1.default.info(`Updating Type: ': ${type.slug}`);
87
+ logger_1.default.info(`Updating Type: ${type.slug}`);
88
88
  const updatedType = await new sdk_1.Entities().update({
89
89
  entityName: 'type',
90
90
  id: found.id,
@@ -124,7 +124,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
124
124
  try {
125
125
  const found = currentPropertyTypeBySlug[newPropertyType.slug];
126
126
  if (!found && !newPropertyType.inherited) {
127
- logger_1.default.info(`Creating Type-Property: ': ${newPropertyType.slug}`);
127
+ logger_1.default.info(`Creating Type-Property: ${newPropertyType.slug}`);
128
128
  await sdk_1.Request.request(`/types/${type.id}/type-properties`, {
129
129
  method: 'POST',
130
130
  body: JSON.stringify({
@@ -155,7 +155,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
155
155
  else if (found &&
156
156
  !newPropertyType.inherited &&
157
157
  !typePropertiesEqual(found, newPropertyType, optionSetIdByIdentifier)) {
158
- logger_1.default.info(`Updating Type-Property: ': ${newPropertyType.slug}`);
158
+ logger_1.default.info(`Updating Type-Property: ${newPropertyType.slug}`);
159
159
  await new sdk_1.Entities().update({
160
160
  entityName: 'type-property',
161
161
  id: found.id,
@@ -189,7 +189,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
189
189
  try {
190
190
  const found = newPropertyTypesBySlug[currentPropertyType.slug];
191
191
  if (!found && !currentPropertyType.inherited) {
192
- logger_1.default.info(`Deleting Type-Property: ': ${currentPropertyType.slug}`);
192
+ logger_1.default.info(`Deleting Type-Property: ${currentPropertyType.slug}`);
193
193
  await sdk_1.Request.request(`/types/${type.id}/type-properties/${currentPropertyType.id}`, {
194
194
  method: 'DELETE',
195
195
  headers: {
@@ -4,7 +4,7 @@ appDescription: "APP_DESCRIPTION_STUB" # Give your app a description
4
4
  visibility: private # This should be private unless you want to develop an app for all VibeIQ customers to use
5
5
  hidden: false # can be used with a public app to prevent it from showing on the marketplace, but still installable by other orgs
6
6
  publisher: "Your company name" # Your company name, used for public apps
7
- version: 1.0.0
7
+ version: "1.0.0"
8
8
 
9
9
  # Properties you can configure when you install the app.
10
10
  # These property values will be available to all of your actions when they run
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.2.1",
2
+ "version": "2.2.3",
3
3
  "commands": {
4
4
  "app:create": {
5
5
  "id": "app:create",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "bin": {
6
6
  "contrail-cli": "./bin/run",