@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.
- package/CONTRIBUTING.md +7 -0
- package/DELTA.md +235 -0
- package/README.md +107 -0
- package/docs/Command.md +299 -0
- package/messages.json +317 -0
- package/package.json +51 -0
- package/postinstall.js +8 -0
- package/resources/FUTC-LICENSE.txt +115 -0
- package/src/ApplicationConstants.js +87 -0
- package/src/CLI.js +202 -0
- package/src/CLIException.js +21 -0
- package/src/ExecutionEnvironmentContext.js +39 -0
- package/src/SdkExecutionContext.js +90 -0
- package/src/SdkExecutor.js +160 -0
- package/src/commands/Command.js +158 -0
- package/src/commands/account/manageauth/ManageAccountAction.js +126 -0
- package/src/commands/account/manageauth/ManageAccountCommand.js +20 -0
- package/src/commands/account/manageauth/ManageAccountInputHandler.js +215 -0
- package/src/commands/account/manageauth/ManageAccountOutputHandler.js +30 -0
- package/src/commands/account/setup/SetupAction.js +39 -0
- package/src/commands/account/setup/SetupCommand.js +21 -0
- package/src/commands/account/setup/SetupInputHandler.js +169 -0
- package/src/commands/account/setup/SetupOutputHandler.js +65 -0
- package/src/commands/account/setupci/AccountSetupCiAction.js +58 -0
- package/src/commands/account/setupci/AccountSetupCiCommand.js +20 -0
- package/src/commands/account/setupci/AccountSetupCiConstants.js +21 -0
- package/src/commands/account/setupci/AccountSetupCiOutputHandler.js +40 -0
- package/src/commands/account/setupci/AccountSetupCiValidation.js +100 -0
- package/src/commands/base/BaseAction.js +37 -0
- package/src/commands/base/BaseInputHandler.js +24 -0
- package/src/commands/base/BaseOutputHandler.js +30 -0
- package/src/commands/custom/hello/Action.js +58 -0
- package/src/commands/custom/hello/Command.js +20 -0
- package/src/commands/custom/hello/Handler.js +26 -0
- package/src/commands/custom/hello/README.md +78 -0
- package/src/commands/custom/hook/Action.js +28 -0
- package/src/commands/custom/hook/Command.js +22 -0
- package/src/commands/custom/hook/InputHandler.js +8 -0
- package/src/commands/custom/hook/OutputHandler.js +8 -0
- package/src/commands/custom/hook/README.md +32 -0
- package/src/commands/file/create/CreateFileAction.js +89 -0
- package/src/commands/file/create/CreateFileCommand.js +20 -0
- package/src/commands/file/create/CreateFileInputHandler.js +175 -0
- package/src/commands/file/create/CreateFileOutputHandler.js +22 -0
- package/src/commands/file/import/ImportFilesAction.js +112 -0
- package/src/commands/file/import/ImportFilesCommand.js +22 -0
- package/src/commands/file/import/ImportFilesInputHandler.js +130 -0
- package/src/commands/file/import/ImportFilesOutputHandler.js +53 -0
- package/src/commands/file/list/ListFilesAction.js +55 -0
- package/src/commands/file/list/ListFilesCommand.js +20 -0
- package/src/commands/file/list/ListFilesInputHandler.js +55 -0
- package/src/commands/file/list/ListFilesOutputHandler.js +24 -0
- package/src/commands/file/upload/UploadFilesAction.js +67 -0
- package/src/commands/file/upload/UploadFilesCommand.js +20 -0
- package/src/commands/file/upload/UploadFilesInputHandler.js +125 -0
- package/src/commands/file/upload/UploadFilesOutputHandler.js +49 -0
- package/src/commands/object/create/CreateObjectAction.js +33 -0
- package/src/commands/object/create/CreateObjectCommand.js +19 -0
- package/src/commands/object/create/CreateObjectInputHandler.js +82 -0
- package/src/commands/object/import/ImportObjectsAction.js +225 -0
- package/src/commands/object/import/ImportObjectsCommand.js +20 -0
- package/src/commands/object/import/ImportObjectsInputHandler.js +310 -0
- package/src/commands/object/import/ImportObjectsOutputHandler.js +114 -0
- package/src/commands/object/list/ListObjectsAction.js +62 -0
- package/src/commands/object/list/ListObjectsCommand.js +20 -0
- package/src/commands/object/list/ListObjectsInputHandler.js +148 -0
- package/src/commands/object/list/ListObjectsOutputHandler.js +29 -0
- package/src/commands/object/update/UpdateAction.js +138 -0
- package/src/commands/object/update/UpdateCommand.js +20 -0
- package/src/commands/object/update/UpdateInputHandler.js +170 -0
- package/src/commands/object/update/UpdateOutputHandler.js +61 -0
- package/src/commands/project/adddependencies/AddDependenciesAction.js +55 -0
- package/src/commands/project/adddependencies/AddDependenciesCommand.js +19 -0
- package/src/commands/project/adddependencies/AddDependenciesOutputHandler.js +114 -0
- package/src/commands/project/create/CreateProjectAction.js +370 -0
- package/src/commands/project/create/CreateProjectCommand.js +20 -0
- package/src/commands/project/create/CreateProjectInputHandler.js +169 -0
- package/src/commands/project/create/CreateProjectOutputHandler.js +36 -0
- package/src/commands/project/deploy/DeployAction.js +161 -0
- package/src/commands/project/deploy/DeployCommand.js +20 -0
- package/src/commands/project/deploy/DeployInputHandler.js +100 -0
- package/src/commands/project/deploy/DeployOutputHandler.js +49 -0
- package/src/commands/project/package/PackageAction.js +59 -0
- package/src/commands/project/package/PackageCommand.js +18 -0
- package/src/commands/project/package/PackageOutputHandler.js +18 -0
- package/src/commands/project/validate/ValidateAction.js +106 -0
- package/src/commands/project/validate/ValidateCommand.js +20 -0
- package/src/commands/project/validate/ValidateInputHandler.js +92 -0
- package/src/commands/project/validate/ValidateOutputHandler.js +74 -0
- package/src/core/CommandActionExecutor.js +347 -0
- package/src/core/CommandAuthentication.js +13 -0
- package/src/core/CommandOptionsValidator.js +42 -0
- package/src/core/CommandRegistrationService.js +130 -0
- package/src/core/CommandsMetadataService.js +104 -0
- package/src/core/extensibility/CLIConfigurationService.js +192 -0
- package/src/core/extensibility/CommandUserExtension.js +64 -0
- package/src/core/sdksetup/SdkDownloadService.js +109 -0
- package/src/core/sdksetup/SdkLicense.js +39 -0
- package/src/core/sdksetup/SdkProperties.js +51 -0
- package/src/loggers/ConsoleLogger.js +32 -0
- package/src/loggers/LoggerFontFormatter.mjs +17 -0
- package/src/loggers/LoggerOsConstants.js +12 -0
- package/src/loggers/NodeConsoleLogger.js +47 -0
- package/src/metadata/CommandGenerators.json +92 -0
- package/src/metadata/NodeCommandsMetadata.json +139 -0
- package/src/metadata/ObjectTypesMetadata.js +615 -0
- package/src/metadata/SdkCommandsMetadata.json +846 -0
- package/src/metadata/SdkCommandsMetadataPatch.json +130 -0
- package/src/metadata/SuiteScriptModulesMetadata.js +152 -0
- package/src/metadata/SuiteScriptTypesMetadata.js +64 -0
- package/src/services/AccountFileCabinetService.js +86 -0
- package/src/services/EnvironmentInformationService.js +31 -0
- package/src/services/ExecutionContextService.js +108 -0
- package/src/services/FileCabinetService.js +65 -0
- package/src/services/FileSystemService.js +245 -0
- package/src/services/NodeTranslationService.js +22 -0
- package/src/services/NpmInstallRunner.js +33 -0
- package/src/services/ProjectInfoService.js +209 -0
- package/src/services/SuiteCloudAuthProxyService.js +469 -0
- package/src/services/TranslationKeys.js +506 -0
- package/src/services/TranslationService.js +30 -0
- package/src/services/actionresult/ActionResult.js +129 -0
- package/src/services/actionresult/AuthenticateActionResult.js +85 -0
- package/src/services/actionresult/CreateProjectActionResult.js +100 -0
- package/src/services/actionresult/DeployActionResult.js +69 -0
- package/src/services/actionresult/HelloActionResult.js +13 -0
- package/src/services/actionresult/ManageAccountActionResult.js +70 -0
- package/src/services/settings/CLISettings.js +46 -0
- package/src/services/settings/CLISettingsService.js +132 -0
- package/src/suitecloud.js +33 -0
- package/src/templates/TemplateKeys.js +25 -0
- package/src/templates/objects/commerceextension.xml +9 -0
- package/src/templates/projectconfigs/default_gitignore.template +47 -0
- package/src/templates/projectconfigs/sdf.config.js +4 -0
- package/src/templates/projectconfigs/suitecloud.config.js +4 -0
- package/src/templates/scripts/blankscript.js +3 -0
- package/src/templates/unittest/jest.config.js.template +7 -0
- package/src/templates/unittest/jsconfig.json.template +5 -0
- package/src/templates/unittest/package.json.template +12 -0
- package/src/templates/unittest/sample-test.js.template +37 -0
- package/src/templates/unittest/suitecloud.config.js.template +15 -0
- package/src/ui/CliSpinner.js +34 -0
- package/src/utils/AccountCredentialsFormatter.js +62 -0
- package/src/utils/AccountSpecificValuesUtils.js +55 -0
- package/src/utils/ActionResultUtils.js +47 -0
- package/src/utils/ApplyInstallationPreferencesUtils.js +41 -0
- package/src/utils/AuthenticationUtils.js +262 -0
- package/src/utils/CommandUtils.js +50 -0
- package/src/utils/CryptoUtils.js +41 -0
- package/src/utils/ExceptionUtils.js +33 -0
- package/src/utils/FileUtils.js +43 -0
- package/src/utils/SdkOperationResult.js +68 -0
- package/src/utils/SdkOperationResultUtils.js +20 -0
- package/src/utils/ValidationErrorsFormatter.js +23 -0
- package/src/utils/http/HttpConstants.js +39 -0
- package/src/utils/http/ProxyAgent.js +110 -0
- package/src/validation/InteractiveAnswersValidator.js +205 -0
|
@@ -0,0 +1,245 @@
|
|
|
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 { lstatSync, readdirSync, readFile, writeFile, mkdirSync, renameSync, existsSync, unlinkSync, rmdirSync } = require('fs');
|
|
8
|
+
const CLIException = require('../CLIException');
|
|
9
|
+
const assert = require('assert');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const NodeTranslationService = require('../services/NodeTranslationService');
|
|
12
|
+
const { CANT_CREATE_FOLDER } = require('../services/TranslationKeys').ERRORS;
|
|
13
|
+
|
|
14
|
+
const CHAR_ENCODING_UTF8 = 'utf-8';
|
|
15
|
+
|
|
16
|
+
module.exports = class FileSystemService {
|
|
17
|
+
getFoldersFromDirectory(parentFolder) {
|
|
18
|
+
assert(parentFolder);
|
|
19
|
+
const getDirectories = source =>
|
|
20
|
+
readdirSync(source)
|
|
21
|
+
.map(name => path.join(source, name))
|
|
22
|
+
.filter(source => lstatSync(source).isDirectory());
|
|
23
|
+
|
|
24
|
+
const availableDirectories = getDirectories(parentFolder);
|
|
25
|
+
|
|
26
|
+
return availableDirectories;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getFoldersFromDirectoryRecursively(parentFolder) {
|
|
30
|
+
assert(parentFolder);
|
|
31
|
+
if (!existsSync(parentFolder)) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const folders = [];
|
|
35
|
+
const getFoldersRecursively = source =>
|
|
36
|
+
this.getFoldersFromDirectory(source).forEach(folder => {
|
|
37
|
+
folders.push(folder);
|
|
38
|
+
getFoldersRecursively(folder);
|
|
39
|
+
});
|
|
40
|
+
getFoldersRecursively(parentFolder);
|
|
41
|
+
|
|
42
|
+
return folders;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getFilesFromDirectory(parentFolder) {
|
|
46
|
+
assert(parentFolder);
|
|
47
|
+
const fullPathFiles = [];
|
|
48
|
+
const getFilesRecursively = source =>
|
|
49
|
+
readdirSync(source).forEach(file => {
|
|
50
|
+
const fullPath = path.join(source, file);
|
|
51
|
+
if (lstatSync(fullPath).isDirectory()) {
|
|
52
|
+
getFilesRecursively(fullPath);
|
|
53
|
+
} else {
|
|
54
|
+
fullPathFiles.push(fullPath);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
getFilesRecursively(parentFolder);
|
|
59
|
+
return fullPathFiles;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @see {FileSystemService}
|
|
64
|
+
*/
|
|
65
|
+
getFirstAncestorByName(names, startingPath, isDirectory = false) {
|
|
66
|
+
assert(names);
|
|
67
|
+
assert(names.length);
|
|
68
|
+
assert(startingPath);
|
|
69
|
+
let filesFound = [];
|
|
70
|
+
let limitReached = false;
|
|
71
|
+
try {
|
|
72
|
+
const getAncestorsRecursively = source => {
|
|
73
|
+
if (source === '/') limitReached = true;
|
|
74
|
+
|
|
75
|
+
if(limitReached) return;
|
|
76
|
+
|
|
77
|
+
const firstFound = readdirSync(source).find(fileOrDir => {
|
|
78
|
+
const fullPath = path.join(source, fileOrDir);
|
|
79
|
+
if(isDirectory && lstatSync(fullPath).isDirectory()){
|
|
80
|
+
if( names.includes(fileOrDir)) return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (lstatSync(fullPath).isFile()) {
|
|
84
|
+
if (fileOrDir === 'package.json') limitReached = true;
|
|
85
|
+
if (!isDirectory && names.includes(fileOrDir)) return true;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
const nextPath = path.join(source, '..');
|
|
89
|
+
if (nextPath === source) limitReached = true;
|
|
90
|
+
|
|
91
|
+
if( firstFound ) {
|
|
92
|
+
filesFound.push(path.resolve(path.join(source,firstFound)));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if(limitReached) return;
|
|
97
|
+
|
|
98
|
+
getAncestorsRecursively(nextPath);
|
|
99
|
+
}
|
|
100
|
+
getAncestorsRecursively(startingPath);
|
|
101
|
+
} catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return filesFound.shift();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
createFileFromTemplate(options) {
|
|
109
|
+
assert(options.template);
|
|
110
|
+
assert(options.destinationFolder);
|
|
111
|
+
assert(options.fileName);
|
|
112
|
+
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
readFile(options.template, CHAR_ENCODING_UTF8, (readingError, content) => {
|
|
115
|
+
if (readingError) {
|
|
116
|
+
reject(readingError);
|
|
117
|
+
}
|
|
118
|
+
if (Array.isArray(options.bindings)) {
|
|
119
|
+
content = this._processTemplateBindings(content, options.bindings);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const fullFileName = options.fileExtension ? `${options.fileName}.${options.fileExtension}` : `${options.fileName}`;
|
|
123
|
+
|
|
124
|
+
writeFile(
|
|
125
|
+
path.join(options.destinationFolder, fullFileName),
|
|
126
|
+
content.toString(),
|
|
127
|
+
(writingError, data) => {
|
|
128
|
+
if (writingError) {
|
|
129
|
+
reject(writingError);
|
|
130
|
+
}
|
|
131
|
+
resolve();
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
createFolder(parentFolderPath, folderName) {
|
|
139
|
+
assert(parentFolderPath);
|
|
140
|
+
assert(folderName);
|
|
141
|
+
|
|
142
|
+
return this.createFolderFromAbsolutePath(path.join(parentFolderPath, folderName));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
createFolderFromAbsolutePath(folderAbsolutePath) {
|
|
146
|
+
assert(folderAbsolutePath);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
if (!existsSync(folderAbsolutePath)) {
|
|
150
|
+
mkdirSync(path.join(folderAbsolutePath));
|
|
151
|
+
}
|
|
152
|
+
} catch (e) {
|
|
153
|
+
throw new CLIException(NodeTranslationService.getMessage(CANT_CREATE_FOLDER, e.path, e.code));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return folderAbsolutePath;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
renameFolder(oldPath, newPath) {
|
|
160
|
+
assert(oldPath);
|
|
161
|
+
assert(newPath);
|
|
162
|
+
|
|
163
|
+
if (existsSync(oldPath) && oldPath !== newPath) {
|
|
164
|
+
renameSync(oldPath, newPath);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
deleteFolderRecursive(folderPath) {
|
|
169
|
+
assert(folderPath);
|
|
170
|
+
|
|
171
|
+
let self = this;
|
|
172
|
+
if (existsSync(folderPath)) {
|
|
173
|
+
readdirSync(folderPath).forEach(file => {
|
|
174
|
+
let currentPath = path.join(folderPath, file);
|
|
175
|
+
if (lstatSync(currentPath).isDirectory()) {
|
|
176
|
+
self.deleteFolderRecursive(currentPath);
|
|
177
|
+
} else {
|
|
178
|
+
unlinkSync(currentPath);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
rmdirSync(folderPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
emptyFolderRecursive(folderPath) {
|
|
186
|
+
assert(folderPath);
|
|
187
|
+
let self = this;
|
|
188
|
+
if (existsSync(folderPath)) {
|
|
189
|
+
readdirSync(folderPath).forEach(file => {
|
|
190
|
+
let currentPath = path.join(folderPath, file);
|
|
191
|
+
if (lstatSync(currentPath).isDirectory()) {
|
|
192
|
+
self.deleteFolderRecursive(currentPath);
|
|
193
|
+
} else {
|
|
194
|
+
unlinkSync(currentPath);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
replaceStringInFile(filePath, fromString, toString) {
|
|
201
|
+
assert(filePath);
|
|
202
|
+
assert(fromString);
|
|
203
|
+
assert(toString);
|
|
204
|
+
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
readFile(filePath, CHAR_ENCODING_UTF8, (readingError, content) => {
|
|
207
|
+
if (readingError) {
|
|
208
|
+
reject(readingError);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let result = content.replace(new RegExp(fromString, 'g'), toString);
|
|
212
|
+
|
|
213
|
+
writeFile(filePath, result, function(writingError) {
|
|
214
|
+
if (writingError) {
|
|
215
|
+
reject(writingError);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
resolve();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
folderExists(path) {
|
|
225
|
+
assert(path);
|
|
226
|
+
return existsSync(path);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
fileExists(path) {
|
|
230
|
+
return this.folderExists(path);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
isFolderEmpty(path) {
|
|
234
|
+
assert(path);
|
|
235
|
+
return readdirSync(path).length === 0;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
_processTemplateBindings(content, bindings) {
|
|
239
|
+
let processedContent = content;
|
|
240
|
+
bindings.forEach(binding => {
|
|
241
|
+
processedContent = content.replace(`{{${binding.id}}}`, binding.value);
|
|
242
|
+
});
|
|
243
|
+
return processedContent;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
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 TranslationService = require('./TranslationService');
|
|
9
|
+
const { DEFAULT_MESSAGES_FILE } = require('../ApplicationConstants');
|
|
10
|
+
const FileUtils = require('../utils/FileUtils');
|
|
11
|
+
|
|
12
|
+
class NodeTranslationService extends TranslationService {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
const filePath = path.join(__dirname, DEFAULT_MESSAGES_FILE);
|
|
16
|
+
// TODO refactor: use node require instead of FileUtils.readAsJson the initialize this._MESSAGES.
|
|
17
|
+
// Once the refactor is done FileUtils will be able to use NodeTranslationService again without a circular dependency.
|
|
18
|
+
this._MESSAGES = FileUtils.readAsJson(filePath);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = new NodeTranslationService();
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
const childProcess = require('child_process');
|
|
6
|
+
|
|
7
|
+
const PLATFORM_WIN = 'win32';
|
|
8
|
+
const COMMAND_NPM_WIN = 'npm.cmd';
|
|
9
|
+
const COMMAND_NPM_UNIX = 'npm';
|
|
10
|
+
const NPM_ARG_INSTALL = 'install';
|
|
11
|
+
const NPM_RESULT_CLOSE = 'close';
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
run: function(projectAbsolutePath) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let npm = process.platform === PLATFORM_WIN ? COMMAND_NPM_WIN : COMMAND_NPM_UNIX;
|
|
17
|
+
|
|
18
|
+
const result = childProcess.spawn(npm, [NPM_ARG_INSTALL], {
|
|
19
|
+
cwd: projectAbsolutePath,
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
windowsHide: true
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
result.on(NPM_RESULT_CLOSE, code => {
|
|
25
|
+
if (code === 0) {
|
|
26
|
+
resolve();
|
|
27
|
+
} else if (code !== 0) {
|
|
28
|
+
reject();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,209 @@
|
|
|
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 { ERRORS } = require('./TranslationKeys');
|
|
8
|
+
const {
|
|
9
|
+
FILES,
|
|
10
|
+
FOLDERS,
|
|
11
|
+
LINKS: { INFO },
|
|
12
|
+
PROJECT_ACP,
|
|
13
|
+
PROJECT_SUITEAPP
|
|
14
|
+
} = require('../ApplicationConstants');
|
|
15
|
+
const CLIException = require('../CLIException');
|
|
16
|
+
const FileUtils = require('../utils/FileUtils');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const NodeTranslationService = require('./NodeTranslationService');
|
|
19
|
+
const xml2js = require('xml2js');
|
|
20
|
+
const assert = require('assert');
|
|
21
|
+
const { lineBreak } = require('../loggers/LoggerOsConstants');
|
|
22
|
+
|
|
23
|
+
const MANIFEST_TAG_XML_PATH = '/manifest';
|
|
24
|
+
const PROJECT_TYPE_ATTRIBUTE = 'projecttype';
|
|
25
|
+
const MANIFEST_TAG_REGEX = '[\\s\\n]*<manifest.*>[^]*</manifest>[\\s\\n]*$';
|
|
26
|
+
|
|
27
|
+
module.exports = class ProjectInfoService {
|
|
28
|
+
constructor(projectFolder) {
|
|
29
|
+
assert(projectFolder);
|
|
30
|
+
this._CACHED_PROJECT_TYPE = null;
|
|
31
|
+
this._CACHED_PROJECT_NAME = null;
|
|
32
|
+
this._CACHED_PUBLISHER_ID = null;
|
|
33
|
+
this._CACHED_PROJECT_ID = null;
|
|
34
|
+
this._projectFolder = projectFolder;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* This validation function has to be defined in xml2js.Parser in the "validator" option
|
|
39
|
+
* When calling parserString this function will be executed for every tag of the xml we are
|
|
40
|
+
* parsing.
|
|
41
|
+
* @param {string} xmlPath Path of the tag that it's being evaluated at the current moment.
|
|
42
|
+
* @param {Object} previousValue Existing value at this path if there is already one (e.g. this
|
|
43
|
+
* is the second or later item in an array).
|
|
44
|
+
* @param {Object} newValue Value of the tag that it's being evaluated at the current moment.
|
|
45
|
+
* @throws ValidationError if the validation fails
|
|
46
|
+
*/
|
|
47
|
+
_validateXml(xmlPath, previousValue, newValue) {
|
|
48
|
+
//TODO Add more cases
|
|
49
|
+
if (xmlPath === MANIFEST_TAG_XML_PATH) {
|
|
50
|
+
let manifestTagAttributes = newValue['$'];
|
|
51
|
+
if (!manifestTagAttributes || !manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE]) {
|
|
52
|
+
throw new xml2js.ValidationError(
|
|
53
|
+
NodeTranslationService.getMessage(ERRORS.XML_PROJECTTYPE_ATTRIBUTE_MISSING)
|
|
54
|
+
);
|
|
55
|
+
} else if (
|
|
56
|
+
manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE] !== PROJECT_SUITEAPP &&
|
|
57
|
+
manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE] !== PROJECT_ACP
|
|
58
|
+
) {
|
|
59
|
+
throw new xml2js.ValidationError(
|
|
60
|
+
NodeTranslationService.getMessage(ERRORS.XML_PROJECTTYPE_INCORRECT)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return newValue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getProjectType() {
|
|
68
|
+
if (!this._CACHED_PROJECT_TYPE) {
|
|
69
|
+
this._parseManifest();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return this._CACHED_PROJECT_TYPE;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getProjectName() {
|
|
76
|
+
if (!this._CACHED_PROJECT_NAME) {
|
|
77
|
+
this._parseManifest();
|
|
78
|
+
}
|
|
79
|
+
return this._CACHED_PROJECT_NAME;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getPublisherId() {
|
|
83
|
+
if (!this._CACHED_PUBLISHER_ID) {
|
|
84
|
+
this._parseManifest();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this._CACHED_PUBLISHER_ID;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getProjectId() {
|
|
91
|
+
if (!this._CACHED_PROJECT_ID) {
|
|
92
|
+
this._parseManifest();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return this._CACHED_PROJECT_ID;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getApplicationId() {
|
|
99
|
+
return this.getPublisherId() + '.' + this.getProjectId();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
_parseManifest() {
|
|
103
|
+
const manifestPath = this._getManifestPath();
|
|
104
|
+
const manifestString = this._getManifestString(manifestPath);
|
|
105
|
+
|
|
106
|
+
let projectName;
|
|
107
|
+
let projectType;
|
|
108
|
+
let publisherId;
|
|
109
|
+
let projectId;
|
|
110
|
+
let validationError;
|
|
111
|
+
|
|
112
|
+
let parser = new xml2js.Parser({ validator: this._validateXml });
|
|
113
|
+
|
|
114
|
+
parser.parseString(manifestString, function (err, result) {
|
|
115
|
+
if (err) {
|
|
116
|
+
const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) +
|
|
117
|
+
' ' +
|
|
118
|
+
NodeTranslationService.getMessage(ERRORS.FILE, manifestPath);
|
|
119
|
+
validationError = errorMessage + ' ' + err;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (result) {
|
|
123
|
+
projectType = result.manifest.$.projecttype;
|
|
124
|
+
projectName = result.manifest.projectname;
|
|
125
|
+
publisherId = result.manifest.publisherid;
|
|
126
|
+
projectId = result.manifest.projectid;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
//TODO CHECK XML IS VALID
|
|
131
|
+
if (validationError) {
|
|
132
|
+
throw new CLIException(validationError);
|
|
133
|
+
}
|
|
134
|
+
this._CACHED_PROJECT_TYPE = projectType;
|
|
135
|
+
this._CACHED_PROJECT_NAME = projectName;
|
|
136
|
+
this._CACHED_PUBLISHER_ID = publisherId;
|
|
137
|
+
this._CACHED_PROJECT_ID = projectId;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_getManifestPath() {
|
|
141
|
+
const manifestPath = path.join(this._projectFolder, FILES.MANIFEST_XML);
|
|
142
|
+
|
|
143
|
+
if (!FileUtils.exists(manifestPath)) {
|
|
144
|
+
const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) +
|
|
145
|
+
' ' +
|
|
146
|
+
NodeTranslationService.getMessage(ERRORS.FILE_NOT_EXIST, manifestPath) +
|
|
147
|
+
lineBreak +
|
|
148
|
+
NodeTranslationService.getMessage(ERRORS.SEE_PROJECT_STRUCTURE, INFO.PROJECT_STRUCTURE);
|
|
149
|
+
|
|
150
|
+
throw new CLIException(errorMessage);
|
|
151
|
+
}
|
|
152
|
+
return manifestPath;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
_getManifestString(manifestPath) {
|
|
156
|
+
const manifestString = FileUtils.readAsString(manifestPath);
|
|
157
|
+
|
|
158
|
+
if (!manifestString.match(MANIFEST_TAG_REGEX)) {
|
|
159
|
+
const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) +
|
|
160
|
+
' ' +
|
|
161
|
+
NodeTranslationService.getMessage(ERRORS.XML_MANIFEST_TAG_MISSING);
|
|
162
|
+
throw new CLIException(errorMessage);
|
|
163
|
+
}
|
|
164
|
+
return manifestString;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
hasLockAndHideFiles() {
|
|
168
|
+
const pathToInstallationPreferences = path.join(
|
|
169
|
+
this._projectFolder,
|
|
170
|
+
FOLDERS.INSTALLATION_PREFERENCES
|
|
171
|
+
);
|
|
172
|
+
return (
|
|
173
|
+
FileUtils.exists(
|
|
174
|
+
path.join(pathToInstallationPreferences, FILES.HIDING_PREFERENCE)
|
|
175
|
+
) &&
|
|
176
|
+
FileUtils.exists(
|
|
177
|
+
path.join(pathToInstallationPreferences, FILES.LOCKING_PREFERENCE)
|
|
178
|
+
)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
isAccountCustomizationProject() {
|
|
183
|
+
try {
|
|
184
|
+
return this.getProjectType() === PROJECT_ACP;
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
isSuiteAppProject() {
|
|
191
|
+
try {
|
|
192
|
+
return this.getProjectType() === PROJECT_SUITEAPP;
|
|
193
|
+
} catch (error) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
isSuiteCloudProject() {
|
|
199
|
+
return this.isAccountCustomizationProject() || this.isSuiteAppProject();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
checkWorkingDirectoryContainsValidProject(commandName) {
|
|
203
|
+
if (!FileUtils.exists(path.join(this._projectFolder, FILES.MANIFEST_XML))) {
|
|
204
|
+
const errorMessage = NodeTranslationService.getMessage(ERRORS.NOT_PROJECT_FOLDER, FILES.MANIFEST_XML, this._projectFolder, commandName)
|
|
205
|
+
+ lineBreak + NodeTranslationService.getMessage(ERRORS.SEE_PROJECT_STRUCTURE, INFO.PROJECT_STRUCTURE);
|
|
206
|
+
throw new CLIException(errorMessage);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|