@contrail/cli 3.3.4 → 3.3.6-alpha.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 +4 -2
- package/dist/__mocks__/@contrail/sdk.d.ts +123 -0
- package/dist/__mocks__/@contrail/sdk.js +716 -0
- package/dist/commands/app/create.js +1 -14
- package/dist/commands/app/init.js +0 -14
- package/dist/commands/types/uploadTypes.d.ts +2 -1
- package/dist/commands/types/uploadTypes.js +9 -3
- package/dist/helpers/app/setup-template.d.ts +0 -2
- package/dist/helpers/app/setup-template.js +1 -2
- package/dist/helpers/types/type-uploader.d.ts +3 -1
- package/dist/helpers/types/type-uploader.js +50 -39
- package/dist/helpers/types/type-uploader.spec.js +506 -0
- package/dist/templates/typescript/app.yml +1 -1
- package/oclif.manifest.json +9 -1
- package/package.json +1 -1
|
@@ -27,7 +27,6 @@ class CreateApp extends basecommand_1.BaseCommand {
|
|
|
27
27
|
const defaultAppIdentifier = `@${username}/hello-world`;
|
|
28
28
|
const defaultAppDescription = `Hello world app by ${currentUser.email}`;
|
|
29
29
|
const defaultAppPublisher = `${currentUser.email}`;
|
|
30
|
-
const defaultNodeRuntime = entity_types_1.NodeRuntime.NODEJS_22_X;
|
|
31
30
|
const answers = await inquirer_1.default.prompt([
|
|
32
31
|
{
|
|
33
32
|
type: 'input',
|
|
@@ -57,17 +56,6 @@ class CreateApp extends basecommand_1.BaseCommand {
|
|
|
57
56
|
default: defaultAppPublisher,
|
|
58
57
|
required: true,
|
|
59
58
|
},
|
|
60
|
-
{
|
|
61
|
-
type: 'list',
|
|
62
|
-
name: 'nodeRuntime',
|
|
63
|
-
message: 'Select the Node.js runtime for your app:',
|
|
64
|
-
choices: [
|
|
65
|
-
{ name: 'Node.js 22.x (recommended)', value: entity_types_1.NodeRuntime.NODEJS_22_X },
|
|
66
|
-
{ name: 'Node.js 18.x (deprecated)', value: entity_types_1.NodeRuntime.NODEJS_18_X },
|
|
67
|
-
],
|
|
68
|
-
default: defaultNodeRuntime,
|
|
69
|
-
required: true,
|
|
70
|
-
},
|
|
71
59
|
]);
|
|
72
60
|
let sanitizedIdentifier = answers.appIdentifier;
|
|
73
61
|
if (!sanitizedIdentifier.startsWith('@')) {
|
|
@@ -81,7 +69,7 @@ class CreateApp extends basecommand_1.BaseCommand {
|
|
|
81
69
|
public: false,
|
|
82
70
|
description: answers.appDescription,
|
|
83
71
|
frameworkVersion: 2,
|
|
84
|
-
nodeRuntime:
|
|
72
|
+
nodeRuntime: entity_types_1.NodeRuntime.NODEJS_22_X,
|
|
85
73
|
};
|
|
86
74
|
try {
|
|
87
75
|
await new sdk_1.Entities().create({ entityName: 'app', object: newApp });
|
|
@@ -95,7 +83,6 @@ class CreateApp extends basecommand_1.BaseCommand {
|
|
|
95
83
|
appIdentifier: sanitizedIdentifier,
|
|
96
84
|
appDescription: answers.appDescription,
|
|
97
85
|
appPublisher: answers.appPublisher,
|
|
98
|
-
nodeRuntime: answers.nodeRuntime,
|
|
99
86
|
});
|
|
100
87
|
try {
|
|
101
88
|
let appDeclaration = (0, load_app_config_1.loadAppConfig)();
|
|
@@ -6,7 +6,6 @@ const login_1 = require("../../auth/login");
|
|
|
6
6
|
const basecommand_1 = require("../../basecommand");
|
|
7
7
|
const setup_template_1 = require("../../helpers/app/setup-template");
|
|
8
8
|
const sdk_1 = require("@contrail/sdk");
|
|
9
|
-
const entity_types_1 = require("@contrail/entity-types");
|
|
10
9
|
class InitApp extends basecommand_1.BaseCommand {
|
|
11
10
|
static description = 'Initialize an app directory from a template';
|
|
12
11
|
static examples = [
|
|
@@ -24,7 +23,6 @@ class InitApp extends basecommand_1.BaseCommand {
|
|
|
24
23
|
const defaultAppIdentifier = `@${username}/hello-world`;
|
|
25
24
|
const defaultAppDescription = `Hello world app by ${currentUser.email}`;
|
|
26
25
|
const defaultAppPublisher = `${currentUser.email}`;
|
|
27
|
-
const defaultNodeRuntime = entity_types_1.NodeRuntime.NODEJS_22_X;
|
|
28
26
|
const answers = await inquirer_1.default.prompt([
|
|
29
27
|
{
|
|
30
28
|
type: 'input',
|
|
@@ -54,17 +52,6 @@ class InitApp extends basecommand_1.BaseCommand {
|
|
|
54
52
|
default: defaultAppPublisher,
|
|
55
53
|
required: true,
|
|
56
54
|
},
|
|
57
|
-
{
|
|
58
|
-
type: 'list',
|
|
59
|
-
name: 'nodeRuntime',
|
|
60
|
-
message: 'Select the Node.js runtime for your app:',
|
|
61
|
-
choices: [
|
|
62
|
-
{ name: 'Node.js 22.x (recommended)', value: entity_types_1.NodeRuntime.NODEJS_22_X },
|
|
63
|
-
{ name: 'Node.js 18.x (deprecated)', value: entity_types_1.NodeRuntime.NODEJS_18_X },
|
|
64
|
-
],
|
|
65
|
-
default: defaultNodeRuntime,
|
|
66
|
-
required: true,
|
|
67
|
-
},
|
|
68
55
|
]);
|
|
69
56
|
let sanitizedIdentifier = answers.appIdentifier;
|
|
70
57
|
if (!sanitizedIdentifier.startsWith('@')) {
|
|
@@ -75,7 +62,6 @@ class InitApp extends basecommand_1.BaseCommand {
|
|
|
75
62
|
appIdentifier: sanitizedIdentifier,
|
|
76
63
|
appDescription: answers.appDescription,
|
|
77
64
|
appPublisher: answers.appPublisher,
|
|
78
|
-
nodeRuntime: answers.nodeRuntime,
|
|
79
65
|
});
|
|
80
66
|
}
|
|
81
67
|
}
|
|
@@ -4,9 +4,10 @@ export default class UploadTypes extends BaseCommand {
|
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
6
6
|
dir: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
merge: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
8
|
alwaysConfirmEnv: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
9
|
logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
10
|
};
|
|
10
11
|
run(): Promise<void>;
|
|
11
12
|
}
|
|
12
|
-
export declare function uploadTypes(dir: string): Promise<void>;
|
|
13
|
+
export declare function uploadTypes(dir: string, isMerge: boolean): Promise<void>;
|
|
@@ -18,13 +18,19 @@ class UploadTypes extends basecommand_1.BaseCommand {
|
|
|
18
18
|
required: false,
|
|
19
19
|
default: '.',
|
|
20
20
|
}),
|
|
21
|
+
merge: core_1.Flags.boolean({
|
|
22
|
+
char: 'm',
|
|
23
|
+
description: 'Merge types and type properties without deleting missing ones. Only adds/updates those present in the source files.',
|
|
24
|
+
required: false,
|
|
25
|
+
default: false,
|
|
26
|
+
}),
|
|
21
27
|
};
|
|
22
28
|
async run() {
|
|
23
|
-
return await uploadTypes(this.flags.dir);
|
|
29
|
+
return await uploadTypes(this.flags.dir, this.flags.merge);
|
|
24
30
|
}
|
|
25
31
|
}
|
|
26
32
|
exports.default = UploadTypes;
|
|
27
|
-
async function uploadTypes(dir) {
|
|
28
|
-
await (0, type_uploader_1.uploadTypes)(dir);
|
|
33
|
+
async function uploadTypes(dir, isMerge) {
|
|
34
|
+
await (0, type_uploader_1.uploadTypes)(dir, { isMerge });
|
|
29
35
|
}
|
|
30
36
|
exports.uploadTypes = uploadTypes;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { NodeRuntime } from '@contrail/entity-types';
|
|
2
1
|
interface AppSetUpInputs {
|
|
3
2
|
appName: string;
|
|
4
3
|
appIdentifier: string;
|
|
5
4
|
appDescription: string;
|
|
6
5
|
appPublisher: string;
|
|
7
|
-
nodeRuntime: NodeRuntime;
|
|
8
6
|
}
|
|
9
7
|
export declare function setUpTemplate(appInput: AppSetUpInputs): Promise<void>;
|
|
10
8
|
export {};
|
|
@@ -38,8 +38,7 @@ async function setUpTemplate(appInput) {
|
|
|
38
38
|
.replace(/APP_IDENTIFIER_STUB/g, appInput.appIdentifier)
|
|
39
39
|
.replace(/APP_NAME_STUB/g, appInput.appName)
|
|
40
40
|
.replace(/APP_DESCRIPTION_STUB/g, appInput.appDescription)
|
|
41
|
-
.replace(/APP_PUBLISHER_STUB/g, appInput.appPublisher)
|
|
42
|
-
.replace(/NODE_RUNTIME_STUB/g, appInput.nodeRuntime);
|
|
41
|
+
.replace(/APP_PUBLISHER_STUB/g, appInput.appPublisher);
|
|
43
42
|
fs_1.default.writeFileSync(appYmlFileLoc, newAppYml);
|
|
44
43
|
}
|
|
45
44
|
catch (e) {
|
|
@@ -10,12 +10,12 @@ const _ = tslib_1.__importStar(require("lodash"));
|
|
|
10
10
|
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
11
11
|
const login_1 = require("../../auth/login");
|
|
12
12
|
const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
13
|
-
async function uploadTypes(dir) {
|
|
13
|
+
async function uploadTypes(dir, options = { isMerge: false }) {
|
|
14
14
|
try {
|
|
15
15
|
const userConfig = await (0, login_1.authUser)();
|
|
16
16
|
logger_1.default.info(`START Getting all types for org ${userConfig.orgSlug}`);
|
|
17
17
|
logger_1.default.info('TYPES Uploading ');
|
|
18
|
-
await uploadReducedTypes(dir);
|
|
18
|
+
await uploadReducedTypes(dir, options);
|
|
19
19
|
logger_1.default.info(`${chalk_1.default.yellow.bold('TYPES')} Uploaded`);
|
|
20
20
|
}
|
|
21
21
|
catch (e) {
|
|
@@ -39,7 +39,7 @@ function loadReducedTypes(fromDir) {
|
|
|
39
39
|
throw new Error(`ERROR PARSING YAML: ${e}`);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
async function uploadReducedTypes(dir) {
|
|
42
|
+
async function uploadReducedTypes(dir, options) {
|
|
43
43
|
const types = loadReducedTypes(dir);
|
|
44
44
|
const currentTypesWithoutProperties = await new sdk_1.Entities().get({
|
|
45
45
|
entityName: 'type',
|
|
@@ -88,15 +88,15 @@ async function uploadReducedTypes(dir) {
|
|
|
88
88
|
});
|
|
89
89
|
const newTypeProperties = (await new sdk_1.Types().getType({ id: createdType.id }))
|
|
90
90
|
.typeProperties;
|
|
91
|
-
await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties, optionSets);
|
|
91
|
+
await uploadReducedTypeProperties(createdType, newTypeProperties, type.typeProperties, optionSets, options);
|
|
92
92
|
}
|
|
93
93
|
else {
|
|
94
|
-
const proposedType = {
|
|
94
|
+
const proposedType = Object.fromEntries(Object.entries({
|
|
95
95
|
slug: type.slug,
|
|
96
96
|
label: type.label,
|
|
97
97
|
typePath: type.typePath,
|
|
98
98
|
isArchived: type.isArchived,
|
|
99
|
-
};
|
|
99
|
+
}).filter(([_, value]) => value !== undefined));
|
|
100
100
|
const differences = extractValueDifferences(found, proposedType, [
|
|
101
101
|
'id',
|
|
102
102
|
'createdOn',
|
|
@@ -116,7 +116,10 @@ async function uploadReducedTypes(dir) {
|
|
|
116
116
|
'typeInterfaces',
|
|
117
117
|
]);
|
|
118
118
|
let updatedType = found;
|
|
119
|
-
|
|
119
|
+
const hasChangesToSave = options.isMerge
|
|
120
|
+
? Boolean(differences.updates.length || differences.adds.length)
|
|
121
|
+
: Boolean(differences.updates.length || differences.adds.length || differences.deletions.length);
|
|
122
|
+
if (hasChangesToSave) {
|
|
120
123
|
logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
|
|
121
124
|
logger_1.default.info(`Updating Type: ${type.slug}`);
|
|
122
125
|
updatedType = await new sdk_1.Entities().update({
|
|
@@ -128,7 +131,7 @@ async function uploadReducedTypes(dir) {
|
|
|
128
131
|
else {
|
|
129
132
|
logger_1.default.debug(`Skipping empty update of type ${type.typePath}`);
|
|
130
133
|
}
|
|
131
|
-
await uploadReducedTypeProperties(updatedType, found.typeProperties, type.typeProperties, optionSets);
|
|
134
|
+
await uploadReducedTypeProperties(updatedType, found.typeProperties, type.typeProperties, optionSets, options);
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
catch (err) {
|
|
@@ -136,7 +139,7 @@ async function uploadReducedTypes(dir) {
|
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
141
|
}
|
|
139
|
-
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes, optionSets) {
|
|
142
|
+
async function uploadReducedTypeProperties(type, currentPropertyTypes, newPropertyTypes, optionSets, options) {
|
|
140
143
|
const currentPropertyTypeBySlug = {};
|
|
141
144
|
for (const currentPropertyType of currentPropertyTypes) {
|
|
142
145
|
currentPropertyTypeBySlug[currentPropertyType.slug] = currentPropertyType;
|
|
@@ -201,40 +204,42 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
201
204
|
// !typePropertiesEqual(found, newPropertyType, optionSetIdBySlug)
|
|
202
205
|
) {
|
|
203
206
|
// Skip platform-managed entities
|
|
204
|
-
if (newPropertyType.core) {
|
|
207
|
+
if (found.core || newPropertyType.core) {
|
|
205
208
|
logger_1.default.debug(`Skipping platform-managed property: ${newPropertyType.slug}`);
|
|
206
209
|
continue;
|
|
207
210
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
211
|
+
const defaultValueForUndefinedEntries = options.isMerge ? undefined : null;
|
|
212
|
+
const defaultIfUndefined = (value) => value === undefined ? defaultValueForUndefinedEntries : value;
|
|
213
|
+
const proposedTypeProperty = Object.fromEntries(Object.entries({
|
|
214
|
+
isArchived: defaultIfUndefined(newPropertyType.isArchived),
|
|
215
|
+
propertyType: defaultIfUndefined(newPropertyType.propertyType),
|
|
216
|
+
slug: defaultIfUndefined(newPropertyType.slug),
|
|
217
|
+
label: defaultIfUndefined(newPropertyType.label),
|
|
218
|
+
editable: defaultIfUndefined(newPropertyType.editable),
|
|
219
|
+
searchable: defaultIfUndefined(newPropertyType.searchable),
|
|
220
|
+
core: defaultIfUndefined(newPropertyType.core),
|
|
221
|
+
typePropertyOptionSetId: defaultIfUndefined(optionSetIdBySlug[newPropertyType.typePropertyOptionSetSlug]),
|
|
222
|
+
formula: defaultIfUndefined(newPropertyType.formula),
|
|
223
|
+
referencedTypePath: defaultIfUndefined(newPropertyType.referencedTypePath),
|
|
224
|
+
carryOverBehavior: defaultIfUndefined(newPropertyType.carryOverBehavior),
|
|
225
|
+
carryOverDefault: defaultIfUndefined(newPropertyType.carryOverDefault),
|
|
226
|
+
referencedTypeRootSlug: defaultIfUndefined(newPropertyType.referencedTypeRootSlug),
|
|
227
|
+
defaultValue: defaultIfUndefined(newPropertyType.defaultValue),
|
|
228
|
+
propertyLevel: defaultIfUndefined(newPropertyType.propertyLevel),
|
|
224
229
|
typePropertyUserListId,
|
|
225
|
-
referencedTypeRole: newPropertyType.referencedTypeRole
|
|
226
|
-
isUniqueProperty: newPropertyType.isUniqueProperty
|
|
227
|
-
isUniquePropertyInFamily: newPropertyType.isUniquePropertyInFamily
|
|
228
|
-
formulaFunction: newPropertyType.formulaFunction
|
|
229
|
-
validationFunction: newPropertyType.validationFunction
|
|
230
|
-
numberFormat: newPropertyType.numberFormat
|
|
231
|
-
sequenceSeedValue: newPropertyType.sequenceSeedValue
|
|
232
|
-
copyBehavior: newPropertyType.copyBehavior
|
|
233
|
-
};
|
|
230
|
+
referencedTypeRole: defaultIfUndefined(newPropertyType.referencedTypeRole),
|
|
231
|
+
isUniqueProperty: defaultIfUndefined(newPropertyType.isUniqueProperty),
|
|
232
|
+
isUniquePropertyInFamily: defaultIfUndefined(newPropertyType.isUniquePropertyInFamily),
|
|
233
|
+
formulaFunction: defaultIfUndefined(newPropertyType.formulaFunction),
|
|
234
|
+
validationFunction: defaultIfUndefined(newPropertyType.validationFunction),
|
|
235
|
+
numberFormat: defaultIfUndefined(newPropertyType.numberFormat),
|
|
236
|
+
sequenceSeedValue: defaultIfUndefined(newPropertyType.sequenceSeedValue),
|
|
237
|
+
copyBehavior: defaultIfUndefined(newPropertyType.copyBehavior),
|
|
238
|
+
}).filter(([_, value]) => value !== undefined));
|
|
234
239
|
// logger.debug(
|
|
235
240
|
// `found type property option set: ${newPropertyType.typePropertyOptionSetSlug}, ${proposedTP.typePropertyOptionSetId}, `,
|
|
236
241
|
// );
|
|
237
|
-
const differences = extractValueDifferences(found,
|
|
242
|
+
const differences = extractValueDifferences(found, proposedTypeProperty, [
|
|
238
243
|
'id',
|
|
239
244
|
'createdOn',
|
|
240
245
|
'updatedOn',
|
|
@@ -256,13 +261,16 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
256
261
|
'used',
|
|
257
262
|
'typePropertyPolicyIds',
|
|
258
263
|
]);
|
|
259
|
-
|
|
264
|
+
const hasChangesToSave = options.isMerge
|
|
265
|
+
? Boolean(differences.updates.length || differences.adds.length)
|
|
266
|
+
: Boolean(differences.updates.length || differences.adds.length || differences.deletions.length);
|
|
267
|
+
if (hasChangesToSave) {
|
|
260
268
|
logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
|
|
261
|
-
logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(
|
|
269
|
+
logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(proposedTypeProperty, null, 2)}`);
|
|
262
270
|
await new sdk_1.Entities().update({
|
|
263
271
|
entityName: 'type-property',
|
|
264
272
|
id: found.id,
|
|
265
|
-
object:
|
|
273
|
+
object: proposedTypeProperty,
|
|
266
274
|
});
|
|
267
275
|
}
|
|
268
276
|
else {
|
|
@@ -274,6 +282,9 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
|
|
|
274
282
|
logger_1.default.info(`Error Creating Properties: ${err}`);
|
|
275
283
|
}
|
|
276
284
|
}
|
|
285
|
+
if (options.isMerge) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
277
288
|
for (const currentPropertyType of currentPropertyTypes) {
|
|
278
289
|
try {
|
|
279
290
|
const found = newPropertyTypesBySlug[currentPropertyType.slug];
|