@ui5/builder 3.0.0-alpha.4 → 3.0.0-alpha.7
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 +46 -1
- package/index.js +0 -39
- package/lib/lbt/analyzer/JSModuleAnalyzer.js +13 -2
- package/lib/lbt/bundle/Builder.js +18 -48
- 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/transformApiJson.js +13 -4
- 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 +118 -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 +4 -5
- 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,519 +0,0 @@
|
|
|
1
|
-
const log = require("@ui5/logger").getLogger("types:library:LibraryFormatter");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const fs = require("graceful-fs");
|
|
4
|
-
const {promisify} = require("util");
|
|
5
|
-
const readFile = promisify(fs.readFile);
|
|
6
|
-
const glob = require("globby");
|
|
7
|
-
const AbstractUi5Formatter = require("../AbstractUi5Formatter");
|
|
8
|
-
|
|
9
|
-
const SAP_THEMES_NS_EXEMPTIONS = ["themelib_sap_fiori_3", "themelib_sap_bluecrystal", "themelib_sap_belize"];
|
|
10
|
-
|
|
11
|
-
function isFrameworkProject(project) {
|
|
12
|
-
return project.id.startsWith("@openui5/") || project.id.startsWith("@sapui5/");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class LibraryFormatter extends AbstractUi5Formatter {
|
|
16
|
-
/**
|
|
17
|
-
* Formats and validates the project
|
|
18
|
-
*
|
|
19
|
-
* @returns {Promise}
|
|
20
|
-
*/
|
|
21
|
-
async format() {
|
|
22
|
-
const project = this._project;
|
|
23
|
-
await this.validate();
|
|
24
|
-
|
|
25
|
-
log.verbose("Formatting library project %s...", project.metadata.name);
|
|
26
|
-
project.resources.pathMappings = {
|
|
27
|
-
"/resources/": project.resources.configuration.paths.src
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
if (project.resources.configuration.paths.test) {
|
|
31
|
-
// Directory 'test' is somewhat optional for libraries
|
|
32
|
-
project.resources.pathMappings["/test-resources/"] = project.resources.configuration.paths.test;
|
|
33
|
-
} else {
|
|
34
|
-
log.verbose(`Ignoring 'test' directory for project ${project.metadata.name}. ` +
|
|
35
|
-
"Either no setting was provided or the path not found.");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
project.metadata.namespace = await this.getNamespace();
|
|
40
|
-
} catch (err) {
|
|
41
|
-
if (SAP_THEMES_NS_EXEMPTIONS.includes(this._project.metadata.name)) {
|
|
42
|
-
// Exceptional handling for SAP theme libraries which used to be of type "library"
|
|
43
|
-
// (today they use "theme-library").
|
|
44
|
-
// To allow use of OpenUI5 theme libraries in versions lower than 1.75 we must ignore
|
|
45
|
-
// namespace detection errors.
|
|
46
|
-
log.verbose(`Ignoring failed namespace detection for exempted SAP theme library ` +
|
|
47
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
48
|
-
} else {
|
|
49
|
-
throw err;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
project.metadata.copyright = await this.getCopyright();
|
|
55
|
-
} catch (err) {
|
|
56
|
-
// Catch error because copyright is optional
|
|
57
|
-
// TODO 2.0: Make copyright mandatory and just let the error throw
|
|
58
|
-
log.verbose(err.message);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (isFrameworkProject(project) && !SAP_THEMES_NS_EXEMPTIONS.includes(this._project.metadata.name)) {
|
|
62
|
-
if (project.builder && project.builder.libraryPreload && project.builder.libraryPreload.excludes) {
|
|
63
|
-
log.verbose(
|
|
64
|
-
`Using preload excludes for framework library ${project.metadata.name} from project configuration`);
|
|
65
|
-
} else {
|
|
66
|
-
log.verbose(
|
|
67
|
-
`No preload excludes defined in project configuration of framework library ` +
|
|
68
|
-
`${project.metadata.name}. Falling back to .library...`);
|
|
69
|
-
const excludes = await this.getPreloadExcludesFromDotLibrary();
|
|
70
|
-
if (excludes) {
|
|
71
|
-
if (!project.builder) {
|
|
72
|
-
project.builder = {};
|
|
73
|
-
}
|
|
74
|
-
if (!project.builder.libraryPreload) {
|
|
75
|
-
project.builder.libraryPreload = {};
|
|
76
|
-
}
|
|
77
|
-
project.builder.libraryPreload.excludes = excludes;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Returns the base *source* path of the project. Runtime resources like manifest.json are expected
|
|
85
|
-
* to be located inside this path.
|
|
86
|
-
*
|
|
87
|
-
* @param {boolean} [posix] whether to return a POSIX path
|
|
88
|
-
* @returns {string} Base source path of the project
|
|
89
|
-
*/
|
|
90
|
-
getSourceBasePath(posix) {
|
|
91
|
-
let p = path;
|
|
92
|
-
let projectPath = this._project.path;
|
|
93
|
-
if (posix) {
|
|
94
|
-
projectPath = projectPath.replace(/\\/g, "/");
|
|
95
|
-
p = path.posix;
|
|
96
|
-
}
|
|
97
|
-
return p.join(projectPath, this._project.resources.pathMappings["/resources/"]);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Determine library namespace by checking manifest.json with fallback to .library.
|
|
102
|
-
* Any maven placeholders are resolved from the projects pom.xml
|
|
103
|
-
*
|
|
104
|
-
* @returns {string} Namespace of the project
|
|
105
|
-
* @throws {Error} if namespace can not be determined
|
|
106
|
-
*/
|
|
107
|
-
async getNamespace() {
|
|
108
|
-
// Trigger both reads asynchronously
|
|
109
|
-
const [{
|
|
110
|
-
namespace: manifestNs,
|
|
111
|
-
fsPath: manifestPath
|
|
112
|
-
}, {
|
|
113
|
-
namespace: dotLibraryNs,
|
|
114
|
-
fsPath: dotLibraryPath
|
|
115
|
-
}] = await Promise.all([
|
|
116
|
-
this.getNamespaceFromManifest(),
|
|
117
|
-
this.getNamespaceFromDotLibrary()
|
|
118
|
-
]);
|
|
119
|
-
|
|
120
|
-
let libraryNs;
|
|
121
|
-
let fsNamespacePath;
|
|
122
|
-
if (manifestNs && dotLibraryNs) {
|
|
123
|
-
// Both files present
|
|
124
|
-
// => check whether they are on the same level
|
|
125
|
-
const manifestDepth = manifestPath.split(path.sep).length;
|
|
126
|
-
const dotLibraryDepth = dotLibraryPath.split(path.sep).length;
|
|
127
|
-
|
|
128
|
-
if (manifestDepth < dotLibraryDepth) {
|
|
129
|
-
// We see the .library file as the "leading" file of a library
|
|
130
|
-
// Therefore, a manifest.json on a higher level is something we do not except
|
|
131
|
-
throw new Error(`Failed to detect namespace for project ${this._project.metadata.name}: ` +
|
|
132
|
-
`Found a manifest.json on a higher directory level than the .library file. ` +
|
|
133
|
-
`It should be on the same or a lower level. ` +
|
|
134
|
-
`Note that a manifest.json on a lower level will be ignored.\n` +
|
|
135
|
-
` manifest.json path: ${manifestPath}\n` +
|
|
136
|
-
` is higher than\n` +
|
|
137
|
-
` .library path: ${dotLibraryPath}`);
|
|
138
|
-
}
|
|
139
|
-
if (manifestDepth === dotLibraryDepth) {
|
|
140
|
-
if (path.dirname(manifestPath) !== path.dirname(dotLibraryPath)) {
|
|
141
|
-
// This just should not happen in your project
|
|
142
|
-
throw new Error(`Failed to detect namespace for project ${this._project.metadata.name}: ` +
|
|
143
|
-
`Found a manifest.json on the same directory level but in a different directory ` +
|
|
144
|
-
`than the .library file. They should be in the same directory.\n` +
|
|
145
|
-
` manifest.json path: ${manifestPath}\n` +
|
|
146
|
-
` is different to\n` +
|
|
147
|
-
` .library path: ${dotLibraryPath}`);
|
|
148
|
-
}
|
|
149
|
-
// Typical scenario if both files are present
|
|
150
|
-
log.verbose(`Found a manifest.json and a .library file on the same level for ` +
|
|
151
|
-
`project ${this._project.metadata.name}.`);
|
|
152
|
-
log.verbose(`Resolving namespace of project ${this._project.metadata.name} from manifest.json...`);
|
|
153
|
-
libraryNs = manifestNs;
|
|
154
|
-
fsNamespacePath = path.dirname(manifestPath);
|
|
155
|
-
} else {
|
|
156
|
-
// Typical scenario: Some nested component has a manifest.json but the library itself only
|
|
157
|
-
// features a .library. => Ignore the manifest.json
|
|
158
|
-
log.verbose(`Ignoring manifest.json found on a lower level than the .library file of ` +
|
|
159
|
-
`project ${this._project.metadata.name}.`);
|
|
160
|
-
log.verbose(`Resolving namespace of project ${this._project.metadata.name} from .library...`);
|
|
161
|
-
libraryNs = dotLibraryNs;
|
|
162
|
-
fsNamespacePath = path.dirname(dotLibraryPath);
|
|
163
|
-
}
|
|
164
|
-
} else if (manifestNs) {
|
|
165
|
-
// Only manifest available
|
|
166
|
-
log.verbose(`Resolving namespace of project ${this._project.metadata.name} from manifest.json...`);
|
|
167
|
-
libraryNs = manifestNs;
|
|
168
|
-
fsNamespacePath = path.dirname(manifestPath);
|
|
169
|
-
} else if (dotLibraryNs) {
|
|
170
|
-
// Only .library available
|
|
171
|
-
log.verbose(`Resolving namespace of project ${this._project.metadata.name} from .library...`);
|
|
172
|
-
libraryNs = dotLibraryNs;
|
|
173
|
-
fsNamespacePath = path.dirname(dotLibraryPath);
|
|
174
|
-
} else {
|
|
175
|
-
log.verbose(`Failed to resolve namespace of project ${this._project.metadata.name} from manifest.json ` +
|
|
176
|
-
`or .library file. Falling back to library.js file path...`);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
let namespace;
|
|
180
|
-
if (libraryNs) {
|
|
181
|
-
// Maven placeholders can only exist in manifest.json or .library configuration
|
|
182
|
-
if (this.hasMavenPlaceholder(libraryNs)) {
|
|
183
|
-
try {
|
|
184
|
-
libraryNs = await this.resolveMavenPlaceholder(libraryNs);
|
|
185
|
-
} catch (err) {
|
|
186
|
-
throw new Error(
|
|
187
|
-
`Failed to resolve namespace maven placeholder of project ` +
|
|
188
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
namespace = libraryNs.replace(/\./g, "/");
|
|
193
|
-
|
|
194
|
-
const namespacePath = this.getNamespaceFromFsPath(fsNamespacePath);
|
|
195
|
-
if (namespacePath !== namespace) {
|
|
196
|
-
throw new Error(
|
|
197
|
-
`Detected namespace "${namespace}" does not match detected directory ` +
|
|
198
|
-
`structure "${namespacePath}" for project ${this._project.metadata.name}`);
|
|
199
|
-
}
|
|
200
|
-
} else {
|
|
201
|
-
try {
|
|
202
|
-
const fsPath = await this.getLibraryJsPath();
|
|
203
|
-
namespace = this.getNamespaceFromFsPath(path.dirname(fsPath));
|
|
204
|
-
if (!namespace || namespace === "/") {
|
|
205
|
-
throw new Error(`Found library.js file in root directory. ` +
|
|
206
|
-
`Expected it to be in namespace directory.`);
|
|
207
|
-
}
|
|
208
|
-
log.verbose(`Deriving namespace for project ${this._project.metadata.name} from ` +
|
|
209
|
-
`path of library.js file`);
|
|
210
|
-
} catch (err) {
|
|
211
|
-
log.verbose(`Namespace resolution from library.js file path failed for project ` +
|
|
212
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (!namespace) {
|
|
217
|
-
throw new Error(`Failed to detect namespace or namespace is empty for ` +
|
|
218
|
-
`project ${this._project.metadata.name}. Check verbose log for details.`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
log.verbose(`Namespace of project ${this._project.metadata.name} is ${namespace}`);
|
|
222
|
-
return namespace;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async getNamespaceFromManifest() {
|
|
226
|
-
try {
|
|
227
|
-
const {content: manifest, fsPath} = await this.getManifest();
|
|
228
|
-
// check for a proper sap.app/id in manifest.json to determine namespace
|
|
229
|
-
if (manifest["sap.app"] && manifest["sap.app"].id) {
|
|
230
|
-
const namespace = manifest["sap.app"].id;
|
|
231
|
-
log.verbose(`Found namespace ${namespace} in manifest.json of project ${this._project.metadata.name} ` +
|
|
232
|
-
`at ${fsPath}`);
|
|
233
|
-
return {
|
|
234
|
-
namespace,
|
|
235
|
-
fsPath
|
|
236
|
-
};
|
|
237
|
-
} else {
|
|
238
|
-
log.verbose(
|
|
239
|
-
`No sap.app/id configuration found in manifest.json of project ${this._project.metadata.name} ` +
|
|
240
|
-
`at ${fsPath}`);
|
|
241
|
-
}
|
|
242
|
-
} catch (err) {
|
|
243
|
-
log.verbose(`Namespace resolution from manifest.json failed for project ` +
|
|
244
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
245
|
-
}
|
|
246
|
-
return {};
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async getNamespaceFromDotLibrary() {
|
|
250
|
-
try {
|
|
251
|
-
const {content: dotLibrary, fsPath} = await this.getDotLibrary();
|
|
252
|
-
if (dotLibrary && dotLibrary.library && dotLibrary.library.name) {
|
|
253
|
-
const namespace = dotLibrary.library.name._;
|
|
254
|
-
log.verbose(`Found namespace ${namespace} in .library file of project ${this._project.metadata.name} ` +
|
|
255
|
-
`at ${fsPath}`);
|
|
256
|
-
return {
|
|
257
|
-
namespace,
|
|
258
|
-
fsPath
|
|
259
|
-
};
|
|
260
|
-
} else {
|
|
261
|
-
throw new Error(
|
|
262
|
-
`No library name found in .library of project ${this._project.metadata.name} ` +
|
|
263
|
-
`at ${fsPath}`);
|
|
264
|
-
}
|
|
265
|
-
} catch (err) {
|
|
266
|
-
log.verbose(`Namespace resolution from .library failed for project ` +
|
|
267
|
-
`${this._project.metadata.name}: ${err.message}`);
|
|
268
|
-
}
|
|
269
|
-
return {};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
getNamespaceFromFsPath(fsPath) {
|
|
273
|
-
// Regex to ensure trailing slash
|
|
274
|
-
const rOptionalTrailingSlash = /\/?$/;
|
|
275
|
-
|
|
276
|
-
// Transform path to POSIX and ensure a trailing slash for correct comparison
|
|
277
|
-
const posixFsPath = fsPath.replace(/\\/g, "/").replace(rOptionalTrailingSlash, "/");
|
|
278
|
-
const posixBasePath = this.getSourceBasePath(true).replace(rOptionalTrailingSlash, "/");
|
|
279
|
-
|
|
280
|
-
if (posixBasePath === posixFsPath) {
|
|
281
|
-
// The given file system path does not contain a namespace path since it is equal to the source base path
|
|
282
|
-
// Therefore return an empty namespace
|
|
283
|
-
return "";
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (!posixFsPath.startsWith(posixBasePath)) {
|
|
287
|
-
throw new Error(`Given file system path ${posixFsPath} is not based on source base ` +
|
|
288
|
-
`path ${posixBasePath}.`);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Remove base path from fsPath to get the namespace
|
|
292
|
-
let namespacePath = posixFsPath.replace(posixBasePath, "");
|
|
293
|
-
|
|
294
|
-
// Remove any leading and trailing slash
|
|
295
|
-
namespacePath = namespacePath.replace(/(?:^\/)|(?:\/$)/g, "");
|
|
296
|
-
return namespacePath;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Determines library copyright from given project configuration with fallback to .library.
|
|
301
|
-
*
|
|
302
|
-
* @returns {string} Copyright of the project
|
|
303
|
-
* @throws {Error} if copyright can not be determined
|
|
304
|
-
*/
|
|
305
|
-
async getCopyright() {
|
|
306
|
-
if (this._project.metadata.copyright) {
|
|
307
|
-
return this._project.metadata.copyright;
|
|
308
|
-
}
|
|
309
|
-
// If no copyright replacement was provided by ui5.yaml,
|
|
310
|
-
// check if the .library file has a valid copyright replacement
|
|
311
|
-
const {content: dotLibrary} = await this.getDotLibrary();
|
|
312
|
-
if (dotLibrary && dotLibrary.library && dotLibrary.library.copyright) {
|
|
313
|
-
log.verbose(`Using copyright from .library for project ${this._project.metadata.name}...`);
|
|
314
|
-
return dotLibrary.library.copyright._;
|
|
315
|
-
} else {
|
|
316
|
-
throw new Error(`No copyright configuration found in .library ` +
|
|
317
|
-
`of project ${this._project.metadata.name}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
async getPreloadExcludesFromDotLibrary() {
|
|
322
|
-
const {content: dotLibrary, fsPath} = await this.getDotLibrary();
|
|
323
|
-
if (dotLibrary && dotLibrary.library && dotLibrary.library.appData &&
|
|
324
|
-
dotLibrary.library.appData.packaging &&
|
|
325
|
-
dotLibrary.library.appData.packaging["all-in-one"] &&
|
|
326
|
-
dotLibrary.library.appData.packaging["all-in-one"].exclude
|
|
327
|
-
) {
|
|
328
|
-
let excludes = dotLibrary.library.appData.packaging["all-in-one"].exclude;
|
|
329
|
-
if (!Array.isArray(excludes)) {
|
|
330
|
-
excludes = [excludes];
|
|
331
|
-
}
|
|
332
|
-
log.verbose(`Found ${excludes.length} preload excludes in .library file of ` +
|
|
333
|
-
`project ${this._project.metadata.name} at ${fsPath}`);
|
|
334
|
-
return excludes.map((exclude) => {
|
|
335
|
-
return exclude.$.name;
|
|
336
|
-
});
|
|
337
|
-
} else {
|
|
338
|
-
log.verbose(
|
|
339
|
-
`No preload excludes found in .library of project ${this._project.metadata.name} ` +
|
|
340
|
-
`at ${fsPath}`);
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Reads the projects manifest.json
|
|
347
|
-
*
|
|
348
|
-
* @returns {Promise<object>} resolves with an object containing the <code>content</code> (as JSON) and
|
|
349
|
-
* <code>fsPath</code> (as string) of the manifest.json file
|
|
350
|
-
*/
|
|
351
|
-
async getManifest() {
|
|
352
|
-
if (this._pManifest) {
|
|
353
|
-
return this._pManifest;
|
|
354
|
-
}
|
|
355
|
-
const basePath = this.getSourceBasePath();
|
|
356
|
-
return this._pManifest = glob("**/manifest.json", {
|
|
357
|
-
cwd: basePath,
|
|
358
|
-
followSymbolicLinks: false
|
|
359
|
-
}).then(async (manifestResources) => {
|
|
360
|
-
if (!manifestResources.length) {
|
|
361
|
-
throw new Error(`Could not find manifest.json file for project ${this._project.metadata.name}`);
|
|
362
|
-
}
|
|
363
|
-
if (manifestResources.length > 1) {
|
|
364
|
-
throw new Error(`Found multiple (${manifestResources.length}) manifest.json files ` +
|
|
365
|
-
`for project ${this._project.metadata.name}`);
|
|
366
|
-
}
|
|
367
|
-
const fsPath = path.join(basePath, manifestResources[0]);
|
|
368
|
-
try {
|
|
369
|
-
const content = await readFile(fsPath);
|
|
370
|
-
return {
|
|
371
|
-
content: JSON.parse(content),
|
|
372
|
-
fsPath
|
|
373
|
-
};
|
|
374
|
-
} catch (err) {
|
|
375
|
-
throw new Error(
|
|
376
|
-
`Failed to read manifest.json for project ${this._project.metadata.name}: ${err.message}`);
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Reads the .library file
|
|
383
|
-
*
|
|
384
|
-
* @returns {Promise<object>} resolves with an object containing the <code>content</code> (as JSON) and
|
|
385
|
-
* <code>fsPath</code> (as string) of the .library file
|
|
386
|
-
*/
|
|
387
|
-
async getDotLibrary() {
|
|
388
|
-
if (this._pDotLibrary) {
|
|
389
|
-
return this._pDotLibrary;
|
|
390
|
-
}
|
|
391
|
-
const basePath = this.getSourceBasePath();
|
|
392
|
-
return this._pDotLibrary = glob("**/.library", {
|
|
393
|
-
cwd: basePath,
|
|
394
|
-
followSymbolicLinks: false
|
|
395
|
-
}).then(async (dotLibraryResources) => {
|
|
396
|
-
if (!dotLibraryResources.length) {
|
|
397
|
-
throw new Error(`Could not find .library file for project ${this._project.metadata.name}`);
|
|
398
|
-
}
|
|
399
|
-
if (dotLibraryResources.length > 1) {
|
|
400
|
-
throw new Error(`Found multiple (${dotLibraryResources.length}) .library files ` +
|
|
401
|
-
`for project ${this._project.metadata.name}`);
|
|
402
|
-
}
|
|
403
|
-
const fsPath = path.join(basePath, dotLibraryResources[0]);
|
|
404
|
-
const content = await readFile(fsPath);
|
|
405
|
-
const xml2js = require("xml2js");
|
|
406
|
-
const parser = new xml2js.Parser({
|
|
407
|
-
explicitArray: false,
|
|
408
|
-
explicitCharkey: true
|
|
409
|
-
});
|
|
410
|
-
const readXML = promisify(parser.parseString);
|
|
411
|
-
const contentJson = await readXML(content);
|
|
412
|
-
return {
|
|
413
|
-
content: contentJson,
|
|
414
|
-
fsPath
|
|
415
|
-
};
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* Determines the path of the library.js file
|
|
421
|
-
*
|
|
422
|
-
* @returns {Promise<string>} resolves with an a string containing the file system path
|
|
423
|
-
* of the library.js file
|
|
424
|
-
*/
|
|
425
|
-
async getLibraryJsPath() {
|
|
426
|
-
if (this._pLibraryJs) {
|
|
427
|
-
return this._pLibraryJs;
|
|
428
|
-
}
|
|
429
|
-
const basePath = this.getSourceBasePath();
|
|
430
|
-
return this._pLibraryJs = glob("**/library.js", {
|
|
431
|
-
cwd: basePath,
|
|
432
|
-
followSymbolicLinks: false
|
|
433
|
-
}).then(async (libraryJsResources) => {
|
|
434
|
-
if (!libraryJsResources.length) {
|
|
435
|
-
throw new Error(`Could not find library.js file for project ${this._project.metadata.name}`);
|
|
436
|
-
}
|
|
437
|
-
if (libraryJsResources.length > 1) {
|
|
438
|
-
throw new Error(`Found multiple (${libraryJsResources.length}) library.js files ` +
|
|
439
|
-
`for project ${this._project.metadata.name}`);
|
|
440
|
-
}
|
|
441
|
-
const fsPath = path.join(basePath, libraryJsResources[0]);
|
|
442
|
-
|
|
443
|
-
// Content is not yet relevant, so don't read it
|
|
444
|
-
return fsPath;
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Validates the project
|
|
450
|
-
*
|
|
451
|
-
* @returns {Promise} resolves if successfully validated
|
|
452
|
-
* @throws {Error} if validation fails
|
|
453
|
-
*/
|
|
454
|
-
validate() {
|
|
455
|
-
const project = this._project;
|
|
456
|
-
return Promise.resolve().then(() => {
|
|
457
|
-
if (!project) {
|
|
458
|
-
throw new Error("Project is undefined");
|
|
459
|
-
} else if (!project.metadata || !project.metadata.name) {
|
|
460
|
-
throw new Error(`"metadata.name" configuration is missing for project ${project.id}`);
|
|
461
|
-
} else if (!project.type) {
|
|
462
|
-
throw new Error(`"type" configuration is missing for project ${project.id}`);
|
|
463
|
-
} else if (project.version === undefined) {
|
|
464
|
-
throw new Error(`"version" is missing for project ${project.id}`);
|
|
465
|
-
}
|
|
466
|
-
if (!project.resources) {
|
|
467
|
-
project.resources = {};
|
|
468
|
-
}
|
|
469
|
-
if (!project.resources.configuration) {
|
|
470
|
-
project.resources.configuration = {};
|
|
471
|
-
}
|
|
472
|
-
if (!project.resources.configuration.paths) {
|
|
473
|
-
project.resources.configuration.paths = {};
|
|
474
|
-
}
|
|
475
|
-
if (!project.resources.configuration.paths.src) {
|
|
476
|
-
project.resources.configuration.paths.src = "src";
|
|
477
|
-
}
|
|
478
|
-
if (!project.resources.configuration.paths.test) {
|
|
479
|
-
project.resources.configuration.paths.test = "test";
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (!project.resources.configuration.propertiesFileSourceEncoding) {
|
|
483
|
-
if (["0.1", "1.0", "1.1"].includes(project.specVersion)) {
|
|
484
|
-
// default encoding to "ISO-8859-1" for old specVersions
|
|
485
|
-
project.resources.configuration.propertiesFileSourceEncoding = "ISO-8859-1";
|
|
486
|
-
} else {
|
|
487
|
-
// default encoding to "UTF-8" for all projects starting with specVersion 2.0
|
|
488
|
-
project.resources.configuration.propertiesFileSourceEncoding = "UTF-8";
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
if (!["ISO-8859-1", "UTF-8"].includes(project.resources.configuration.propertiesFileSourceEncoding)) {
|
|
492
|
-
throw new Error(`Invalid properties file encoding specified for project ${project.id}. ` +
|
|
493
|
-
`Encoding provided: ${project.resources.configuration.propertiesFileSourceEncoding}. ` +
|
|
494
|
-
`Must be either "ISO-8859-1" or "UTF-8".`);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
const absoluteSrcPath = path.join(project.path, project.resources.configuration.paths.src);
|
|
498
|
-
const absoluteTestPath = path.join(project.path, project.resources.configuration.paths.test);
|
|
499
|
-
return Promise.all([
|
|
500
|
-
this.dirExists(absoluteSrcPath).then(function(bExists) {
|
|
501
|
-
if (!bExists) {
|
|
502
|
-
throw new Error(`Could not find source directory of project ${project.id}: ` +
|
|
503
|
-
`${absoluteSrcPath}`);
|
|
504
|
-
}
|
|
505
|
-
}),
|
|
506
|
-
this.dirExists(absoluteTestPath).then(function(bExists) {
|
|
507
|
-
if (!bExists) {
|
|
508
|
-
log.verbose(`Could not find (optional) test directory of project ${project.id}: ` +
|
|
509
|
-
`${absoluteTestPath}`);
|
|
510
|
-
// Current signal to following consumers that "test" is not available is null
|
|
511
|
-
project.resources.configuration.paths.test = null;
|
|
512
|
-
}
|
|
513
|
-
})
|
|
514
|
-
]);
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
module.exports = LibraryFormatter;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const LibraryFormatter = require("./LibraryFormatter");
|
|
2
|
-
const LibraryBuilder = require("./LibraryBuilder");
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
format: function(project) {
|
|
6
|
-
return new LibraryFormatter({project}).format();
|
|
7
|
-
},
|
|
8
|
-
build: function({resourceCollections, tasks, project, parentLogger, taskUtil}) {
|
|
9
|
-
return new LibraryBuilder({resourceCollections, project, parentLogger, taskUtil}).build(tasks);
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
// Export type classes for extensibility
|
|
13
|
-
Builder: LibraryBuilder,
|
|
14
|
-
Formatter: LibraryFormatter
|
|
15
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
const log = require("@ui5/logger").getLogger("types:module:ModuleFormatter");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const AbstractFormatter = require("../AbstractFormatter");
|
|
4
|
-
|
|
5
|
-
class ModuleFormatter extends AbstractFormatter {
|
|
6
|
-
format() {
|
|
7
|
-
return this.validate().then(() => {
|
|
8
|
-
const project = this._project;
|
|
9
|
-
log.verbose("Formatting project %s...", project.metadata.name);
|
|
10
|
-
project.resources.pathMappings = project.resources.configuration.paths;
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
validate() {
|
|
15
|
-
const project = this._project;
|
|
16
|
-
return Promise.resolve().then(() => {
|
|
17
|
-
if (!project) {
|
|
18
|
-
throw new Error("Project is undefined");
|
|
19
|
-
} else if (!project.metadata || !project.metadata.name) {
|
|
20
|
-
throw new Error(`"metadata.name" configuration is missing for project ${project.id}`);
|
|
21
|
-
} else if (!project.type) {
|
|
22
|
-
throw new Error(`"type" configuration is missing for project ${project.id}`);
|
|
23
|
-
} else if (project.version === undefined) {
|
|
24
|
-
throw new Error(`"version" is missing for project ${project.id}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!project.resources) {
|
|
28
|
-
project.resources = {};
|
|
29
|
-
}
|
|
30
|
-
if (!project.resources.configuration) {
|
|
31
|
-
project.resources.configuration = {};
|
|
32
|
-
}
|
|
33
|
-
if (!project.resources.configuration.paths) {
|
|
34
|
-
project.resources.configuration.paths = {
|
|
35
|
-
"/": ""
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const paths = project.resources.configuration.paths;
|
|
39
|
-
const dirChecks =[];
|
|
40
|
-
for (const virPath of Object.keys(paths)) {
|
|
41
|
-
const absolutePath = path.join(project.path, paths[virPath]);
|
|
42
|
-
dirChecks.push(this.dirExists(absolutePath).then((bExists) => {
|
|
43
|
-
if (!bExists) {
|
|
44
|
-
throw new Error(`Could not find "${virPath}" directory of project ${project.id} at ` +
|
|
45
|
-
`${absolutePath}`);
|
|
46
|
-
}
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
return Promise.all(dirChecks);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
module.exports = ModuleFormatter;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const ModuleFormatter = require("./ModuleFormatter");
|
|
2
|
-
const ModuleBuilder = require("./ModuleBuilder");
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
format: function(project) {
|
|
6
|
-
return new ModuleFormatter({project}).format();
|
|
7
|
-
},
|
|
8
|
-
build: function({resourceCollections, tasks, project, parentLogger, taskUtil}) {
|
|
9
|
-
return new ModuleBuilder({resourceCollections, project, parentLogger, taskUtil}).build(tasks);
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
// Export type classes for extensibility
|
|
13
|
-
Builder: ModuleBuilder,
|
|
14
|
-
Formatter: ModuleFormatter
|
|
15
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const AbstractBuilder = require("../AbstractBuilder");
|
|
2
|
-
const {getTask} = require("../../tasks/taskRepository");
|
|
3
|
-
|
|
4
|
-
class ThemeLibraryBuilder extends AbstractBuilder {
|
|
5
|
-
addStandardTasks({resourceCollections, project, log, taskUtil}) {
|
|
6
|
-
this.addTask("replaceCopyright", async () => {
|
|
7
|
-
return getTask("replaceCopyright").task({
|
|
8
|
-
workspace: resourceCollections.workspace,
|
|
9
|
-
options: {
|
|
10
|
-
copyright: project.metadata.copyright,
|
|
11
|
-
pattern: "/resources/**/*.{less,theme}"
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
this.addTask("replaceVersion", async () => {
|
|
17
|
-
return getTask("replaceVersion").task({
|
|
18
|
-
workspace: resourceCollections.workspace,
|
|
19
|
-
options: {
|
|
20
|
-
version: project.version,
|
|
21
|
-
pattern: "/resources/**/*.{less,theme}"
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
this.addTask("buildThemes", async () => {
|
|
27
|
-
return getTask("buildThemes").task({
|
|
28
|
-
workspace: resourceCollections.workspace,
|
|
29
|
-
dependencies: resourceCollections.dependencies,
|
|
30
|
-
options: {
|
|
31
|
-
projectName: project.metadata.name,
|
|
32
|
-
librariesPattern: !taskUtil.isRootProject() ? "/resources/**/(*.library|library.js)" : undefined,
|
|
33
|
-
themesPattern: !taskUtil.isRootProject() ? "/resources/sap/ui/core/themes/*" : undefined,
|
|
34
|
-
inputPattern: "/resources/**/themes/*/library.source.less",
|
|
35
|
-
cssVariables: taskUtil.getBuildOption("cssVariables")
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
this.addTask("generateThemeDesignerResources", async () => {
|
|
41
|
-
return getTask("generateThemeDesignerResources").task({
|
|
42
|
-
workspace: resourceCollections.workspace,
|
|
43
|
-
dependencies: resourceCollections.dependencies,
|
|
44
|
-
options: {
|
|
45
|
-
projectName: project.metadata.name,
|
|
46
|
-
version: project.version
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
this.addTask("generateResourcesJson", () => {
|
|
52
|
-
return getTask("generateResourcesJson").task({
|
|
53
|
-
workspace: resourceCollections.workspace,
|
|
54
|
-
dependencies: resourceCollections.dependencies,
|
|
55
|
-
taskUtil,
|
|
56
|
-
options: {
|
|
57
|
-
projectName: project.metadata.name
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
module.exports = ThemeLibraryBuilder;
|