2020-02-03 10:24:25 +01:00
|
|
|
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-"
|
2019-12-22 08:12:21 +01:00
|
|
|
const isFolder = val => {
|
2020-02-03 10:24:25 +01:00
|
|
|
if (isUndefined(val)) {
|
|
|
|
throw new Error("Passed undefined value for folder")
|
|
|
|
}
|
|
|
|
return val.includes(folderMarker)
|
2019-12-22 08:12:21 +01:00
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
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])
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const addItemToParentFolder = (data, path) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
if (getParentFolderKey(path) === "/") return
|
|
|
|
const parentFolder = getParentFolder(data, path)
|
|
|
|
parentFolder.items.push(getLastPartInKey(path))
|
|
|
|
data[getParentFolderKey(path)] = JSON.stringify(parentFolder)
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export const createFile = data => async (path, content) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
if (await exists(data)(path)) {
|
|
|
|
throw new Error(path + " already exists")
|
|
|
|
}
|
|
|
|
addItemToParentFolder(data, path)
|
|
|
|
data[path] = content
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
export const updateFile = data => async (path, content) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
// 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
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
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
|
|
|
|
}
|
2019-12-22 08:12:21 +01:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
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
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export const renameFile = data => async (oldKey, newKey) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
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]
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
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: [] })
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
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)
|
2019-12-22 08:12:21 +01:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
}
|
2019-12-22 08:12:21 +01:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
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
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
export default data => {
|
2020-02-03 10:24:25 +01:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|