@genexus/mercury 0.35.1 → 0.36.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/README.md +0 -29
- package/dist/assets-manager.d.ts +3 -3
- 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/register-mercury.js +1 -1
- package/package.json +14 -26
- package/dist/assets/MERCURY_ASSETS.ts +0 -19314
- package/dist/assets/images/mercury-favicon-32x32.png +0 -0
- package/dist/assets/images/noise-texture-200x200-original.png +0 -0
- package/dist/assets/images/noise-texture-200x200.png +0 -0
- package/dist/cli/bundle.d.ts +0 -2
- package/dist/cli/bundle.js +0 -191
- package/dist/cli/internal/constants.d.ts +0 -19
- package/dist/cli/internal/constants.js +0 -24
- package/dist/cli/internal/create-bundles-with-custom-paths.d.ts +0 -10
- package/dist/cli/internal/create-bundles-with-custom-paths.js +0 -114
- package/dist/cli/internal/file-management.d.ts +0 -5
- package/dist/cli/internal/file-management.js +0 -53
- package/dist/cli/internal/print-utils.d.ts +0 -18
- package/dist/cli/internal/print-utils.js +0 -35
- package/dist/cli/internal/transpile-bundle-and-create-mappings.d.ts +0 -2
- package/dist/cli/internal/transpile-bundle-and-create-mappings.js +0 -57
- package/dist/cli/internal/types.d.ts +0 -20
- package/dist/cli/internal/types.js +0 -1
- package/dist/cli/internal/utils.d.ts +0 -14
- package/dist/cli/internal/utils.js +0 -47
- package/dist/cli/internal/validate-args.d.ts +0 -2
- package/dist/cli/internal/validate-args.js +0 -126
- package/dist/cli/internal/watch-fs.d.ts +0 -3
- package/dist/cli/internal/watch-fs.js +0 -101
- package/dist/cli/mercury.d.ts +0 -2
- package/dist/cli/mercury.js +0 -14
- /package/dist/{assets/MERCURY_ASSETS.d.ts → MERCURY_ASSETS.d.ts} +0 -0
- /package/dist/{assets/MERCURY_ASSETS.js → MERCURY_ASSETS.js} +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli/bundle.d.ts
DELETED
package/dist/cli/bundle.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { Worker, isMainThread, parentPort } from "worker_threads";
|
|
7
|
-
import { BASE_BUNDLES_OUT_DIR, CSS_BUNDLES_OUT_DIR, SCSS_BUNDLES_INPUT_DIR
|
|
8
|
-
// SCSS_BUNDLES_OUT_DIR
|
|
9
|
-
} from "./internal/constants.js";
|
|
10
|
-
import { ensureDirectoryExistsAndItsClear, getFilesInDir, refreshAngularBrowser
|
|
11
|
-
// copyDirectories
|
|
12
|
-
} from "./internal/file-management.js";
|
|
13
|
-
import { transpileCssBundleWithPlaceholder } from "./internal/transpile-bundle-and-create-mappings.js";
|
|
14
|
-
import { measureTime } from "./internal/utils.js";
|
|
15
|
-
import { createBundlesWithCustomPaths } from "./internal/create-bundles-with-custom-paths.js";
|
|
16
|
-
import { printBundleWasTranspiled } from "./internal/print-utils.js";
|
|
17
|
-
import { getArguments } from "./internal/validate-args.js";
|
|
18
|
-
import { printRebuilding, stopRebuildingStdout, watchFileSystemChanges } from "./internal/watch-fs.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
|
-
const ciMode = args.find(arg => arg === "--ci");
|
|
27
|
-
let cliArgs;
|
|
28
|
-
// Check if the bundles processing is running in watch mode
|
|
29
|
-
if (watchMode || ciMode) {
|
|
30
|
-
cliArgs = getArguments();
|
|
31
|
-
if (!cliArgs) {
|
|
32
|
-
process.exit();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// This is a WA to have __filename and __dirname in ES modules
|
|
36
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
37
|
-
const THREADS = Math.min(8, os.cpus().length / 2);
|
|
38
|
-
const workers = [];
|
|
39
|
-
/**
|
|
40
|
-
* Files to transpile
|
|
41
|
-
*/
|
|
42
|
-
let allFilesToProcess = [];
|
|
43
|
-
let firstBuild = true;
|
|
44
|
-
// - - - - - - - - - - - - Sets to implement cache - - - - - - - - - - - -
|
|
45
|
-
const BUNDLES_TO_AVOID_REBUILD = [
|
|
46
|
-
"all",
|
|
47
|
-
"base/icons",
|
|
48
|
-
"resets/box-sizing",
|
|
49
|
-
"utils/form--full"
|
|
50
|
-
];
|
|
51
|
-
const CSS_FILES_TO_AVOID_REMOVE = new Set(BUNDLES_TO_AVOID_REBUILD.map(bundleName => path.join(CSS_BUNDLES_OUT_DIR, bundleName + ".css")));
|
|
52
|
-
const SCSS_FILES_TO_AVOID_TRANSPILE = new Set(BUNDLES_TO_AVOID_REBUILD.map(bundleName => path.join(SCSS_BUNDLES_INPUT_DIR, bundleName + ".scss")));
|
|
53
|
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
54
|
-
const createWorkers = () => {
|
|
55
|
-
for (let index = 0; index < THREADS; index++) {
|
|
56
|
-
const worker = new Worker(__filename);
|
|
57
|
-
workers.push(worker);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const ensureAllDirectoryExists = (filesToProcess) => {
|
|
61
|
-
const CSS_CREATED_DIRS = new Set();
|
|
62
|
-
return filesToProcess.map(async (fileMetadata) => {
|
|
63
|
-
const cssOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_INPUT_DIR, CSS_BUNDLES_OUT_DIR);
|
|
64
|
-
// Create the file directory if it does not exists
|
|
65
|
-
if (CSS_CREATED_DIRS.has(cssOutDir)) {
|
|
66
|
-
return Promise.resolve();
|
|
67
|
-
}
|
|
68
|
-
CSS_CREATED_DIRS.add(cssOutDir);
|
|
69
|
-
return fs.mkdir(cssOutDir, { recursive: true });
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
const compileBundles = async (options) => {
|
|
73
|
-
let completedProcessingIndex = 0;
|
|
74
|
-
// First build where the directory has to be discovered
|
|
75
|
-
if (firstBuild) {
|
|
76
|
-
allFilesToProcess = await getFilesInDir(SCSS_BUNDLES_INPUT_DIR);
|
|
77
|
-
createWorkers();
|
|
78
|
-
}
|
|
79
|
-
const ACTUAL_FILES_TO_PROCESS = structuredClone(allFilesToProcess).filter(fileMetadata => !options ||
|
|
80
|
-
!options.scssFilesToAvoidTranspile.has(fileMetadata.filePath));
|
|
81
|
-
const TOTAL_FILES = ACTUAL_FILES_TO_PROCESS.length;
|
|
82
|
-
// Clear bundle directories
|
|
83
|
-
await ensureDirectoryExistsAndItsClear(BASE_BUNDLES_OUT_DIR, options?.cssFilesToAvoidRemove);
|
|
84
|
-
// Ensure all directories exists before transpiling any bundle
|
|
85
|
-
await Promise.all(ensureAllDirectoryExists(ACTUAL_FILES_TO_PROCESS));
|
|
86
|
-
let workersProcessingMetadata = 0;
|
|
87
|
-
let thereWasAnError = false;
|
|
88
|
-
const sendFileMetadataToWorker = (worker, fileMetadata) => {
|
|
89
|
-
worker.postMessage({ fileMetadata, cliArgs }); // Send the data to process the file
|
|
90
|
-
workersProcessingMetadata++;
|
|
91
|
-
};
|
|
92
|
-
const updateFileProcessingStatus = () => {
|
|
93
|
-
completedProcessingIndex++;
|
|
94
|
-
workersProcessingMetadata--;
|
|
95
|
-
};
|
|
96
|
-
return new Promise((resolve, reject) => workers.forEach(worker => {
|
|
97
|
-
let fileMetadata = ACTUAL_FILES_TO_PROCESS.pop();
|
|
98
|
-
sendFileMetadataToWorker(worker, fileMetadata);
|
|
99
|
-
// When the worker completes the processing, increase the index and
|
|
100
|
-
// check if there is work remaining to process in the thread
|
|
101
|
-
worker.on("message", message => {
|
|
102
|
-
updateFileProcessingStatus();
|
|
103
|
-
if (message === MESSAGE_TYPE.ERROR) {
|
|
104
|
-
thereWasAnError = true;
|
|
105
|
-
}
|
|
106
|
-
// Stop all workers when there is an error
|
|
107
|
-
if (thereWasAnError) {
|
|
108
|
-
worker.removeAllListeners("message");
|
|
109
|
-
if (workersProcessingMetadata === 0) {
|
|
110
|
-
reject();
|
|
111
|
-
}
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (!watchMode && !ciMode) {
|
|
115
|
-
printBundleWasTranspiled(fileMetadata.filePath);
|
|
116
|
-
}
|
|
117
|
-
// All metadatas were processed. Resolve the Promise
|
|
118
|
-
if (completedProcessingIndex === TOTAL_FILES) {
|
|
119
|
-
worker.removeAllListeners("message");
|
|
120
|
-
resolve(ACTUAL_FILES_TO_PROCESS);
|
|
121
|
-
}
|
|
122
|
-
// There is more metadata to be processed, add a new processing in
|
|
123
|
-
// the thread
|
|
124
|
-
else if (ACTUAL_FILES_TO_PROCESS.length > 0) {
|
|
125
|
-
fileMetadata = ACTUAL_FILES_TO_PROCESS.pop();
|
|
126
|
-
sendFileMetadataToWorker(worker, fileMetadata);
|
|
127
|
-
}
|
|
128
|
-
// Waiting for the last compilation to end. There is nothing to do,
|
|
129
|
-
// so we need to remove the listeners to ensure the following
|
|
130
|
-
// processing uses the workers in a "fresh" state
|
|
131
|
-
else {
|
|
132
|
-
worker.removeAllListeners("message");
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
}));
|
|
136
|
-
};
|
|
137
|
-
const compileAndCreateBundles = async () => {
|
|
138
|
-
printRebuilding(firstBuild);
|
|
139
|
-
try {
|
|
140
|
-
// Compile all CSSs into the standard output (dist/bundles/css)
|
|
141
|
-
await compileBundles(firstBuild
|
|
142
|
-
? undefined
|
|
143
|
-
: {
|
|
144
|
-
cssFilesToAvoidRemove: CSS_FILES_TO_AVOID_REMOVE,
|
|
145
|
-
scssFilesToAvoidTranspile: SCSS_FILES_TO_AVOID_TRANSPILE
|
|
146
|
-
});
|
|
147
|
-
// Clear the CLI dir output target
|
|
148
|
-
await ensureDirectoryExistsAndItsClear(cliArgs.outDirPath);
|
|
149
|
-
// Remove "Rebuilding..." message, since the next function will print
|
|
150
|
-
// some output in the console
|
|
151
|
-
stopRebuildingStdout();
|
|
152
|
-
// Copy the files from the standard output (dist/bundles/css) to the CLI
|
|
153
|
-
// output by applying the transformations for the icons and custom fonts
|
|
154
|
-
// paths.
|
|
155
|
-
//
|
|
156
|
-
// Last true value meaning: Don't hash the bundles in watch mode to avoid
|
|
157
|
-
// issues with Angular that caches the bundle mapping file, causing to
|
|
158
|
-
// not update the hashes for the fetches
|
|
159
|
-
await createBundlesWithCustomPaths(cliArgs, true);
|
|
160
|
-
refreshAngularBrowser();
|
|
161
|
-
firstBuild = false;
|
|
162
|
-
}
|
|
163
|
-
catch (err) {
|
|
164
|
-
stopRebuildingStdout();
|
|
165
|
-
if (err) {
|
|
166
|
-
console.log(err);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
if (watchMode) {
|
|
171
|
-
measureTime(compileAndCreateBundles).finally(() => watchFileSystemChanges(compileAndCreateBundles));
|
|
172
|
-
}
|
|
173
|
-
else if (ciMode) {
|
|
174
|
-
await compileAndCreateBundles();
|
|
175
|
-
process.exit();
|
|
176
|
-
}
|
|
177
|
-
// There is no need to wait for any changes, since the watch mode is not enabled
|
|
178
|
-
else {
|
|
179
|
-
await measureTime(compileBundles);
|
|
180
|
-
process.exit();
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// Worker thread code
|
|
184
|
-
else {
|
|
185
|
-
parentPort.on("message", (data) => transpileCssBundleWithPlaceholder(data.fileMetadata, data.cliArgs)
|
|
186
|
-
.then(() => parentPort.postMessage(MESSAGE_TYPE.SUCCESS))
|
|
187
|
-
.catch(err => {
|
|
188
|
-
console.error(err);
|
|
189
|
-
parentPort.postMessage(MESSAGE_TYPE.ERROR);
|
|
190
|
-
}));
|
|
191
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare const KB = 1000;
|
|
2
|
-
export declare const SCSS_BUNDLES_INPUT_DIR: string;
|
|
3
|
-
export declare const BASE_BUNDLES_OUT_DIR: string;
|
|
4
|
-
export declare const SCSS_BUNDLES_OUT_DIR: string;
|
|
5
|
-
export declare const CSS_BUNDLES_OUT_DIR: string;
|
|
6
|
-
export declare const BASE_BUNDLE = "base/base";
|
|
7
|
-
export declare const BASE_GLOBANT_BUNDLE = "base/base-globant";
|
|
8
|
-
export declare const BUNDLE_MAPPING_TO_HASH_FILE = "bundle-to-hash-mappings.ts";
|
|
9
|
-
export declare const BASE_CSS_FILE = "base.css";
|
|
10
|
-
export declare const BASE_GLOBANT_CSS_FILE = "base-globant.css";
|
|
11
|
-
export declare const ICONS_PATH_PLACEHOLDER = "{{ICONS_PATH}}";
|
|
12
|
-
export declare const FONT_FACE_PATH_PLACEHOLDER = "{{FONT_FACE_PATH}}";
|
|
13
|
-
export declare const DEFAULT_FONT_FACE_PATH = "./assets/fonts/";
|
|
14
|
-
export declare const DEFAULT_ICONS_PATH = "./assets/icons/";
|
|
15
|
-
export declare const DEFAULT_OUT_DIR_PATH = "./.mercury";
|
|
16
|
-
export declare const SEPARATE_BY_COMMA_REGEX: RegExp;
|
|
17
|
-
export declare const SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX: RegExp;
|
|
18
|
-
export declare const HASH_LENGTH = 16;
|
|
19
|
-
export declare const HASH_AND_LETTER_LENGTH: number;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
// import type { BundleAssociationMetadata } from "./types";
|
|
3
|
-
export const KB = 1000;
|
|
4
|
-
export const SCSS_BUNDLES_INPUT_DIR = path.join("src", "bundles", "scss");
|
|
5
|
-
export const BASE_BUNDLES_OUT_DIR = path.join("dist", "bundles");
|
|
6
|
-
export const SCSS_BUNDLES_OUT_DIR = path.join(BASE_BUNDLES_OUT_DIR, "scss");
|
|
7
|
-
export const CSS_BUNDLES_OUT_DIR = path.join(BASE_BUNDLES_OUT_DIR, "css");
|
|
8
|
-
export const BASE_BUNDLE = "base/base";
|
|
9
|
-
export const BASE_GLOBANT_BUNDLE = "base/base-globant";
|
|
10
|
-
// Files
|
|
11
|
-
export const BUNDLE_MAPPING_TO_HASH_FILE = "bundle-to-hash-mappings.ts";
|
|
12
|
-
export const BASE_CSS_FILE = "base.css";
|
|
13
|
-
export const BASE_GLOBANT_CSS_FILE = "base-globant.css";
|
|
14
|
-
// Placeholders
|
|
15
|
-
export const ICONS_PATH_PLACEHOLDER = "{{ICONS_PATH}}";
|
|
16
|
-
export const FONT_FACE_PATH_PLACEHOLDER = "{{FONT_FACE_PATH}}";
|
|
17
|
-
// Defaults
|
|
18
|
-
export const DEFAULT_FONT_FACE_PATH = "./assets/fonts/";
|
|
19
|
-
export const DEFAULT_ICONS_PATH = "./assets/icons/";
|
|
20
|
-
export const DEFAULT_OUT_DIR_PATH = "./.mercury";
|
|
21
|
-
export const SEPARATE_BY_COMMA_REGEX = /\s*,\s*/g;
|
|
22
|
-
export const SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX = /[/-]/g;
|
|
23
|
-
export const HASH_LENGTH = 16;
|
|
24
|
-
export const HASH_AND_LETTER_LENGTH = HASH_LENGTH + 1;
|
|
@@ -1,10 +0,0 @@
|
|
|
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,114 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
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"
|
|
16
|
-
});
|
|
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
|
-
};
|
|
35
|
-
};
|
|
36
|
-
export const createBundlesWithCustomPaths = async (args, avoidAllHashes = false) => {
|
|
37
|
-
const hasGlobantVariant = args.globant;
|
|
38
|
-
const outDir = path.join(args.outDirPath);
|
|
39
|
-
const CREATED_DIRS = new Set();
|
|
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 });
|
|
67
|
-
}
|
|
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
|
-
}
|
|
78
|
-
}
|
|
79
|
-
copiedFiles.push(createBundleWithCustomPath(args, options, fileMetadata, avoidAllHashes, actualFilePath));
|
|
80
|
-
});
|
|
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);
|
|
84
|
-
const bundleMappingFilePath = path.join(outDir, BUNDLE_MAPPING_TO_HASH_FILE);
|
|
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
|
|
113
|
-
});
|
|
114
|
-
};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { FileMetadata } from "./types";
|
|
2
|
-
export declare const ensureDirectoryExistsAndItsClear: (dirPath: string, filesToNotRemove?: Set<string>) => Promise<void>;
|
|
3
|
-
export declare const getFilesInDir: (dir: string) => Promise<FileMetadata[]>;
|
|
4
|
-
export declare const copyDirectories: (srcDir: string, outDir: string) => void;
|
|
5
|
-
export declare const refreshAngularBrowser: () => void;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
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 {
|
|
20
|
-
fs.rmSync(dirPath, { recursive: true });
|
|
21
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
};
|
|
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
|
-
});
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return files;
|
|
41
|
-
};
|
|
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,18 +0,0 @@
|
|
|
1
|
-
export declare const printBundleWasCreatedTableHeader: (args: {
|
|
2
|
-
outDir: string;
|
|
3
|
-
largestBundleLength: number;
|
|
4
|
-
}) => void;
|
|
5
|
-
export declare const printBundleWasCreated: (args: {
|
|
6
|
-
outDir: string;
|
|
7
|
-
bundleNameWithHash: string;
|
|
8
|
-
largestBundleLength: number;
|
|
9
|
-
largestFileSizeLength: number;
|
|
10
|
-
fileSize: string;
|
|
11
|
-
}) => void;
|
|
12
|
-
export declare const printBundleWasTranspiled: (filePath: string) => void;
|
|
13
|
-
export declare const printArgumentDoesNotExistsError: (arg: string) => void;
|
|
14
|
-
export declare const printDuplicatedArgumentError: (arg: string) => void;
|
|
15
|
-
export declare const printInvalidArgumentError: (arg: string) => void;
|
|
16
|
-
export declare const printMissingFontPathArgumentWarning: () => void;
|
|
17
|
-
export declare const printMissingIconsPathArgumentWarning: () => void;
|
|
18
|
-
export declare const printMissingOutDirPathArgumentWarning: () => void;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { styleText } from "node:util";
|
|
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));
|
|
15
|
-
export const printBundleWasTranspiled = (filePath) => console.log(styleText("greenBright", " Transpiled: ") +
|
|
16
|
-
styleText("white", SCSS_BUNDLES_OUT_DIR) +
|
|
17
|
-
styleText("whiteBright", filePath.replace(SCSS_BUNDLES_INPUT_DIR, "")));
|
|
18
|
-
export const printArgumentDoesNotExistsError = (arg) => console.log(styleText("red", " error ") +
|
|
19
|
-
styleText("gray", "Argument does not exists: ") +
|
|
20
|
-
`'${arg}'`);
|
|
21
|
-
export const printDuplicatedArgumentError = (arg) => console.log(styleText("red", " error ") +
|
|
22
|
-
styleText("gray", "Duplicated argument type: ") +
|
|
23
|
-
`'${arg}'`);
|
|
24
|
-
export const printInvalidArgumentError = (arg) => console.log(styleText("red", " error ") +
|
|
25
|
-
styleText("gray", "Invalid argument: ") +
|
|
26
|
-
`'${arg}'`);
|
|
27
|
-
export const printMissingFontPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --font-face-path argument. The path ") +
|
|
28
|
-
styleText("cyan", `'${DEFAULT_FONT_FACE_PATH}'`) +
|
|
29
|
-
styleText("yellow", " will be used as default."));
|
|
30
|
-
export const printMissingIconsPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --icons-path argument. The path ") +
|
|
31
|
-
styleText("cyan", `'${DEFAULT_ICONS_PATH}'`) +
|
|
32
|
-
styleText("yellow", " will be used as default."));
|
|
33
|
-
export const printMissingOutDirPathArgumentWarning = () => console.log(styleText("yellow", " [warning]: Missing --outDir argument. The path ") +
|
|
34
|
-
styleText("cyan", `'${DEFAULT_OUT_DIR_PATH}'`) +
|
|
35
|
-
styleText("yellow", " will be used as default."));
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import * as sass from "sass";
|
|
4
|
-
import { BASE_BUNDLE, BASE_GLOBANT_BUNDLE, BASE_GLOBANT_CSS_FILE, CSS_BUNDLES_OUT_DIR, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH, SCSS_BUNDLES_INPUT_DIR, SCSS_BUNDLES_OUT_DIR } from "./constants.js";
|
|
5
|
-
import { replacePlaceholdersInBundle, sanitizeBundleName } from "./utils.js";
|
|
6
|
-
const transpileBundle = (filePath, globant) => sass.compile(filePath, {
|
|
7
|
-
loadPaths: [globant ? "src/config/globant" : "src/config/default"],
|
|
8
|
-
style: "compressed"
|
|
9
|
-
}).css;
|
|
10
|
-
const BUNDLES = [];
|
|
11
|
-
const transpileGlobantCssFile = async (fileMetadata, cssOutDir) => {
|
|
12
|
-
const { filePath } = fileMetadata;
|
|
13
|
-
BUNDLES.push({
|
|
14
|
-
fileDir: fileMetadata.dir
|
|
15
|
-
.replace(SCSS_BUNDLES_OUT_DIR, "")
|
|
16
|
-
.replace("\\", "/")
|
|
17
|
-
});
|
|
18
|
-
const transpiledBundle = transpileBundle(filePath, true);
|
|
19
|
-
// Store the CSS file with its default values
|
|
20
|
-
await fs.writeFile(path.join(cssOutDir, BASE_GLOBANT_CSS_FILE), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
|
|
21
|
-
};
|
|
22
|
-
export const transpileCssBundleWithPlaceholder = async (fileMetadata, args) => {
|
|
23
|
-
const { fileName } = fileMetadata;
|
|
24
|
-
let actualFilePath = fileMetadata.filePath;
|
|
25
|
-
const hasGlobantVariant = args?.globant ?? false;
|
|
26
|
-
const cssOutDir = fileMetadata.dir.replace(SCSS_BUNDLES_INPUT_DIR, CSS_BUNDLES_OUT_DIR);
|
|
27
|
-
const fileNameCssExt = fileName.replace(".scss", ".css");
|
|
28
|
-
const bundleName = sanitizeBundleName(actualFilePath.replace(SCSS_BUNDLES_INPUT_DIR, "").replace(".scss", ""));
|
|
29
|
-
// There is no need to generate the base-globant.css file, since the base.css
|
|
30
|
-
// file already contains this file
|
|
31
|
-
if (hasGlobantVariant) {
|
|
32
|
-
if (bundleName === BASE_GLOBANT_BUNDLE) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
// Replace the content of the base bundle with the Globant variant
|
|
36
|
-
if (bundleName === BASE_BUNDLE) {
|
|
37
|
-
actualFilePath = actualFilePath.replace(BASE_BUNDLE, BASE_GLOBANT_BUNDLE);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// The Globant variant is not forced, so we are creating both bundles, the
|
|
41
|
-
// base/base and base/base-globant bundles
|
|
42
|
-
else if (bundleName === BASE_BUNDLE) {
|
|
43
|
-
transpileGlobantCssFile({
|
|
44
|
-
dir: fileMetadata.dir,
|
|
45
|
-
fileName: fileName.replace(BASE_BUNDLE, BASE_GLOBANT_BUNDLE),
|
|
46
|
-
filePath: actualFilePath
|
|
47
|
-
}, cssOutDir);
|
|
48
|
-
}
|
|
49
|
-
BUNDLES.push({
|
|
50
|
-
fileDir: fileMetadata.dir
|
|
51
|
-
.replace(SCSS_BUNDLES_INPUT_DIR, "")
|
|
52
|
-
.replace("\\", "/")
|
|
53
|
-
});
|
|
54
|
-
const transpiledBundle = transpileBundle(actualFilePath, hasGlobantVariant);
|
|
55
|
-
// Store the CSS file with its default values
|
|
56
|
-
await fs.writeFile(path.join(cssOutDir, fileNameCssExt), replacePlaceholdersInBundle(transpiledBundle, DEFAULT_FONT_FACE_PATH, DEFAULT_ICONS_PATH));
|
|
57
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export type BundleMetadata = {
|
|
2
|
-
fileDir: string;
|
|
3
|
-
};
|
|
4
|
-
export type BundleAssociationMetadata = {
|
|
5
|
-
bundleName: string;
|
|
6
|
-
fileDir: string;
|
|
7
|
-
transpiledBundle: string;
|
|
8
|
-
};
|
|
9
|
-
export type FileMetadata = {
|
|
10
|
-
dir: string;
|
|
11
|
-
fileName: string;
|
|
12
|
-
filePath: string;
|
|
13
|
-
};
|
|
14
|
-
export type CLIArguments = {
|
|
15
|
-
avoidHash: Set<string>;
|
|
16
|
-
globant: boolean;
|
|
17
|
-
iconsPath: string;
|
|
18
|
-
fontFacePath: string;
|
|
19
|
-
outDirPath: string;
|
|
20
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { FileMetadata } from "./types";
|
|
2
|
-
export declare const getFileSize: (fileContent: string) => string;
|
|
3
|
-
export declare const getHash: (fileContent: string) => string;
|
|
4
|
-
export declare const getFileNameWithHash: <B extends string, H extends string>(bundleName: B, hash: H) => `${B}-${H}`;
|
|
5
|
-
export declare const replacePlaceholdersInBundle: (transpiledBundle: string, fontFaceValue: string, iconsValue: string) => string;
|
|
6
|
-
export declare const measureTime: (callback: (() => void) | (() => Promise<void>)) => Promise<void>;
|
|
7
|
-
export declare const sanitizeBundleName: (bundleName: string) => string;
|
|
8
|
-
export declare const getBundleFolder: (fileMetadata: FileMetadata) => string;
|
|
9
|
-
export declare const getBundleFolderAndFileBaseDir: (fileMetadata: FileMetadata, outDir: string) => {
|
|
10
|
-
bundleFolder: string;
|
|
11
|
-
fileBaseDirToWrite: string;
|
|
12
|
-
};
|
|
13
|
-
export declare const getFileNameWithoutExt: (fileMetadata: FileMetadata) => string;
|
|
14
|
-
export declare const getBundleName: (fileMetadata: FileMetadata) => string;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import crypto from "node:crypto";
|
|
2
|
-
import { styleText } from "node:util";
|
|
3
|
-
import { CSS_BUNDLES_OUT_DIR, FONT_FACE_PATH_PLACEHOLDER, HASH_LENGTH, ICONS_PATH_PLACEHOLDER, KB
|
|
4
|
-
// SPECIAL_CHARS_IN_BUNDLE_NAME_REGEX
|
|
5
|
-
} from "./constants.js";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
export const getFileSize = (fileContent) => {
|
|
8
|
-
const fileLength = fileContent.length;
|
|
9
|
-
if (fileLength < KB) {
|
|
10
|
-
return fileLength + " bytes";
|
|
11
|
-
}
|
|
12
|
-
const fileLengthInKB = fileLength / KB;
|
|
13
|
-
if (fileLengthInKB < KB) {
|
|
14
|
-
return fileLengthInKB.toFixed(2) + " kB";
|
|
15
|
-
}
|
|
16
|
-
const fileLengthInMB = fileLengthInKB / KB;
|
|
17
|
-
if (fileLengthInMB < KB) {
|
|
18
|
-
return fileLengthInMB.toFixed(2) + " MB";
|
|
19
|
-
}
|
|
20
|
-
const fileLengthInGB = fileLengthInMB / KB;
|
|
21
|
-
return fileLengthInGB.toFixed(2) + " GB";
|
|
22
|
-
};
|
|
23
|
-
export const getHash = (fileContent) => crypto
|
|
24
|
-
.createHash("md5")
|
|
25
|
-
.update(fileContent)
|
|
26
|
-
.digest("hex")
|
|
27
|
-
.substring(HASH_LENGTH);
|
|
28
|
-
export const getFileNameWithHash = (bundleName, hash) => `${bundleName}-${hash}`;
|
|
29
|
-
export const replacePlaceholdersInBundle = (transpiledBundle, fontFaceValue, iconsValue) => transpiledBundle
|
|
30
|
-
.replaceAll(ICONS_PATH_PLACEHOLDER, iconsValue)
|
|
31
|
-
.replaceAll(FONT_FACE_PATH_PLACEHOLDER, fontFaceValue);
|
|
32
|
-
export const measureTime = async (callback) => {
|
|
33
|
-
console.time(styleText("green", "Done in"));
|
|
34
|
-
await callback();
|
|
35
|
-
console.timeEnd(styleText("green", "Done in"));
|
|
36
|
-
};
|
|
37
|
-
export const sanitizeBundleName = (bundleName) => bundleName.replaceAll("\\", "/").replace(/^\//, "");
|
|
38
|
-
export const getBundleFolder = (fileMetadata) => fileMetadata.dir.split(CSS_BUNDLES_OUT_DIR)[1];
|
|
39
|
-
export const getBundleFolderAndFileBaseDir = (fileMetadata, outDir) => {
|
|
40
|
-
const bundleFolder = getBundleFolder(fileMetadata);
|
|
41
|
-
return {
|
|
42
|
-
bundleFolder,
|
|
43
|
-
fileBaseDirToWrite: path.join(outDir, bundleFolder)
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
export const getFileNameWithoutExt = (fileMetadata) => fileMetadata.fileName.replace(/.css$/, "");
|
|
47
|
-
export const getBundleName = (fileMetadata) => sanitizeBundleName(`${getBundleFolder(fileMetadata)}/${getFileNameWithoutExt(fileMetadata)}`);
|