UNPKG

@eluvio/elv-utils-js

Version:

Utilities for the Eluvio Content Fabric

137 lines (114 loc) 4.05 kB
// Code for working with files within content fabric objects const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel') const getPath = require('@eluvio/elv-js-helpers/Functional/getPath') const isNumber = require('@eluvio/elv-js-helpers/Boolean/isNumber') const sortBy = require('@eluvio/elv-js-helpers/Functional/sortBy') const throwIfArgsBad = require('@eluvio/elv-js-helpers/Validation/throwIfArgsBad') const FabricFilePathModel = require('../models/FabricFilePathModel') const LibraryIdModel = require('../models/LibraryIdModel') const ObjectIdModel = require('../models/ObjectIdModel') const VersionHashModel = require('../models/VersionHashModel') const Client = require('./Client') const Logger = require('./Logger') const Metadata = require('./Metadata') const blueprint = { name: 'FabricFile', concerns: [Client, Logger, Metadata] } const READ_FILE_PATH_ARGS_MODEL = defObjectModel('exists()', { filePath: FabricFilePathModel, libraryId: [LibraryIdModel], objectId: [ObjectIdModel], versionHash: [VersionHashModel] }) const isDir = fileMapEntry => fileMapEntry['.']?.type === 'directory' const isEncrypted = fileMapEntry => fileMapEntry['.']?.encryption?.scheme === 'cgck' const isFile = fileMapEntry => !isDir(fileMapEntry) && !isLink(fileMapEntry) const isLink = fileMapEntry => fileMapEntry['.']?.reference?.path !== undefined const mapEntry = (listFilesResult, filePath) => { const pathArray = pathToArray(filePath) return getPath(pathArray, listFilesResult) } const mapToList = (obj, currentPath = '/') => { let result = [] for (const [k,v] of Object.entries(obj)) { if(v.type !== 'directory') { if(isNumber(v['.']?.size)) { result.push({ path:`${currentPath}${k}`, size: v['.'].reference?.size || v['.'].size, encrypted: isEncrypted(v), link_remote_path: v['.'].reference?.path }) } else { result = result.concat(mapToList(v, `${currentPath}${k}/`)) } } } return sortBy(e => [(e.path.match(/\//g) || []).length, e.path.toLowerCase()], result) } const pathToArray = filePath => { throwIfArgsBad({filePath: FabricFilePathModel},{filePath}) return filePath.slice(1).split('/') } const New = context => { // const logger = context.concerns.Logger; // checks if a file exists const exists = async ({filePath, libraryId, objectId, versionHash}) => { throwIfArgsBad(READ_FILE_PATH_ARGS_MODEL,{filePath, libraryId, objectId, versionHash}) let filesMap = await filesMap({ libraryId, objectId, versionHash }) const entry = mapEntry(filesMap, filePath) return entry !== undefined } const fileList = async ({libraryId, objectId, versionHash}) => { const fMap = await filesMap({libraryId, objectId, versionHash}) return mapToList(fMap) } const filesMap = async ({libraryId, objectId, versionHash}) => { const client = await context.concerns.Client.get() try { return await client.ListFiles({ libraryId, objectId, versionHash }) } catch (e) { // try retrieving all metadata, so we can get better error if e.g. object not found const objMetadata = await context.concerns.Metadata.get({libraryId, objectId, versionHash}) if(Object.keys(objMetadata).includes('files')) { // should never be the case, but return anyway if somehow found return objMetadata.files } else { // return empty map - no files return {} } } } const pathInfo = async ({filePath, libraryId, objectId, versionHash}) => { throwIfArgsBad(READ_FILE_PATH_ARGS_MODEL,{filePath, libraryId, objectId, versionHash}) const fMap = await filesMap({libraryId, objectId, versionHash}) return mapEntry(fMap, filePath) } // instance interface return { exists, fileList, filesMap, pathInfo } } module.exports = { blueprint, isDir, isEncrypted, isFile, isLink, mapEntry, mapToList, New, pathToArray }