@ui5/builder 3.0.0-alpha.6 → 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.
Files changed (42) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/index.js +0 -39
  3. package/lib/lbt/bundle/Builder.js +18 -48
  4. package/lib/lbt/resources/LocatorResource.js +1 -1
  5. package/lib/lbt/utils/escapePropertiesFile.js +3 -6
  6. package/lib/processors/bundlers/moduleBundler.js +2 -3
  7. package/lib/processors/jsdoc/lib/transformApiJson.js +13 -4
  8. package/lib/processors/manifestCreator.js +8 -45
  9. package/lib/tasks/TaskUtil.js +82 -17
  10. package/lib/tasks/bundlers/generateComponentPreload.js +14 -14
  11. package/lib/tasks/bundlers/generateFlexChangesBundle.js +6 -2
  12. package/lib/tasks/bundlers/generateLibraryPreload.js +84 -91
  13. package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
  14. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +7 -2
  15. package/lib/tasks/bundlers/utils/createModuleNameMapping.js +3 -2
  16. package/lib/tasks/generateCachebusterInfo.js +7 -3
  17. package/lib/tasks/generateLibraryManifest.js +5 -1
  18. package/lib/tasks/generateResourcesJson.js +1 -1
  19. package/lib/tasks/generateThemeDesignerResources.js +8 -2
  20. package/lib/tasks/generateVersionInfo.js +5 -5
  21. package/lib/tasks/taskRepository.js +1 -13
  22. package/lib/tasks/transformBootstrapHtml.js +6 -1
  23. package/package.json +4 -5
  24. package/lib/builder/BuildContext.js +0 -60
  25. package/lib/builder/ProjectBuildContext.js +0 -61
  26. package/lib/builder/builder.js +0 -425
  27. package/lib/types/AbstractBuilder.js +0 -270
  28. package/lib/types/AbstractFormatter.js +0 -66
  29. package/lib/types/AbstractUi5Formatter.js +0 -95
  30. package/lib/types/application/ApplicationBuilder.js +0 -211
  31. package/lib/types/application/ApplicationFormatter.js +0 -227
  32. package/lib/types/application/applicationType.js +0 -15
  33. package/lib/types/library/LibraryBuilder.js +0 -231
  34. package/lib/types/library/LibraryFormatter.js +0 -519
  35. package/lib/types/library/libraryType.js +0 -15
  36. package/lib/types/module/ModuleBuilder.js +0 -7
  37. package/lib/types/module/ModuleFormatter.js +0 -54
  38. package/lib/types/module/moduleType.js +0 -15
  39. package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -64
  40. package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
  41. package/lib/types/themeLibrary/themeLibraryType.js +0 -15
  42. package/lib/types/typeRepository.js +0 -46
@@ -1,61 +0,0 @@
1
- const ResourceTagCollection = require("@ui5/fs").ResourceTagCollection;
2
-
3
- // Note: When adding standard tags, always update the public documentation in TaskUtil
4
- // (Type "module:@ui5/builder.tasks.TaskUtil~StandardBuildTags")
5
- const STANDARD_TAGS = {
6
- OmitFromBuildResult: "ui5:OmitFromBuildResult",
7
- IsBundle: "ui5:IsBundle",
8
- };
9
-
10
- /**
11
- * Build context of a single project. Always part of an overall
12
- * [Build Context]{@link module:@ui5/builder.builder.BuildContext}
13
- *
14
- * @private
15
- * @memberof module:@ui5/builder.builder
16
- */
17
- class ProjectBuildContext {
18
- constructor({buildContext, globalTags, project, resources}) {
19
- if (!buildContext || !globalTags || !project || !resources) {
20
- throw new Error(`One or more mandatory parameters are missing`);
21
- }
22
- this._buildContext = buildContext;
23
- this._project = project;
24
- // this.resources = resources;
25
- this.queues = {
26
- cleanup: []
27
- };
28
-
29
- this.STANDARD_TAGS = Object.assign({}, STANDARD_TAGS, globalTags);
30
- Object.freeze(this.STANDARD_TAGS);
31
-
32
- this._resourceTagCollection = new ResourceTagCollection({
33
- allowedTags: Object.values(this.STANDARD_TAGS),
34
- superCollection: this._buildContext.getResourceTagCollection()
35
- });
36
- }
37
-
38
- isRootProject() {
39
- return this._project === this._buildContext.getRootProject();
40
- }
41
-
42
- getOption(key) {
43
- return this._buildContext.getOption(key);
44
- }
45
-
46
- registerCleanupTask(callback) {
47
- this.queues.cleanup.push(callback);
48
- }
49
-
50
- async executeCleanupTasks() {
51
- await Promise.all(this.queues.cleanup.map((callback) => {
52
- return callback();
53
- }));
54
- }
55
-
56
- getResourceTagCollection() {
57
- return this._resourceTagCollection;
58
- }
59
- }
60
-
61
- module.exports = ProjectBuildContext;
@@ -1,425 +0,0 @@
1
- const {promisify} = require("util");
2
- const rimraf = promisify(require("rimraf"));
3
- const log = require("@ui5/logger").getGroupLogger("builder:builder");
4
- const resourceFactory = require("@ui5/fs").resourceFactory;
5
- const MemAdapter = require("@ui5/fs").adapters.Memory;
6
- const typeRepository = require("../types/typeRepository");
7
- const taskRepository = require("../tasks/taskRepository");
8
- const BuildContext = require("./BuildContext");
9
-
10
-
11
- // Set of tasks for development
12
- const devTasks = [
13
- "replaceCopyright",
14
- "replaceVersion",
15
- "replaceBuildtime",
16
- "buildThemes"
17
- ];
18
-
19
- /**
20
- * Calculates the elapsed build time and returns a prettified output
21
- *
22
- * @private
23
- * @param {Array} startTime Array provided by <code>process.hrtime()</code>
24
- * @returns {string} Difference between now and the provided time array as formatted string
25
- */
26
- function getElapsedTime(startTime) {
27
- const prettyHrtime = require("pretty-hrtime");
28
- const timeDiff = process.hrtime(startTime);
29
- return prettyHrtime(timeDiff);
30
- }
31
-
32
- /**
33
- * Creates the list of tasks to be executed by the build process
34
- *
35
- * Sets specific tasks to be disabled by default, these tasks need to be included explicitly.
36
- * Based on the selected build mode (dev|selfContained|preload), different tasks are enabled.
37
- * Tasks can be enabled or disabled. The wildcard <code>*</code> is also supported and affects all tasks.
38
- *
39
- * @private
40
- * @param {object} parameters
41
- * @param {boolean} parameters.dev Sets development mode, which only runs essential tasks
42
- * @param {boolean} parameters.selfContained
43
- * True if a the build should be self-contained or false for prelead build bundles
44
- * @param {boolean} parameters.jsdoc True if a JSDoc build should be executed
45
- * @param {Array} parameters.includedTasks Task list to be included from build
46
- * @param {Array} parameters.excludedTasks Task list to be excluded from build
47
- * @returns {Array} Return a task list for the builder
48
- */
49
- function composeTaskList({dev, selfContained, jsdoc, includedTasks, excludedTasks}) {
50
- const definedTasks = taskRepository.getAllTaskNames();
51
- let selectedTasks = definedTasks.reduce((list, key) => {
52
- list[key] = true;
53
- return list;
54
- }, {});
55
-
56
- // Exclude non default tasks
57
- selectedTasks.generateManifestBundle = false;
58
- selectedTasks.generateStandaloneAppBundle = false;
59
- selectedTasks.transformBootstrapHtml = false;
60
- selectedTasks.generateJsdoc = false;
61
- selectedTasks.executeJsdocSdkTransformation = false;
62
- selectedTasks.generateCachebusterInfo = false;
63
- selectedTasks.generateApiIndex = false;
64
- selectedTasks.generateThemeDesignerResources = false;
65
-
66
- // Disable generateResourcesJson due to performance.
67
- // When executed it analyzes each module's AST and therefore
68
- // takes up much time (~10% more)
69
- selectedTasks.generateResourcesJson = false;
70
-
71
- if (selfContained) {
72
- // No preloads, bundle only
73
- selectedTasks.generateComponentPreload = false;
74
- selectedTasks.generateStandaloneAppBundle = true;
75
- selectedTasks.transformBootstrapHtml = true;
76
- selectedTasks.generateLibraryPreload = false;
77
- }
78
-
79
- // TODO 3.0: exclude generateVersionInfo if not --all is used
80
-
81
- if (jsdoc) {
82
- // Include JSDoc tasks
83
- selectedTasks.generateJsdoc = true;
84
- selectedTasks.executeJsdocSdkTransformation = true;
85
- selectedTasks.generateApiIndex = true;
86
-
87
- // Include theme build as required for SDK
88
- selectedTasks.buildThemes = true;
89
-
90
- // Exclude all tasks not relevant to JSDoc generation
91
- selectedTasks.replaceCopyright = false;
92
- selectedTasks.replaceVersion = false;
93
- selectedTasks.replaceBuildtime = false;
94
- selectedTasks.generateComponentPreload = false;
95
- selectedTasks.generateLibraryPreload = false;
96
- selectedTasks.generateLibraryManifest = false;
97
- selectedTasks.minify = false;
98
- selectedTasks.generateFlexChangesBundle = false;
99
- selectedTasks.generateManifestBundle = false;
100
- }
101
-
102
- // Only run essential tasks in development mode, it is not desired to run time consuming tasks during development.
103
- if (dev) {
104
- // Overwrite all other tasks with noop promise
105
- Object.keys(selectedTasks).forEach((key) => {
106
- if (devTasks.indexOf(key) === -1) {
107
- selectedTasks[key] = false;
108
- }
109
- });
110
- }
111
-
112
- // Exclude tasks
113
- for (let i = 0; i < excludedTasks.length; i++) {
114
- const taskName = excludedTasks[i];
115
- if (taskName === "*") {
116
- Object.keys(selectedTasks).forEach((sKey) => {
117
- selectedTasks[sKey] = false;
118
- });
119
- break;
120
- }
121
- if (selectedTasks[taskName] === true) {
122
- selectedTasks[taskName] = false;
123
- } else if (typeof selectedTasks[taskName] === "undefined") {
124
- log.warn(`Unable to exclude task '${taskName}': Task is unknown`);
125
- }
126
- }
127
-
128
- // Include tasks
129
- for (let i = 0; i < includedTasks.length; i++) {
130
- const taskName = includedTasks[i];
131
- if (taskName === "*") {
132
- Object.keys(selectedTasks).forEach((sKey) => {
133
- selectedTasks[sKey] = true;
134
- });
135
- break;
136
- }
137
- if (selectedTasks[taskName] === false) {
138
- selectedTasks[taskName] = true;
139
- } else if (typeof selectedTasks[taskName] === "undefined") {
140
- log.warn(`Unable to include task '${taskName}': Task is unknown`);
141
- }
142
- }
143
-
144
- // Filter only for tasks that will be executed
145
- selectedTasks = Object.keys(selectedTasks).filter((task) => selectedTasks[task]);
146
-
147
- return selectedTasks;
148
- }
149
-
150
- async function executeCleanupTasks(buildContext) {
151
- log.info("Executing cleanup tasks...");
152
- await buildContext.executeCleanupTasks();
153
- }
154
-
155
- function registerCleanupSigHooks(buildContext) {
156
- function createListener(exitCode) {
157
- return function() {
158
- // Asynchronously cleanup resources, then exit
159
- executeCleanupTasks(buildContext).then(() => {
160
- process.exit(exitCode);
161
- });
162
- };
163
- }
164
-
165
- const processSignals = {
166
- "SIGHUP": createListener(128 + 1),
167
- "SIGINT": createListener(128 + 2),
168
- "SIGTERM": createListener(128 + 15),
169
- "SIGBREAK": createListener(128 + 21)
170
- };
171
-
172
- for (const signal of Object.keys(processSignals)) {
173
- process.on(signal, processSignals[signal]);
174
- }
175
-
176
- // == TO BE DISCUSSED: Also cleanup for unhandled rejections and exceptions?
177
- // Add additional events like signals since they are registered on the process
178
- // event emitter in a similar fashion
179
- // processSignals["unhandledRejection"] = createListener(1);
180
- // process.once("unhandledRejection", processSignals["unhandledRejection"]);
181
- // processSignals["uncaughtException"] = function(err, origin) {
182
- // const fs = require("fs");
183
- // fs.writeSync(
184
- // process.stderr.fd,
185
- // `Caught exception: ${err}\n` +
186
- // `Exception origin: ${origin}`
187
- // );
188
- // createListener(1)();
189
- // };
190
- // process.once("uncaughtException", processSignals["uncaughtException"]);
191
-
192
- return processSignals;
193
- }
194
-
195
- function deregisterCleanupSigHooks(signals) {
196
- for (const signal of Object.keys(signals)) {
197
- process.removeListener(signal, signals[signal]);
198
- }
199
- }
200
-
201
- /**
202
- * Builder
203
- *
204
- * @public
205
- * @namespace
206
- * @alias module:@ui5/builder.builder
207
- */
208
- module.exports = {
209
- /**
210
- * Configures the project build and starts it.
211
- *
212
- * @public
213
- * @param {object} parameters Parameters
214
- * @param {object} parameters.tree Project tree as generated by the
215
- * [@ui5/project.normalizer]{@link module:@ui5/project.normalizer}
216
- * @param {string} parameters.destPath Target path
217
- * @param {boolean} [parameters.cleanDest=false] Decides whether project should clean the target path before build
218
- * @param {boolean} [parameters.buildDependencies=false] Decides whether project dependencies are built as well
219
- * @param {Array.<string|RegExp>} [parameters.includedDependencies=[]]
220
- * List of build dependencies to be included if buildDependencies is true
221
- * @param {Array.<string|RegExp>} [parameters.excludedDependencies=[]]
222
- * List of build dependencies to be excluded if buildDependencies is true.
223
- * If the wildcard '*' is provided, only the included dependencies will be built.
224
- * @param {boolean} [parameters.dev=false]
225
- * Decides whether a development build should be activated (skips non-essential and time-intensive tasks)
226
- * @param {boolean} [parameters.selfContained=false] Flag to activate self contained build
227
- * @param {boolean} [parameters.cssVariables=false] Flag to activate CSS variables generation
228
- * @param {boolean} [parameters.jsdoc=false] Flag to activate JSDoc build
229
- * @param {Array.<string>} [parameters.includedTasks=[]] List of tasks to be included
230
- * @param {Array.<string>} [parameters.excludedTasks=[]] List of tasks to be excluded.
231
- * If the wildcard '*' is provided, only the included tasks will be executed.
232
- * @param {Array.<string>} [parameters.devExcludeProject=[]] List of projects to be excluded from development build
233
- * @returns {Promise} Promise resolving to <code>undefined</code> once build has finished
234
- */
235
- async build({
236
- tree, destPath, cleanDest = false,
237
- buildDependencies = false, includedDependencies = [], excludedDependencies = [],
238
- dev = false, selfContained = false, cssVariables = false, jsdoc = false,
239
- includedTasks = [], excludedTasks = [], devExcludeProject = []
240
- }) {
241
- const startTime = process.hrtime();
242
- log.info(`Building project ${tree.metadata.name}` + (buildDependencies ? "" : " not") +
243
- " including dependencies..." + (dev ? " [dev mode]" : ""));
244
- log.verbose(`Building to ${destPath}...`);
245
-
246
- const selectedTasks = composeTaskList({dev, selfContained, jsdoc, includedTasks, excludedTasks});
247
-
248
- const fsTarget = resourceFactory.createAdapter({
249
- fsBasePath: destPath,
250
- virBasePath: "/"
251
- });
252
-
253
- const buildContext = new BuildContext({
254
- rootProject: tree,
255
- options: {
256
- cssVariables: cssVariables
257
- }
258
- });
259
- const cleanupSigHooks = registerCleanupSigHooks(buildContext);
260
-
261
- const projects = {}; // Unique project index to prevent building the same project multiple times
262
- const projectWriters = {}; // Collection of memory adapters of already built libraries
263
- function projectFilter(project) {
264
- function projectMatchesAny(deps) {
265
- return deps.some((dep) => dep instanceof RegExp ?
266
- dep.test(project.metadata.name) : dep === project.metadata.name);
267
- }
268
-
269
- // if everything is included, this overrules exclude lists
270
- if (includedDependencies.includes("*")) return true;
271
- let test = !excludedDependencies.includes("*"); // exclude everything?
272
-
273
- if (test && projectMatchesAny(excludedDependencies)) {
274
- test = false;
275
- }
276
- if (!test && projectMatchesAny(includedDependencies)) {
277
- test = true;
278
- }
279
-
280
- return test;
281
- }
282
-
283
- const projectCountMarker = {};
284
- function projectCount(project, count = 0) {
285
- if (buildDependencies) {
286
- count = project.dependencies.filter(projectFilter).reduce((depCount, depProject) => {
287
- return projectCount(depProject, depCount);
288
- }, count);
289
- }
290
- if (!projectCountMarker[project.metadata.name]) {
291
- count++;
292
- projectCountMarker[project.metadata.name] = true;
293
- }
294
- return count;
295
- }
296
- const buildLogger = log.createTaskLogger("🛠 ", projectCount(tree));
297
-
298
- function buildProject(project) {
299
- const projectBasePath = `/resources/${project.metadata.namespace}`;
300
- let depPromise;
301
- let projectTasks = selectedTasks;
302
-
303
- // Build dependencies in sequence as it is far easier to detect issues and reduces
304
- // side effects or other issues such as too many open files
305
- if (buildDependencies) {
306
- depPromise = project.dependencies.filter(projectFilter).reduce(function(p, depProject) {
307
- return p.then(() => buildProject(depProject));
308
- }, Promise.resolve());
309
- } else {
310
- depPromise = Promise.resolve();
311
- }
312
-
313
- // Build the project after all dependencies have been built
314
- return depPromise.then(() => {
315
- if (projects[project.metadata.name]) {
316
- return Promise.resolve();
317
- } else {
318
- projects[project.metadata.name] = true;
319
- }
320
- buildLogger.startWork(`Building project ${project.metadata.name}`);
321
-
322
- const projectType = typeRepository.getType(project.type);
323
- const resourceCollections = resourceFactory.createCollectionsForTree(project, {
324
- virtualReaders: projectWriters,
325
- getVirtualBasePathPrefix: function({project, virBasePath}) {
326
- if (project.type === "application" && project.metadata.namespace) {
327
- return projectBasePath;
328
- }
329
- },
330
- getProjectExcludes: function(project) {
331
- if (project.builder && project.builder.resources) {
332
- return project.builder.resources.excludes;
333
- }
334
- }
335
- });
336
-
337
- const writer = new MemAdapter({
338
- virBasePath: "/"
339
- });
340
- // Store project writer as virtual reader for parent projects
341
- // so they can access the build results of this project
342
- projectWriters[project.metadata.name] = writer;
343
-
344
- // TODO: Add getter for writer of DuplexColection
345
- const workspace = resourceFactory.createWorkspace({
346
- virBasePath: "/",
347
- writer,
348
- reader: resourceCollections.source,
349
- name: project.metadata.name
350
- });
351
-
352
- const projectContext = buildContext.createProjectContext({
353
- project, // TODO 2.0: Add project facade object/instance here
354
- resources: {
355
- workspace,
356
- dependencies: resourceCollections.dependencies
357
- }
358
- });
359
-
360
- const TaskUtil = require("../tasks/TaskUtil");
361
- const taskUtil = new TaskUtil({
362
- projectBuildContext: projectContext
363
- });
364
-
365
- if (dev && devExcludeProject.indexOf(project.metadata.name) !== -1) {
366
- projectTasks = composeTaskList({dev: false, selfContained, includedTasks, excludedTasks});
367
- }
368
-
369
- return projectType.build({
370
- resourceCollections: {
371
- workspace,
372
- dependencies: resourceCollections.dependencies
373
- },
374
- tasks: projectTasks,
375
- project,
376
- parentLogger: log,
377
- taskUtil
378
- }).then(() => {
379
- log.verbose("Finished building project %s. Writing out files...", project.metadata.name);
380
- buildLogger.completeWork(1);
381
-
382
- return workspace.byGlob("/**/*").then((resources) => {
383
- const tagCollection = projectContext.getResourceTagCollection();
384
- return Promise.all(resources.map((resource) => {
385
- if (tagCollection.getTag(resource, projectContext.STANDARD_TAGS.OmitFromBuildResult)) {
386
- log.verbose(`Skipping write of resource tagged as "OmitFromBuildResult": ` +
387
- resource.getPath());
388
- return; // Skip target write for this resource
389
- }
390
- if (projectContext.isRootProject() && project.type === "application" &&
391
- project.metadata.namespace) {
392
- // Root-application projects only: Remove namespace prefix if given
393
- const resourcePath = resource.getPath();
394
- if (resourcePath.startsWith(projectBasePath)) {
395
- resource.setPath(resourcePath.replace(projectBasePath, ""));
396
- }
397
- }
398
- return fsTarget.write(resource);
399
- }));
400
- });
401
- });
402
- });
403
- }
404
-
405
- try {
406
- if (cleanDest) {
407
- await rimraf(destPath);
408
- }
409
- await buildProject(tree);
410
- log.info(`Build succeeded in ${getElapsedTime(startTime)}`);
411
- } catch (err) {
412
- log.error(`Build failed in ${getElapsedTime(startTime)}`);
413
- throw err;
414
- } finally {
415
- deregisterCleanupSigHooks(cleanupSigHooks);
416
- await executeCleanupTasks(buildContext);
417
- }
418
- }
419
- };
420
-
421
- // Export local function for testing only
422
- /* istanbul ignore else */
423
- if (process.env.NODE_ENV === "test") {
424
- module.exports._composeTaskList = composeTaskList;
425
- }