176 lines
6.2 KiB
JavaScript
176 lines
6.2 KiB
JavaScript
import {isUndefined, has} from "lodash";
|
|
import {take} from "lodash/fp";
|
|
import {Readable, Writable} from "readable-stream";
|
|
import { Buffer } from "safe-buffer";
|
|
import {splitKey, joinKey, $, keySep, getFileFromKey} from "../src/common";
|
|
import {getLastPartInKey} from "../src/templateApi/hierarchy";
|
|
|
|
const folderMarker = "OH-YES-ITSA-FOLDER-";
|
|
const isFolder = val => {
|
|
if(isUndefined(val)) {
|
|
throw new Error("Passed undefined value for folder");
|
|
}
|
|
return val.includes(folderMarker);
|
|
}
|
|
|
|
const getParentFolderKey = key =>
|
|
$(key, [
|
|
splitKey,
|
|
take((splitKey(key).length - 1)),
|
|
joinKey,
|
|
]);
|
|
|
|
const getParentFolder = (data,key) => {
|
|
if(key === keySep) return null;
|
|
const parentKey = getParentFolderKey(key);
|
|
if(parentKey === keySep) return null;
|
|
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");
|
|
if(!getParentFolder(data, path)) {
|
|
throw new Error("Parent folder for " + 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();
|
|
};
|
|
|
|
addItemToParentFolder(data, path);
|
|
|
|
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];
|
|
|
|
const parent = getParentFolder(data, newKey);
|
|
const oldFileName = getFileFromKey(oldKey);
|
|
const newFileName = getFileFromKey(newKey);
|
|
parent.items = [...parent.items.filter(i => i !== oldFileName), newFileName];
|
|
data[getParentFolderKey(newKey)] = JSON.stringify(parent);
|
|
};
|
|
|
|
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");
|
|
|
|
for(let item of JSON.parse(data[path]).items) {
|
|
const fullItemPath = `${path}/${item}`;
|
|
if(isFolder(data[fullItemPath])) {
|
|
await deleteFolder(data)(fullItemPath);
|
|
} else {
|
|
await deleteFile(data)(fullItemPath);
|
|
}
|
|
}
|
|
|
|
const parent = getParentFolder(data, path);
|
|
if(parent) {
|
|
parent.items = parent.items.filter(f => f !== getLastPartInKey(path));
|
|
data[getParentFolderKey(path)] = JSON.stringify(parent);
|
|
}
|
|
|
|
delete data[path];
|
|
}
|
|
|
|
export const getFolderContents = data => async (folderPath) => {
|
|
if(!await exists(data)(folderPath))
|
|
throw new Error("Folder does not exist: " + folderPath);
|
|
if(!isFolder(data[folderPath]))
|
|
throw new Error("Not a folder: " + 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
|
|
};
|
|
}; |