@genexus/mercury 0.19.2 → 0.21.0
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/dist/assets/MERCURY_ASSETS.d.ts +28 -0
- package/dist/assets/MERCURY_ASSETS.js +1 -1
- package/dist/assets/MERCURY_ASSETS.ts +23130 -23102
- package/dist/assets/icons/patterns-default-associated/dark/default-associated-modified.svg +16 -0
- package/dist/assets/icons/patterns-default-associated/dark/default-associated-synchronized.svg +16 -0
- package/dist/assets/icons/patterns-default-associated/light/default-associated-modified.svg +16 -0
- package/dist/assets/icons/patterns-default-associated/light/default-associated-synchronized.svg +16 -0
- package/dist/bundles/css/all.css +1 -1
- package/dist/bundles/css/base/base-globant.css +1 -1
- package/dist/bundles/css/base/base.css +1 -1
- package/dist/bundles/css/base/icons.css +1 -1
- package/dist/bundles/css/components/accordion.css +1 -1
- package/dist/bundles/css/components/button.css +1 -1
- package/dist/bundles/css/components/chat.css +1 -1
- package/dist/bundles/css/components/code.css +1 -1
- package/dist/bundles/css/components/combo-box.css +1 -1
- package/dist/bundles/css/components/dialog.css +1 -1
- package/dist/bundles/css/components/dropdown.css +1 -1
- package/dist/bundles/css/components/edit.css +1 -1
- package/dist/bundles/css/components/flexible-layout.css +1 -1
- package/dist/bundles/css/components/icon.css +1 -1
- package/dist/bundles/css/components/list-box.css +1 -1
- package/dist/bundles/css/components/markdown-viewer.css +1 -1
- package/dist/bundles/css/components/navigation-list.css +1 -1
- package/dist/bundles/css/components/pills.css +1 -1
- package/dist/bundles/css/components/segmented-control.css +1 -1
- package/dist/bundles/css/components/slider.css +1 -1
- package/dist/bundles/css/components/switch.css +1 -1
- package/dist/bundles/css/components/tab.css +1 -1
- package/dist/bundles/css/components/tabular-grid.css +1 -1
- package/dist/bundles/css/components/tooltip.css +1 -1
- package/dist/bundles/css/utils/form--full.css +1 -1
- package/dist/bundles/css/utils/form.css +1 -1
- package/dist/bundles/css/utils/spacing.css +1 -1
- package/dist/cli/bundle.js +185 -17
- package/dist/cli/internal/constants.d.ts +3 -12
- package/dist/cli/internal/constants.js +4 -13
- package/dist/cli/internal/create-bundles-with-custom-paths.d.ts +10 -2
- package/dist/cli/internal/create-bundles-with-custom-paths.js +102 -55
- package/dist/cli/internal/file-management.d.ts +3 -2
- package/dist/cli/internal/file-management.js +45 -12
- package/dist/cli/internal/print-utils.d.ts +6 -6
- package/dist/cli/internal/print-utils.js +14 -12
- package/dist/cli/internal/transpile-bundle-and-create-mappings.d.ts +2 -3
- package/dist/cli/internal/transpile-bundle-and-create-mappings.js +37 -66
- package/dist/cli/internal/types.d.ts +0 -1
- package/dist/cli/internal/utils.d.ts +11 -8
- package/dist/cli/internal/utils.js +27 -22
- package/dist/cli/internal/validate-args.js +7 -1
- package/dist/cli/internal/watch-fs.d.ts +3 -0
- package/dist/cli/internal/watch-fs.js +92 -0
- package/dist/cli/mercury.js +2 -2
- package/package.json +17 -12
- package/dist/bundles/js/all.js +0 -1
- package/dist/bundles/js/base/base-globant.js +0 -1
- package/dist/bundles/js/base/base.js +0 -1
- package/dist/bundles/js/base/icons.js +0 -1
- package/dist/bundles/js/bundle-mappings.js +0 -237
- package/dist/bundles/js/chameleon/scrollbar.js +0 -1
- package/dist/bundles/js/components/accordion.js +0 -1
- package/dist/bundles/js/components/button.js +0 -1
- package/dist/bundles/js/components/chat.js +0 -1
- package/dist/bundles/js/components/checkbox.js +0 -1
- package/dist/bundles/js/components/code.js +0 -1
- package/dist/bundles/js/components/combo-box.js +0 -1
- package/dist/bundles/js/components/dialog.js +0 -1
- package/dist/bundles/js/components/dropdown.js +0 -1
- package/dist/bundles/js/components/edit.js +0 -1
- package/dist/bundles/js/components/flexible-layout.js +0 -1
- package/dist/bundles/js/components/icon.js +0 -1
- package/dist/bundles/js/components/layout-splitter.js +0 -1
- package/dist/bundles/js/components/list-box.js +0 -1
- package/dist/bundles/js/components/markdown-viewer.js +0 -1
- package/dist/bundles/js/components/navigation-list.js +0 -1
- package/dist/bundles/js/components/pills.js +0 -1
- package/dist/bundles/js/components/radio-group.js +0 -1
- package/dist/bundles/js/components/segmented-control.js +0 -1
- package/dist/bundles/js/components/sidebar.js +0 -1
- package/dist/bundles/js/components/slider.js +0 -1
- package/dist/bundles/js/components/switch.js +0 -1
- package/dist/bundles/js/components/tab.js +0 -1
- package/dist/bundles/js/components/tabular-grid.js +0 -1
- package/dist/bundles/js/components/ticket-list.js +0 -1
- package/dist/bundles/js/components/tooltip.js +0 -1
- package/dist/bundles/js/components/tree-view.js +0 -1
- package/dist/bundles/js/components/widget.js +0 -1
- package/dist/bundles/js/resets/box-sizing.js +0 -1
- package/dist/bundles/js/utils/elevation.js +0 -1
- package/dist/bundles/js/utils/form--full.js +0 -1
- package/dist/bundles/js/utils/form.js +0 -1
- package/dist/bundles/js/utils/layout.js +0 -1
- package/dist/bundles/js/utils/spacing.js +0 -1
- package/dist/bundles/js/utils/typography.js +0 -1
- package/dist/bundles/scss/all.scss +0 -8
- package/dist/bundles/scss/base/base.scss +0 -24
- package/dist/bundles/scss/base/icons.scss +0 -4
- package/dist/bundles/scss/chameleon/scrollbar.scss +0 -3
- package/dist/bundles/scss/components/accordion.scss +0 -3
- package/dist/bundles/scss/components/button.scss +0 -8
- package/dist/bundles/scss/components/chat.scss +0 -3
- package/dist/bundles/scss/components/checkbox.scss +0 -3
- package/dist/bundles/scss/components/code.scss +0 -3
- package/dist/bundles/scss/components/combo-box.scss +0 -3
- package/dist/bundles/scss/components/dialog.scss +0 -3
- package/dist/bundles/scss/components/dropdown.scss +0 -3
- package/dist/bundles/scss/components/edit.scss +0 -3
- package/dist/bundles/scss/components/flexible-layout.scss +0 -3
- package/dist/bundles/scss/components/icon.scss +0 -8
- package/dist/bundles/scss/components/layout-splitter.scss +0 -3
- package/dist/bundles/scss/components/list-box.scss +0 -3
- package/dist/bundles/scss/components/markdown-viewer.scss +0 -3
- package/dist/bundles/scss/components/navigation-list.scss +0 -3
- package/dist/bundles/scss/components/pills.scss +0 -3
- package/dist/bundles/scss/components/radio-group.scss +0 -3
- package/dist/bundles/scss/components/segmented-control.scss +0 -3
- package/dist/bundles/scss/components/sidebar.scss +0 -3
- package/dist/bundles/scss/components/slider.scss +0 -3
- package/dist/bundles/scss/components/switch.scss +0 -3
- package/dist/bundles/scss/components/tab.scss +0 -3
- package/dist/bundles/scss/components/tabular-grid.scss +0 -10
- package/dist/bundles/scss/components/ticket-list.scss +0 -3
- package/dist/bundles/scss/components/tooltip.scss +0 -3
- package/dist/bundles/scss/components/tree-view.scss +0 -3
- package/dist/bundles/scss/components/widget.scss +0 -3
- package/dist/bundles/scss/resets/box-sizing.scss +0 -3
- package/dist/bundles/scss/utils/elevation.scss +0 -4
- package/dist/bundles/scss/utils/form--full.scss +0 -20
- package/dist/bundles/scss/utils/form.scss +0 -4
- package/dist/bundles/scss/utils/layout.scss +0 -4
- package/dist/bundles/scss/utils/spacing.scss +0 -4
- package/dist/bundles/scss/utils/typography.scss +0 -9
- package/dist/mercury.scss +0 -24789
package/dist/cli/bundle.js
CHANGED
|
@@ -1,20 +1,188 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { Worker, isMainThread, parentPort } from "worker_threads";
|
|
7
|
+
import { ensureDirectoryExistsAndItsClear, getFilesInDir, refreshAngularBrowser
|
|
8
|
+
// copyDirectories
|
|
9
|
+
} from "./internal/file-management.js";
|
|
10
|
+
import { BASE_BUNDLES_OUT_DIR, CSS_BUNDLES_OUT_DIR, SCSS_BUNDLES_INPUT_DIR
|
|
11
|
+
// SCSS_BUNDLES_OUT_DIR
|
|
12
|
+
} from "./internal/constants.js";
|
|
13
|
+
import { transpileCssBundleWithPlaceholder } from "./internal/transpile-bundle-and-create-mappings.js";
|
|
5
14
|
import { measureTime } from "./internal/utils.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
import { printBundleWasTranspiled } from "./internal/print-utils.js";
|
|
16
|
+
import { printRebuilding, stopRebuildingStdout, watchFileSystemChanges } from "./internal/watch-fs.js";
|
|
17
|
+
import { getArguments } from "./internal/validate-args.js";
|
|
18
|
+
import { createBundlesWithCustomPaths } from "./internal/create-bundles-with-custom-paths.js";
|
|
19
|
+
const MESSAGE_TYPE = {
|
|
20
|
+
SUCCESS: "Success",
|
|
21
|
+
ERROR: "Error"
|
|
22
|
+
};
|
|
23
|
+
if (isMainThread) {
|
|
24
|
+
const [, , ...args] = process.argv;
|
|
25
|
+
const watchMode = args.find(arg => arg === "--watch");
|
|
26
|
+
let cliArgs;
|
|
27
|
+
// Check if the bundles processing is running in watch mode
|
|
28
|
+
if (watchMode) {
|
|
29
|
+
cliArgs = getArguments();
|
|
30
|
+
if (!cliArgs) {
|
|
31
|
+
process.exit();
|
|
32
|
+
}
|
|
17
33
|
}
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
// This is a WA to have __filename and __dirname in ES modules
|
|
35
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
36
|
+
const THREADS = Math.min(8, os.cpus().length / 2);
|
|
37
|
+
const workers = [];
|
|
38
|
+
/**
|
|
39
|
+
* Files to transpile
|
|
40
|
+
*/
|
|
41
|
+
let allFilesToProcess = [];
|
|
42
|
+
let firstBuild = true;
|
|
43
|
+
// - - - - - - - - - - - - Sets to implement cache - - - - - - - - - - - -
|
|
44
|
+
const BUNDLES_TO_AVOID_REBUILD = [
|
|
45
|
+
"all",
|
|
46
|
+
"base/icons",
|
|
47
|
+
"resets/box-sizing",
|
|
48
|
+
"utils/form--full"
|
|
49
|
+
];
|
|
50
|
+
const CSS_FILES_TO_AVOID_REMOVE = new Set(BUNDLES_TO_AVOID_REBUILD.map(bundleName => path.join(CSS_BUNDLES_OUT_DIR, bundleName + ".css")));
|
|
51
|
+
const SCSS_FILES_TO_AVOID_TRANSPILE = new Set(BUNDLES_TO_AVOID_REBUILD.map(bundleName => path.join(SCSS_BUNDLES_INPUT_DIR, bundleName + ".scss")));
|
|
52
|
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
53
|
+
const createWorkers = () => {
|
|
54
|
+
for (let index = 0; index < THREADS; index++) {
|
|
55
|
+
const worker = new Worker(__filename);
|
|
56
|
+
workers.push(worker);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const ensureAllDirectoryExists = (filesToProcess) => {
|
|
60
|
+
const CSS_CREATED_DIRS = new Set();
|
|
61
|
+
return filesToProcess.map(async (fileMetadata) => {
|
|
62
|
+
const cssOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_INPUT_DIR, CSS_BUNDLES_OUT_DIR);
|
|
63
|
+
// Create the file directory if it does not exists
|
|
64
|
+
if (CSS_CREATED_DIRS.has(cssOutDir)) {
|
|
65
|
+
return Promise.resolve();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
CSS_CREATED_DIRS.add(cssOutDir);
|
|
69
|
+
return fs.mkdir(cssOutDir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const compileBundles = async (options) => {
|
|
74
|
+
let completedProcessingIndex = 0;
|
|
75
|
+
// First build where the directory has to be discovered
|
|
76
|
+
if (firstBuild) {
|
|
77
|
+
allFilesToProcess = await getFilesInDir(SCSS_BUNDLES_INPUT_DIR);
|
|
78
|
+
createWorkers();
|
|
79
|
+
}
|
|
80
|
+
const ACTUAL_FILES_TO_PROCESS = structuredClone(allFilesToProcess).filter(fileMetadata => !options ||
|
|
81
|
+
!options.scssFilesToAvoidTranspile.has(fileMetadata.filePath));
|
|
82
|
+
const TOTAL_FILES = ACTUAL_FILES_TO_PROCESS.length;
|
|
83
|
+
// Clear bundle directories
|
|
84
|
+
await ensureDirectoryExistsAndItsClear(BASE_BUNDLES_OUT_DIR, options?.cssFilesToAvoidRemove);
|
|
85
|
+
// Ensure all directories exists before transpiling any bundle
|
|
86
|
+
await Promise.all(ensureAllDirectoryExists(ACTUAL_FILES_TO_PROCESS));
|
|
87
|
+
let workersProcessingMetadata = 0;
|
|
88
|
+
let thereWasAnError = false;
|
|
89
|
+
const sendFileMetadataToWorker = (worker, fileMetadata) => {
|
|
90
|
+
worker.postMessage({ fileMetadata, cliArgs }); // Send the data to process the file
|
|
91
|
+
workersProcessingMetadata++;
|
|
92
|
+
};
|
|
93
|
+
const updateFileProcessingStatus = () => {
|
|
94
|
+
completedProcessingIndex++;
|
|
95
|
+
workersProcessingMetadata--;
|
|
96
|
+
};
|
|
97
|
+
return new Promise((resolve, reject) => workers.forEach(worker => {
|
|
98
|
+
let fileMetadata = ACTUAL_FILES_TO_PROCESS.pop();
|
|
99
|
+
sendFileMetadataToWorker(worker, fileMetadata);
|
|
100
|
+
// When the worker completes the processing, increase the index and
|
|
101
|
+
// check if there is work remaining to process in the thread
|
|
102
|
+
worker.on("message", message => {
|
|
103
|
+
updateFileProcessingStatus();
|
|
104
|
+
if (message === MESSAGE_TYPE.ERROR) {
|
|
105
|
+
thereWasAnError = true;
|
|
106
|
+
}
|
|
107
|
+
// Stop all workers when there is an error
|
|
108
|
+
if (thereWasAnError) {
|
|
109
|
+
worker.removeAllListeners("message");
|
|
110
|
+
if (workersProcessingMetadata === 0) {
|
|
111
|
+
reject();
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (!watchMode) {
|
|
116
|
+
printBundleWasTranspiled(fileMetadata.filePath);
|
|
117
|
+
}
|
|
118
|
+
// All metadatas were processed. Resolve the Promise
|
|
119
|
+
if (completedProcessingIndex === TOTAL_FILES) {
|
|
120
|
+
worker.removeAllListeners("message");
|
|
121
|
+
resolve(ACTUAL_FILES_TO_PROCESS);
|
|
122
|
+
}
|
|
123
|
+
// There is more metadata to be processed, add a new processing in
|
|
124
|
+
// the thread
|
|
125
|
+
else if (ACTUAL_FILES_TO_PROCESS.length > 0) {
|
|
126
|
+
fileMetadata = ACTUAL_FILES_TO_PROCESS.pop();
|
|
127
|
+
sendFileMetadataToWorker(worker, fileMetadata);
|
|
128
|
+
}
|
|
129
|
+
// Waiting for the last compilation to end. There is nothing to do,
|
|
130
|
+
// so we need to remove the listeners to ensure the following
|
|
131
|
+
// processing uses the workers in a "fresh" state
|
|
132
|
+
else {
|
|
133
|
+
worker.removeAllListeners("message");
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}));
|
|
137
|
+
};
|
|
138
|
+
const compileAndCreateBundles = async () => {
|
|
139
|
+
printRebuilding(firstBuild);
|
|
140
|
+
try {
|
|
141
|
+
// Compile all CSSs into the standard output (dist/bundles/css)
|
|
142
|
+
await compileBundles(firstBuild
|
|
143
|
+
? undefined
|
|
144
|
+
: {
|
|
145
|
+
cssFilesToAvoidRemove: CSS_FILES_TO_AVOID_REMOVE,
|
|
146
|
+
scssFilesToAvoidTranspile: SCSS_FILES_TO_AVOID_TRANSPILE
|
|
147
|
+
});
|
|
148
|
+
// Clear the CLI dir output target
|
|
149
|
+
await ensureDirectoryExistsAndItsClear(cliArgs.outDirPath);
|
|
150
|
+
// Remove "Rebuilding..." message, since the next function will print
|
|
151
|
+
// some output in the console
|
|
152
|
+
stopRebuildingStdout();
|
|
153
|
+
// Copy the files from the standard output (dist/bundles/css) to the CLI
|
|
154
|
+
// output by applying the transformations for the icons and custom fonts
|
|
155
|
+
// paths.
|
|
156
|
+
//
|
|
157
|
+
// Last true value meaning: Don't hash the bundles in watch mode to avoid
|
|
158
|
+
// issues with Angular that caches the bundle mapping file, causing to
|
|
159
|
+
// not update the hashes for the fetches
|
|
160
|
+
await createBundlesWithCustomPaths(cliArgs, true);
|
|
161
|
+
refreshAngularBrowser();
|
|
162
|
+
firstBuild = false;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
stopRebuildingStdout();
|
|
166
|
+
if (err) {
|
|
167
|
+
console.log(err);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
if (watchMode) {
|
|
172
|
+
measureTime(compileAndCreateBundles).finally(() => watchFileSystemChanges(compileAndCreateBundles));
|
|
173
|
+
}
|
|
174
|
+
// There is no need to wait for any changes, since the watch mode is not enabled
|
|
175
|
+
else {
|
|
176
|
+
await measureTime(compileBundles);
|
|
177
|
+
process.exit();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Worker thread code
|
|
181
|
+
else {
|
|
182
|
+
parentPort.on("message", (data) => transpileCssBundleWithPlaceholder(data.fileMetadata, data.cliArgs)
|
|
183
|
+
.then(() => parentPort.postMessage(MESSAGE_TYPE.SUCCESS))
|
|
184
|
+
.catch(err => {
|
|
185
|
+
console.error(err);
|
|
186
|
+
parentPort.postMessage(MESSAGE_TYPE.ERROR);
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
@@ -3,17 +3,11 @@ export declare const SCSS_BUNDLES_INPUT_DIR: string;
|
|
|
3
3
|
export declare const BASE_BUNDLES_OUT_DIR: string;
|
|
4
4
|
export declare const SCSS_BUNDLES_OUT_DIR: string;
|
|
5
5
|
export declare const CSS_BUNDLES_OUT_DIR: string;
|
|
6
|
-
export declare const JS_BUNDLES_OUT_DIR: string;
|
|
7
6
|
export declare const BASE_BUNDLE = "base/base";
|
|
8
|
-
export declare const BASE_BUNDLE_WITH_BACK_SLASH = "\\base\\base";
|
|
9
7
|
export declare const BASE_GLOBANT_BUNDLE = "base/base-globant";
|
|
10
|
-
export declare const BUNDLE_MAPPING_FILE = "bundle-mappings.js";
|
|
11
8
|
export declare const BUNDLE_MAPPING_TO_HASH_FILE = "bundle-to-hash-mappings.ts";
|
|
12
|
-
export declare const
|
|
13
|
-
export declare const BASE_GLOBANT_FILE = "base-globant";
|
|
9
|
+
export declare const BASE_CSS_FILE = "base.css";
|
|
14
10
|
export declare const BASE_GLOBANT_CSS_FILE = "base-globant.css";
|
|
15
|
-
export declare const BASE_GLOBANT_JS_FILE = "base-globant.js";
|
|
16
|
-
export declare const BASE_GLOBANT_SCSS_FILE = "base-globant.scss";
|
|
17
11
|
export declare const ICONS_PATH_PLACEHOLDER = "{{ICONS_PATH}}";
|
|
18
12
|
export declare const FONT_FACE_PATH_PLACEHOLDER = "{{FONT_FACE_PATH}}";
|
|
19
13
|
export declare const DEFAULT_FONT_FACE_PATH = "./assets/fonts/";
|
|
@@ -21,8 +15,5 @@ export declare const DEFAULT_ICONS_PATH = "./assets/icons/";
|
|
|
21
15
|
export declare const DEFAULT_OUT_DIR_PATH = "./.mercury";
|
|
22
16
|
export declare const SEPARATE_BY_COMMA_REGEX: RegExp;
|
|
23
17
|
export declare const SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX: RegExp;
|
|
24
|
-
export declare const
|
|
25
|
-
|
|
26
|
-
readonly FILE_DIR: "fileDir";
|
|
27
|
-
readonly TRANSPILED_BUNDLE: "transpiledBundle";
|
|
28
|
-
};
|
|
18
|
+
export declare const HASH_LENGTH = 16;
|
|
19
|
+
export declare const HASH_AND_LETTER_LENGTH: number;
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
// import type { BundleAssociationMetadata } from "./types";
|
|
2
3
|
export const KB = 1000;
|
|
3
4
|
export const SCSS_BUNDLES_INPUT_DIR = path.join("src", "bundles", "scss");
|
|
4
5
|
export const BASE_BUNDLES_OUT_DIR = path.join("dist", "bundles");
|
|
5
6
|
export const SCSS_BUNDLES_OUT_DIR = path.join(BASE_BUNDLES_OUT_DIR, "scss");
|
|
6
7
|
export const CSS_BUNDLES_OUT_DIR = path.join(BASE_BUNDLES_OUT_DIR, "css");
|
|
7
|
-
export const JS_BUNDLES_OUT_DIR = path.join(BASE_BUNDLES_OUT_DIR, "js");
|
|
8
8
|
export const BASE_BUNDLE = "base/base";
|
|
9
|
-
export const BASE_BUNDLE_WITH_BACK_SLASH = "\\base\\base";
|
|
10
9
|
export const BASE_GLOBANT_BUNDLE = "base/base-globant";
|
|
11
10
|
// Files
|
|
12
|
-
export const BUNDLE_MAPPING_FILE = "bundle-mappings.js";
|
|
13
11
|
export const BUNDLE_MAPPING_TO_HASH_FILE = "bundle-to-hash-mappings.ts";
|
|
14
|
-
export const
|
|
15
|
-
export const BASE_GLOBANT_FILE = "base-globant";
|
|
12
|
+
export const BASE_CSS_FILE = "base.css";
|
|
16
13
|
export const BASE_GLOBANT_CSS_FILE = "base-globant.css";
|
|
17
|
-
export const BASE_GLOBANT_JS_FILE = "base-globant.js";
|
|
18
|
-
export const BASE_GLOBANT_SCSS_FILE = "base-globant.scss";
|
|
19
14
|
// Placeholders
|
|
20
15
|
export const ICONS_PATH_PLACEHOLDER = "{{ICONS_PATH}}";
|
|
21
16
|
export const FONT_FACE_PATH_PLACEHOLDER = "{{FONT_FACE_PATH}}";
|
|
@@ -25,9 +20,5 @@ export const DEFAULT_ICONS_PATH = "./assets/icons/";
|
|
|
25
20
|
export const DEFAULT_OUT_DIR_PATH = "./.mercury";
|
|
26
21
|
export const SEPARATE_BY_COMMA_REGEX = /\s*,\s*/g;
|
|
27
22
|
export const SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX = /[\/-]/g;
|
|
28
|
-
|
|
29
|
-
export const
|
|
30
|
-
BUNDLE_NAME: "bundleName",
|
|
31
|
-
FILE_DIR: "fileDir",
|
|
32
|
-
TRANSPILED_BUNDLE: "transpiledBundle"
|
|
33
|
-
};
|
|
23
|
+
export const HASH_LENGTH = 16;
|
|
24
|
+
export const HASH_AND_LETTER_LENGTH = HASH_LENGTH + 1;
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
import type { CLIArguments } from "./types";
|
|
2
|
-
export declare const
|
|
1
|
+
import type { CLIArguments, FileMetadata } from "./types";
|
|
2
|
+
export declare const createBundleWithCustomPath: (args: CLIArguments, options: {
|
|
3
|
+
bundleFolder: string;
|
|
4
|
+
fileBaseDirToWrite: string;
|
|
5
|
+
}, fileMetadata: FileMetadata, avoidAllHashes: boolean, actualFilePath: string) => {
|
|
6
|
+
bundleName: string;
|
|
7
|
+
bundleNameWithHash: string;
|
|
8
|
+
fileSize: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const createBundlesWithCustomPaths: (args: CLIArguments, avoidAllHashes?: boolean) => Promise<void>;
|
|
@@ -1,67 +1,114 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { BASE_BUNDLE, BASE_CSS_FILE, BASE_GLOBANT_BUNDLE, BASE_GLOBANT_CSS_FILE, BUNDLE_MAPPING_TO_HASH_FILE, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, HASH_AND_LETTER_LENGTH } from "./constants.js";
|
|
5
|
+
import { getFilesInDir } from "./file-management.js";
|
|
6
|
+
import { getBundleFolderAndFileBaseDir, getBundleName, getFileNameWithHash, getFileNameWithoutExt, getFileSize, getHash, sanitizeBundleName } from "./utils.js";
|
|
7
|
+
import { printBundleWasCreated, printBundleWasCreatedTableHeader } from "./print-utils.js";
|
|
8
|
+
export const createBundleWithCustomPath = (args, options, fileMetadata, avoidAllHashes, actualFilePath) => {
|
|
9
|
+
const { avoidHash, fontFacePath, iconsPath } = args;
|
|
10
|
+
const { bundleFolder, fileBaseDirToWrite } = options;
|
|
11
|
+
const fileNameWithoutExt = getFileNameWithoutExt(fileMetadata);
|
|
12
|
+
const bundleName = getBundleName(fileMetadata);
|
|
13
|
+
// Copy CSS bundle
|
|
14
|
+
let css = fs.readFileSync(actualFilePath ?? fileMetadata.filePath, {
|
|
15
|
+
encoding: "utf8"
|
|
12
16
|
});
|
|
13
|
-
|
|
17
|
+
if (fontFacePath !== DEFAULT_FONT_FACE_PATH) {
|
|
18
|
+
css = css.replaceAll(DEFAULT_FONT_FACE_PATH, fontFacePath);
|
|
19
|
+
}
|
|
20
|
+
if (iconsPath !== DEFAULT_ICONS_PATH) {
|
|
21
|
+
css = css.replaceAll(DEFAULT_ICONS_PATH, iconsPath);
|
|
22
|
+
}
|
|
23
|
+
const fileNameWithHash = avoidAllHashes || avoidHash.has(bundleName)
|
|
24
|
+
? fileNameWithoutExt
|
|
25
|
+
: getFileNameWithHash(fileNameWithoutExt, getHash(css));
|
|
26
|
+
const fileNameToWriteCss = `${fileNameWithHash}.css`;
|
|
27
|
+
const filePathWithHash = path.join(fileBaseDirToWrite, fileNameToWriteCss);
|
|
28
|
+
// Create the CSS bundle with hash
|
|
29
|
+
fs.writeFileSync(filePathWithHash, css);
|
|
30
|
+
return {
|
|
31
|
+
bundleName,
|
|
32
|
+
bundleNameWithHash: sanitizeBundleName(`${bundleFolder}/${fileNameWithHash}`),
|
|
33
|
+
fileSize: getFileSize(css)
|
|
34
|
+
};
|
|
14
35
|
};
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
: bundleName;
|
|
18
|
-
const shouldSkipBundleCreation = (bundleName, globant) => (bundleName === BASE_BUNDLE && globant) ||
|
|
19
|
-
(bundleName === BASE_GLOBANT_BUNDLE && !globant);
|
|
20
|
-
export const createBundlesWithCustomPaths = (args) => {
|
|
21
|
-
const { avoidHash, fontFacePath, iconsPath, globant } = args;
|
|
36
|
+
export const createBundlesWithCustomPaths = async (args, avoidAllHashes = false) => {
|
|
37
|
+
const hasGlobantVariant = args.globant;
|
|
22
38
|
const outDir = path.join(args.outDirPath);
|
|
23
39
|
const CREATED_DIRS = new Set();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
// This is a WA to have __filename and __dirname in ES modules
|
|
41
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
42
|
+
// Directory name where the script is located (<path from root to node_modules/@genexus/mercury>/dist/cli/)
|
|
43
|
+
const __dirname = path.dirname(__filename);
|
|
44
|
+
const cssOutput = path.join(__dirname, "../../bundles/css");
|
|
45
|
+
/**
|
|
46
|
+
* Files to transpile
|
|
47
|
+
*/
|
|
48
|
+
const allFilesToCopy = await getFilesInDir(cssOutput);
|
|
49
|
+
let largestBundleLength = BUNDLE_MAPPING_TO_HASH_FILE.length;
|
|
50
|
+
let largestFileSizeLength = 0;
|
|
51
|
+
allFilesToCopy.forEach(fileMetadata => {
|
|
52
|
+
const options = getBundleFolderAndFileBaseDir(fileMetadata, outDir);
|
|
53
|
+
largestBundleLength = Math.max(largestBundleLength, options.bundleFolder.length + fileMetadata.fileName.length);
|
|
54
|
+
});
|
|
55
|
+
if (!avoidAllHashes) {
|
|
56
|
+
largestBundleLength += HASH_AND_LETTER_LENGTH;
|
|
57
|
+
}
|
|
58
|
+
const copiedFiles = [];
|
|
59
|
+
allFilesToCopy.forEach(fileMetadata => {
|
|
60
|
+
const bundleName = getBundleName(fileMetadata);
|
|
61
|
+
const options = getBundleFolderAndFileBaseDir(fileMetadata, outDir);
|
|
62
|
+
const { fileBaseDirToWrite } = options;
|
|
63
|
+
let actualFilePath = fileMetadata.filePath;
|
|
64
|
+
if (!CREATED_DIRS.has(fileBaseDirToWrite)) {
|
|
65
|
+
CREATED_DIRS.add(fileBaseDirToWrite);
|
|
66
|
+
fs.mkdirSync(path.join(fileBaseDirToWrite), { recursive: true });
|
|
30
67
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
// There is no need to copy the base-globant.css file, since the base.css
|
|
69
|
+
// file already contains this file
|
|
70
|
+
if (hasGlobantVariant) {
|
|
71
|
+
if (bundleName === BASE_GLOBANT_BUNDLE) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Replace the content of the base bundle with the Globant variant
|
|
75
|
+
if (bundleName === BASE_BUNDLE) {
|
|
76
|
+
actualFilePath = actualFilePath.replace(BASE_CSS_FILE, BASE_GLOBANT_CSS_FILE);
|
|
77
|
+
}
|
|
37
78
|
}
|
|
38
|
-
|
|
39
|
-
? actualBundleName
|
|
40
|
-
: getBundleNameWithHash(actualBundleName, hash);
|
|
41
|
-
const filePathToCreateBundle = path.join(outDir, `${bundleNameWithHash}.css`);
|
|
42
|
-
fs.writeFileSync(filePathToCreateBundle, compiledBundleWithoutPlaceholders);
|
|
43
|
-
printBundleWasCreated({
|
|
44
|
-
outDir,
|
|
45
|
-
bundleName: actualBundleName,
|
|
46
|
-
compiledBundleWithoutPlaceholders,
|
|
47
|
-
filePathToCreateBundle,
|
|
48
|
-
// WA to improve style
|
|
49
|
-
largestBundleLength: largestBundleLength + (avoidHash.has(actualBundleName) ? 17 : 0)
|
|
50
|
-
});
|
|
51
|
-
// Store the bundle mapping.
|
|
52
|
-
// For example: "components/button" --> "components/button-9f82641938b85445"
|
|
53
|
-
const bundleToHashEntry = ` "${actualBundleName}": "${bundleNameWithHash}"`;
|
|
54
|
-
// Concat entries in the object
|
|
55
|
-
bundleMappingToHashObjectEntries +=
|
|
56
|
-
bundleMappingToHashObjectEntries === ""
|
|
57
|
-
? bundleToHashEntry
|
|
58
|
-
: ",\n" + bundleToHashEntry;
|
|
79
|
+
copiedFiles.push(createBundleWithCustomPath(args, options, fileMetadata, avoidAllHashes, actualFilePath));
|
|
59
80
|
});
|
|
60
|
-
|
|
81
|
+
copiedFiles.sort((a, b) => (a.bundleName <= b.bundleName ? -1 : 0));
|
|
82
|
+
const bundleMappingFileContent = `export const bundleToHashMappings = {\n${copiedFiles.map(entry => ` "${entry.bundleName}": "${entry.bundleNameWithHash}"`).join(",\n")}\n} as const;\n`;
|
|
83
|
+
const bundleMappingFileSize = getFileSize(bundleMappingFileContent);
|
|
61
84
|
const bundleMappingFilePath = path.join(outDir, BUNDLE_MAPPING_TO_HASH_FILE);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
85
|
+
// Compute the largest fileName length
|
|
86
|
+
largestFileSizeLength = copiedFiles.reduce((acc, copiedFile) => Math.max(acc, copiedFile.fileSize.length), bundleMappingFileSize.length);
|
|
87
|
+
printBundleWasCreatedTableHeader({
|
|
88
|
+
largestBundleLength: avoidAllHashes
|
|
89
|
+
? largestBundleLength
|
|
90
|
+
: largestBundleLength + 1,
|
|
91
|
+
outDir
|
|
92
|
+
});
|
|
93
|
+
// Print bundle created message
|
|
94
|
+
for (let index = 0; index < copiedFiles.length; index++) {
|
|
95
|
+
const entry = copiedFiles[index];
|
|
96
|
+
printBundleWasCreated({
|
|
97
|
+
bundleNameWithHash: `${entry.bundleNameWithHash}.css`,
|
|
98
|
+
fileSize: entry.fileSize,
|
|
99
|
+
largestBundleLength,
|
|
100
|
+
largestFileSizeLength,
|
|
101
|
+
outDir
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
fs.writeFileSync(bundleMappingFilePath, bundleMappingFileContent);
|
|
105
|
+
// Separate the TS file
|
|
106
|
+
console.log("");
|
|
107
|
+
printBundleWasCreated({
|
|
108
|
+
bundleNameWithHash: BUNDLE_MAPPING_TO_HASH_FILE,
|
|
109
|
+
fileSize: getFileSize(bundleMappingFileContent),
|
|
110
|
+
largestBundleLength,
|
|
111
|
+
largestFileSizeLength,
|
|
112
|
+
outDir
|
|
66
113
|
});
|
|
67
114
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FileMetadata } from "./types";
|
|
2
|
-
export declare const ensureDirectoryExistsAndItsClear: (dirPath: string) => void
|
|
3
|
-
export declare
|
|
2
|
+
export declare const ensureDirectoryExistsAndItsClear: (dirPath: string, filesToNotRemove?: Set<string>) => Promise<void>;
|
|
3
|
+
export declare const getFilesInDir: (dir: string) => Promise<FileMetadata[]>;
|
|
4
4
|
export declare const copyDirectories: (srcDir: string, outDir: string) => void;
|
|
5
|
+
export declare const refreshAngularBrowser: () => void;
|
|
@@ -1,20 +1,53 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { readdir, rm } from "node:fs/promises";
|
|
4
|
+
export const ensureDirectoryExistsAndItsClear = async (dirPath, filesToNotRemove) => {
|
|
5
|
+
// First build
|
|
6
|
+
if (!fs.existsSync(dirPath)) {
|
|
7
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
// Incremental rebuild keeps some file without any changes, so we must skip
|
|
11
|
+
// the file deletion
|
|
12
|
+
if (filesToNotRemove) {
|
|
13
|
+
const filesInDir = await getFilesInDir(dirPath);
|
|
14
|
+
await Promise.all(filesInDir.map(file => filesToNotRemove.has(file.filePath)
|
|
15
|
+
? Promise.resolve()
|
|
16
|
+
: rm(file.filePath)));
|
|
17
|
+
}
|
|
18
|
+
// Incremental rebuild did not include any file to exclude its removal
|
|
19
|
+
else {
|
|
5
20
|
fs.rmSync(dirPath, { recursive: true });
|
|
21
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
6
22
|
}
|
|
7
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
8
23
|
};
|
|
9
|
-
export
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
export const getFilesInDir = async (dir) => {
|
|
25
|
+
const filesAndDirs = await readdir(dir, {
|
|
26
|
+
withFileTypes: true,
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
const files = [];
|
|
30
|
+
for (let index = 0; index < filesAndDirs.length; index++) {
|
|
31
|
+
const file = filesAndDirs[index];
|
|
32
|
+
if (file.isFile()) {
|
|
33
|
+
files.push({
|
|
34
|
+
dir: file.parentPath,
|
|
35
|
+
fileName: file.name,
|
|
36
|
+
filePath: path.join(file.parentPath, file.name)
|
|
37
|
+
});
|
|
17
38
|
}
|
|
18
39
|
}
|
|
19
|
-
|
|
40
|
+
return files;
|
|
41
|
+
};
|
|
20
42
|
export const copyDirectories = (srcDir, outDir) => fs.cpSync(srcDir, outDir, { recursive: true });
|
|
43
|
+
export const refreshAngularBrowser = () => {
|
|
44
|
+
const ANGULAR_FILE_TO_TRIGGER_RELOAD = path.join(process.cwd(), "../showcase/src/index.html");
|
|
45
|
+
const FILE_CONTENT = fs.readFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, {
|
|
46
|
+
encoding: "utf8"
|
|
47
|
+
});
|
|
48
|
+
// Trigger a dummy write in the index.html
|
|
49
|
+
fs.writeFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, FILE_CONTENT + "\n");
|
|
50
|
+
// Rollback that write to not provoke any changes, but do it after the
|
|
51
|
+
// debounce of the Angular CLI has completed the queued HMR
|
|
52
|
+
setTimeout(() => fs.writeFileSync(ANGULAR_FILE_TO_TRIGGER_RELOAD, FILE_CONTENT), 300);
|
|
53
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const printBundleWasCreatedTableHeader: (args: {
|
|
2
2
|
outDir: string;
|
|
3
|
-
bundleName: string;
|
|
4
3
|
largestBundleLength: number;
|
|
5
|
-
filePathToCreateBundle: string;
|
|
6
|
-
compiledBundleWithoutPlaceholders: string;
|
|
7
4
|
}) => void;
|
|
8
|
-
export declare const
|
|
5
|
+
export declare const printBundleWasCreated: (args: {
|
|
9
6
|
outDir: string;
|
|
10
|
-
|
|
7
|
+
bundleNameWithHash: string;
|
|
8
|
+
largestBundleLength: number;
|
|
9
|
+
largestFileSizeLength: number;
|
|
10
|
+
fileSize: string;
|
|
11
11
|
}) => void;
|
|
12
12
|
export declare const printBundleWasTranspiled: (filePath: string) => void;
|
|
13
13
|
export declare const printArgumentDoesNotExistsError: (arg: string) => void;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { styleText } from "node:util";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export const
|
|
10
|
-
styleText("greenBright",
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
import { DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, DEFAULT_OUT_DIR_PATH, SCSS_BUNDLES_INPUT_DIR, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const separator = () => styleText(["gray"], " | ");
|
|
5
|
+
export const printBundleWasCreatedTableHeader = (args) => console.log(styleText(["white", "bold"], "Files") +
|
|
6
|
+
" ".repeat(args.largestBundleLength + args.outDir.length - "Files".length) +
|
|
7
|
+
separator() +
|
|
8
|
+
styleText(["white", "bold"], "Raw size"));
|
|
9
|
+
export const printBundleWasCreated = (args) => console.log(styleText("white", args.outDir) +
|
|
10
|
+
styleText("greenBright", path.join(args.outDir, args.bundleNameWithHash).replace(args.outDir, "")) +
|
|
11
|
+
" ".repeat(Math.max(args.largestBundleLength - args.bundleNameWithHash.length, 0)) +
|
|
12
|
+
separator() +
|
|
13
|
+
" ".repeat(Math.max(args.largestFileSizeLength - args.fileSize.length, 0)) +
|
|
14
|
+
styleText("cyanBright", args.fileSize));
|
|
13
15
|
export const printBundleWasTranspiled = (filePath) => console.log(styleText("greenBright", " Transpiled: ") +
|
|
14
16
|
styleText("white", SCSS_BUNDLES_OUT_DIR) +
|
|
15
|
-
styleText("whiteBright", filePath.replace(
|
|
17
|
+
styleText("whiteBright", filePath.replace(SCSS_BUNDLES_INPUT_DIR, "")));
|
|
16
18
|
export const printArgumentDoesNotExistsError = (arg) => console.log(styleText("red", " error ") +
|
|
17
19
|
styleText("gray", "Argument does not exists: ") +
|
|
18
20
|
`'${arg}'`);
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { FileMetadata } from "./types
|
|
2
|
-
export declare const transpileCssBundleWithPlaceholder: (fileMetadata: FileMetadata) => void
|
|
3
|
-
export declare const createBundleMappingsFile: () => void;
|
|
1
|
+
import type { CLIArguments, FileMetadata } from "./types";
|
|
2
|
+
export declare const transpileCssBundleWithPlaceholder: (fileMetadata: FileMetadata, args?: CLIArguments) => Promise<void>;
|