@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
package/src/CLI.js ADDED
@@ -0,0 +1,202 @@
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 path = require('path');
8
+ const assert = require('assert');
9
+ const program = require('commander');
10
+ const NodeConsoleLogger = require('./loggers/NodeConsoleLogger');
11
+ const NodeTranslationService = require('./services/NodeTranslationService');
12
+ const {
13
+ CLI: { INTERACTIVE_OPTION_DESCRIPTION, TITLE, USAGE, VERSION_HELP },
14
+ COMMAND_OPTIONS,
15
+ ERRORS,
16
+ } = require('./services/TranslationKeys');
17
+ const unwrapExceptionMessage = require('./utils/ExceptionUtils').unwrapExceptionMessage;
18
+ const INTERACTIVE_ALIAS = '-i';
19
+ const INTERACTIVE_OPTION = '--interactive';
20
+
21
+ // suitecloud executable is in {root}/src/suitecloud.js. package.json file is one level before
22
+ const PACKAGE_FILE = `${path.dirname(require.main.filename)}/../package.json`;
23
+ const configFile = require(PACKAGE_FILE);
24
+ const CLI_VERSION = configFile ? configFile.version : 'unknown';
25
+ const { nsCompatibleVersion } = require(PACKAGE_FILE);
26
+ const COMMAND_ALIAS = '[command]';
27
+ const HELP_COMMAND = 'help';
28
+ const HELP_OPTION = '--help';
29
+ const HELP_ALIAS = '-h';
30
+ const VERSION_OPTION = '--version';
31
+
32
+ module.exports = class CLI {
33
+ constructor(dependencies) {
34
+ assert(dependencies);
35
+ assert(dependencies.commandsMetadataService);
36
+ assert(dependencies.commandActionExecutor);
37
+ assert(dependencies.commandRegistrationService);
38
+
39
+ this._commandsMetadataService = dependencies.commandsMetadataService;
40
+ this._commandActionExecutor = dependencies.commandActionExecutor;
41
+ this._commandRegistrationService = dependencies.commandRegistrationService;
42
+ }
43
+
44
+ start(process) {
45
+ try {
46
+ const commandMetadataList = this._commandsMetadataService.getCommandsMetadata();
47
+
48
+ this._addUbiquitousOptions(commandMetadataList, [] );
49
+ const thirdArgument = process.argv[2];
50
+ if (
51
+ thirdArgument &&
52
+ thirdArgument !== HELP_ALIAS &&
53
+ thirdArgument !== HELP_OPTION &&
54
+ thirdArgument !== HELP_COMMAND &&
55
+ thirdArgument !== VERSION_OPTION
56
+ ) {
57
+ this._validateCommandExists(commandMetadataList, thirdArgument);
58
+ } else if (thirdArgument == HELP_COMMAND && process.argv[3]) {
59
+ this._validateCommandExists(commandMetadataList, process.argv[3]);
60
+ }
61
+
62
+ if (process.argv.length > 3 && (process.argv.includes(HELP_ALIAS) || process.argv.includes(HELP_OPTION))) {
63
+ process.argv = this._leaveOnlyHelpArguments();
64
+ }
65
+
66
+ const runInInteractiveMode = this._isRunningInInteractiveMode();
67
+ this._initializeCommands(commandMetadataList, runInInteractiveMode);
68
+
69
+ // If there are no arguments, we print SuiteCloud version header
70
+ if (!process.argv || process.argv.length <= 2) {
71
+ NodeConsoleLogger.info(NodeTranslationService.getMessage(TITLE, nsCompatibleVersion));
72
+ }
73
+
74
+ program
75
+ .version(CLI_VERSION, VERSION_OPTION, NodeTranslationService.getMessage(VERSION_HELP))
76
+ .option(
77
+ `${INTERACTIVE_ALIAS}, ${INTERACTIVE_OPTION}`,
78
+ NodeTranslationService.getMessage(INTERACTIVE_OPTION_DESCRIPTION),
79
+ this._validateInteractive
80
+ )
81
+ .helpOption(`${HELP_ALIAS}, ${HELP_OPTION}`, NodeTranslationService.getMessage(COMMAND_OPTIONS.HELP))
82
+ .addHelpCommand(`${HELP_COMMAND} ${COMMAND_ALIAS}`, NodeTranslationService.getMessage(COMMAND_OPTIONS.HELP))
83
+ .on('command:*', (args) => {
84
+ NodeConsoleLogger.error(NodeTranslationService.getMessage(ERRORS.COMMAND_DOES_NOT_EXIST, args[0]));
85
+ })
86
+ .usage(NodeTranslationService.getMessage(USAGE))
87
+ .parse(process.argv);
88
+ } catch (exception) {
89
+ NodeConsoleLogger.error(unwrapExceptionMessage(exception));
90
+ }
91
+ }
92
+
93
+ _validateCommandExists(commandMetadataList, possibleCommand) {
94
+ if (!commandMetadataList.hasOwnProperty(possibleCommand)) {
95
+ throw NodeTranslationService.getMessage(ERRORS.COMMAND_DOES_NOT_EXIST, possibleCommand);
96
+ }
97
+ }
98
+
99
+ _leaveOnlyHelpArguments() {
100
+ return process.argv.slice(0, 3).concat(HELP_ALIAS); //We only leave commandName and help argument
101
+ }
102
+
103
+ _isRunningInInteractiveMode() {
104
+ return process.argv.includes(INTERACTIVE_ALIAS) || process.argv.includes(INTERACTIVE_OPTION);
105
+ }
106
+
107
+ _validateInteractive() {
108
+ let additionalAllowed = 0;
109
+ process.argv.forEach((arg)=>{
110
+ if( /\b(authid|project|config|debug)\b/.test(arg) ) additionalAllowed += 2;
111
+ });
112
+ if (process.argv.length > (4 + additionalAllowed) ) {
113
+ // There are more options apart from -i or --interactive
114
+ throw NodeTranslationService.getMessage(ERRORS.INTERACTIVE_MODE_MORE_OPTIONS);
115
+ }
116
+ }
117
+
118
+ _addUbiquitousOptions(commandMetadataList, exemptions= []) {
119
+ Object.values(commandMetadataList).forEach((commandMetadata) => {
120
+ if(exemptions.includes( commandMetadata.name )) return;
121
+
122
+ Object.assign(
123
+ commandMetadata.options,
124
+ {
125
+ "config": {
126
+ "name": "config",
127
+ "option": "config",
128
+ "description": "Specify a config file to use. Otherwise cli will discover closest config file",
129
+ "mandatory": false,
130
+ "type": "SINGLE",
131
+ "usage": "\"./path/to/sdf.config.alt.js\"",
132
+ "defaultOption": false,
133
+ "disableInIntegrationMode": false,
134
+ "conflicts": ["noconfig"]
135
+ },
136
+ "noconfig": {
137
+ "name": "noconfig",
138
+ "option": "noconfig",
139
+ "description": "Do not use any config file",
140
+ "mandatory": false,
141
+ "type": "FLAG",
142
+ "usage": "",
143
+ "defaultOption": false,
144
+ "disableInIntegrationMode": false,
145
+ "conflicts": ["config"]
146
+ },
147
+ "customflag": {
148
+ "name": "customflag",
149
+ "option": "customflag",
150
+ "description": "A custom boolean that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
151
+ "mandatory": false,
152
+ "type": "FLAG",
153
+ "usage": "",
154
+ "defaultOption": false,
155
+ "disableInIntegrationMode": false
156
+ },
157
+ "customoptions": {
158
+ "name": "customoptions",
159
+ "option": "customoptions",
160
+ "description": "Custom string values that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
161
+ "mandatory": false,
162
+ "type": "MULTIPLE",
163
+ "usage": "\"value1\" \"value2\"",
164
+ "defaultOption": false,
165
+ "disableInIntegrationMode": false
166
+ },
167
+ "debug": {
168
+ "name": "debug",
169
+ "option": "debug",
170
+ "description": "Directory to dump debug data for debugging. Creates a unique {command}.{datetime}.json file per run",
171
+ "mandatory": false,
172
+ "type": "SINGLE",
173
+ "usage": "\"./debug-output\"",
174
+ "defaultOption": false,
175
+ "disableInIntegrationMode": false
176
+ }
177
+ }
178
+ );
179
+ });
180
+ }
181
+
182
+ _initializeCommands(commandMetadataList, runInInteractiveMode) {
183
+ const commandsMetadataArraySortedByCommandName = Object.values(commandMetadataList).sort((command1, command2) =>
184
+ command1.name.localeCompare(command2.name)
185
+ );
186
+
187
+ commandsMetadataArraySortedByCommandName.forEach((commandMetadata) => {
188
+ this._commandRegistrationService.register({
189
+ commandMetadata: commandMetadata,
190
+ program: program,
191
+ runInInteractiveMode: runInInteractiveMode,
192
+ executeCommandFunction: async (options) => {
193
+ return this._commandActionExecutor.executeAction({
194
+ commandName: commandMetadata.name,
195
+ runInInteractiveMode: runInInteractiveMode,
196
+ arguments: options,
197
+ });
198
+ },
199
+ });
200
+ });
201
+ }
202
+ };
@@ -0,0 +1,21 @@
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
+ module.exports = class CLIException {
8
+ constructor(defaultMessage, infoMessage, translationKey) {
9
+ this._defaultMessage = defaultMessage;
10
+ this._infoMessage = infoMessage;
11
+ this._translationKey = translationKey;
12
+ }
13
+
14
+ getInfoMessage() {
15
+ return this._infoMessage;
16
+ }
17
+
18
+ getErrorMessage() {
19
+ return this._defaultMessage;
20
+ }
21
+ };
@@ -0,0 +1,39 @@
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 { SDK_CLIENT_PLATFORM } = require('./ApplicationConstants');
8
+
9
+ module.exports = class ExecutionEnvironmentContext {
10
+
11
+ constructor(params) {
12
+ this._platform = SDK_CLIENT_PLATFORM;
13
+ this._platformVersion = process.version;
14
+
15
+ if (!params) {
16
+ params = {
17
+ platform: SDK_CLIENT_PLATFORM,
18
+ platformVersion: process.version,
19
+ };
20
+ }
21
+
22
+ if (params.platform) {
23
+ this._platform = params.platform;
24
+ }
25
+
26
+ if (params.platformVersion) {
27
+ this._platformVersion = params.platformVersion;
28
+ }
29
+ }
30
+
31
+ getPlatform() {
32
+ return this._platform;
33
+ }
34
+
35
+ getPlatformVersion() {
36
+ return this._platformVersion;
37
+ }
38
+
39
+ }
@@ -0,0 +1,90 @@
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 assert = require('assert');
8
+
9
+ class SdkExecutionContext {
10
+ constructor(options) {
11
+ assert(options.command, 'Command is mandatory option');
12
+ this._command = options.command;
13
+ this._integrationMode = options.integrationMode;
14
+ this._params = options.params;
15
+ this._flags = options.flags;
16
+ }
17
+
18
+ getCommand() {
19
+ return this._command;
20
+ }
21
+
22
+ getParams() {
23
+ return this._params;
24
+ }
25
+
26
+ getFlags() {
27
+ return this._flags;
28
+ }
29
+
30
+ isIntegrationMode() {
31
+ return this._integrationMode;
32
+ }
33
+
34
+ static get Builder() {
35
+ return new SdkExecutionContextBuilder();
36
+ }
37
+ }
38
+
39
+ class SdkExecutionContextBuilder {
40
+ constructor() {
41
+ this._params = {};
42
+ this._flags = [];
43
+ this._integrationMode = false;
44
+ }
45
+
46
+ forCommand(command) {
47
+ this._command = command;
48
+ return this;
49
+ }
50
+
51
+ integration() {
52
+ this._integrationMode = true;
53
+ return this;
54
+ }
55
+
56
+ addParams(params) {
57
+ Object.keys(params).forEach((key) => {
58
+ this.addParam(key, params[key]);
59
+ });
60
+ return this;
61
+ }
62
+
63
+ addParam(param, value) {
64
+ this._params[`-${param}`] = value;
65
+ return this;
66
+ }
67
+
68
+ addFlags(flags) {
69
+ flags.forEach((flag) => {
70
+ this.addFlag(flag);
71
+ });
72
+ return this;
73
+ }
74
+
75
+ addFlag(flag) {
76
+ this._flags.push(`-${flag}`);
77
+ return this;
78
+ }
79
+
80
+ build() {
81
+ return new SdkExecutionContext({
82
+ command: this._command,
83
+ params: this._params,
84
+ flags: this._flags,
85
+ integrationMode: this._integrationMode,
86
+ });
87
+ }
88
+ }
89
+
90
+ module.exports = SdkExecutionContext;
@@ -0,0 +1,160 @@
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 {
8
+ SDK_INTEGRATION_MODE_JVM_OPTION,
9
+ SDK_CLIENT_PLATFORM_JVM_OPTION,
10
+ SDK_CLIENT_PLATFORM_VERSION_JVM_OPTION,
11
+ SDK_COMPATIBLE_JAVA_VERSIONS,
12
+ } = require('./ApplicationConstants');
13
+ const path = require('path');
14
+ const FileUtils = require('./utils/FileUtils');
15
+ const spawn = require('child_process').spawn;
16
+ const CLISettingsService = require('./services/settings/CLISettingsService');
17
+ const EnvironmentInformationService = require('./services/EnvironmentInformationService');
18
+ const url = require('url');
19
+ const NodeTranslationService = require('./services/NodeTranslationService');
20
+ const { ERRORS } = require('./services/TranslationKeys');
21
+ const ExecutionEnvironmentContext = require('./ExecutionEnvironmentContext');
22
+
23
+ const DATA_EVENT = 'data';
24
+ const CLOSE_EVENT = 'close';
25
+ const UTF8 = 'utf8';
26
+
27
+ module.exports = class SdkExecutor {
28
+ constructor(sdkPath, executionEnvironmentContext) {
29
+ this._sdkPath = sdkPath;
30
+
31
+ this._CLISettingsService = new CLISettingsService();
32
+ this._environmentInformationService = new EnvironmentInformationService();
33
+ this.childProcess = null;
34
+
35
+ if (!executionEnvironmentContext) {
36
+ this._executionEnvironmentContext = new ExecutionEnvironmentContext();
37
+ } else {
38
+ this._executionEnvironmentContext = executionEnvironmentContext;
39
+ }
40
+ }
41
+
42
+ execute(executionContext, token) {
43
+ return new Promise((resolve, reject) => {
44
+ if (token !== undefined && token !== null) {
45
+ token.cancel = (reason) => {
46
+ this.childProcess.kill('SIGKILL');
47
+ reject(reason);
48
+ };
49
+ }
50
+ try {
51
+ this.childProcess = this._launchJvmCommand(executionContext);
52
+ this._addChildProcessListeners(executionContext.isIntegrationMode(), resolve, reject);
53
+ } catch (e) {
54
+ reject(e);
55
+ }
56
+ });
57
+ }
58
+
59
+ _addChildProcessListeners(isIntegrationMode, resolve, reject) {
60
+ let lastSdkOutput = '';
61
+ let lastSdkError = '';
62
+
63
+ this.childProcess.stderr.on(DATA_EVENT, (data) => {
64
+ lastSdkError += data.toString(UTF8);
65
+ });
66
+ this.childProcess.stdout.on(DATA_EVENT, (data) => {
67
+ lastSdkOutput += data.toString(UTF8);
68
+ });
69
+
70
+ this.childProcess.on(CLOSE_EVENT, (code) => {
71
+ if (code === 0) {
72
+ try {
73
+ const output = isIntegrationMode ? JSON.parse(lastSdkOutput) : lastSdkOutput;
74
+ resolve(output);
75
+ } catch (error) {
76
+ reject(NodeTranslationService.getMessage(ERRORS.SDKEXECUTOR.RUNNING_COMMAND, error));
77
+ }
78
+ } else {
79
+ const javaVersionError = this._checkIfJavaVersionIssue();
80
+ if (javaVersionError) {
81
+ reject(javaVersionError);
82
+ }
83
+ reject(NodeTranslationService.getMessage(ERRORS.SDKEXECUTOR.SDK_ERROR, code, lastSdkError));
84
+ }
85
+ });
86
+ }
87
+
88
+ _launchJvmCommand(executionContext) {
89
+ if (!this._CLISettingsService.isJavaVersionValid()) {
90
+ const javaVersionError = this._checkIfJavaVersionIssue();
91
+ if (javaVersionError) {
92
+ throw javaVersionError;
93
+ }
94
+ }
95
+
96
+ const cliParams = this._convertParamsObjToString(executionContext.getParams(), executionContext.getFlags());
97
+
98
+ const integrationModeOption = executionContext.isIntegrationMode() ? SDK_INTEGRATION_MODE_JVM_OPTION : '';
99
+
100
+ const clientPlatform = `${SDK_CLIENT_PLATFORM_JVM_OPTION}=${this._executionEnvironmentContext.getPlatform()}`;
101
+ const clientPlatformVersionOption = `${SDK_CLIENT_PLATFORM_VERSION_JVM_OPTION}=${this._executionEnvironmentContext.getPlatformVersion()}`;
102
+ const customVmOptions = this._getCustomVmOptionsString();
103
+
104
+ if (!FileUtils.exists(this._sdkPath)) {
105
+ throw NodeTranslationService.getMessage(ERRORS.SDKEXECUTOR.NO_JAR_FILE_FOUND, path.join(__dirname, '..'));
106
+ }
107
+ const quotedSdkJarPath = `"${this._sdkPath}"`;
108
+
109
+ const vmOptions = `${integrationModeOption} ${clientPlatform} ${clientPlatformVersionOption} ${customVmOptions}`;
110
+ const jvmCommand = `java -jar ${vmOptions} ${quotedSdkJarPath} ${executionContext.getCommand()} ${cliParams}`;
111
+
112
+ return spawn(jvmCommand, [], { shell: true });
113
+ }
114
+
115
+ _convertParamsObjToString(cliParams, flags) {
116
+ let cliParamsAsString = '';
117
+ for (const param in cliParams) {
118
+ if (cliParams.hasOwnProperty(param)) {
119
+ const value = cliParams[param] ? ` ${cliParams[param]} ` : ' ';
120
+ cliParamsAsString += param + value;
121
+ }
122
+ }
123
+
124
+ if (flags && Array.isArray(flags)) {
125
+ flags.forEach((flag) => {
126
+ cliParamsAsString += ` ${flag} `;
127
+ });
128
+ }
129
+
130
+ return cliParamsAsString;
131
+ }
132
+
133
+ _getCustomVmOptionsString() {
134
+ const customVmOptions = this._CLISettingsService.getCustomVmOptions();
135
+ if (!customVmOptions) {
136
+ return '';
137
+ }
138
+
139
+ const addVmOptionToString = (prevString, vmOptionKey) =>
140
+ (prevString += customVmOptions[vmOptionKey] === '' ? ` ${vmOptionKey}` : ` ${vmOptionKey}="${customVmOptions[vmOptionKey].trim()}"`);
141
+ // customVmOptions are already validated at CLISettingsService, it will be an object at this point
142
+ return Object.keys(customVmOptions).reduce(addVmOptionToString, '').trim();
143
+ }
144
+
145
+ _checkIfJavaVersionIssue() {
146
+ const javaVersionInstalled = this._environmentInformationService.getInstalledJavaVersionString();
147
+ for (const compatibleJavaVersion of SDK_COMPATIBLE_JAVA_VERSIONS) {
148
+ if (javaVersionInstalled.startsWith(compatibleJavaVersion)) {
149
+ this._CLISettingsService.setJavaVersionValid(true);
150
+ return;
151
+ }
152
+ }
153
+
154
+ this._CLISettingsService.setJavaVersionValid(false);
155
+ if (javaVersionInstalled === '') {
156
+ return NodeTranslationService.getMessage(ERRORS.CLI_SDK_JAVA_VERSION_NOT_INSTALLED, SDK_COMPATIBLE_JAVA_VERSIONS.join(', '));
157
+ }
158
+ return NodeTranslationService.getMessage(ERRORS.CLI_SDK_JAVA_VERSION_NOT_COMPATIBLE, javaVersionInstalled, SDK_COMPATIBLE_JAVA_VERSIONS.join(', '));
159
+ }
160
+ };
@@ -0,0 +1,158 @@
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 assert = require('assert');
8
+ const CommandOptionsValidator = require('../core/CommandOptionsValidator');
9
+ const { throwValidationException } = require('../utils/ExceptionUtils');
10
+ const { ActionResult } = require('../services/actionresult/ActionResult');
11
+
12
+ const BaseAction = require('./base/BaseAction');
13
+ const BaseInputHandler = require('./base/BaseInputHandler');
14
+ const BaseOutputHandler = require('./base/BaseOutputHandler');
15
+
16
+ const INTERACTIVE_MODE = {
17
+ NEVER: 'NEVER',
18
+ ALWAYS: 'ALWAYS',
19
+ DEFAULT: 'DEFAULT',
20
+ };
21
+
22
+ const NEVER_PARAMS = {
23
+ 'CONFIG': 'config',
24
+ 'NOCONFIG': 'noconfig',
25
+ 'CUSTOMFLAG': 'customflag',
26
+ 'CUSTOMOPTIONS': 'customoptions',
27
+ 'DEBUG': 'debug'
28
+ };
29
+
30
+ /** @type {import('./Command')} */
31
+ class Command {
32
+ constructor(options, action, inputHandler, outputHandler) {
33
+ assert(options);
34
+ assert(options.commandMetadata);
35
+ assert(options.projectFolder);
36
+ assert(options.log);
37
+ assert(options.interactiveSupport);
38
+ assert(typeof options.runInInteractiveMode === 'boolean');
39
+
40
+ assert(action, 'Commands must have an action');
41
+ assert(inputHandler, 'Commands must have an input handler');
42
+ assert(outputHandler, 'Commands must have an output handler');
43
+
44
+ this._commandMetadata = options.commandMetadata;
45
+ this._projectFolder = options.projectFolder;
46
+ this.__executionPath = options.executionPath;
47
+ this._runInInteractiveMode = options.runInInteractiveMode;
48
+ this._interactiveSupport = options.interactiveSupport;
49
+ this._log = options.log;
50
+
51
+ this._action = new action(options);
52
+ this._inputHandler = new inputHandler(options);
53
+ this._outputHandler = new outputHandler(options);
54
+ }
55
+
56
+ get _executionPath(){
57
+ debugger;
58
+ return this.__executionPath;
59
+ }
60
+
61
+ async run(inputParams) {
62
+ this._cleanNeverParams(inputParams);
63
+ const execParams =
64
+ this._interactiveSupport === INTERACTIVE_MODE.ALWAYS || (this._interactiveSupport !== INTERACTIVE_MODE.NEVER && this._runInInteractiveMode)
65
+ ? await this._inputHandler.getParameters(inputParams)
66
+ : inputParams;
67
+
68
+ if( this._interactiveSupport === INTERACTIVE_MODE.ALWAYS || (this._interactiveSupport !== INTERACTIVE_MODE.NEVER && this._runInInteractiveMode)) {
69
+ if( inputParams.authid) execParams.authid = inputParams.authid
70
+ }
71
+
72
+ const preExec = await this._action.preExecute(execParams);
73
+
74
+ this._validateActionParameters(preExec);
75
+
76
+ const exec = await this._action.execute(preExec);
77
+ const actionResult = await this._action.postExecute(exec);
78
+
79
+ if (!(actionResult instanceof ActionResult)) {
80
+ throw 'INTERNAL ERROR: Command must return an ActionResult object.';
81
+ } else if (!actionResult.isSuccess()) {
82
+ return this._outputHandler.parseError(actionResult);
83
+ } else {
84
+ return this._outputHandler.parse(actionResult);
85
+ }
86
+ }
87
+
88
+ _cleanNeverParams(params){
89
+ Object.values(NEVER_PARAMS).forEach((p)=>{
90
+ if( Reflect.has(params,p)) delete params[p];
91
+ })
92
+ }
93
+
94
+ _validateActionParameters(params) {
95
+ const commandOptionsValidator = new CommandOptionsValidator();
96
+ const validationErrors = commandOptionsValidator.validate({
97
+ commandOptions: this._commandMetadata.options,
98
+ arguments: params,
99
+ });
100
+ if (validationErrors.length > 0) {
101
+ throwValidationException(validationErrors, this._runInInteractiveMode, this._commandMetadata);
102
+ }
103
+ }
104
+
105
+ static get Builder() {
106
+ return new CommandBuilder();
107
+ }
108
+ }
109
+
110
+ class CommandBuilder {
111
+ constructor() {
112
+ this._options = {
113
+ interactiveSupport: INTERACTIVE_MODE.DEFAULT,
114
+ };
115
+ this._action = BaseAction;
116
+ this._input = BaseInputHandler;
117
+ this._output = BaseOutputHandler;
118
+ }
119
+
120
+ withOptions(options) {
121
+ this._options = {
122
+ ...this._options,
123
+ ...options,
124
+ };
125
+ return this;
126
+ }
127
+
128
+ neverInteractive() {
129
+ this._options.interactiveSupport = INTERACTIVE_MODE.NEVER;
130
+ return this;
131
+ }
132
+
133
+ alwaysInteractive() {
134
+ this._options.interactiveSupport = INTERACTIVE_MODE.ALWAYS;
135
+ return this;
136
+ }
137
+
138
+ withAction(action) {
139
+ this._action = action;
140
+ return this;
141
+ }
142
+
143
+ withInput(input) {
144
+ this._input = input;
145
+ return this;
146
+ }
147
+
148
+ withOutput(output) {
149
+ this._output = output;
150
+ return this;
151
+ }
152
+
153
+ build() {
154
+ return new Command(this._options, this._action, this._input, this._output);
155
+ }
156
+ }
157
+
158
+ module.exports = Command;