UNPKG

@contentstack/cli-utilities

Version:

Utilities for contentstack projects

380 lines (379 loc) 14.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFileList = exports.getDirectories = void 0; const tslib_1 = require("tslib"); const mkdirp_1 = tslib_1.__importDefault(require("mkdirp")); const keys_1 = tslib_1.__importDefault(require("lodash/keys")); const uuid_1 = require("uuid"); const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty")); const node_path_1 = require("node:path"); const node_fs_1 = require("node:fs"); const helper_1 = require("./helper"); class FsUtility { constructor(options = {}) { var _a; this.isArray = false; this.prefixKey = ''; this.currentFileName = ''; this.keepMetadata = false; this.metaData = {}; this.readIndexer = {}; this.writeIndexer = {}; this.pageInfo = { after: 0, before: 0, hasNextPage: false, hasPreviousPage: false, pageInfoUpdated: false, }; const { isArray, fileExt, omitKeys, basePath, moduleName, metaHandler, keepMetadata, metaPickKeys, chunkFileSize, indexFileName, defaultInitContent, useIndexer = false, createDirIfNotExist = true, } = options; this.metaHandler = metaHandler; this.isArray = isArray; this.basePath = basePath || ''; this.omitKeys = omitKeys || []; this.fileExt = fileExt || 'json'; this.metaPickKeys = metaPickKeys || []; this.moduleName = moduleName || 'chunk'; this.chunkFileSize = chunkFileSize || 10; this.keepMetadata = keepMetadata || ((_a = keepMetadata === undefined) !== null && _a !== void 0 ? _a : true); this.indexFileName = indexFileName || 'index.json'; this.pageInfo.hasNextPage = (0, keys_1.default)(this.indexFileContent).length > 0; this.defaultInitContent = defaultInitContent || this.isArray ? '[' : this.fileExt === 'json' ? '{' : ''; if (useIndexer) { this.writeIndexer = this.indexFileContent; } if (createDirIfNotExist) { this.createFolderIfNotExist(this.basePath); } } get isNewFsStructure() { return (0, node_fs_1.existsSync)(`${this.basePath}/metadata.json`) && (0, node_fs_1.existsSync)(`${this.basePath}/files`); } get isIndexFileExist() { return (0, node_fs_1.existsSync)(`${this.basePath}/${this.indexFileName}`); } get currentPageDetails() { return this.pageInfo; } get indexFileContent() { let indexData = {}; const indexPath = `${this.basePath}/${this.indexFileName}`; if ((0, node_fs_1.existsSync)(indexPath)) { indexData = JSON.parse((0, node_fs_1.readFileSync)(indexPath, 'utf8')); } return indexData; } /** * @method readChunkFiles * @returns Object */ get readChunkFiles() { return { next: this.next.bind(this), previous: this.previous.bind(this), get: this.getFileByIndex.bind(this), }; } // STUB old utility methods /** * @method readFile * @param filePath string * @param parse boolean | undefined * @returns string | undefined */ readFile(filePath, parse = undefined) { let data; filePath = (0, node_path_1.resolve)(filePath); parse = typeof parse === 'undefined' ? true : parse; if ((0, node_fs_1.existsSync)(filePath)) { data = parse ? JSON.parse((0, node_fs_1.readFileSync)(filePath, 'utf8')) : data; } return data; } /** * @method writeFile * @param filePath string * @param data Object | undefined * @return void */ writeFile(filePath, data, mapKeyVal = false) { if (mapKeyVal) { data = (0, helper_1.mapKeyAndVal)(data, 'uid', this.omitKeys); // NOTE Map values as Key/value pair object } data = typeof data === 'object' ? JSON.stringify(data) : data || '{}'; (0, node_fs_1.writeFileSync)(filePath, data); } /** * @method makeDirectory * @param path string * @return Promise<string | undefined> */ makeDirectory(path) { return (0, mkdirp_1.default)(path); } /** * @method readdir * @param dirPath string | Buffer | URL * @returns [string] */ readdir(dirPath) { return (0, node_fs_1.existsSync)(dirPath) ? (0, node_fs_1.readdirSync)(dirPath) : []; } // STUB End of old utility /** * @method createFolderIfNotExist * @param path string * @return {void} */ createFolderIfNotExist(path) { if (path && !(0, node_fs_1.existsSync)(path)) { (0, node_fs_1.mkdirSync)(path, { recursive: true }); } } /** * @method writeIntoFile * @param {String|Object|Array} chunk Record<string, string>[] * @param {WriteFileOptions} options WriteFileOptions * @return void */ writeIntoFile(chunk, options) { if (!this.writableStream) { this.createNewFile(); } this.writeIntoExistingFile(chunk, options); } /** * @method createNewFile * @return {void} * @description creating new chunk file */ createNewFile() { const fileName = `${(0, uuid_1.v4)()}-${this.moduleName || 'chunk'}.${this.fileExt}`; this.currentFileName = fileName; this.writeIndexer[(0, keys_1.default)(this.writeIndexer).length + 1] = fileName; this.currentFileRelativePath = `${this.basePath}/${fileName}`; (0, node_fs_1.writeFileSync)(this.currentFileRelativePath, this.defaultInitContent); this.writableStream = (0, node_fs_1.createWriteStream)(this.currentFileRelativePath, { flags: 'a', }); } /** * @method writeIntoExistingFile * @param chunk Record<string, string>[] | object | Array<any> | string; * @param options WriteFileOptions * @returns void */ writeIntoExistingFile(chunk, options) { var _a; let fileContent = chunk; let fileSizeReachedLimit = false; const { keyName, mapKeyVal } = options || { keyName: 'uid', mapKeyVal: false, }; if (mapKeyVal) { fileContent = this.handleKeyValMapAndMetaData(chunk, keyName); // NOTE Map values as Key/value pair object } if (typeof fileContent === 'object') { fileContent = JSON.stringify(fileContent).slice(1, -1); } const { size } = (0, node_fs_1.statSync)(this.currentFileRelativePath); if ((options === null || options === void 0 ? void 0 : options.closeFile) === true || size / (1024 * 1024) >= this.chunkFileSize) { // NOTE Each chunk file size Ex. 5 (MB) fileSizeReachedLimit = true; } const suffix = fileSizeReachedLimit ? (this.isArray ? ']' : '}') : ''; fileContent = this.fileExt === 'json' ? `${this.prefixKey}${fileContent}${suffix}` : fileContent; (_a = this.writableStream) === null || _a === void 0 ? void 0 : _a.write(fileContent); if (!this.prefixKey) this.prefixKey = ','; if (fileSizeReachedLimit) { this.closeFile((options === null || options === void 0 ? void 0 : options.closeFile) === true); } } /** * @method handleKeyValMapAndMetaData * @param chunk Chunk * @param keyName string * @returns Chunk */ handleKeyValMapAndMetaData(chunk, keyName) { const fileContent = (0, helper_1.mapKeyAndVal)(chunk, keyName || 'uid', this.omitKeys); // NOTE Map values as Key/value pair object // NOTE update metadata if (this.keepMetadata) { const metadata = (0, helper_1.getMetaData)(chunk, this.metaPickKeys, this.metaHandler); if (metadata && !(0, isEmpty_1.default)(metadata)) { if ((0, isEmpty_1.default)(this.metaData[this.currentFileName])) this.metaData[this.currentFileName] = []; this.metaData[this.currentFileName].push(...metadata); } } return fileContent; } /** * @method completeFile * @param closeIndexer boolean * @return {void} * @description writing chunks into existing file */ completeFile(closeIndexer) { if (this.writableStream) { if (this.fileExt === 'json') { this.writableStream.write(this.isArray ? ']' : '}'); } } this.closeFile(closeIndexer); } /** * @method closeFile * @param closeIndexer boolean * @return {void} * @description closing current write stream */ closeFile(closeIndexer = true) { if (closeIndexer) { // NOTE write file index details into a file (0, node_fs_1.writeFileSync)(`${this.basePath}/${this.indexFileName}`, JSON.stringify(this.writeIndexer)); // NOTE write metadata into a file if (this.keepMetadata) { (0, node_fs_1.writeFileSync)(`${this.basePath}/metadata.json`, JSON.stringify(this.metaData)); } } if (this.writableStream instanceof node_fs_1.WriteStream) { this.writableStream.end(); this.prefixKey = ''; this.writableStream = null; } } saveMeta(meta) { (0, node_fs_1.writeFileSync)(`${this.basePath}/metadata.json`, JSON.stringify(meta)); } getPlainMeta(basePath) { const path = basePath || (0, node_path_1.resolve)(this.basePath, 'metadata.json'); if (!(0, node_fs_1.existsSync)(path)) return {}; return JSON.parse((0, node_fs_1.readFileSync)(path, { encoding: 'utf8' })); } /** * @method getFileByIndex * @param _self FsUtility * @param index number * @returns Promise<string> */ getFileByIndex(index = 1) { return new Promise((resolve, reject) => { if (index <= 0) { reject(new Error('Invalid index')); return; } this.updatePageInfo(null, index); if ((0, isEmpty_1.default)(this.readIndexer[index])) { reject(new Error('File not found!')); return; } const fileContent = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(this.basePath, this.readIndexer[index]), { encoding: 'utf8', }); resolve(this.fileExt === 'json' ? JSON.parse(fileContent) : fileContent); }); } /** * @method next * @returns Promise<string> */ next() { return new Promise((resolve, reject) => { this.updatePageInfo(true); if ((0, isEmpty_1.default)(this.readIndexer[this.pageInfo.after])) { reject(new Error('File not found!')); return; } const fileContent = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(this.basePath, this.readIndexer[this.pageInfo.after]), { encoding: 'utf8', }); resolve(this.fileExt === 'json' ? JSON.parse(fileContent) : fileContent); }); } /** * @method previous * @param _self FsUtility * @returns Promise<string> */ previous() { return new Promise((resolve, reject) => { this.updatePageInfo(false); if ((0, isEmpty_1.default)(this.readIndexer[this.pageInfo.before])) { reject(new Error('File not found')); return; } const fileContent = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(this.basePath, this.readIndexer[this.pageInfo.before]), { encoding: 'utf8', }); resolve(this.fileExt === 'json' ? JSON.parse(fileContent) : fileContent); }); } /** * @method updatePageInfo * @param _self FsUtility * @param isNext boolean * @param index number * @returns void */ updatePageInfo(isNext = true, index = null) { if (!this.pageInfo.pageInfoUpdated) { this.readIndexer = this.indexFileContent; this.pageInfo.pageInfoUpdated = true; } const { after, before } = this.pageInfo; if (isNext === true) { this.pageInfo.before = 1; this.pageInfo.after = after + 1; } else if (isNext === false) { this.pageInfo.after = 0; this.pageInfo.before = before - 1; } else { this.pageInfo.after = index || 0; this.pageInfo.before = 1; } /* eslint-disable unicorn/consistent-destructuring */ if (!(0, isEmpty_1.default)(this.readIndexer[this.pageInfo.after + 1])) { this.pageInfo.hasNextPage = true; } /* eslint-disable unicorn/consistent-destructuring */ if (!(0, isEmpty_1.default)(this.readIndexer[this.pageInfo.after - 1])) { this.pageInfo.hasPreviousPage = true; } } removeFile(path) { if ((0, node_fs_1.existsSync)(path)) (0, node_fs_1.unlinkSync)(path); } } exports.default = FsUtility; function getDirectories(source) { if (!(0, node_fs_1.existsSync)(source)) return []; return (0, node_fs_1.readdirSync)(source, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) .map((dirent) => dirent.name); } exports.getDirectories = getDirectories; async function getFileList(dirName, onlyName = true) { if (!(0, node_fs_1.existsSync)(dirName)) return []; let files = []; const items = (0, node_fs_1.readdirSync)(dirName, { withFileTypes: true }); for (const item of items) { if (item.isDirectory()) { /* eslint-disable no-await-in-loop */ files = [...files, ...(await getFileList(`${dirName}/${item.name}`))]; } else { files.push(onlyName ? item.name : `${dirName}/${item.name}`); } } return files; } exports.getFileList = getFileList;