@contrail/cli 3.4.0-alpha → 3.4.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.
Files changed (61) hide show
  1. package/README.md +4 -151
  2. package/dist/__mocks__/@contrail/sdk.d.ts +123 -0
  3. package/dist/__mocks__/@contrail/sdk.js +716 -0
  4. package/dist/api/types.d.ts +0 -35
  5. package/dist/api/types.js +1 -47
  6. package/dist/auth/login.js +8 -0
  7. package/dist/basecommand.d.ts +1 -3
  8. package/dist/basecommand.js +1 -1
  9. package/dist/commands/app/create.js +1 -14
  10. package/dist/commands/app/extension/deploy.js +4 -2
  11. package/dist/commands/app/init.js +0 -14
  12. package/dist/commands/types/uploadTypes.d.ts +2 -1
  13. package/dist/commands/types/uploadTypes.js +9 -3
  14. package/dist/commands/types/uploadUsageInfo.js +16 -2
  15. package/dist/common.d.ts +1 -1
  16. package/dist/helpers/app/app-deployer.js +8 -4
  17. package/dist/helpers/app/extension-package-deployer.js +1 -1
  18. package/dist/helpers/app/setup-template.d.ts +0 -2
  19. package/dist/helpers/app/setup-template.js +1 -2
  20. package/dist/helpers/config/config.js +3 -3
  21. package/dist/helpers/file-helpers.d.ts +0 -1
  22. package/dist/helpers/file-helpers.js +1 -19
  23. package/dist/helpers/types/type-uploader.d.ts +3 -1
  24. package/dist/helpers/types/type-uploader.js +55 -37
  25. package/dist/helpers/types/type-uploader.spec.js +506 -0
  26. package/dist/interfaces.d.ts +1 -0
  27. package/dist/templates/typescript/README.md +3 -1
  28. package/dist/templates/typescript/app.yml +1 -1
  29. package/dist/templates/typescript/assets/sample.json +1 -1
  30. package/dist/templates/typescript/eslintrc.json +1 -4
  31. package/dist/templates/typescript/tsconfig.json +5 -21
  32. package/oclif.manifest.json +9 -361
  33. package/package.json +5 -6
  34. package/dist/commands/entities/create.d.ts +0 -37
  35. package/dist/commands/entities/create.js +0 -555
  36. package/dist/commands/entities/create.spec.d.ts +0 -1
  37. package/dist/commands/entities/create.spec.js +0 -514
  38. package/dist/commands/entities/delete.d.ts +0 -16
  39. package/dist/commands/entities/delete.js +0 -118
  40. package/dist/commands/entities/get.d.ts +0 -20
  41. package/dist/commands/entities/get.js +0 -204
  42. package/dist/commands/entities/update.d.ts +0 -18
  43. package/dist/commands/entities/update.js +0 -116
  44. package/dist/helpers/entities/assortment-items.d.ts +0 -10
  45. package/dist/helpers/entities/assortment-items.js +0 -84
  46. package/dist/helpers/entities/batchFetch.d.ts +0 -8
  47. package/dist/helpers/entities/batchFetch.js +0 -41
  48. package/dist/helpers/entities/index.d.ts +0 -3
  49. package/dist/helpers/entities/index.js +0 -6
  50. package/dist/helpers/entities/items.d.ts +0 -10
  51. package/dist/helpers/entities/items.js +0 -102
  52. package/dist/helpers/entities/project-items.d.ts +0 -3
  53. package/dist/helpers/entities/project-items.js +0 -65
  54. package/dist/helpers/propertySpecifications/dateRanges.d.ts +0 -38
  55. package/dist/helpers/propertySpecifications/dateRanges.js +0 -89
  56. package/dist/helpers/propertySpecifications/dateRanges.spec.d.ts +0 -1
  57. package/dist/helpers/propertySpecifications/dateRanges.spec.js +0 -95
  58. package/dist/helpers/propertySpecifications/propertySpecifications.d.ts +0 -27
  59. package/dist/helpers/propertySpecifications/propertySpecifications.js +0 -70
  60. package/dist/helpers/propertySpecifications/propertySpecifications.spec.d.ts +0 -1
  61. package/dist/helpers/propertySpecifications/propertySpecifications.spec.js +0 -266
@@ -1,5 +1,3 @@
1
- import { TypeProperty as SDKTypeProperty } from '@contrail/types';
2
- import { PropertyLevel, PropertyType, Type } from '@contrail/types';
3
1
  export declare function getOptionSets(): Promise<any[]>;
4
2
  export declare function getUserLists(): Promise<any[]>;
5
3
  export declare function getOptionSetHierarchies(): Promise<any[]>;
@@ -11,36 +9,3 @@ export declare function getTypePropertyPolicies(): Promise<any[]>;
11
9
  export declare function getTypePropertyPolicyLinks(): Promise<any[]>;
12
10
  export declare function getTypePolicies(): Promise<any[]>;
13
11
  export declare function getTypePolicyLinks(): Promise<any[]>;
14
- type ColonDelimitedHelper<S extends string> = S extends `${infer Head}:${infer Tail}` ? `${Head}:${ColonDelimitedHelper<Tail>}` : S;
15
- export type ColonDelimited = ColonDelimitedHelper<string>;
16
- export type TypeWithProperties = Type & {
17
- typeProperties: TypeProperty[];
18
- };
19
- export interface Option {
20
- value: string;
21
- display: string;
22
- disabled?: boolean;
23
- }
24
- export interface TypeProperty extends SDKTypeProperty {
25
- propertyType?: PropertyType;
26
- referencedTypePath?: string;
27
- referencedTypeRootSlug?: string;
28
- propertyLevel?: PropertyLevel;
29
- }
30
- export interface TypePropertyOptionSet {
31
- id?: string;
32
- orgId?: string;
33
- name: string;
34
- slug: string;
35
- optionSet: Option[];
36
- isArchived?: boolean;
37
- }
38
- export type TypeReferencesCacheByPath = Map<string, TypeWithProperties>;
39
- export declare function getTypeByPath(path: ColonDelimited): Promise<TypeWithProperties>;
40
- export declare function buildLocalTypesCache(paths: ColonDelimited[]): Promise<TypeReferencesCacheByPath>;
41
- export declare function parseTypePath(path: ColonDelimited): {
42
- root: string;
43
- path: string;
44
- };
45
- export declare function getReferencedTypePaths(type: TypeWithProperties): ColonDelimited[];
46
- export {};
package/dist/api/types.js CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getReferencedTypePaths = exports.parseTypePath = exports.buildLocalTypesCache = exports.getTypeByPath = exports.getTypePolicyLinks = exports.getTypePolicies = exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchyLinks = exports.getOptionSetHierarchies = exports.getUserLists = exports.getOptionSets = void 0;
3
+ exports.getTypePolicyLinks = exports.getTypePolicies = exports.getTypePropertyPolicyLinks = exports.getTypePropertyPolicies = exports.getUsageInfo = exports.getRuleSetLinks = exports.getRuleSets = exports.getOptionSetHierarchyLinks = exports.getOptionSetHierarchies = exports.getUserLists = exports.getOptionSets = void 0;
4
4
  const sdk_1 = require("@contrail/sdk");
5
- const types_1 = require("@contrail/types");
6
5
  async function getOptionSets() {
7
6
  return await new sdk_1.Entities().get({
8
7
  entityName: 'type-property-option-set',
@@ -78,48 +77,3 @@ async function getTypePolicyLinks() {
78
77
  });
79
78
  }
80
79
  exports.getTypePolicyLinks = getTypePolicyLinks;
81
- const TYPES_CACHE_BY_PATH = new Map();
82
- async function fetchTypeByPath(path) {
83
- const { root } = parseTypePath(path);
84
- const client = new sdk_1.Entities();
85
- const type = await client.get({
86
- entityName: 'type',
87
- suffix: `roots/${root}/path/${path}`,
88
- relations: ['typeProperties'],
89
- });
90
- return type;
91
- }
92
- async function getTypeByPath(path) {
93
- if (TYPES_CACHE_BY_PATH.has(path)) {
94
- return TYPES_CACHE_BY_PATH.get(path);
95
- }
96
- const type = await fetchTypeByPath(path);
97
- TYPES_CACHE_BY_PATH.set(path, type);
98
- return type;
99
- }
100
- exports.getTypeByPath = getTypeByPath;
101
- async function buildLocalTypesCache(paths) {
102
- const types = await Promise.all(paths.map((path) => getTypeByPath(path)));
103
- const newCache = types.reduce((acc, type) => {
104
- acc.set(type.typePath, type);
105
- return acc;
106
- }, new Map());
107
- return newCache;
108
- }
109
- exports.buildLocalTypesCache = buildLocalTypesCache;
110
- function parseTypePath(path) {
111
- const parts = path.split(':').filter(Boolean);
112
- if (parts.length === 0) {
113
- throw new Error('Path cannot be empty');
114
- }
115
- const root = parts[0];
116
- return { root, path };
117
- }
118
- exports.parseTypePath = parseTypePath;
119
- function getReferencedTypePaths(type) {
120
- const properties = type.typeProperties || [];
121
- return properties
122
- .filter((prop) => prop.propertyType === types_1.PropertyType.TypeReference)
123
- .map(({ referencedTypePath }) => referencedTypePath);
124
- }
125
- exports.getReferencedTypePaths = getReferencedTypePaths;
@@ -40,6 +40,10 @@ async function authUser() {
40
40
  return await refreshCurrentUserOrg();
41
41
  }
42
42
  catch (e) {
43
+ if (isNetworkConnectionError(e)) {
44
+ logger_1.default.error("Encountered a network connection issue. Please ensure you're connected to the internet and try again");
45
+ process.exit(1);
46
+ }
43
47
  logger_1.default.info('Token expired. Requesting auth credentials...');
44
48
  }
45
49
  }
@@ -211,3 +215,7 @@ async function returnAndStoreConfig(config) {
211
215
  await (0, config_1.storeConfig)(configCopy);
212
216
  return configCopy;
213
217
  }
218
+ function isNetworkConnectionError(e) {
219
+ const cause = e?.cause;
220
+ return cause?.code === 'ENOTFOUND' || cause?.code === 'ECONNREFUSED';
221
+ }
@@ -8,9 +8,7 @@ export declare abstract class BaseCommand extends Command {
8
8
  logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
9
9
  };
10
10
  protected flags: any;
11
- protected args: {
12
- [key: string]: any;
13
- };
11
+ protected args: any;
14
12
  init(): Promise<void>;
15
13
  setLogLevel(logLevel: string, config?: any): void;
16
14
  private confirmEnv;
@@ -17,7 +17,7 @@ class BaseCommand extends core_1.Command {
17
17
  ...baseFlags_1.baseFlags,
18
18
  };
19
19
  flags;
20
- args = {};
20
+ args;
21
21
  async init() {
22
22
  await super.init();
23
23
  if (!this.ctor?.flags)
@@ -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: answers.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)();
@@ -40,10 +40,12 @@ class DeployExtension extends basecommand_1.BaseCommand {
40
40
  await this.validateExtensionDeclaration(appDeclaration, extensionIdentifier);
41
41
  const extensionDir = this.getExtensionDirectory(extensionIdentifier);
42
42
  // 2. Package and upload extension
43
- const createdPackage = await (0, extension_package_deployer_1.createExtensionPackage)(app.id, extensionDir, { debug: this.flags.debug });
43
+ const createdPackage = await (0, extension_package_deployer_1.createExtensionPackage)(app.id, extensionDir, {
44
+ debug: this.flags.debug,
45
+ });
44
46
  // 3. Poll until package is ready (timeout after 1 minute)
45
47
  const readyPackage = await this.pollUntilPackageIsReady(createdPackage);
46
- logger_1.default.info("Extension package is ready...Checking for extension deployment");
48
+ logger_1.default.info('Extension package is ready...Checking for extension deployment');
47
49
  logger_1.default.debug(JSON.stringify(readyPackage, null, 2));
48
50
  const deployment = await this.pollUntilDeploymentIsReady(readyPackage.deploymentId);
49
51
  logger_1.default.info(`${chalk_1.default.green.bold('SUCCESS')} Extension package is ready.`);
@@ -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;
@@ -103,6 +103,7 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
103
103
  numberFormat: loadedUI.numberFormat,
104
104
  defaultValue: loadedUI.defaultValue,
105
105
  label: loadedUI.label,
106
+ isArchived: loadedUI.isArchived,
106
107
  },
107
108
  });
108
109
  }
@@ -115,8 +116,21 @@ async function uploadUsageInfoObjects(loadedUsageInfo) {
115
116
  entityName: 'type-property-usage-info',
116
117
  id: found.id,
117
118
  object: {
118
- editable: loadedUI.editable,
119
- used: loadedUI.used,
119
+ editable: loadedUI?.editable,
120
+ used: loadedUI?.used,
121
+ formulaFunction: loadedUI?.formulaFunction,
122
+ validationFunction: loadedUI?.validationFunction,
123
+ numberFormat: loadedUI?.numberFormat,
124
+ defaultValue: loadedUI?.defaultValue,
125
+ label: loadedUI?.label,
126
+ required: loadedUI?.required,
127
+ searchable: loadedUI?.searchable,
128
+ isUniqueProperty: loadedUI?.isUniqueProperty,
129
+ isUniquePropertyInFamily: loadedUI?.isUniquePropertyInFamily,
130
+ copyBehavior: loadedUI?.copyBehavior,
131
+ copyDefault: loadedUI?.copyDefault,
132
+ propertyLevel: loadedUI?.propertyLevel,
133
+ isArchived: loadedUI?.isArchived,
120
134
  },
121
135
  });
122
136
  }
package/dist/common.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /// <reference types="node" />
2
2
  export declare function getSeparatorByPlatform(): string;
3
3
  export declare function delay(ms: number): Promise<NodeJS.Timeout>;
4
- export declare function removeSlash(string: string): string;
4
+ export declare function removeSlash(string: any): string;
@@ -107,6 +107,7 @@ class AppDeployer {
107
107
  if (appDeclaration?.accessGrants) {
108
108
  accessGrants = await app_template_parsers_1.AccessGrantsParser.buildAccessGrants(appDeclaration);
109
109
  }
110
+ // eslint-disable-next-line no-prototype-builtins
110
111
  if (appDeclaration.hasOwnProperty('dockerImageRef')) {
111
112
  throw new Error('Docker apps are no longer supported. Please use a node app.');
112
113
  }
@@ -201,7 +202,11 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
201
202
  logger_1.default.info('Installing production dependencies done.');
202
203
  logger_1.default.info('Building package...');
203
204
  try {
204
- child_process_1.default.execSync('npx tsc --outDir tmp/dist');
205
+ // Check for tsconfig.build.json first, fallback to tsconfig.json
206
+ const buildConfigPath = fs_1.default.existsSync('tsconfig.build.json')
207
+ ? 'tsconfig.build.json'
208
+ : 'tsconfig.json';
209
+ child_process_1.default.execSync(`npx tsc --project ${buildConfigPath} --outDir tmp/dist`);
205
210
  }
206
211
  catch (e) {
207
212
  logger_1.default.error(`${chalk_1.default.red.bold('APP')} Failed to build package.`);
@@ -228,7 +233,7 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
228
233
  return {};
229
234
  }
230
235
  logger_1.default.info('Uploading package to S3...');
231
- let apps = await entitiesClient.get({ entityName: 'app' });
236
+ const apps = await entitiesClient.get({ entityName: 'app' });
232
237
  const thisApp = apps.find((x) => x.identifier === appIdentifier);
233
238
  if (!thisApp) {
234
239
  throw new Error('App not found');
@@ -238,8 +243,7 @@ async function createNodePackage(appIdentifier, debug, dryRun) {
238
243
  object: { appId: thisApp.id },
239
244
  });
240
245
  // upload an s3 object using a signed url with an https put request
241
- const readStream = fs_1.default.readFileSync('tmp.zip');
242
- const postBody = Buffer.from(readStream);
246
+ const postBody = fs_1.default.readFileSync('tmp.zip');
243
247
  // await axios.put(uploadUrlObject.signedUrl, postBody.toString());
244
248
  await axios_1.default.request({
245
249
  method: 'PUT',
@@ -119,7 +119,7 @@ async function createExtensionPackage(appId, extensionDir, options) {
119
119
  await uploadExtensionPackage(appExtensionPackage, tmpDir, options);
120
120
  logger_1.default.info(`${chalk_1.default.green.bold('COMPLETE')} Extension packaged and uploaded.`);
121
121
  if (options.debug) {
122
- logger_1.default.debug("debug mode enabled. Not cleaning up tmp dir.");
122
+ logger_1.default.debug('debug mode enabled. Not cleaning up tmp dir.');
123
123
  }
124
124
  else {
125
125
  cleanUp(tmpDir);
@@ -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) {
@@ -103,13 +103,13 @@ exports.writeConfig = writeConfig;
103
103
  async function getConfig() {
104
104
  let fileContent;
105
105
  try {
106
- fileContent = await (await node_fs_1.promises.readFile(configFileLocation)).toString();
106
+ fileContent = (await node_fs_1.promises.readFile(configFileLocation)).toString();
107
107
  }
108
108
  catch {
109
109
  logger_1.default.debug(`failed to open config file (${configFileLocation}) for reading.`);
110
110
  logger_1.default.debug('trying to initialize config file');
111
111
  await initializeVibeIQConfig();
112
- fileContent = await (await node_fs_1.promises.readFile(configFileLocation)).toString();
112
+ fileContent = (await node_fs_1.promises.readFile(configFileLocation)).toString();
113
113
  }
114
114
  try {
115
115
  const configFileJSON = JSON.parse(fileContent);
@@ -156,7 +156,7 @@ async function getConfigContent(fileName) {
156
156
  const configFilePath = (0, node_path_1.join)(configDirectoryLocation, `${fileName}.json`);
157
157
  let fileContent;
158
158
  try {
159
- fileContent = await (await node_fs_1.promises.readFile(configFilePath)).toString();
159
+ fileContent = (await node_fs_1.promises.readFile(configFilePath)).toString();
160
160
  return JSON.parse(fileContent);
161
161
  }
162
162
  catch (error) {
@@ -1,3 +1,2 @@
1
1
  export declare function safeFileOverwrite(fileLocation: string, overwrite: boolean): Promise<boolean>;
2
2
  export declare function parseCSVData(data: string): any;
3
- export declare function parseFileAsJsonArray(fileName: string): any[];
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseFileAsJsonArray = exports.parseCSVData = exports.safeFileOverwrite = void 0;
3
+ exports.parseCSVData = exports.safeFileOverwrite = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const fs_1 = tslib_1.__importDefault(require("fs"));
6
5
  const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
7
6
  const logger_1 = tslib_1.__importDefault(require("../logger"));
8
7
  const sync_1 = require("csv-parse/sync");
@@ -35,20 +34,3 @@ function parseCSVData(data) {
35
34
  });
36
35
  }
37
36
  exports.parseCSVData = parseCSVData;
38
- function parseFileAsJsonArray(fileName) {
39
- if (!fs_1.default.existsSync(fileName)) {
40
- throw new Error(`File not found: ${fileName}`);
41
- }
42
- const fileContent = fs_1.default.readFileSync(fileName, 'utf-8');
43
- try {
44
- const jsonArray = JSON.parse(fileContent);
45
- if (!Array.isArray(jsonArray)) {
46
- throw new Error(`File content is not a valid JSON array: ${fileName}`);
47
- }
48
- return jsonArray;
49
- }
50
- catch (error) {
51
- throw new Error(`Error parsing JSON from file ${fileName}: ${error.message}`);
52
- }
53
- }
54
- exports.parseFileAsJsonArray = parseFileAsJsonArray;
@@ -1,4 +1,6 @@
1
- export declare function uploadTypes(dir: string): Promise<void>;
1
+ export declare function uploadTypes(dir: string, options?: {
2
+ isMerge: boolean;
3
+ }): Promise<void>;
2
4
  export interface ValueDiff {
3
5
  adds: any[];
4
6
  updates: any[];
@@ -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
- if (differences.updates.length || differences.adds.length || differences.deletions.length) {
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;
@@ -188,6 +191,7 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
188
191
  validationFunction: newPropertyType.validationFunction,
189
192
  numberFormat: newPropertyType.numberFormat,
190
193
  sequenceSeedValue: newPropertyType.sequenceSeedValue,
194
+ copyBehavior: newPropertyType?.copyBehavior,
191
195
  }),
192
196
  headers: {
193
197
  Accept: 'application/json',
@@ -199,35 +203,43 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
199
203
  // !newPropertyType.inherited &&
200
204
  // !typePropertiesEqual(found, newPropertyType, optionSetIdBySlug)
201
205
  ) {
202
- const proposedTP = {
203
- isArchived: newPropertyType.isArchived ?? null,
204
- propertyType: newPropertyType.propertyType ?? null,
205
- slug: newPropertyType.slug ?? null,
206
- label: newPropertyType.label ?? null,
207
- editable: newPropertyType.editable ?? null,
208
- searchable: newPropertyType.searchable ?? null,
209
- core: newPropertyType.core ?? null,
210
- typePropertyOptionSetId: optionSetIdBySlug[newPropertyType.typePropertyOptionSetSlug] ?? null,
211
- formula: newPropertyType.formula ?? null,
212
- referencedTypePath: newPropertyType.referencedTypePath ?? null,
213
- carryOverBehavior: newPropertyType.carryOverBehavior ?? null,
214
- carryOverDefault: newPropertyType.carryOverDefault ?? null,
215
- referencedTypeRootSlug: newPropertyType.referencedTypeRootSlug ?? null,
216
- defaultValue: newPropertyType.defaultValue ?? null,
217
- propertyLevel: newPropertyType.propertyLevel ?? null,
206
+ // Skip platform-managed entities
207
+ if (found.core || newPropertyType.core) {
208
+ logger_1.default.debug(`Skipping platform-managed property: ${newPropertyType.slug}`);
209
+ continue;
210
+ }
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),
218
229
  typePropertyUserListId,
219
- referencedTypeRole: newPropertyType.referencedTypeRole ?? null,
220
- isUniqueProperty: newPropertyType.isUniqueProperty ?? null,
221
- isUniquePropertyInFamily: newPropertyType.isUniquePropertyInFamily ?? null,
222
- formulaFunction: newPropertyType.formulaFunction ?? null,
223
- validationFunction: newPropertyType.validationFunction ?? null,
224
- numberFormat: newPropertyType.numberFormat ?? null,
225
- sequenceSeedValue: newPropertyType.sequenceSeedValue ?? null,
226
- };
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));
227
239
  // logger.debug(
228
240
  // `found type property option set: ${newPropertyType.typePropertyOptionSetSlug}, ${proposedTP.typePropertyOptionSetId}, `,
229
241
  // );
230
- const differences = extractValueDifferences(found, proposedTP, [
242
+ const differences = extractValueDifferences(found, proposedTypeProperty, [
231
243
  'id',
232
244
  'createdOn',
233
245
  'updatedOn',
@@ -249,13 +261,16 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
249
261
  'used',
250
262
  'typePropertyPolicyIds',
251
263
  ]);
252
- if (differences.updates.length || differences.adds.length || differences.deletions.length) {
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) {
253
268
  logger_1.default.debug(`found differences: ${JSON.stringify(differences, null, 2)}`);
254
- logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(proposedTP, null, 2)}`);
269
+ logger_1.default.debug(`Updating Type-Property: ${newPropertyType.slug}, ${found.id}, ${JSON.stringify(proposedTypeProperty, null, 2)}`);
255
270
  await new sdk_1.Entities().update({
256
271
  entityName: 'type-property',
257
272
  id: found.id,
258
- object: proposedTP,
273
+ object: proposedTypeProperty,
259
274
  });
260
275
  }
261
276
  else {
@@ -267,6 +282,9 @@ async function uploadReducedTypeProperties(type, currentPropertyTypes, newProper
267
282
  logger_1.default.info(`Error Creating Properties: ${err}`);
268
283
  }
269
284
  }
285
+ if (options.isMerge) {
286
+ return;
287
+ }
270
288
  for (const currentPropertyType of currentPropertyTypes) {
271
289
  try {
272
290
  const found = newPropertyTypesBySlug[currentPropertyType.slug];