@ibgib/helper-gib
Version:
common helper/utils/etc used in ibgib libs. Node v19+ needed for heavily-used isomorphic webcrypto hashing consumed in both node and browsers.
177 lines • 6.76 kB
JavaScript
import { readdir } from 'node:fs/promises';
import { statSync } from 'node:fs';
import * as pathUtils from 'path';
import { HELPER_LOG_A_LOT } from './constants.mjs';
import { pretty } from './helpers/utils-helper.mjs';
import { getGlobalRespecGib } from './respec-gib/respec-gib.mjs';
import { respecFileHasExtraRespec } from './respec-gib/respec-gib-helper.mjs';
// #region settings
/**
* This is how I enable/disable verbose logging. Do with it what you will.
*/
const logalot = HELPER_LOG_A_LOT || false;
/** set this to the root of the respecs to look at */
const RESPEC_ROOT_DIR_RELATIVE_TO_BASE = './dist';
/** change this to suit your naming convention */
const RESPEC_FILE_REG_EXP = /^.+respec\.mjs$/;
// const RESPEC_FILE_REG_EXP = /^.*respec-gib.respec\.mjs$/;
// if (respecPath.includes('respec-gib.respec.mjs')) {
/**
* If on, will first load a file and see if there is an extra respecful
* `respecfully`/`ifWe` block. Use these if you want to focus on a single or
* subset of respecs.
*
* If there are no extra respecful blocks found in an entire file, that file
* will be skipped.
*
* Note: this only is a flag to search through respec files.
*/
const LOOK_FOR_EXTRA_RESPEC = true;
/**
* The names of the functions that indicate that we want to focus on just those
* blocks.
*
* ATOW, for first run implementation here, I am implementing it such that it
* will filter out files that don't have these indicators. The respec files that
* do have these will execute fully, but the output will only include these
* particular blocks.
*/
const EXTRA_RESPEC_FUNCTION_NAMES = ['respecfullyDear', 'ifWeMight'];
// #endregion settings
// #region 1. get respec paths
const basePath = process.cwd();
const srcPath = pathUtils.join(basePath, RESPEC_ROOT_DIR_RELATIVE_TO_BASE);
if (logalot) {
console.log(`cwd: ${process.cwd()}`);
}
if (logalot) {
console.log(`basePath: ${basePath}`);
}
if (logalot) {
console.log(`srcPath: ${srcPath}`);
}
const respecGib = getGlobalRespecGib();
const allRespecPaths = await getRespecFileFullPaths(srcPath, []);
if (logalot) {
console.log(`allRespecPaths: ${allRespecPaths} (I: f5182a455375a8cf2aa6e1127a082423)`);
}
let filteredRespecPaths = undefined;
if (LOOK_FOR_EXTRA_RESPEC) {
const hasExtraRespecPromises = allRespecPaths.map(async (respecPath) => {
const hasExtra = await respecFileHasExtraRespec(respecPath, EXTRA_RESPEC_FUNCTION_NAMES);
return [respecPath, hasExtra];
});
const resPathHasExtraTuples = await Promise.all(hasExtraRespecPromises);
filteredRespecPaths = resPathHasExtraTuples
.filter(([_respecPath, hasExtra]) => hasExtra)
.map(([respecPath, _hasExtra]) => respecPath);
// if there are no files that have extra respec then we do all files
if (filteredRespecPaths.length === 0) {
if (logalot) {
console.log(`filteredRespecPaths is empty. doing allRespecPaths found (I: b98f54656899646025eecb4c028ab523)`);
}
filteredRespecPaths = allRespecPaths.concat();
}
else {
console.log(`filteredRespecPaths for extra respec: ${filteredRespecPaths} (I: b98f54656899646025eecb4c028ab523)`);
respecGib.extraRespecOnly = true;
}
}
// #endregion 1. get respec paths
respecGib.allRespecPaths = allRespecPaths;
respecGib.filteredRespecPaths = filteredRespecPaths;
const respecPaths = filteredRespecPaths ?? allRespecPaths;
respecGib.respecPaths = respecPaths;
if (logalot) {
console.log(`respecPaths found:\n${respecPaths}`);
}
// #region 2. execute paths' respective respecs
// for now, we'll do sequentially, but in the future we could conceivable farm
// these out to other node processes, or at least Promise.all
for (let i = 0; i < respecPaths.length; i++) {
const respecPath = respecPaths[i];
if (logalot) {
console.log(respecPath);
}
const esm = await import(respecPath);
if (logalot) {
console.log(pretty(Object.keys(esm)));
}
}
const skippedRespecPathCount = respecGib.allRespecPaths.length - respecGib.respecPaths.length;
if (skippedRespecPathCount > 0) {
console.log('');
console.error('\x1b[33m%s\x1b[0m', `${skippedRespecPathCount} respec files completely skipped.`); // yellow
}
if (respecGib.ifWeBlocksSkipped > 0) {
console.log('');
console.error('\x1b[33m%s\x1b[0m', `${respecGib.ifWeBlocksSkipped} ifWe blocks ran but skipped reporting`); // yellow
}
if (respecGib.errorMsgs.length === 0) {
console.log('');
console.error('\x1b[32m%s\x1b[0m', `💚💚 nothing but respec 💚💚`); // green
}
else {
console.log('');
console.error('\x1b[31m%s\x1b[0m', `💔💔 DISrespec found 💔💔`); // red
for (const errorMsg of respecGib.errorMsgs) {
console.error('\x1b[31m%s\x1b[0m', errorMsg); // red
}
}
// #endregion 2. execute paths' respective respecs
// #region helper functions
/**
* builds a list of respec file paths, recursively traversing subdirectories
* starting from `dirPath`.
*
* @param dirPath a full path corresponding to a directory
* @param found respec paths already found (used in recursive calls)
* @returns list of all respec paths according to the respec regexp constant {@link RESPEC_FILE_REG_EXP}
*/
async function getRespecFileFullPaths(dirPath, found) {
const lc = `[${getRespecFileFullPaths.name}][${dirPath}]`;
try {
if (logalot) {
console.log(`${lc} starting... (I: 16026290523925f79ba1933847e2a623)`);
}
found ??= [];
const children = await readdir(dirPath);
if (logalot) {
for (let i = 0; i < children.length; i++) {
console.log(children[i]);
}
}
const files = [];
const dirs = [];
children.forEach(name => {
const fullPath = pathUtils.join(dirPath, name);
const stat = statSync(fullPath);
if (stat.isDirectory()) {
// symbolic link could create a loop
if (!stat.isSymbolicLink()) {
dirs.push(fullPath);
}
}
else if (!!name.match(RESPEC_FILE_REG_EXP)) {
files.push(fullPath);
}
});
found = found.concat(files);
for (let i = 0; i < dirs.length; i++) {
const subfound = await getRespecFileFullPaths(dirs[i], found);
found = found.concat(subfound);
}
return Array.from(new Set(found)); // unique
}
catch (error) {
console.error(`${lc} ${error.message}`);
throw error;
}
finally {
if (logalot) {
console.log(`${lc} complete.`);
}
}
}
// #endregion helper functions
//# sourceMappingURL=respec-gib.node.mjs.map