@hotglue/cli
Version:
hotglue CLI tools
245 lines (196 loc) • 6.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.streamToString = exports.makeSetFromArray = exports.getFolderFiles = exports.filterFiles = exports.buildChunks = void 0;
exports.userSetOption = userSetOption;
var _path = _interopRequireDefault(require("path"));
var _promises = require("fs/promises");
var _debug = _interopRequireDefault(require("./debug"));
var _micromatch = _interopRequireDefault(require("micromatch"));
var _print = require("./print");
var _descriptions = _interopRequireDefault(require("./descriptions"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug.default)('utils');
const makeSetFromArray = arr => {
const result = new Set();
arr.forEach(item => result.add(item));
return result;
};
/**
* Get list of files in given folder and its subfolders that match against a pattern.
* ex: await getSubFolderFiles(process.cwd(), ['!d/sync-output', '!d/etl-output', '!d/snapshots']);
* @param {string} dir starting directory
* @param {Array<string>} pattern The match patterns. ex: '!my_folder', 'd/uploads', '!f/exclude.txt'
* @returns {Array<string>} All file paths that meet the pattern criteria
*/
exports.makeSetFromArray = makeSetFromArray;
const getSubFolderFiles = async (dir, pattern) => {
const matches = {
excludedDirs: new Set(),
excludedFiles: new Set(),
includedDirs: new Set(),
includedFiles: new Set()
};
if (pattern && pattern.length > 0) {
const excluded = [];
const included = [];
pattern.forEach(item => {
if (item.startsWith('!')) excluded.push(item.substring(1));else included.push(item);
});
included.forEach(item => {
if (item.startsWith('d/')) matches.includedDirs.add(item.substring(2));else if (item.startsWith('f/')) matches.includedFiles.add(item.substring(2));else {
matches.includedDirs.add(item);
matches.includedFiles.add(item);
}
});
excluded.forEach(item => {
if (item.startsWith('d/')) matches.excludedDirs.add(item.substring(2));else if (item.startsWith('f/')) matches.excludedFiles.add(item.substring(2));else {
matches.excludedDirs.add(item);
matches.excludedFiles.add(item);
}
});
}
return _getSubFolderFiles(dir, matches);
};
const _getSubFolderFiles = async (dir, matches) => {
const files = await (0, _promises.readdir)(dir, {
withFileTypes: true
});
const result = [];
for (const file of files) {
if (!file.isSymbolicLink()) {
if (file.isFile() && (!matches.excludedFiles.has(file.name) || matches.includedFiles.has(file.name))) result.push(_path.default.resolve(dir, file.name));else if (file.isDirectory() && (!matches.excludedDirs.has(file.name) || matches.includedFiles.has(file.name))) {
const sub = await _getSubFolderFiles(_path.default.resolve(dir, file.name), matches);
if (sub.length > 0) result.push(...sub);
}
}
}
return result;
};
const _getFolderFiles = async (dir, options, result = []) => {
const {
includeSymLinks,
recursive,
filter
} = options;
const {
matcher
} = filter;
const fullPath = _path.default.resolve(dir);
const files = await (0, _promises.readdir)(fullPath, {
withFileTypes: true
});
for (const file of files) {
const filePath = _path.default.resolve(fullPath, file.name);
if (file.isSymbolicLink() && !includeSymLinks) {
continue;
}
if (matcher && !matcher(filePath)) {
debug('skip', filePath);
continue;
}
if (file.isFile()) {
result.push(_path.default.resolve(fullPath, file.name));
} else if (file.isDirectory() && recursive) {
await _getFolderFiles(_path.default.resolve(fullPath, file.name), options, result);
}
}
return result;
};
const getFolderFiles = async (dir, options) => {
const _options = {
includeSymLinks: false,
recursive: false,
filter: {},
...options
};
const {
pattern
} = _options.filter;
if (pattern) {
_options.filter.matcher = _micromatch.default.matcher(pattern);
}
return _getFolderFiles(dir, _options);
};
exports.getFolderFiles = getFolderFiles;
const filterFiles = (files, filter) => {
debug('filter-in', files);
const {
pattern
} = { ...filter
};
let result = files;
if (pattern) result = (0, _micromatch.default)(result, pattern);
debug('filter-out', result);
return result;
};
/**
* todo: implement my variant:
* - explicit f/ and d/ prefixes
* -
* @param {*} pattern
* @returns a matcher instance
*/
exports.filterFiles = filterFiles;
function createMatcher(pattern) {
const matches = {
excludedDirs: new Set(),
excludedFiles: new Set(),
includedDirs: new Set(),
includedFiles: new Set()
};
const excluded = [];
const included = [];
pattern.forEach(item => {
if (item.startsWith('!')) excluded.push(item.substring(1));else included.push(item);
});
included.forEach(item => {
if (item.startsWith('d/')) matches.includedDirs.add(item.substring(2));else if (item.startsWith('f/')) matches.includedFiles.add(item.substring(2));else {
matches.includedDirs.add(item);
matches.includedFiles.add(item);
}
});
excluded.forEach(item => {
if (item.startsWith('d/')) matches.excludedDirs.add(item.substring(2));else if (item.startsWith('f/')) matches.excludedFiles.add(item.substring(2));else {
matches.excludedDirs.add(item);
matches.excludedFiles.add(item);
}
});
const match = path => {};
return {
match
};
}
function userSetOption(option) {
var _descriptions$options, _descriptions$options2;
function wasArgPassed(option) {
return process.argv.indexOf(option) > -1;
}
if (wasArgPassed(`--${option}`)) {
return true;
} // Handle aliases for same option
const aliases = ((_descriptions$options = _descriptions.default.options[option]) === null || _descriptions$options === void 0 ? void 0 : (_descriptions$options2 = _descriptions$options.config) === null || _descriptions$options2 === void 0 ? void 0 : _descriptions$options2.alias) || [];
for (let i in aliases) {
if (wasArgPassed(`-${aliases[i]}`)) return true;
}
return false;
}
const streamToString = stream => {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('error', reject);
stream.on('data', c => chunks.push(Buffer.from(c)));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
});
};
exports.streamToString = streamToString;
const buildChunks = (array, chunkSize = 10) => {
const resultArray = [];
for (let i = 0; i < array.length; i += chunkSize) {
const chunk = array.slice(i, i + chunkSize);
resultArray.push(chunk);
}
return resultArray;
};
exports.buildChunks = buildChunks;