@ui5/builder 3.0.0-alpha.5 → 3.0.0-alpha.8
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/CHANGELOG.md +34 -1
- package/index.js +0 -39
- package/lib/lbt/analyzer/JSModuleAnalyzer.js +13 -2
- package/lib/lbt/bundle/Builder.js +19 -49
- package/lib/lbt/resources/LocatorResource.js +1 -1
- package/lib/lbt/resources/ResourceCollector.js +22 -15
- package/lib/lbt/resources/ResourceInfoList.js +0 -1
- package/lib/lbt/resources/ResourcePool.js +7 -6
- package/lib/lbt/utils/escapePropertiesFile.js +3 -6
- package/lib/processors/bundlers/moduleBundler.js +2 -3
- package/lib/processors/jsdoc/lib/createIndexFiles.js +1 -1
- package/lib/processors/jsdoc/lib/transformApiJson.js +20 -20
- package/lib/processors/jsdoc/lib/ui5/plugin.js +111 -6
- package/lib/processors/jsdoc/lib/ui5/template/publish.js +112 -91
- package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +1 -1
- package/lib/processors/manifestCreator.js +8 -45
- package/lib/tasks/TaskUtil.js +82 -17
- package/lib/tasks/bundlers/generateComponentPreload.js +14 -14
- package/lib/tasks/bundlers/generateFlexChangesBundle.js +6 -2
- package/lib/tasks/bundlers/generateLibraryPreload.js +84 -91
- package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
- package/lib/tasks/bundlers/generateStandaloneAppBundle.js +7 -2
- package/lib/tasks/bundlers/utils/createModuleNameMapping.js +3 -2
- package/lib/tasks/generateCachebusterInfo.js +7 -3
- package/lib/tasks/generateLibraryManifest.js +6 -8
- package/lib/tasks/generateResourcesJson.js +1 -1
- package/lib/tasks/generateThemeDesignerResources.js +8 -2
- package/lib/tasks/generateVersionInfo.js +5 -5
- package/lib/tasks/taskRepository.js +1 -13
- package/lib/tasks/transformBootstrapHtml.js +6 -1
- package/package.json +6 -7
- package/lib/builder/BuildContext.js +0 -60
- package/lib/builder/ProjectBuildContext.js +0 -61
- package/lib/builder/builder.js +0 -425
- package/lib/types/AbstractBuilder.js +0 -270
- package/lib/types/AbstractFormatter.js +0 -66
- package/lib/types/AbstractUi5Formatter.js +0 -95
- package/lib/types/application/ApplicationBuilder.js +0 -211
- package/lib/types/application/ApplicationFormatter.js +0 -227
- package/lib/types/application/applicationType.js +0 -15
- package/lib/types/library/LibraryBuilder.js +0 -232
- package/lib/types/library/LibraryFormatter.js +0 -519
- package/lib/types/library/libraryType.js +0 -15
- package/lib/types/module/ModuleBuilder.js +0 -7
- package/lib/types/module/ModuleFormatter.js +0 -54
- package/lib/types/module/moduleType.js +0 -15
- package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -64
- package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
- package/lib/types/themeLibrary/themeLibraryType.js +0 -15
- package/lib/types/typeRepository.js +0 -46
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
const fs = require("graceful-fs");
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Base class for the formatter implementation of a project type.
|
|
5
|
-
*
|
|
6
|
-
* @abstract
|
|
7
|
-
*/
|
|
8
|
-
class AbstractFormatter {
|
|
9
|
-
/**
|
|
10
|
-
* Constructor
|
|
11
|
-
*
|
|
12
|
-
* @param {object} parameters
|
|
13
|
-
* @param {object} parameters.project Project
|
|
14
|
-
*/
|
|
15
|
-
constructor({project}) {
|
|
16
|
-
if (new.target === AbstractFormatter) {
|
|
17
|
-
throw new TypeError("Class 'AbstractFormatter' is abstract");
|
|
18
|
-
}
|
|
19
|
-
this._project = project;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Formats and validates the project
|
|
24
|
-
*
|
|
25
|
-
* @returns {Promise}
|
|
26
|
-
*/
|
|
27
|
-
format() {
|
|
28
|
-
throw new Error("AbstractFormatter: Function format Not implemented");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Validates the project
|
|
33
|
-
*
|
|
34
|
-
* @returns {Promise} resolves if successfully validated
|
|
35
|
-
* @throws {Error} if validation fails
|
|
36
|
-
*/
|
|
37
|
-
validate() {
|
|
38
|
-
throw new Error("AbstractFormatter: Function validate Not implemented");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Checks whether or not the given input is a directory on the file system.
|
|
43
|
-
*
|
|
44
|
-
* @param {string} dirPath directory
|
|
45
|
-
* @returns {Promise<boolean>} whether or not the given directory exists.
|
|
46
|
-
* <code>true</code> directory exists
|
|
47
|
-
* <code>false</code> directory does not exist
|
|
48
|
-
*/
|
|
49
|
-
dirExists(dirPath) {
|
|
50
|
-
return new Promise((resolve, reject) => {
|
|
51
|
-
fs.stat(dirPath, (err, stats) => {
|
|
52
|
-
if (err) {
|
|
53
|
-
if (err.code === "ENOENT") { // "File or directory does not exist"
|
|
54
|
-
resolve(false);
|
|
55
|
-
} else {
|
|
56
|
-
reject(err);
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
resolve(stats.isDirectory());
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
module.exports = AbstractFormatter;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
const log = require("@ui5/logger").getLogger("types:AbstractUi5Formatter");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const fs = require("graceful-fs");
|
|
4
|
-
const AbstractFormatter = require("./AbstractFormatter");
|
|
5
|
-
const {promisify} = require("util");
|
|
6
|
-
const readFile = promisify(fs.readFile);
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Base class for formatters that require access to some UI5 specific resources
|
|
10
|
-
* like pom.xml
|
|
11
|
-
*
|
|
12
|
-
* @abstract
|
|
13
|
-
*/
|
|
14
|
-
class AbstractUi5Formatter extends AbstractFormatter {
|
|
15
|
-
/**
|
|
16
|
-
* Constructor
|
|
17
|
-
*
|
|
18
|
-
* @param {object} parameters
|
|
19
|
-
* @param {object} parameters.project Project
|
|
20
|
-
*/
|
|
21
|
-
constructor(parameters) {
|
|
22
|
-
super(parameters);
|
|
23
|
-
if (new.target === AbstractUi5Formatter) {
|
|
24
|
-
throw new TypeError("Class 'AbstractUi5Formatter' is abstract");
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Checks whether a given string contains a maven placeholder.
|
|
30
|
-
* E.g. <code>${appId}</code>.
|
|
31
|
-
*
|
|
32
|
-
* @param {string} value String to check
|
|
33
|
-
* @returns {boolean} True if given string contains a maven placeholder
|
|
34
|
-
*/
|
|
35
|
-
hasMavenPlaceholder(value) {
|
|
36
|
-
return !!value.match(/^\$\{(.*)\}$/);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Resolves a maven placeholder in a given string using the projects pom.xml
|
|
41
|
-
*
|
|
42
|
-
* @param {string} value String containing a maven placeholder
|
|
43
|
-
* @returns {Promise<string>} Resolved string
|
|
44
|
-
*/
|
|
45
|
-
async resolveMavenPlaceholder(value) {
|
|
46
|
-
const parts = value && value.match(/^\$\{(.*)\}$/);
|
|
47
|
-
if (parts) {
|
|
48
|
-
log.verbose(`"${value} contains a maven placeholder "${parts[1]}". Resolving from projects pom.xml...`);
|
|
49
|
-
const pom = await this.getPom();
|
|
50
|
-
let mvnValue;
|
|
51
|
-
if (pom.project && pom.project.properties && pom.project.properties[parts[1]]) {
|
|
52
|
-
mvnValue = pom.project.properties[parts[1]];
|
|
53
|
-
} else {
|
|
54
|
-
let obj = pom;
|
|
55
|
-
parts[1].split(".").forEach((part) => {
|
|
56
|
-
obj = obj && obj[part];
|
|
57
|
-
});
|
|
58
|
-
mvnValue = obj;
|
|
59
|
-
}
|
|
60
|
-
if (!mvnValue) {
|
|
61
|
-
throw new Error(`"${value}" couldn't be resolved from maven property ` +
|
|
62
|
-
`"${parts[1]}" of pom.xml of project ${this._project.metadata.name}`);
|
|
63
|
-
}
|
|
64
|
-
return mvnValue;
|
|
65
|
-
} else {
|
|
66
|
-
throw new Error(`"${value}" is not a maven placeholder`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Reads the projects pom.xml file
|
|
72
|
-
*
|
|
73
|
-
* @returns {Promise<object>} Resolves with a JSON representation of the content
|
|
74
|
-
*/
|
|
75
|
-
async getPom() {
|
|
76
|
-
if (this._pPom) {
|
|
77
|
-
return this._pPom;
|
|
78
|
-
}
|
|
79
|
-
const fsPath = path.join(this._project.path, "pom.xml");
|
|
80
|
-
return this._pPom = readFile(fsPath).then(async (content) => {
|
|
81
|
-
const xml2js = require("xml2js");
|
|
82
|
-
const parser = new xml2js.Parser({
|
|
83
|
-
explicitArray: false,
|
|
84
|
-
ignoreAttrs: true
|
|
85
|
-
});
|
|
86
|
-
const readXML = promisify(parser.parseString);
|
|
87
|
-
return readXML(content);
|
|
88
|
-
}).catch((err) => {
|
|
89
|
-
throw new Error(
|
|
90
|
-
`Failed to read pom.xml for project ${this._project.metadata.name}: ${err.message}`);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
module.exports = AbstractUi5Formatter;
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
const AbstractBuilder = require("../AbstractBuilder");
|
|
2
|
-
const {getTask} = require("../../tasks/taskRepository");
|
|
3
|
-
|
|
4
|
-
class ApplicationBuilder extends AbstractBuilder {
|
|
5
|
-
addStandardTasks({resourceCollections, project, log, taskUtil}) {
|
|
6
|
-
if (!project.metadata.namespace) {
|
|
7
|
-
// TODO 3.0: Throw here
|
|
8
|
-
log.info("Skipping some tasks due to missing application namespace information. If your project contains " +
|
|
9
|
-
"a Component.js, you might be missing a manifest.json file. " +
|
|
10
|
-
"Also see: https://sap.github.io/ui5-tooling/pages/Builder/#application");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
this.addTask("escapeNonAsciiCharacters", async () => {
|
|
14
|
-
const propertiesFileSourceEncoding = project.resources &&
|
|
15
|
-
project.resources.configuration &&
|
|
16
|
-
project.resources.configuration.propertiesFileSourceEncoding;
|
|
17
|
-
return getTask("escapeNonAsciiCharacters").task({
|
|
18
|
-
workspace: resourceCollections.workspace,
|
|
19
|
-
options: {
|
|
20
|
-
encoding: propertiesFileSourceEncoding,
|
|
21
|
-
pattern: "/**/*.properties"
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
this.addTask("replaceCopyright", async () => {
|
|
27
|
-
return getTask("replaceCopyright").task({
|
|
28
|
-
workspace: resourceCollections.workspace,
|
|
29
|
-
options: {
|
|
30
|
-
copyright: project.metadata.copyright,
|
|
31
|
-
pattern: "/**/*.{js,json}"
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
this.addTask("replaceVersion", async () => {
|
|
37
|
-
return getTask("replaceVersion").task({
|
|
38
|
-
workspace: resourceCollections.workspace,
|
|
39
|
-
options: {
|
|
40
|
-
version: project.version,
|
|
41
|
-
pattern: "/**/*.{js,json}"
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// Support rules should not be minified to have readable code in the Support Assistant
|
|
47
|
-
const minificationPattern = ["/**/*.js", "!**/*.support.js"];
|
|
48
|
-
if (["2.6"].includes(project.specVersion)) {
|
|
49
|
-
const minificationExcludes = project.builder && project.builder.minification &&
|
|
50
|
-
project.builder.minification.excludes;
|
|
51
|
-
if (minificationExcludes) {
|
|
52
|
-
// TODO 3.0: namespaces should become mandatory, see existing check above
|
|
53
|
-
const patternPrefix = project.metadata.namespace ? "/resources/" : "/";
|
|
54
|
-
this.enhancePatternWithExcludes(minificationPattern, minificationExcludes, patternPrefix);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
this.addTask("minify", async () => {
|
|
58
|
-
return getTask("minify").task({
|
|
59
|
-
workspace: resourceCollections.workspace,
|
|
60
|
-
taskUtil,
|
|
61
|
-
options: {
|
|
62
|
-
pattern: minificationPattern
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
this.addTask("generateFlexChangesBundle", async () => {
|
|
68
|
-
const generateFlexChangesBundle = getTask("generateFlexChangesBundle").task;
|
|
69
|
-
return generateFlexChangesBundle({
|
|
70
|
-
workspace: resourceCollections.workspace,
|
|
71
|
-
taskUtil,
|
|
72
|
-
options: {
|
|
73
|
-
namespace: project.metadata.namespace
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
if (project.metadata.namespace) {
|
|
79
|
-
this.addTask("generateManifestBundle", async () => {
|
|
80
|
-
const generateManifestBundle = getTask("generateManifestBundle").task;
|
|
81
|
-
return generateManifestBundle({
|
|
82
|
-
workspace: resourceCollections.workspace,
|
|
83
|
-
options: {
|
|
84
|
-
projectName: project.metadata.name,
|
|
85
|
-
namespace: project.metadata.namespace
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const componentPreload = project.builder && project.builder.componentPreload;
|
|
92
|
-
if (componentPreload && (componentPreload.namespaces || componentPreload.paths)) {
|
|
93
|
-
this.addTask("generateComponentPreload", async () => {
|
|
94
|
-
return getTask("generateComponentPreload").task({
|
|
95
|
-
workspace: resourceCollections.workspace,
|
|
96
|
-
dependencies: resourceCollections.dependencies,
|
|
97
|
-
taskUtil,
|
|
98
|
-
options: {
|
|
99
|
-
projectName: project.metadata.name,
|
|
100
|
-
paths: componentPreload.paths,
|
|
101
|
-
namespaces: componentPreload.namespaces,
|
|
102
|
-
excludes: componentPreload.excludes
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
} else if (project.metadata.namespace) {
|
|
107
|
-
// Default component preload for application namespace
|
|
108
|
-
this.addTask("generateComponentPreload", async () => {
|
|
109
|
-
return getTask("generateComponentPreload").task({
|
|
110
|
-
workspace: resourceCollections.workspace,
|
|
111
|
-
dependencies: resourceCollections.dependencies,
|
|
112
|
-
taskUtil,
|
|
113
|
-
options: {
|
|
114
|
-
projectName: project.metadata.name,
|
|
115
|
-
namespaces: [project.metadata.namespace],
|
|
116
|
-
excludes: componentPreload && componentPreload.excludes
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.addTask("generateStandaloneAppBundle", async () => {
|
|
123
|
-
return getTask("generateStandaloneAppBundle").task({
|
|
124
|
-
workspace: resourceCollections.workspace,
|
|
125
|
-
dependencies: resourceCollections.dependencies,
|
|
126
|
-
taskUtil,
|
|
127
|
-
options: {
|
|
128
|
-
projectName: project.metadata.name,
|
|
129
|
-
namespace: project.metadata.namespace
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
this.addTask("transformBootstrapHtml", async () => {
|
|
135
|
-
return getTask("transformBootstrapHtml").task({
|
|
136
|
-
workspace: resourceCollections.workspace,
|
|
137
|
-
options: {
|
|
138
|
-
projectName: project.metadata.name,
|
|
139
|
-
namespace: project.metadata.namespace
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const bundles = project.builder && project.builder.bundles;
|
|
145
|
-
if (bundles) {
|
|
146
|
-
this.addTask("generateBundle", async () => {
|
|
147
|
-
return Promise.all(bundles.map((bundle) => {
|
|
148
|
-
return getTask("generateBundle").task({
|
|
149
|
-
workspace: resourceCollections.workspace,
|
|
150
|
-
dependencies: resourceCollections.dependencies,
|
|
151
|
-
taskUtil,
|
|
152
|
-
options: {
|
|
153
|
-
projectName: project.metadata.name,
|
|
154
|
-
bundleDefinition: bundle.bundleDefinition,
|
|
155
|
-
bundleOptions: bundle.bundleOptions
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}));
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.addTask("generateVersionInfo", async () => {
|
|
163
|
-
return getTask("generateVersionInfo").task({
|
|
164
|
-
workspace: resourceCollections.workspace,
|
|
165
|
-
dependencies: resourceCollections.dependencies,
|
|
166
|
-
options: {
|
|
167
|
-
rootProject: project,
|
|
168
|
-
pattern: "/resources/**/.library"
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
if (project.metadata.namespace) {
|
|
174
|
-
this.addTask("generateCachebusterInfo", async () => {
|
|
175
|
-
return getTask("generateCachebusterInfo").task({
|
|
176
|
-
workspace: resourceCollections.workspace,
|
|
177
|
-
dependencies: resourceCollections.dependencies,
|
|
178
|
-
options: {
|
|
179
|
-
namespace: project.metadata.namespace,
|
|
180
|
-
signatureType: project.builder &&
|
|
181
|
-
project.builder.cachebuster &&
|
|
182
|
-
project.builder.cachebuster.signatureType,
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
this.addTask("generateApiIndex", async () => {
|
|
189
|
-
return getTask("generateApiIndex").task({
|
|
190
|
-
workspace: resourceCollections.workspace,
|
|
191
|
-
dependencies: resourceCollections.dependencies,
|
|
192
|
-
options: {
|
|
193
|
-
projectName: project.metadata.name
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
this.addTask("generateResourcesJson", () => {
|
|
199
|
-
return getTask("generateResourcesJson").task({
|
|
200
|
-
workspace: resourceCollections.workspace,
|
|
201
|
-
dependencies: resourceCollections.dependencies,
|
|
202
|
-
taskUtil,
|
|
203
|
-
options: {
|
|
204
|
-
projectName: project.metadata.name
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
module.exports = ApplicationBuilder;
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
const log = require("@ui5/logger").getLogger("types:application:ApplicationFormatter");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const fs = require("graceful-fs");
|
|
4
|
-
const {promisify} = require("util");
|
|
5
|
-
const readFile = promisify(fs.readFile);
|
|
6
|
-
const AbstractUi5Formatter = require("../AbstractUi5Formatter");
|
|
7
|
-
|
|
8
|
-
class ApplicationFormatter extends AbstractUi5Formatter {
|
|
9
|
-
/**
|
|
10
|
-
* Constructor
|
|
11
|
-
*
|
|
12
|
-
* @param {object} parameters
|
|
13
|
-
* @param {object} parameters.project Project
|
|
14
|
-
*/
|
|
15
|
-
constructor(parameters) {
|
|
16
|
-
super(parameters);
|
|
17
|
-
this._pManifests = {};
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Formats and validates the project
|
|
21
|
-
*
|
|
22
|
-
* @returns {Promise}
|
|
23
|
-
*/
|
|
24
|
-
async format() {
|
|
25
|
-
const project = this._project;
|
|
26
|
-
await this.validate();
|
|
27
|
-
log.verbose("Formatting application project %s...", project.metadata.name);
|
|
28
|
-
project.resources.pathMappings = {
|
|
29
|
-
"/": project.resources.configuration.paths.webapp
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
project.metadata.namespace = await this.getNamespace();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Returns the base *source* path of the project. Runtime resources like manifest.json are expected
|
|
37
|
-
* to be located inside this path.
|
|
38
|
-
*
|
|
39
|
-
* @param {boolean} [posix] whether to return a POSIX path
|
|
40
|
-
* @returns {string} Base source path of the project
|
|
41
|
-
*/
|
|
42
|
-
getSourceBasePath(posix) {
|
|
43
|
-
let p = path;
|
|
44
|
-
let projectPath = this._project.path;
|
|
45
|
-
if (posix) {
|
|
46
|
-
projectPath = projectPath.replace(/\\/g, "/");
|
|
47
|
-
p = path.posix;
|
|
48
|
-
}
|
|
49
|
-
return p.join(projectPath, this._project.resources.pathMappings["/"]);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Determine application namespace either based on a project`s
|
|
54
|
-
* manifest.json or manifest.appdescr_variant (fallback if present)
|
|
55
|
-
*
|
|
56
|
-
* @returns {string} Namespace of the project
|
|
57
|
-
* @throws {Error} if namespace can not be determined
|
|
58
|
-
*/
|
|
59
|
-
async getNamespace() {
|
|
60
|
-
try {
|
|
61
|
-
return await this.getNamespaceFromManifestJson();
|
|
62
|
-
} catch (manifestJsonError) {
|
|
63
|
-
if (manifestJsonError.code !== "ENOENT") {
|
|
64
|
-
throw manifestJsonError;
|
|
65
|
-
}
|
|
66
|
-
// No manifest.json present
|
|
67
|
-
// => attempt fallback to manifest.appdescr_variant (typical for App Variants)
|
|
68
|
-
try {
|
|
69
|
-
return await this.getNamespaceFromManifestAppDescVariant();
|
|
70
|
-
} catch (appDescVarError) {
|
|
71
|
-
if (appDescVarError.code === "ENOENT") {
|
|
72
|
-
// Fallback not possible: No manifest.appdescr_variant present
|
|
73
|
-
// => Throw error indicating missing manifest.json
|
|
74
|
-
// (do not mention manifest.appdescr_variant since it is only
|
|
75
|
-
// relevant for the rather "uncommon" App Variants)
|
|
76
|
-
throw new Error(
|
|
77
|
-
`Could not find required manifest.json for project ` +
|
|
78
|
-
`${this._project.metadata.name}: ${manifestJsonError.message}`);
|
|
79
|
-
}
|
|
80
|
-
throw appDescVarError;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Determine application namespace by checking manifest.json.
|
|
87
|
-
* Any maven placeholders are resolved from the projects pom.xml
|
|
88
|
-
*
|
|
89
|
-
* @returns {string} Namespace of the project
|
|
90
|
-
* @throws {Error} if namespace can not be determined
|
|
91
|
-
*/
|
|
92
|
-
async getNamespaceFromManifestJson() {
|
|
93
|
-
const {content: manifest} = await this.getJson("manifest.json");
|
|
94
|
-
let appId;
|
|
95
|
-
// check for a proper sap.app/id in manifest.json to determine namespace
|
|
96
|
-
if (manifest["sap.app"] && manifest["sap.app"].id) {
|
|
97
|
-
appId = manifest["sap.app"].id;
|
|
98
|
-
} else {
|
|
99
|
-
throw new Error(
|
|
100
|
-
`No sap.app/id configuration found in manifest.json of project ${this._project.metadata.name}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (this.hasMavenPlaceholder(appId)) {
|
|
104
|
-
try {
|
|
105
|
-
appId = await this.resolveMavenPlaceholder(appId);
|
|
106
|
-
} catch (err) {
|
|
107
|
-
throw new Error(
|
|
108
|
-
`Failed to resolve namespace of project ${this._project.metadata.name}: ${err.message}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const namespace = appId.replace(/\./g, "/");
|
|
112
|
-
log.verbose(
|
|
113
|
-
`Namespace of project ${this._project.metadata.name} is ${namespace} (from manifest.json)`);
|
|
114
|
-
return namespace;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Determine application namespace by checking manifest.appdescr_variant.
|
|
119
|
-
*
|
|
120
|
-
* @returns {string} Namespace of the project
|
|
121
|
-
* @throws {Error} if namespace can not be determined
|
|
122
|
-
*/
|
|
123
|
-
async getNamespaceFromManifestAppDescVariant() {
|
|
124
|
-
const {content: manifest} = await this.getJson("manifest.appdescr_variant");
|
|
125
|
-
let appId;
|
|
126
|
-
// check for the id property in manifest.appdescr_variant to determine namespace
|
|
127
|
-
if (manifest && manifest.id) {
|
|
128
|
-
appId = manifest.id;
|
|
129
|
-
} else {
|
|
130
|
-
throw new Error(
|
|
131
|
-
`No "id" property found in manifest.appdescr_variant of project ${this._project.metadata.name}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const namespace = appId.replace(/\./g, "/");
|
|
135
|
-
log.verbose(
|
|
136
|
-
`Namespace of project ${this._project.metadata.name} is ${namespace} (from manifest.appdescr_variant)`);
|
|
137
|
-
return namespace;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Reads and parses a JSON file with the provided name from the projects source directory
|
|
142
|
-
*
|
|
143
|
-
* @param {string} fileName Name of the JSON file to read. Typically "manifest.json" or "manifest.appdescr_variant"
|
|
144
|
-
* @returns {Promise<object>} resolves with an object containing the <code>content</code> (as JSON) and
|
|
145
|
-
* <code>fsPath</code> (as string) of the requested file
|
|
146
|
-
*/
|
|
147
|
-
async getJson(fileName) {
|
|
148
|
-
if (this._pManifests[fileName]) {
|
|
149
|
-
return this._pManifests[fileName];
|
|
150
|
-
}
|
|
151
|
-
const fsPath = path.join(this.getSourceBasePath(), fileName);
|
|
152
|
-
return this._pManifests[fileName] = readFile(fsPath)
|
|
153
|
-
.then((content) => {
|
|
154
|
-
return {
|
|
155
|
-
content: JSON.parse(content),
|
|
156
|
-
fsPath
|
|
157
|
-
};
|
|
158
|
-
})
|
|
159
|
-
.catch((err) => {
|
|
160
|
-
if (err.code === "ENOENT") {
|
|
161
|
-
throw err;
|
|
162
|
-
}
|
|
163
|
-
throw new Error(
|
|
164
|
-
`Failed to read ${fileName} for project ` +
|
|
165
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Validates the project
|
|
171
|
-
*
|
|
172
|
-
* @returns {Promise} resolves if successfully validated
|
|
173
|
-
* @throws {Error} if validation fails
|
|
174
|
-
*/
|
|
175
|
-
validate() {
|
|
176
|
-
const project = this._project;
|
|
177
|
-
return Promise.resolve().then(() => {
|
|
178
|
-
if (!project) {
|
|
179
|
-
throw new Error("Project is undefined");
|
|
180
|
-
} else if (!project.metadata || !project.metadata.name) {
|
|
181
|
-
throw new Error(`"metadata.name" configuration is missing for project ${project.id}`);
|
|
182
|
-
} else if (!project.type) {
|
|
183
|
-
throw new Error(`"type" configuration is missing for project ${project.id}`);
|
|
184
|
-
} else if (project.version === undefined) {
|
|
185
|
-
throw new Error(`"version" is missing for project ${project.id}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (!project.resources) {
|
|
189
|
-
project.resources = {};
|
|
190
|
-
}
|
|
191
|
-
if (!project.resources.configuration) {
|
|
192
|
-
project.resources.configuration = {};
|
|
193
|
-
}
|
|
194
|
-
if (!project.resources.configuration.paths) {
|
|
195
|
-
project.resources.configuration.paths = {};
|
|
196
|
-
}
|
|
197
|
-
if (!project.resources.configuration.paths.webapp) {
|
|
198
|
-
project.resources.configuration.paths.webapp = "webapp";
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!project.resources.configuration.propertiesFileSourceEncoding) {
|
|
202
|
-
if (["0.1", "1.0", "1.1"].includes(project.specVersion)) {
|
|
203
|
-
// default encoding to "ISO-8859-1" for old specVersions
|
|
204
|
-
project.resources.configuration.propertiesFileSourceEncoding = "ISO-8859-1";
|
|
205
|
-
} else {
|
|
206
|
-
// default encoding to "UTF-8" for all projects starting with specVersion 2.0
|
|
207
|
-
project.resources.configuration.propertiesFileSourceEncoding = "UTF-8";
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if (!["ISO-8859-1", "UTF-8"].includes(project.resources.configuration.propertiesFileSourceEncoding)) {
|
|
211
|
-
throw new Error(`Invalid properties file encoding specified for project ${project.id}. ` +
|
|
212
|
-
`Encoding provided: ${project.resources.configuration.propertiesFileSourceEncoding}. ` +
|
|
213
|
-
`Must be either "ISO-8859-1" or "UTF-8".`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const absolutePath = path.join(project.path, project.resources.configuration.paths.webapp);
|
|
217
|
-
return this.dirExists(absolutePath).then((bExists) => {
|
|
218
|
-
if (!bExists) {
|
|
219
|
-
throw new Error(`Could not find application directory of project ${project.id}: ` +
|
|
220
|
-
`${absolutePath}`);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
module.exports = ApplicationFormatter;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const ApplicationFormatter = require("./ApplicationFormatter");
|
|
2
|
-
const ApplicationBuilder = require("./ApplicationBuilder");
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
format: function(project) {
|
|
6
|
-
return new ApplicationFormatter({project}).format();
|
|
7
|
-
},
|
|
8
|
-
build: function({resourceCollections, tasks, project, parentLogger, taskUtil}) {
|
|
9
|
-
return new ApplicationBuilder({resourceCollections, project, parentLogger, taskUtil}).build(tasks);
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
// Export type classes for extensibility
|
|
13
|
-
Builder: ApplicationBuilder,
|
|
14
|
-
Formatter: ApplicationFormatter
|
|
15
|
-
};
|