@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,42 @@
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 NodeTranslationService = require('../services/NodeTranslationService');
8
+ const TRANSLATION_KEYS = require('../services/TranslationKeys');
9
+ const assert = require('assert');
10
+
11
+ module.exports = class CommandOptionsValidator {
12
+ validate(options) {
13
+ assert(options);
14
+ assert(options.commandOptions);
15
+ assert(options.arguments);
16
+
17
+ const validationErrors = [];
18
+
19
+ const isMandatoryOptionPresent = (optionId, aliasId, args) => {
20
+ return args[optionId] || args[aliasId];
21
+ };
22
+
23
+ for (const optionId in options.commandOptions) {
24
+ const option = options.commandOptions[optionId];
25
+ const aliasId = option.alias;
26
+ if (options.commandOptions.hasOwnProperty(optionId)) {
27
+ if (
28
+ option.mandatory &&
29
+ !isMandatoryOptionPresent(optionId, aliasId, options.arguments)
30
+ ) {
31
+ validationErrors.push(
32
+ NodeTranslationService.getMessage(
33
+ TRANSLATION_KEYS.COMMAND_OPTIONS.IS_MANDATORY,
34
+ option.name
35
+ )
36
+ );
37
+ }
38
+ }
39
+ }
40
+ return validationErrors;
41
+ }
42
+ };
@@ -0,0 +1,130 @@
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 { Option } = require('commander');
8
+
9
+ const assert = require('assert');
10
+ const NodeTranslationService = require('../services/NodeTranslationService');
11
+ const { COMMAND_OPTIONS } = require('../services/TranslationKeys');
12
+ const OPTION_TYPE = {
13
+ FLAG: 'FLAG',
14
+ SINGLE: 'SINGLE',
15
+ MULTIPLE: 'MULTIPLE',
16
+ };
17
+ const INTERACTIVE_OPTION_NAME = 'interactive';
18
+ const INTERACTIVE_OPTION_ALIAS = 'i';
19
+ const HELP_OPTION_ALIAS_NAME = '-h, --help';
20
+
21
+ const EXIT_CODE = {
22
+ SUCCESS: 0,
23
+ ERROR: 1,
24
+ };
25
+
26
+ module.exports = class CommandRegistrationService {
27
+ register(options) {
28
+ assert(options);
29
+ assert(options.commandMetadata);
30
+ assert(options.program);
31
+ assert(options.executeCommandFunction);
32
+ assert(typeof options.runInInteractiveMode === 'boolean');
33
+
34
+ const commandMetadata = options.commandMetadata;
35
+ const program = options.program;
36
+ const executeCommandFunction = options.executeCommandFunction;
37
+ const runInInteractiveMode = options.runInInteractiveMode;
38
+
39
+ const helpMessage = NodeTranslationService.getMessage(COMMAND_OPTIONS.HELP);
40
+
41
+ let commandSetup = program.command(commandMetadata.name).helpOption(HELP_OPTION_ALIAS_NAME, helpMessage);
42
+
43
+ if (!runInInteractiveMode) {
44
+ if (commandMetadata.supportsInteractiveMode) {
45
+ const interactiveOptionHelp = NodeTranslationService.getMessage(COMMAND_OPTIONS.INTERACTIVE_HELP, commandMetadata.name);
46
+ commandMetadata.options.interactive = {
47
+ name: INTERACTIVE_OPTION_NAME,
48
+ alias: INTERACTIVE_OPTION_ALIAS,
49
+ description: interactiveOptionHelp,
50
+ type: OPTION_TYPE.FLAG,
51
+ mandatory: false,
52
+ };
53
+ }
54
+ commandSetup = this._addNonInteractiveCommandOptions(commandSetup, commandMetadata.options);
55
+ } else {
56
+ commandSetup = this._addInteractiveCommandOptions(commandSetup, commandMetadata.options);
57
+
58
+ }
59
+
60
+ commandSetup.description(commandMetadata.description).action(async (options) => {
61
+ const actionResult = await executeCommandFunction(options);
62
+ process.exitCode = actionResult.isSuccess() ? EXIT_CODE.SUCCESS : EXIT_CODE.ERROR;
63
+ });
64
+ }
65
+
66
+ _addInteractiveCommandOptions(commandSetup,options){
67
+ const filteredOptions = Object.entries(options).filter(([key,o])=>{
68
+ return ['authid','project','config','debug'].includes(o.name);
69
+ });
70
+ filteredOptions.push(['interactive',{
71
+ "name": "interactive",
72
+ "option": "interactive",
73
+ "description": "Be interactive",
74
+ "mandatory": true,
75
+ "type": "FLAG",
76
+ "usage": "",
77
+ "defaultOption": true,
78
+ "disableInIntegrationMode": false,
79
+ "conflicts": []
80
+ }]);
81
+ return this._addNonInteractiveCommandOptions(commandSetup, Object.fromEntries(filteredOptions));
82
+ }
83
+
84
+ _addNonInteractiveCommandOptions(commandSetup, options) {
85
+ const optionsSortedByName = Object.values(options).sort((option1, option2) => option1.name.localeCompare(option2.name));
86
+ optionsSortedByName.forEach((option) => {
87
+ if (option.disableInIntegrationMode) {
88
+ return;
89
+ }
90
+ const Optional = 'Optional:';
91
+ let optionString = '';
92
+ if (option.alias) {
93
+ optionString = `-${option.alias}, `;
94
+ }
95
+ optionString += `--${option.name}`;
96
+
97
+ if (option.type === OPTION_TYPE.SINGLE) {
98
+ optionString += ` <argument>`;
99
+ } else if (option.type === OPTION_TYPE.MULTIPLE) {
100
+ optionString += ` <arguments...>`;
101
+ }
102
+
103
+ const description = [option.description];
104
+ if( !option.mandatory ) description.unshift(Optional);
105
+ else description.unshift(''.padStart(Optional.length));
106
+
107
+ if( Array.isArray(option.conflicts)){
108
+ description.push('\nConflict: ' + option.conflicts)
109
+ }
110
+
111
+ // if( option.env)
112
+ //description.push('\nEnv:'.padEnd(Optional.length), options.env);
113
+
114
+ const commandOption = new Option(optionString, description.join(' '));
115
+ if (option.hidden) {
116
+ commandOption.hideHelp();
117
+ }
118
+ if( Array.isArray(option.conflicts)){
119
+ commandOption.conflicts(option.conflicts);
120
+ }
121
+
122
+ if( option.env ){
123
+ commandOption.env(option.env)
124
+ }
125
+
126
+ commandSetup.addOption(commandOption);
127
+ });
128
+ return commandSetup;
129
+ }
130
+ };
@@ -0,0 +1,104 @@
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 FileUtils = require('../utils/FileUtils');
9
+ const {
10
+ SDK_COMMANDS_METADATA_FILE,
11
+ SDK_COMMANDS_METADATA_PATCH_FILE,
12
+ NODE_COMMANDS_METADATA_FILE,
13
+ COMMAND_GENERATORS_METADATA_FILE,
14
+ } = require('../ApplicationConstants');
15
+
16
+ let commandsMetadataCache;
17
+
18
+ function executeForEachCommandMetadata(commandsMetadata, func) {
19
+ for (const commandMetadataId in commandsMetadata) {
20
+ if (commandsMetadata.hasOwnProperty(commandMetadataId)) {
21
+ const commandMetadata = commandsMetadata[commandMetadataId];
22
+ func(commandMetadata);
23
+ }
24
+ }
25
+ }
26
+
27
+ module.exports = class CommandsMetadataService {
28
+ constructor() {
29
+ this._rootCLIPath = path.dirname(__dirname, '../');
30
+ this._initializeCommandsMetadata();
31
+ }
32
+
33
+ _initializeCommandsMetadata() {
34
+ if (!commandsMetadataCache) {
35
+ const sdkCommandsMetadata = this._getMetadataFromFile(path.join(this._rootCLIPath, SDK_COMMANDS_METADATA_FILE));
36
+ const SdkCommandsMetadataPatch = this._getMetadataFromFile(path.join(this._rootCLIPath, SDK_COMMANDS_METADATA_PATCH_FILE));
37
+ const nodeCommandsMetadata = this._getMetadataFromFile(path.join(this._rootCLIPath, NODE_COMMANDS_METADATA_FILE));
38
+ const commandGeneratorsMetadata = this._getMetadataFromFile(path.join(this._rootCLIPath, COMMAND_GENERATORS_METADATA_FILE));
39
+
40
+ let combinedSdkCommandMetadata = this._combineMetadata(sdkCommandsMetadata, SdkCommandsMetadataPatch);
41
+ let combinedMetadata = {
42
+ ...combinedSdkCommandMetadata,
43
+ ...nodeCommandsMetadata,
44
+ };
45
+ combinedMetadata = this._addCommandGeneratorMetadata(commandGeneratorsMetadata, combinedMetadata);
46
+ commandsMetadataCache = combinedMetadata;
47
+ }
48
+ }
49
+
50
+ _combineMetadata(sdkCommandsMetadata, modifiedSdkCommandsMetadata) {
51
+ return this._replaceObjectProperties(sdkCommandsMetadata, modifiedSdkCommandsMetadata);
52
+ }
53
+
54
+ _replaceObjectProperties(originalObject, newObject) {
55
+ const resultObject = originalObject;
56
+ Object.entries(newObject).forEach((entry) => {
57
+ const [propertyKey, propertyValue] = entry;
58
+ resultObject[propertyKey] = this._replacePropertyValue(originalObject[propertyKey], propertyValue);
59
+ });
60
+ return resultObject;
61
+ }
62
+
63
+ _replacePropertyValue(originalPropertyValue, newPropertyValue) {
64
+ if (originalPropertyValue && typeof newPropertyValue === 'object') {
65
+ return this._replaceObjectProperties(originalPropertyValue, newPropertyValue);
66
+ } else {
67
+ return newPropertyValue;
68
+ }
69
+ }
70
+
71
+ getCommandsMetadata() {
72
+ return commandsMetadataCache;
73
+ }
74
+
75
+ getCommandMetadataByName(commandName) {
76
+ const commandMetadata = commandsMetadataCache[commandName];
77
+ if (!commandMetadata) {
78
+ throw `No metadata found or initialized for Command ${commandName}`;
79
+ }
80
+ return commandMetadata;
81
+ }
82
+
83
+ _getMetadataFromFile(filepath) {
84
+ if (!FileUtils.exists(filepath)) {
85
+ throw `Commands Metadata in filepath ${filepath} not found`;
86
+ }
87
+ try {
88
+ return FileUtils.readAsJson(filepath);
89
+ } catch (error) {
90
+ throw `Error parsing Commands Metadata from ${filepath}`;
91
+ }
92
+ }
93
+
94
+ _addCommandGeneratorMetadata(commandGeneratorsMetadata, commandsMetadata) {
95
+ executeForEachCommandMetadata(commandsMetadata, (commandMetadata) => {
96
+ const generatorMetadata = commandGeneratorsMetadata.find((generatorMetadata) => {
97
+ return generatorMetadata.commandName === commandMetadata.name;
98
+ });
99
+ commandMetadata.generator = path.join(this._rootCLIPath, generatorMetadata.generator);
100
+ commandMetadata.supportsInteractiveMode = generatorMetadata.supportsInteractiveMode;
101
+ });
102
+ return commandsMetadata;
103
+ }
104
+ };
@@ -0,0 +1,192 @@
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 { lineBreak } = require('../../loggers/LoggerOsConstants');
8
+ const FileUtils = require('../../utils/FileUtils');
9
+ const path = require('path');
10
+ const NodeTranslationService = require('./../../services/NodeTranslationService');
11
+ const { ERRORS } = require('./../../services/TranslationKeys');
12
+ const FileService = require('../../services/FileSystemService');
13
+ const { getProjectDefaultAuthId } = require('../../utils/AuthenticationUtils');
14
+ const CommandUserExtension = require('./CommandUserExtension');
15
+ const { ENV_VARS, FILES, FOLDERS } = require('../../ApplicationConstants');
16
+ const CLI_CONFIG_FILES = [...FILES.CLI_CONFIG_FILE_JS, ...FILES.CLI_CONFIG_FILE_JSON];
17
+ const PROJECT_DIRS = [FOLDERS.FILE_CABINET, FOLDERS.OBJECTS];
18
+ const DEFAULT_AUTH_ID_PROPERTY = 'defaultAuthId';
19
+ const DEFAULT_CONFIG = {
20
+ defaultProjectFolder: '',
21
+ [DEFAULT_AUTH_ID_PROPERTY]: null,
22
+ commands: {},
23
+ };
24
+
25
+ const isString = (str) => typeof str === 'string' || str instanceof String;
26
+
27
+ module.exports = class CLIConfigurationService {
28
+ constructor() {
29
+ this._cliConfig = DEFAULT_CONFIG;
30
+ }
31
+
32
+ initialize(executionPath, override = false) {
33
+ let cliConfigFile;
34
+ const fileServiceInstance = new FileService();
35
+
36
+ if (!override) {
37
+ cliConfigFile = fileServiceInstance.getFirstAncestorByName(CLI_CONFIG_FILES, executionPath, false);
38
+ // try by directory
39
+ } else if (!executionPath) {
40
+ // noconfig mode
41
+ this._executionPath = process.cwd();
42
+ return;
43
+ }
44
+
45
+ // it might be something like @suitegeezus/cool-package/sdf.config.js
46
+ if(/^@\w\b/.test(executionPath)){
47
+ cliConfigFile = require.resolve(executionPath);
48
+ } else if (!/[.]js(on)?$/.test(executionPath)) {
49
+ cliConfigFile = fileServiceInstance.getFirstAncestorByName(CLI_CONFIG_FILES, executionPath, false);
50
+ } else if (typeof executionPath === 'string') {
51
+ cliConfigFile = fileServiceInstance.getFirstAncestorByName(
52
+ [path.basename(executionPath)],
53
+ path.dirname(executionPath),
54
+ false,
55
+ );
56
+ }
57
+ if (!cliConfigFile) {
58
+ const candidateDir = fileServiceInstance.getFirstAncestorByName(PROJECT_DIRS, executionPath, true);
59
+ if (candidateDir) this._executionPath = candidateDir;
60
+ else this._executionPath = executionPath;
61
+ } else {
62
+ this._executionPath = path.dirname(cliConfigFile);
63
+ }
64
+
65
+ if (!FileUtils.exists(cliConfigFile)) {
66
+ return;
67
+ }
68
+
69
+ try {
70
+ this._cliConfig = require(cliConfigFile);
71
+ } catch (error) {
72
+ throw NodeTranslationService.getMessage(ERRORS.CLI_CONFIG_ERROR_LOADING_CONFIGURATION_MODULE, cliConfigFile, lineBreak, error);
73
+ }
74
+ }
75
+
76
+ getCommandUserExtension(commandName) {
77
+ const commandExtension =
78
+ this._cliConfig && this._cliConfig.commands && this._cliConfig.commands[commandName] ? this._cliConfig.commands[commandName] : {};
79
+ return new CommandUserExtension(commandExtension);
80
+ }
81
+
82
+ /**
83
+ * @private
84
+ * @param {string} projectFolder
85
+ * @param {string} file
86
+ * @param {string} property
87
+ * @returns {*}
88
+ * @private
89
+ */
90
+ __getPropertyFromFile(projectFolder, file, property) {
91
+ const projectFilePath = path.join(projectFolder, file);
92
+
93
+ if (FileUtils.exists(projectFilePath)) {
94
+ try {
95
+ const fileContentJson = FileUtils.readAsJson(projectFilePath);
96
+ return fileContentJson[property];
97
+ } catch (error) {
98
+ // if( throwError === false ) return;
99
+ throw NodeTranslationService.getMessage(ERRORS.WRONG_JSON_FILE, projectFilePath, error) +
100
+ lineBreak + NodeTranslationService.getMessage(ERRORS.RUN_SETUP_ACCOUNT);
101
+ }
102
+ }
103
+ }
104
+
105
+ getAuthId(command, projectPath, adhoc) {
106
+ // how do we determine which project.json to use if the folder was specified?
107
+ const lookInConfig = () => {
108
+ try {
109
+ return this.__getPropertyFromFile(projectPath, FILES.PROJECT_JSON, DEFAULT_AUTH_ID_PROPERTY);
110
+ } catch {
111
+ //
112
+ }
113
+ };
114
+
115
+ const commandConfig = this._cliConfig && this._cliConfig.commands && this._cliConfig.commands[command];
116
+ switch (true) {
117
+ // look in the command
118
+ case Boolean(commandConfig && commandConfig.authId):
119
+ return commandConfig.authId;
120
+
121
+ case Boolean(adhoc):
122
+ return adhoc;
123
+
124
+ case Boolean(process.env[ENV_VARS.SUITECLOUD_AUTHID]):
125
+ return process.env[ENV_VARS.SUITECLOUD_AUTHID];
126
+
127
+ case Boolean(lookInConfig()):
128
+ return lookInConfig();
129
+
130
+ // look in fixed config
131
+ case Boolean(this._cliConfig.defaultAuthId):
132
+ return this._cliConfig.defaultAuthId;
133
+
134
+ default:
135
+ throw NodeTranslationService.getMessage(ERRORS.MISSING_DEFAULT_AUTH_ID, DEFAULT_AUTH_ID_PROPERTY);
136
+
137
+ }
138
+ }
139
+
140
+ setAuthId(value) {
141
+ if (!this._authId) {
142
+ this._authId = value;
143
+ return true;
144
+ }
145
+ return false;
146
+ }
147
+
148
+ getProjectFolder(command, adhoc) {
149
+ // recall that empty string is a value projectFolder so we use undefined here
150
+ const pathBits = { projectFolder: undefined };
151
+
152
+ const commandConfig = this._cliConfig && this._cliConfig.commands && this._cliConfig.commands[command];
153
+ /** @todo look in process.cwd()/project.json */
154
+ switch (true) {
155
+
156
+ // look in the command
157
+ case Boolean(commandConfig && isString(commandConfig.projectFolder)):
158
+ pathBits.projectFolder = commandConfig.projectFolder;
159
+ break;
160
+
161
+ // adhoc
162
+ case typeof pathBits.projectFolder !== 'string' && typeof adhoc === 'string' :
163
+ pathBits.projectFolder = adhoc;
164
+ break;
165
+
166
+ // look in env
167
+ case typeof pathBits.projectFolder !== 'string' && typeof process.env[ENV_VARS.SUITECLOUD_PROJECT_FOLDER] === 'string':
168
+ pathBits.projectFolder = process.env[ENV_VARS.SUITECLOUD_PROJECT_FOLDER];
169
+ break;
170
+
171
+ // look in fixed config
172
+ case isString(this._cliConfig.defaultProjectFolder):
173
+ pathBits.projectFolder = this._cliConfig.defaultProjectFolder;
174
+ break;
175
+
176
+ // default
177
+ default: {
178
+ // attempt to resolve
179
+ const files = (new FileService()).getFoldersFromDirectoryRecursively(this._executionPath);
180
+ const firstFc = files.find((f) => /\bFileCabinet\b/.test(f));
181
+ pathBits.projectFolder = path.relative(this._executionPath, firstFc.replace(/^(.*).\bFileCabinet\b.*$/, '$1'));
182
+ break;
183
+ }
184
+ }
185
+
186
+ return pathBits.projectFolder;
187
+ }
188
+
189
+ getProjectPath(projectFolder) {
190
+ return path.join(this._executionPath, projectFolder);
191
+ }
192
+ };
@@ -0,0 +1,64 @@
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 nodePath = require('node:path');
9
+ const NodeTranslationService = require('../../services/NodeTranslationService');
10
+ const { lineBreak } = require('../../loggers/LoggerOsConstants');
11
+ const { ERRORS } = require('../../services/TranslationKeys');
12
+
13
+ module.exports = class CommandUserExtension {
14
+ constructor(cliConfig) {
15
+ this._cliConfig = cliConfig;
16
+ }
17
+
18
+ async beforeExecuting(options) {
19
+ assert(options);
20
+ assert(options.commandName);
21
+ assert(typeof options.projectFolder === 'string');
22
+ assert(options.projectPath);
23
+ assert(options.arguments);
24
+
25
+ try {
26
+ if (!this._cliConfig.beforeExecuting) {
27
+ return options;
28
+ }
29
+ const beforeExecutingContext = {
30
+ command: options.commandName,
31
+ projectPath: options.projectPath,
32
+ projectFolder: nodePath.relative(options.executionPath, options.projectPath),
33
+ arguments: options.arguments,
34
+ };
35
+ if( options.executionPath) beforeExecutingContext.executionPath = options.executionPath;
36
+ if( options.authId) beforeExecutingContext.authId = options.authId;
37
+ const result = await this._cliConfig.beforeExecuting(beforeExecutingContext);
38
+ this._validateBeforeExecutingResult(result);
39
+ return result;
40
+ } catch (error) {
41
+ throw NodeTranslationService.getMessage(ERRORS.CLI_CONFIG_BEFORE_EXECUTING_FAILED, lineBreak, error);
42
+ }
43
+ }
44
+
45
+ onCompleted(options) {
46
+ if (!this._cliConfig.onCompleted) {
47
+ return options;
48
+ }
49
+ this._cliConfig.onCompleted(options);
50
+ }
51
+
52
+ onError(options) {
53
+ if (!this._cliConfig.onError) {
54
+ return options;
55
+ }
56
+ this._cliConfig.onError(options);
57
+ }
58
+
59
+ _validateBeforeExecutingResult(result) {
60
+ if (typeof result === 'undefined' || typeof result.arguments !== 'object') {
61
+ throw NodeTranslationService.getMessage(ERRORS.CLI_CONFIG_BEFORE_EXECUTING_WRONG_RETURN_VALUE);
62
+ }
63
+ }
64
+ };
@@ -0,0 +1,109 @@
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 fs = require('fs');
8
+ const path = require('path');
9
+ const SdkProperties = require('./SdkProperties');
10
+
11
+ const https = require('https');
12
+ const http = require('http');
13
+ const { URL } = require('url');
14
+ const ProxyAgent = require('../../utils/http/ProxyAgent');
15
+ const { ENCODING, EVENT, HEADER, PROTOCOL } = require('../../utils/http/HttpConstants');
16
+
17
+ const HOME_PATH = require('os').homedir();
18
+
19
+ const { FOLDERS } = require('../../ApplicationConstants');
20
+
21
+ const unwrapExceptionMessage = require('../../utils/ExceptionUtils').unwrapExceptionMessage;
22
+
23
+ const NodeTranslationService = require('../../services/NodeTranslationService');
24
+ const FileSystemService = require('../../services/FileSystemService');
25
+
26
+ const { SDK_DOWNLOAD_SERVICE } = require('../../services/TranslationKeys');
27
+
28
+ const VALID_JAR_CONTENT_TYPES = ['application/java-archive', 'application/x-java-archive', 'application/x-jar'];
29
+ const ERROR_CODE = -1;
30
+
31
+ class SdkDownloadService {
32
+ constructor() {
33
+ this._fileSystemService = new FileSystemService();
34
+ }
35
+
36
+ async download() {
37
+ const sdkParentDirectory = this._fileSystemService.createFolder(HOME_PATH, FOLDERS.SUITECLOUD_SDK);
38
+ // remove OLD jar files
39
+ this._removeJarFilesFrom(sdkParentDirectory);
40
+ const sdkDirectory = this._fileSystemService.createFolder(sdkParentDirectory, FOLDERS.NODE_CLI);
41
+
42
+ const fullURL = `${SdkProperties.getDownloadURL()}/${SdkProperties.getSdkFileName()}`;
43
+ const destinationFilePath = path.join(sdkDirectory, SdkProperties.getSdkFileName());
44
+ const proxy = process.env.SUITECLOUD_PROXY || process.env.npm_config_https_proxy || process.env.npm_config_proxy;
45
+ const skipProxy = SdkProperties.configFileExists();
46
+
47
+ try {
48
+ await this._downloadJarFilePromise(fullURL, destinationFilePath, proxy, skipProxy);
49
+ } catch (error) {
50
+ console.error(NodeTranslationService.getMessage(SDK_DOWNLOAD_SERVICE.ERROR, fullURL, unwrapExceptionMessage(error)));
51
+ process.exit(ERROR_CODE);
52
+ }
53
+ }
54
+
55
+ _downloadJarFilePromise(downloadUrl, destinationFilePath, proxy, skipProxy) {
56
+ const downloadUrlObject = new URL(downloadUrl);
57
+ const downloadUrlProtocol = downloadUrlObject.protocol;
58
+
59
+ const requestOptions = {
60
+ encoding: ENCODING.BINARY,
61
+ ...(proxy && !skipProxy && { agent: new ProxyAgent(proxy, { tunnel: true, timeout: 15000 }) }),
62
+ };
63
+
64
+ if (!/^http:$|^https:$/.test(downloadUrlProtocol)) {
65
+ throw new Error(NodeTranslationService.getMessage(SDK_DOWNLOAD_SERVICE.WRONG_DOWNLOAD_URL_PROTOCOL));
66
+ }
67
+
68
+ const httpxModule = PROTOCOL.HTTP.match(downloadUrlObject.protocol) ? http : https;
69
+
70
+ return new Promise((resolve, reject) => {
71
+ const clientReq = httpxModule.get(downloadUrlObject, requestOptions, (response) => {
72
+ const chunks = [];
73
+ response.on(EVENT.DATA, (chunk) => chunks.push(Buffer.from(chunk, ENCODING.BINARY)));
74
+
75
+ response.on(EVENT.END, () => {
76
+ if (!VALID_JAR_CONTENT_TYPES.includes(response.headers[HEADER.CONTENT_TYPE])) {
77
+ reject(NodeTranslationService.getMessage(SDK_DOWNLOAD_SERVICE.FILE_NOT_AVAILABLE_ERROR));
78
+ }
79
+
80
+ const jarFile = fs.createWriteStream(destinationFilePath);
81
+ jarFile.write(Buffer.concat(chunks), ENCODING.BINARY);
82
+ jarFile.end();
83
+ resolve();
84
+ });
85
+
86
+ response.on(EVENT.ERROR, (error) => {
87
+ reject(NodeTranslationService.getMessage(SDK_DOWNLOAD_SERVICE.FILE_NOT_AVAILABLE_ERROR));
88
+ });
89
+ });
90
+
91
+ clientReq
92
+ .once(EVENT.TIMEOUT, () => {
93
+ clientReq.destroy();
94
+ reject(new Error(NodeTranslationService.getMessage(SDK_DOWNLOAD_SERVICE.GET_TIMEOUT)));
95
+ })
96
+ .once(EVENT.ERROR, (err) => reject(err))
97
+ .end();
98
+ });
99
+ }
100
+
101
+ _removeJarFilesFrom(folder) {
102
+ // remove all JAR files before writing response to file
103
+ fs.readdirSync(folder)
104
+ .filter((file) => /[.]jar$/.test(file))
105
+ .map((file) => fs.unlinkSync(path.join(folder, file)));
106
+ }
107
+ }
108
+
109
+ module.exports = new SdkDownloadService();
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const { spawnSync } = require('child_process');
5
+
6
+ const LICENSE_PATH = path.normalize('./resources/FUTC-LICENSE.txt');
7
+ const WINDOWS_PLATFORM = 'win32';
8
+ const LINUX_PLATFORM = 'linux';
9
+ const OSX_PLATFORM = 'darwin';
10
+ const WINDOWS_CMD = 'start';
11
+ const LINUX_CMD = 'xdg-open';
12
+ const OSX_CMD = 'open';
13
+ const ERROR_MESSAGE = 'Something went wrong.';
14
+ const LICENSE_MESSAGE = 'Use the --acceptsuitecloudsdklicense flag to accept the FUTC license:' +
15
+ ' https://www.oracle.com/downloads/licenses/oracle-free-license.html';
16
+ const supportedPlatformsCommands = {
17
+ [WINDOWS_PLATFORM]: WINDOWS_CMD,
18
+ [LINUX_PLATFORM]: LINUX_CMD,
19
+ [OSX_PLATFORM]: OSX_CMD,
20
+ };
21
+
22
+ class SdkLicense {
23
+
24
+ show() {
25
+ if (process.env.npm_config_acceptsuitecloudsdklicense || process.env.npm_config_acceptSuiteCloudSDKLicense) {
26
+ return;
27
+ }
28
+ const currentPlatform = os.platform();
29
+ const command = supportedPlatformsCommands[currentPlatform];
30
+ const execution = spawnSync(command, [LICENSE_PATH], { stdio: 'ignore', detached: true, shell: true });
31
+ if (execution.error || execution.status !== 0) {
32
+ console.error(ERROR_MESSAGE);
33
+ console.error(LICENSE_MESSAGE);
34
+ return process.exit(execution.error?.errno || execution.status);
35
+ }
36
+ }
37
+ }
38
+
39
+ module.exports = new SdkLicense();