@suitegeezus/suitecloud-cli 3.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.
Files changed (157) hide show
  1. package/CONTRIBUTING.md +7 -0
  2. package/DELTA.md +235 -0
  3. package/README.md +107 -0
  4. package/docs/Command.md +299 -0
  5. package/messages.json +317 -0
  6. package/package.json +51 -0
  7. package/postinstall.js +8 -0
  8. package/resources/FUTC-LICENSE.txt +115 -0
  9. package/src/ApplicationConstants.js +87 -0
  10. package/src/CLI.js +202 -0
  11. package/src/CLIException.js +21 -0
  12. package/src/ExecutionEnvironmentContext.js +39 -0
  13. package/src/SdkExecutionContext.js +90 -0
  14. package/src/SdkExecutor.js +160 -0
  15. package/src/commands/Command.js +158 -0
  16. package/src/commands/account/manageauth/ManageAccountAction.js +126 -0
  17. package/src/commands/account/manageauth/ManageAccountCommand.js +20 -0
  18. package/src/commands/account/manageauth/ManageAccountInputHandler.js +215 -0
  19. package/src/commands/account/manageauth/ManageAccountOutputHandler.js +30 -0
  20. package/src/commands/account/setup/SetupAction.js +39 -0
  21. package/src/commands/account/setup/SetupCommand.js +21 -0
  22. package/src/commands/account/setup/SetupInputHandler.js +169 -0
  23. package/src/commands/account/setup/SetupOutputHandler.js +65 -0
  24. package/src/commands/account/setupci/AccountSetupCiAction.js +58 -0
  25. package/src/commands/account/setupci/AccountSetupCiCommand.js +20 -0
  26. package/src/commands/account/setupci/AccountSetupCiConstants.js +21 -0
  27. package/src/commands/account/setupci/AccountSetupCiOutputHandler.js +40 -0
  28. package/src/commands/account/setupci/AccountSetupCiValidation.js +100 -0
  29. package/src/commands/base/BaseAction.js +37 -0
  30. package/src/commands/base/BaseInputHandler.js +24 -0
  31. package/src/commands/base/BaseOutputHandler.js +30 -0
  32. package/src/commands/custom/hello/Action.js +58 -0
  33. package/src/commands/custom/hello/Command.js +20 -0
  34. package/src/commands/custom/hello/Handler.js +26 -0
  35. package/src/commands/custom/hello/README.md +78 -0
  36. package/src/commands/custom/hook/Action.js +28 -0
  37. package/src/commands/custom/hook/Command.js +22 -0
  38. package/src/commands/custom/hook/InputHandler.js +8 -0
  39. package/src/commands/custom/hook/OutputHandler.js +8 -0
  40. package/src/commands/custom/hook/README.md +32 -0
  41. package/src/commands/file/create/CreateFileAction.js +89 -0
  42. package/src/commands/file/create/CreateFileCommand.js +20 -0
  43. package/src/commands/file/create/CreateFileInputHandler.js +175 -0
  44. package/src/commands/file/create/CreateFileOutputHandler.js +22 -0
  45. package/src/commands/file/import/ImportFilesAction.js +112 -0
  46. package/src/commands/file/import/ImportFilesCommand.js +22 -0
  47. package/src/commands/file/import/ImportFilesInputHandler.js +130 -0
  48. package/src/commands/file/import/ImportFilesOutputHandler.js +53 -0
  49. package/src/commands/file/list/ListFilesAction.js +55 -0
  50. package/src/commands/file/list/ListFilesCommand.js +20 -0
  51. package/src/commands/file/list/ListFilesInputHandler.js +55 -0
  52. package/src/commands/file/list/ListFilesOutputHandler.js +24 -0
  53. package/src/commands/file/upload/UploadFilesAction.js +67 -0
  54. package/src/commands/file/upload/UploadFilesCommand.js +20 -0
  55. package/src/commands/file/upload/UploadFilesInputHandler.js +125 -0
  56. package/src/commands/file/upload/UploadFilesOutputHandler.js +49 -0
  57. package/src/commands/object/create/CreateObjectAction.js +33 -0
  58. package/src/commands/object/create/CreateObjectCommand.js +19 -0
  59. package/src/commands/object/create/CreateObjectInputHandler.js +82 -0
  60. package/src/commands/object/import/ImportObjectsAction.js +225 -0
  61. package/src/commands/object/import/ImportObjectsCommand.js +20 -0
  62. package/src/commands/object/import/ImportObjectsInputHandler.js +310 -0
  63. package/src/commands/object/import/ImportObjectsOutputHandler.js +114 -0
  64. package/src/commands/object/list/ListObjectsAction.js +62 -0
  65. package/src/commands/object/list/ListObjectsCommand.js +20 -0
  66. package/src/commands/object/list/ListObjectsInputHandler.js +148 -0
  67. package/src/commands/object/list/ListObjectsOutputHandler.js +29 -0
  68. package/src/commands/object/update/UpdateAction.js +138 -0
  69. package/src/commands/object/update/UpdateCommand.js +20 -0
  70. package/src/commands/object/update/UpdateInputHandler.js +170 -0
  71. package/src/commands/object/update/UpdateOutputHandler.js +61 -0
  72. package/src/commands/project/adddependencies/AddDependenciesAction.js +55 -0
  73. package/src/commands/project/adddependencies/AddDependenciesCommand.js +19 -0
  74. package/src/commands/project/adddependencies/AddDependenciesOutputHandler.js +114 -0
  75. package/src/commands/project/create/CreateProjectAction.js +370 -0
  76. package/src/commands/project/create/CreateProjectCommand.js +20 -0
  77. package/src/commands/project/create/CreateProjectInputHandler.js +169 -0
  78. package/src/commands/project/create/CreateProjectOutputHandler.js +36 -0
  79. package/src/commands/project/deploy/DeployAction.js +161 -0
  80. package/src/commands/project/deploy/DeployCommand.js +20 -0
  81. package/src/commands/project/deploy/DeployInputHandler.js +100 -0
  82. package/src/commands/project/deploy/DeployOutputHandler.js +49 -0
  83. package/src/commands/project/package/PackageAction.js +59 -0
  84. package/src/commands/project/package/PackageCommand.js +18 -0
  85. package/src/commands/project/package/PackageOutputHandler.js +18 -0
  86. package/src/commands/project/validate/ValidateAction.js +106 -0
  87. package/src/commands/project/validate/ValidateCommand.js +20 -0
  88. package/src/commands/project/validate/ValidateInputHandler.js +92 -0
  89. package/src/commands/project/validate/ValidateOutputHandler.js +74 -0
  90. package/src/core/CommandActionExecutor.js +347 -0
  91. package/src/core/CommandAuthentication.js +13 -0
  92. package/src/core/CommandOptionsValidator.js +42 -0
  93. package/src/core/CommandRegistrationService.js +130 -0
  94. package/src/core/CommandsMetadataService.js +104 -0
  95. package/src/core/extensibility/CLIConfigurationService.js +192 -0
  96. package/src/core/extensibility/CommandUserExtension.js +64 -0
  97. package/src/core/sdksetup/SdkDownloadService.js +109 -0
  98. package/src/core/sdksetup/SdkLicense.js +39 -0
  99. package/src/core/sdksetup/SdkProperties.js +51 -0
  100. package/src/loggers/ConsoleLogger.js +32 -0
  101. package/src/loggers/LoggerFontFormatter.mjs +17 -0
  102. package/src/loggers/LoggerOsConstants.js +12 -0
  103. package/src/loggers/NodeConsoleLogger.js +47 -0
  104. package/src/metadata/CommandGenerators.json +92 -0
  105. package/src/metadata/NodeCommandsMetadata.json +139 -0
  106. package/src/metadata/ObjectTypesMetadata.js +615 -0
  107. package/src/metadata/SdkCommandsMetadata.json +846 -0
  108. package/src/metadata/SdkCommandsMetadataPatch.json +130 -0
  109. package/src/metadata/SuiteScriptModulesMetadata.js +152 -0
  110. package/src/metadata/SuiteScriptTypesMetadata.js +64 -0
  111. package/src/services/AccountFileCabinetService.js +86 -0
  112. package/src/services/EnvironmentInformationService.js +31 -0
  113. package/src/services/ExecutionContextService.js +108 -0
  114. package/src/services/FileCabinetService.js +65 -0
  115. package/src/services/FileSystemService.js +245 -0
  116. package/src/services/NodeTranslationService.js +22 -0
  117. package/src/services/NpmInstallRunner.js +33 -0
  118. package/src/services/ProjectInfoService.js +209 -0
  119. package/src/services/SuiteCloudAuthProxyService.js +469 -0
  120. package/src/services/TranslationKeys.js +506 -0
  121. package/src/services/TranslationService.js +30 -0
  122. package/src/services/actionresult/ActionResult.js +129 -0
  123. package/src/services/actionresult/AuthenticateActionResult.js +85 -0
  124. package/src/services/actionresult/CreateProjectActionResult.js +100 -0
  125. package/src/services/actionresult/DeployActionResult.js +69 -0
  126. package/src/services/actionresult/HelloActionResult.js +13 -0
  127. package/src/services/actionresult/ManageAccountActionResult.js +70 -0
  128. package/src/services/settings/CLISettings.js +46 -0
  129. package/src/services/settings/CLISettingsService.js +132 -0
  130. package/src/suitecloud.js +33 -0
  131. package/src/templates/TemplateKeys.js +25 -0
  132. package/src/templates/objects/commerceextension.xml +9 -0
  133. package/src/templates/projectconfigs/default_gitignore.template +47 -0
  134. package/src/templates/projectconfigs/sdf.config.js +4 -0
  135. package/src/templates/projectconfigs/suitecloud.config.js +4 -0
  136. package/src/templates/scripts/blankscript.js +3 -0
  137. package/src/templates/unittest/jest.config.js.template +7 -0
  138. package/src/templates/unittest/jsconfig.json.template +5 -0
  139. package/src/templates/unittest/package.json.template +12 -0
  140. package/src/templates/unittest/sample-test.js.template +37 -0
  141. package/src/templates/unittest/suitecloud.config.js.template +15 -0
  142. package/src/ui/CliSpinner.js +34 -0
  143. package/src/utils/AccountCredentialsFormatter.js +62 -0
  144. package/src/utils/AccountSpecificValuesUtils.js +55 -0
  145. package/src/utils/ActionResultUtils.js +47 -0
  146. package/src/utils/ApplyInstallationPreferencesUtils.js +41 -0
  147. package/src/utils/AuthenticationUtils.js +262 -0
  148. package/src/utils/CommandUtils.js +50 -0
  149. package/src/utils/CryptoUtils.js +41 -0
  150. package/src/utils/ExceptionUtils.js +33 -0
  151. package/src/utils/FileUtils.js +43 -0
  152. package/src/utils/SdkOperationResult.js +68 -0
  153. package/src/utils/SdkOperationResultUtils.js +20 -0
  154. package/src/utils/ValidationErrorsFormatter.js +23 -0
  155. package/src/utils/http/HttpConstants.js +39 -0
  156. package/src/utils/http/ProxyAgent.js +110 -0
  157. package/src/validation/InteractiveAnswersValidator.js +205 -0
@@ -0,0 +1,225 @@
1
+ /*
2
+ ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3
+ ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
4
+ */
5
+ 'use strict';
6
+
7
+ const { ActionResult } = require('../../../services/actionresult/ActionResult');
8
+ const CommandUtils = require('../../../utils/CommandUtils');
9
+ const NodeTranslationService = require('../../../services/NodeTranslationService');
10
+ const CommandsMetadataService = require('../../../core/CommandsMetadataService');
11
+ const executeWithSpinner = require('../../../ui/CliSpinner').executeWithSpinner;
12
+ const SdkOperationResultUtils = require('../../../utils/SdkOperationResultUtils');
13
+ const SdkExecutionContext = require('../../../SdkExecutionContext');
14
+ const { getProjectDefaultAuthId } = require('../../../utils/AuthenticationUtils');
15
+ const BaseAction = require('../../base/BaseAction');
16
+ const {
17
+ COMMAND_IMPORTOBJECTS: { MESSAGES, WARNINGS },
18
+ } = require('../../../services/TranslationKeys');
19
+ const SdkExecutor = require('../../../SdkExecutor');
20
+
21
+ const ANSWERS_NAMES = {
22
+ AUTH_ID: 'authid',
23
+ APP_ID: 'appid',
24
+ SCRIPT_ID: 'scriptid',
25
+ SPECIFY_SCRIPT_ID: 'specifyscriptid',
26
+ SPECIFY_SUITEAPP: 'specifysuiteapp',
27
+ OBJECT_TYPE: 'type',
28
+ SPECIFY_OBJECT_TYPE: 'specifyObjectType',
29
+ TYPE_CHOICES_ARRAY: 'typeChoicesArray',
30
+ DESTINATION_FOLDER: 'destinationfolder',
31
+ PROJECT_FOLDER: 'project',
32
+ OBJECTS_SELECTED: 'objects_selected',
33
+ OVERWRITE_OBJECTS: 'overwrite_objects',
34
+ IMPORT_REFERENCED_SUITESCRIPTS: 'import_referenced_suitescripts',
35
+ };
36
+
37
+ const COMMAND_FLAGS = {
38
+ EXCLUDE_FILES: 'excludefiles',
39
+ };
40
+
41
+ const LIST_OBJECTS_COMMAND_NAME = 'object:list';
42
+ const IMPORT_OBJECTS_COMMAND_TYPE_PARAM_ALL = 'ALL';
43
+ const IMPORT_OBJECTS_COMMAND_SCRIPT_ID_PARAM_ALL = 'ALL';
44
+ const NUMBER_OF_SCRIPTS = 8;
45
+ const MAX_PARALLEL_EXECUTIONS = 4;
46
+
47
+ module.exports = class ImportObjectsAction extends BaseAction {
48
+ constructor(options) {
49
+ super(options);
50
+
51
+ const commandsMetadataService = new CommandsMetadataService();
52
+ this._listObjectsMetadata = commandsMetadataService.getCommandMetadataByName(LIST_OBJECTS_COMMAND_NAME);
53
+ }
54
+
55
+ preExecute(answers) {
56
+ answers[ANSWERS_NAMES.PROJECT_FOLDER] = CommandUtils.quoteString(this._projectFolder);
57
+ if (!this._runInInteractiveMode && answers.hasOwnProperty(ANSWERS_NAMES.DESTINATION_FOLDER)) {
58
+ answers.destinationfolder = CommandUtils.quoteString(answers.destinationfolder);
59
+ }
60
+
61
+ return answers;
62
+ }
63
+
64
+ async execute(params) {
65
+ if (params[ANSWERS_NAMES.OVERWRITE_OBJECTS] === false) {
66
+ throw NodeTranslationService.getMessage(MESSAGES.CANCEL_IMPORT);
67
+ }
68
+
69
+ const flags = [];
70
+ let commandParams = {};
71
+ try {
72
+ let scriptIdArray;
73
+ if (this._runInInteractiveMode) {
74
+ if (params[ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS] !== undefined && !params[ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS]) {
75
+ flags.push(COMMAND_FLAGS.EXCLUDE_FILES);
76
+ delete params[ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS];
77
+ }
78
+
79
+ scriptIdArray = params[ANSWERS_NAMES.SCRIPT_ID];
80
+ } else {
81
+ if (params[COMMAND_FLAGS.EXCLUDE_FILES]) {
82
+ flags.push(COMMAND_FLAGS.EXCLUDE_FILES);
83
+ delete params[COMMAND_FLAGS.EXCLUDE_FILES];
84
+ }
85
+
86
+ if (params[ANSWERS_NAMES.SCRIPT_ID] === IMPORT_OBJECTS_COMMAND_SCRIPT_ID_PARAM_ALL) {
87
+ if (params[ANSWERS_NAMES.OBJECT_TYPE] === IMPORT_OBJECTS_COMMAND_TYPE_PARAM_ALL) {
88
+ scriptIdArray = (await this._getAllScriptIds(params)).map((el) => el.scriptId);
89
+ } else {
90
+ scriptIdArray = (await this._getAllScriptIdsForObjectType(params)).map((el) => el.scriptId);
91
+ }
92
+ } else {
93
+ scriptIdArray = params[ANSWERS_NAMES.SCRIPT_ID];
94
+ }
95
+
96
+ await this._log.info(NodeTranslationService.getMessage(WARNINGS.OVERRIDE));
97
+ }
98
+
99
+ delete params[ANSWERS_NAMES.SCRIPT_ID];
100
+ const operationResultData = {
101
+ failedImports: [],
102
+ successfulImports: [],
103
+ errorImports: [],
104
+ };
105
+ let arrayOfPromises = [];
106
+ const sdkParams = CommandUtils.extractCommandOptions(params, this._commandMetadata);
107
+ const numberOfSdkCalls = Math.ceil(scriptIdArray.length / NUMBER_OF_SCRIPTS);
108
+ const numberOfSteps = Math.ceil(numberOfSdkCalls / MAX_PARALLEL_EXECUTIONS);
109
+
110
+ for (let i = 0; i < numberOfSdkCalls; i++) {
111
+ const partialScriptIds = scriptIdArray.slice(i * NUMBER_OF_SCRIPTS, (i + 1) * NUMBER_OF_SCRIPTS);
112
+ const partialScriptIdsString = partialScriptIds.join(' ');
113
+ const partialExecutionContextForImportObjects = SdkExecutionContext.Builder.forCommand(this._commandMetadata.sdkCommand)
114
+ .integration()
115
+ .addFlags(flags)
116
+ .addParams(sdkParams)
117
+ .addParam(ANSWERS_NAMES.SCRIPT_ID, partialScriptIdsString)
118
+ .build();
119
+
120
+ const sdkExecutor = new SdkExecutor(this._sdkPath, this._executionEnvironmentContext);
121
+ arrayOfPromises.push(
122
+ sdkExecutor
123
+ .execute(partialExecutionContextForImportObjects)
124
+ .then(this._parsePartialResult.bind({ partialScriptIds, operationResultData }))
125
+ );
126
+ if (i % MAX_PARALLEL_EXECUTIONS === (MAX_PARALLEL_EXECUTIONS - 1)) {
127
+ await executeWithSpinner({
128
+ action: Promise.all(arrayOfPromises),
129
+ message: NodeTranslationService.getMessage(MESSAGES.IMPORTING_OBJECTS, (i + 1) / MAX_PARALLEL_EXECUTIONS, numberOfSteps),
130
+ });
131
+ arrayOfPromises = [];
132
+ }
133
+ }
134
+
135
+ await executeWithSpinner({
136
+ action: Promise.all(arrayOfPromises),
137
+ message: NodeTranslationService.getMessage(MESSAGES.IMPORTING_OBJECTS, numberOfSteps, numberOfSteps),
138
+ });
139
+
140
+
141
+ //adding all the scripts id to the params
142
+ commandParams = {...sdkParams, [ANSWERS_NAMES.SCRIPT_ID]: scriptIdArray.join(' ')}
143
+
144
+ // At this point, the OperationResult will never be an error. It's handled before
145
+ return ActionResult.Builder.withData(operationResultData)
146
+ .withResultMessage(operationResultData.resultMessage)
147
+ .withCommandParameters(commandParams)
148
+ .withCommandFlags(flags)
149
+ .build();
150
+
151
+ } catch (error) {
152
+ return ActionResult.Builder.withErrors([error])
153
+ .withCommandParameters(commandParams)
154
+ .withCommandFlags(flags)
155
+ .build();
156
+ }
157
+ }
158
+
159
+ _parsePartialResult(partialOperationResult) {
160
+ if (partialOperationResult.status === SdkOperationResultUtils.STATUS.ERROR) {
161
+ this.operationResultData.errorImports = this.operationResultData.errorImports.concat({
162
+ scriptIds: this.partialScriptIds,
163
+ reason: partialOperationResult.errorMessages[0],
164
+ });
165
+ } else {
166
+ if (partialOperationResult.data.failedImports.length > 0) {
167
+ this.operationResultData.failedImports = this.operationResultData.failedImports.concat(
168
+ partialOperationResult.data.failedImports
169
+ );
170
+ }
171
+ if (partialOperationResult.data.successfulImports.length > 0) {
172
+ this.operationResultData.successfulImports = this.operationResultData.successfulImports.concat(
173
+ partialOperationResult.data.successfulImports
174
+ );
175
+ }
176
+ if (partialOperationResult.resultMessage){
177
+ this.operationResultData.resultMessage = partialOperationResult.resultMessage;
178
+ }
179
+ }
180
+ }
181
+
182
+ async _getAllScriptIdsForObjectType(params) {
183
+ const sdkParams = {};
184
+ sdkParams.type = params[ANSWERS_NAMES.OBJECT_TYPE];
185
+
186
+ return this._callListObjects(params, sdkParams);
187
+ }
188
+
189
+ async _getAllScriptIds(params) {
190
+ return this._callListObjects(params, {});
191
+ }
192
+
193
+ async _callListObjects(params, sdkParams) {
194
+ sdkParams.authid = params[ANSWERS_NAMES.AUTH_ID];
195
+ const appId = params[ANSWERS_NAMES.APP_ID];
196
+ if (appId) {
197
+ sdkParams.appid = appId;
198
+ }
199
+
200
+ const executionContext = SdkExecutionContext.Builder.forCommand(this._listObjectsMetadata.sdkCommand)
201
+ .integration()
202
+ .addParams(sdkParams)
203
+ .build();
204
+
205
+ const actionListObjects = this._sdkExecutor.execute(executionContext);
206
+
207
+ const listObjectsOperationResult = await executeWithSpinner({
208
+ action: actionListObjects,
209
+ message: NodeTranslationService.getMessage(MESSAGES.LOADING_OBJECTS),
210
+ });
211
+
212
+ if (listObjectsOperationResult.status === SdkOperationResultUtils.STATUS.ERROR) {
213
+ throw listObjectsOperationResult.errorMessages;
214
+ }
215
+
216
+ const listObjectsOperationResultData = listObjectsOperationResult.data;
217
+
218
+ if (listObjectsOperationResultData == null || (Array.isArray(listObjectsOperationResultData) && listObjectsOperationResultData.length === 0)) {
219
+ throw NodeTranslationService.getMessage(MESSAGES.NO_OBJECTS_IMPORTED);
220
+ }
221
+
222
+ return listObjectsOperationResultData;
223
+ }
224
+
225
+ };
@@ -0,0 +1,20 @@
1
+ /*
2
+ ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3
+ ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
4
+ */
5
+ 'use strict';
6
+
7
+ const Command = require('../../Command');
8
+ const ImportObjectsAction = require('./ImportObjectsAction');
9
+ const ImportObjectsInputHandler = require('./ImportObjectsInputHandler');
10
+ const ImportObjectsOutputHandler = require('./ImportObjectsOutputHandler');
11
+
12
+ module.exports = {
13
+ create(options) {
14
+ return Command.Builder.withOptions(options)
15
+ .withAction(ImportObjectsAction)
16
+ .withInput(ImportObjectsInputHandler)
17
+ .withOutput(ImportObjectsOutputHandler)
18
+ .build();
19
+ }
20
+ };
@@ -0,0 +1,310 @@
1
+ /*
2
+ ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3
+ ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
4
+ */
5
+ 'use strict';
6
+
7
+ const { join } = require('path');
8
+ const { default : { prompt, Separator } } = require('inquirer');
9
+ const CommandsMetadataService = require('../../../core/CommandsMetadataService');
10
+ const executeWithSpinner = require('../../../ui/CliSpinner').executeWithSpinner;
11
+ const SdkOperationResultUtils = require('../../../utils/SdkOperationResultUtils');
12
+ const SdkExecutionContext = require('../../../SdkExecutionContext');
13
+ const { lineBreak } = require('../../../loggers/LoggerOsConstants');
14
+ const { getProjectDefaultAuthId } = require('../../../utils/AuthenticationUtils');
15
+ const BaseInputHandler = require('../../base/BaseInputHandler');
16
+ const SdkExecutor = require('../../../SdkExecutor');
17
+ const ProjectInfoService = require('../../../services/ProjectInfoService');
18
+ const FileSystemService = require('../../../services/FileSystemService');
19
+ const CommandUtils = require('../../../utils/CommandUtils');
20
+ const NodeTranslationService = require('../../../services/NodeTranslationService');
21
+ const { PROJECT_SUITEAPP, PROJECT_ACP, FOLDERS } = require('../../../ApplicationConstants');
22
+ const OBJECT_TYPES = require('../../../metadata/ObjectTypesMetadata');
23
+ const {
24
+ COMMAND_IMPORTOBJECTS: { MESSAGES, QUESTIONS, ERRORS },
25
+ YES,
26
+ NO,
27
+ ERRORS: { PROMPTING_INTERACTIVE_QUESTIONS_FAILED },
28
+ } = require('../../../services/TranslationKeys');
29
+ const {
30
+ validateArrayIsNotEmpty,
31
+ showValidationResults,
32
+ validateSuiteApp,
33
+ validateScriptId,
34
+ } = require('../../../validation/InteractiveAnswersValidator');
35
+ const FileUtils = require('../../../utils/FileUtils');
36
+
37
+ const ANSWERS_NAMES = {
38
+ AUTH_ID: 'authid',
39
+ APP_ID: 'appid',
40
+ SCRIPT_ID: 'scriptid',
41
+ SPECIFY_SCRIPT_ID: 'specifyscriptid',
42
+ SPECIFY_SUITEAPP: 'specifysuiteapp',
43
+ OBJECT_TYPE: 'type',
44
+ SPECIFY_OBJECT_TYPE: 'specifyObjectType',
45
+ TYPE_CHOICES_ARRAY: 'typeChoicesArray',
46
+ DESTINATION_FOLDER: 'destinationfolder',
47
+ PROJECT_FOLDER: 'project',
48
+ OBJECTS_SELECTED: 'objects_selected',
49
+ OVERWRITE_OBJECTS: 'overwrite_objects',
50
+ IMPORT_REFERENCED_SUITESCRIPTS: 'import_referenced_suitescripts',
51
+ };
52
+
53
+ const LIST_OBJECTS_COMMAND_NAME = 'object:list';
54
+ const CUSTOM_SCRIPT_PREFIX = 'customscript';
55
+
56
+ module.exports = class ImportObjectsInputHandler extends BaseInputHandler {
57
+ constructor(options) {
58
+ super(options);
59
+
60
+ // TODO input handlers shouldn't execute actions. rework this
61
+ this._sdkExecutor = new SdkExecutor(this._sdkPath, this._executionEnvironmentContext);
62
+
63
+ this._projectInfoService = new ProjectInfoService(this._projectFolder);
64
+ this._fileSystemService = new FileSystemService();
65
+ const commandsMetadataService = new CommandsMetadataService();
66
+ this._listObjectsMetadata = commandsMetadataService.getCommandMetadataByName(LIST_OBJECTS_COMMAND_NAME);
67
+ }
68
+
69
+ async getParameters(params) {
70
+ const listObjectQuestions = this._generateListObjectQuestions();
71
+ const listObjectAnswers = await prompt(listObjectQuestions);
72
+
73
+ const paramsForListObjects = this._arrangeAnswersForListObjects(listObjectAnswers);
74
+ const executionContextForListObjects = SdkExecutionContext.Builder.forCommand(this._listObjectsMetadata.sdkCommand)
75
+ .integration()
76
+ .addParams(paramsForListObjects)
77
+ .build();
78
+
79
+ let listObjectsResult;
80
+ try {
81
+ listObjectsResult = await executeWithSpinner({
82
+ action: this._sdkExecutor.execute(executionContextForListObjects),
83
+ message: NodeTranslationService.getMessage(MESSAGES.LOADING_LIST_OF_OBJECTS),
84
+ });
85
+ } catch (error) {
86
+ throw NodeTranslationService.getMessage(ERRORS.CALLING_LIST_OBJECTS, lineBreak, error);
87
+ }
88
+
89
+ if (listObjectsResult.status === SdkOperationResultUtils.STATUS.ERROR) {
90
+ throw listObjectsResult.errorMessages;
91
+ }
92
+ const { data } = listObjectsResult;
93
+
94
+ if (Array.isArray(data) && listObjectsResult.data.length === 0) {
95
+ throw NodeTranslationService.getMessage(MESSAGES.NO_OBJECTS_TO_LIST);
96
+ }
97
+
98
+ let selectionObjectAnswers;
99
+ let answersAfterObjectSelection;
100
+ let overwriteConfirmationAnswer;
101
+ try {
102
+ const selectionObjectQuestions = this._generateSelectionObjectQuestions(listObjectsResult);
103
+ selectionObjectAnswers = await prompt(selectionObjectQuestions);
104
+
105
+ const questionsAfterObjectSelection = this._generateQuestionsAfterObjectSelection(selectionObjectAnswers);
106
+ answersAfterObjectSelection = await prompt(questionsAfterObjectSelection);
107
+
108
+ const overwriteConfirmationQuestion = this._generateOverwriteConfirmationQuestion(answersAfterObjectSelection);
109
+ overwriteConfirmationAnswer = await prompt(overwriteConfirmationQuestion);
110
+ } catch (error) {
111
+ throw NodeTranslationService.getMessage(PROMPTING_INTERACTIVE_QUESTIONS_FAILED, lineBreak, error);
112
+ }
113
+
114
+ const combinedAnswers = { ...listObjectAnswers, ...selectionObjectAnswers, ...answersAfterObjectSelection, ...overwriteConfirmationAnswer };
115
+
116
+ const answers = this._arrangeAnswersForImportObjects(combinedAnswers);
117
+ return answers;
118
+ }
119
+
120
+ _generateListObjectQuestions() {
121
+ const questions = [];
122
+ if (this._projectInfoService.getProjectType() === PROJECT_SUITEAPP) {
123
+ const specifySuiteApp = {
124
+ type: CommandUtils.INQUIRER_TYPES.LIST,
125
+ name: ANSWERS_NAMES.SPECIFY_SUITEAPP,
126
+ message: NodeTranslationService.getMessage(QUESTIONS.SPECIFIC_APPID),
127
+ default: true,
128
+ choices: [
129
+ { name: NodeTranslationService.getMessage(YES), value: true },
130
+ { name: NodeTranslationService.getMessage(NO), value: false },
131
+ ],
132
+ validate: (fieldValue) => showValidationResults(fieldValue, validateArrayIsNotEmpty),
133
+ };
134
+ questions.push(specifySuiteApp);
135
+
136
+ const specifyAppId = {
137
+ when: function (response) {
138
+ return response[ANSWERS_NAMES.SPECIFY_SUITEAPP];
139
+ },
140
+ type: CommandUtils.INQUIRER_TYPES.INPUT,
141
+ name: ANSWERS_NAMES.APP_ID,
142
+ message: NodeTranslationService.getMessage(QUESTIONS.APPID),
143
+ validate: (fieldValue) => showValidationResults(fieldValue, validateSuiteApp),
144
+ };
145
+ questions.push(specifyAppId);
146
+ }
147
+
148
+ const showAllObjects = {
149
+ type: CommandUtils.INQUIRER_TYPES.LIST,
150
+ name: ANSWERS_NAMES.SPECIFY_OBJECT_TYPE,
151
+ message: NodeTranslationService.getMessage(QUESTIONS.SHOW_ALL_CUSTOM_OBJECTS),
152
+ default: false,
153
+ choices: [
154
+ { name: NodeTranslationService.getMessage(YES), value: false },
155
+ { name: NodeTranslationService.getMessage(NO), value: true },
156
+ ],
157
+ };
158
+ questions.push(showAllObjects);
159
+
160
+ const selectObjectType = {
161
+ when: function (answers) {
162
+ return answers[ANSWERS_NAMES.SPECIFY_OBJECT_TYPE];
163
+ },
164
+ type: CommandUtils.INQUIRER_TYPES.CHECKBOX,
165
+ name: ANSWERS_NAMES.TYPE_CHOICES_ARRAY,
166
+ message: NodeTranslationService.getMessage(QUESTIONS.FILTER_BY_CUSTOM_OBJECTS),
167
+ pageSize: 15,
168
+ choices: [
169
+ ...OBJECT_TYPES.map((customObject) => ({
170
+ name: customObject.name,
171
+ value: customObject.value.type,
172
+ })),
173
+ new Separator(),
174
+ ],
175
+ validate: (fieldValue) => showValidationResults(fieldValue, validateArrayIsNotEmpty),
176
+ };
177
+ questions.push(selectObjectType);
178
+
179
+ const filterByScriptId = {
180
+ type: CommandUtils.INQUIRER_TYPES.LIST,
181
+ name: ANSWERS_NAMES.SPECIFY_SCRIPT_ID,
182
+ message: NodeTranslationService.getMessage(QUESTIONS.FILTER_BY_SCRIPT_ID),
183
+ default: false,
184
+ choices: [
185
+ { name: NodeTranslationService.getMessage(YES), value: true },
186
+ { name: NodeTranslationService.getMessage(NO), value: false },
187
+ ],
188
+ };
189
+ questions.push(filterByScriptId);
190
+
191
+ const specifyScriptId = {
192
+ when: function (response) {
193
+ return response[ANSWERS_NAMES.SPECIFY_SCRIPT_ID];
194
+ },
195
+ type: CommandUtils.INQUIRER_TYPES.INPUT,
196
+ name: ANSWERS_NAMES.SCRIPT_ID,
197
+ message: NodeTranslationService.getMessage(QUESTIONS.SCRIPT_ID),
198
+ validate: (fieldValue) => showValidationResults(fieldValue, validateScriptId),
199
+ };
200
+ questions.push(specifyScriptId);
201
+
202
+ return questions;
203
+ }
204
+
205
+ _generateSelectionObjectQuestions(operationResult) {
206
+ const questions = [];
207
+ const { data } = operationResult;
208
+
209
+ const choicesToShow = data.map((object) => ({
210
+ name: object.type + ':' + object.scriptId,
211
+ value: object,
212
+ }));
213
+
214
+ const questionListObjectsSelection = {
215
+ type: CommandUtils.INQUIRER_TYPES.CHECKBOX,
216
+ name: ANSWERS_NAMES.OBJECTS_SELECTED,
217
+ message: NodeTranslationService.getMessage(QUESTIONS.SELECT_OBJECTS),
218
+ choices: choicesToShow,
219
+ validate: (fieldValue) => showValidationResults(fieldValue, validateArrayIsNotEmpty),
220
+ };
221
+ questions.push(questionListObjectsSelection);
222
+ return questions;
223
+ }
224
+
225
+ _generateQuestionsAfterObjectSelection(selectionObjectAnswers) {
226
+ const questions = [];
227
+
228
+ const hasCustomScript = selectionObjectAnswers.objects_selected.some((element) => element.scriptId.startsWith(CUSTOM_SCRIPT_PREFIX));
229
+ if (this._projectInfoService.getProjectType() === PROJECT_ACP && hasCustomScript) {
230
+ const questionImportReferencedSuiteScripts = {
231
+ type: CommandUtils.INQUIRER_TYPES.LIST,
232
+ name: ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS,
233
+ message: NodeTranslationService.getMessage(QUESTIONS.IMPORT_REFERENCED_SUITESCRIPTS),
234
+ default: true,
235
+ choices: [
236
+ { name: NodeTranslationService.getMessage(YES), value: true },
237
+ { name: NodeTranslationService.getMessage(NO), value: false },
238
+ ],
239
+ };
240
+ questions.push(questionImportReferencedSuiteScripts);
241
+ }
242
+
243
+ // extracting root prefix
244
+ // replacing '\' for '/', this is done because destinationfolder option in java-sdf works only with '/'
245
+ // sourroundig "" to the folder string so it will handle blank spaces case
246
+ const transformFoldersToChoicesFunc = (folder) => ({
247
+ name: folder.replace(this._projectFolder, '').replace(/\\/g, '/'),
248
+ value: `\"${folder.replace(this._projectFolder, '').replace(/\\/g, '/')}\"`,
249
+ });
250
+ const objectsFolder = join(this._projectFolder, FOLDERS.OBJECTS);
251
+ if (!FileUtils.exists(objectsFolder)) {
252
+ FileUtils.createDirectory(objectsFolder);
253
+ }
254
+ const objectsSubFolders = this._fileSystemService.getFoldersFromDirectory(objectsFolder);
255
+ const objectDirectoryChoices = [objectsFolder, ...objectsSubFolders].map(transformFoldersToChoicesFunc);
256
+
257
+ const questionDestinationFolder = {
258
+ type: CommandUtils.INQUIRER_TYPES.LIST,
259
+ name: ANSWERS_NAMES.DESTINATION_FOLDER,
260
+ message: NodeTranslationService.getMessage(QUESTIONS.DESTINATION_FOLDER),
261
+ choices: objectDirectoryChoices,
262
+ };
263
+ questions.push(questionDestinationFolder);
264
+ return questions;
265
+ }
266
+
267
+ _generateOverwriteConfirmationQuestion(answersAfterObjectSelection) {
268
+ const questions = [];
269
+
270
+ let overwriteConfirmationMessageKey;
271
+ if (
272
+ answersAfterObjectSelection[ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS] !== undefined &&
273
+ answersAfterObjectSelection[ANSWERS_NAMES.IMPORT_REFERENCED_SUITESCRIPTS]
274
+ ) {
275
+ overwriteConfirmationMessageKey = QUESTIONS.OVERWRITE_OBJECTS_AND_FILES;
276
+ } else {
277
+ overwriteConfirmationMessageKey = QUESTIONS.OVERWRITE_OBJECTS;
278
+ }
279
+
280
+ const questionOverwriteConfirmation = {
281
+ type: CommandUtils.INQUIRER_TYPES.LIST,
282
+ name: ANSWERS_NAMES.OVERWRITE_OBJECTS,
283
+ message: NodeTranslationService.getMessage(overwriteConfirmationMessageKey),
284
+ default: true,
285
+ choices: [
286
+ { name: NodeTranslationService.getMessage(YES), value: true },
287
+ { name: NodeTranslationService.getMessage(NO), value: false },
288
+ ],
289
+ };
290
+ questions.push(questionOverwriteConfirmation);
291
+ return questions;
292
+ }
293
+
294
+ _arrangeAnswersForListObjects(answers) {
295
+ answers[ANSWERS_NAMES.AUTH_ID] = this._authId;
296
+ if (answers[ANSWERS_NAMES.SPECIFY_OBJECT_TYPE]) {
297
+ answers[ANSWERS_NAMES.OBJECT_TYPE] = answers[ANSWERS_NAMES.TYPE_CHOICES_ARRAY].join(' ');
298
+ }
299
+ return CommandUtils.extractCommandOptions(answers, this._listObjectsMetadata);
300
+ }
301
+
302
+ _arrangeAnswersForImportObjects(answers) {
303
+ if (!answers[ANSWERS_NAMES.SPECIFY_OBJECT_TYPE] || answers[ANSWERS_NAMES.TYPE_CHOICES_ARRAY].length > 1) {
304
+ answers[ANSWERS_NAMES.OBJECT_TYPE] = 'ALL';
305
+ }
306
+ answers[ANSWERS_NAMES.SCRIPT_ID] = answers[ANSWERS_NAMES.OBJECTS_SELECTED].map((el) => el.scriptId);
307
+
308
+ return answers;
309
+ }
310
+ };
@@ -0,0 +1,114 @@
1
+ /*
2
+ ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3
+ ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
4
+ */
5
+ 'use strict';
6
+ const BaseOutputHandler = require('../../base/BaseOutputHandler');
7
+ const NodeTranslationService = require('../../../services/NodeTranslationService');
8
+ const ActionResultUtils = require('../../../utils/ActionResultUtils');
9
+
10
+ const {
11
+ COMMAND_IMPORTOBJECTS: { OUTPUT },
12
+ } = require('../../../services/TranslationKeys');
13
+
14
+ module.exports = class ImportObjectsOutputHandler extends BaseOutputHandler {
15
+ constructor(options) {
16
+ super(options);
17
+ }
18
+
19
+ parse(actionResult) {
20
+ if (
21
+ !actionResult.data ||
22
+ !(
23
+ (Array.isArray(actionResult.data.successfulImports) && actionResult.data.successfulImports.length) ||
24
+ (Array.isArray(actionResult.data.failedImports) && actionResult.data.failedImports.length) ||
25
+ (Array.isArray(actionResult.data.errorImports) && actionResult.data.errorImports.length)
26
+ )
27
+ ) {
28
+ ActionResultUtils.logResultMessage(actionResult, this._log);
29
+ return actionResult;
30
+ }
31
+
32
+ this._logImportedObjects(actionResult.data.successfulImports);
33
+ this._logUnImportedObjects(actionResult.data.failedImports);
34
+ this._logErrorImportedObjects(actionResult.data.errorImports);
35
+ return actionResult;
36
+ }
37
+
38
+ _logImportedObjects(importedObjects) {
39
+ if (Array.isArray(importedObjects) && importedObjects.length) {
40
+ this._log.result(NodeTranslationService.getMessage(OUTPUT.IMPORTED_OBJECTS));
41
+ importedObjects.forEach((objectImport) => {
42
+ const importedObjectLogMessage = `${this._log.getPadding(1)}- ${objectImport.customObject.type}:${objectImport.customObject.id}`;
43
+ this._log.result(importedObjectLogMessage);
44
+ this._logReferencedFileImportResult(objectImport.referencedFileImportResult);
45
+ });
46
+ }
47
+ }
48
+
49
+ _logErrorImportedObjects(errorImports) {
50
+ const reasons = errorImports
51
+ .map((errorImport) => errorImport.reason)
52
+ .reduce((totalReasons, reason) => {
53
+ return totalReasons.includes(reason) ? totalReasons : totalReasons.concat(reason);
54
+ }, []);
55
+ reasons.forEach((reason) => {
56
+ this._log.error(NodeTranslationService.getMessage(OUTPUT.OBJECT_ERROR, reason));
57
+ errorImports
58
+ .filter((errorImport) => errorImport.reason === reason)
59
+ .forEach((errorImport) => {
60
+ errorImport.scriptIds.forEach((scriptId) => {
61
+ this._log.error(`${this._log.getPadding(1)}- ${scriptId}`);
62
+ });
63
+ });
64
+ });
65
+ }
66
+
67
+ _logReferencedFileImportResult(referencedFileImportResult) {
68
+ const importedFiles = referencedFileImportResult.successfulImports;
69
+ const unImportedFiles = referencedFileImportResult.failedImports;
70
+
71
+ const thereAreReferencedFiles =
72
+ (Array.isArray(importedFiles) && importedFiles.length) || (Array.isArray(unImportedFiles) && unImportedFiles.length);
73
+ if (thereAreReferencedFiles) {
74
+ const referencedFilesLogMessage = `${this._log.getPadding(2)}- ${NodeTranslationService.getMessage(OUTPUT.REFERENCED_SUITESCRIPT_FILES)}`;
75
+ this._log.result(referencedFilesLogMessage);
76
+ }
77
+
78
+ if (Array.isArray(importedFiles) && importedFiles.length) {
79
+ importedFiles.forEach((importedFile) => {
80
+ const importedFileLogMessage = `${this._log.getPadding(3)}- ${NodeTranslationService.getMessage(
81
+ OUTPUT.REFERENCED_SUITESCRIPT_FILE_IMPORTED,
82
+ importedFile.path
83
+ )}`;
84
+ this._log.result(importedFileLogMessage);
85
+ });
86
+ }
87
+
88
+ if (Array.isArray(unImportedFiles) && unImportedFiles.length) {
89
+ unImportedFiles.forEach((unImportedFile) => {
90
+ const unimportedFileLogMessage = `${this._log.getPadding(3)}- ${NodeTranslationService.getMessage(
91
+ OUTPUT.REFERENCED_SUITESCRIPT_FILE_IMPORT_FAILED,
92
+ unImportedFile.path,
93
+ unImportedFile.message
94
+ )}`;
95
+ this._log.warning(unimportedFileLogMessage);
96
+ });
97
+ }
98
+ }
99
+
100
+ _logUnImportedObjects(unImportedObjects) {
101
+ if (Array.isArray(unImportedObjects) && unImportedObjects.length) {
102
+ this._log.warning(NodeTranslationService.getMessage(OUTPUT.UNIMPORTED_OBJECTS));
103
+ unImportedObjects.forEach((objectImport) => {
104
+ const unimportedObjectLogMessage = `${this._log.getPadding(1)}- ${NodeTranslationService.getMessage(
105
+ OUTPUT.OBJECT_IMPORT_FAILED,
106
+ objectImport.customObject.type,
107
+ objectImport.customObject.id,
108
+ objectImport.customObject.result.message
109
+ )}`;
110
+ this._log.warning(unimportedObjectLogMessage);
111
+ });
112
+ }
113
+ }
114
+ };