import {isUndefined, has} from "lodash"; import {take} from "lodash/fp"; import {Readable, Writable} from "readable-stream"; import { Buffer } from "safe-buffer"; import {splitKey, joinKey, $} from "../src/common"; import {getLastPartInKey} from "../src/templateApi/hierarchy"; const folderMarker = "OH-YES-ITSA-FOLDER-"; const isFolder = val => val.includes(folderMarker); const getParentFolderKey = key => $(key, [ splitKey, take((splitKey(key).length - 1)), joinKey, ]); const getParentFolder = (data,key) => { const parentKey = getParentFolderKey(key); if(data[parentKey] === undefined) throw new Error("Parent folder for " + key + " does not exist (" + parentKey + ")"); return JSON.parse(data[parentKey]); } const addItemToParentFolder = (data, path) => { if(getParentFolderKey(path) === "/") return; const parentFolder = getParentFolder(data, path); parentFolder.items.push( getLastPartInKey(path)); data[getParentFolderKey(path)] = JSON.stringify(parentFolder); } export const createFile = data => async (path, content) => { if(await exists(data)(path)) { throw new Error(path + " already exists"); } addItemToParentFolder(data, path); data[path] = content; }; export const updateFile = data => async (path, content) => { // putting this check in to force use of create if(!await exists(data)(path)) throw new Error("cannot update " + path + " - does not exist"); data[path] = content; } export const writableFileStream = data => async (path) => { //if(!await exists(data)(path)) throw new Error("cannot write stream to " + path + " - does not exist"); const stream = Writable(); stream._write = (chunk, encoding, done) => { data[path] = data[path] === undefined ? [] : data[path]; data[path] = [...data[path], ...chunk]; done(); }; return stream; }; export const readableFileStream = data => async (path) => { if(!await exists(data)(path)) throw new Error("cannot read stream from " + path + " - does not exist"); const s = new Readable(); s._read = () => { s.push(Buffer.from(data[path])); s.push(null); }; return s; }; export const getFileSize = data => async (path) => { if(!await exists(data)(path)) throw new Error("cannot get size of " + path + " - does not exist"); return data[path].length; } export const renameFile = data => async (oldKey, newKey) => { if(!await exists(data)(oldKey)) throw new Error("cannot rename path: " + oldKey + " ... does not exist"); if(await exists(data)(newKey)) throw new Error("cannot rename path: " + newKey + " ... already exists"); data[newKey] = data[oldKey]; delete data[oldKey]; }; export const loadFile = data => async (path) => { const result = data[path]; if(isUndefined(result)) throw new Error("Load failed - path " + path + " does not exist"); return result; }; export const exists = data => async (path) => has(data, path); export const deleteFile = data => async (path) => { if(!await exists(data)(path)) throw new Error("Cannot delete file, path " + path + " does not exist"); if(isFolder(data[path])) throw new Error("DeleteFile: Path " + path + " is a folder, not a file"); const parentFolder = getParentFolder(data, path); parentFolder.items = parentFolder.items.filter(i => i !== getLastPartInKey(path)); data[getParentFolderKey(path)] = JSON.stringify(parentFolder); delete data[path]; } export const createFolder = data => async (path) => { if(await exists(data)(path)) throw new Error("Cannot create folder, path " + path + " already exists"); addItemToParentFolder(data, path); data[path] = JSON.stringify({folderMarker, items:[]}); } export const deleteFolder = data => async (path) => { if(!await exists(data)(path)) throw new Error("Cannot delete folder, path " + path + " does not exist"); if(!isFolder(data[path])) throw new Error("DeleteFolder: Path " + path + " is not a folder"); delete data[path]; } export const getFolderContents = data => async (folderPath) => { if(!isFolder(data[folderPath])) throw new Error("Not a folder: " + folderPath); if(!await exists(data)(folderPath)) throw new Error("Folder does not exist: " + folderPath); return JSON.parse(data[folderPath]).items; }; export default data => { return { createFile : createFile(data), updateFile : updateFile(data), loadFile : loadFile(data), exists : exists(data), deleteFile : deleteFile(data), createFolder: createFolder(data), deleteFolder: deleteFolder(data), readableFileStream: readableFileStream(data), writableFileStream: writableFileStream(data), renameFile: renameFile(data), getFolderContents: getFolderContents(data), getFileSize: getFileSize(data), datastoreType : "memory", datastoreDescription: "", data }; };