diff --git a/__tests__/utils/vfs.js b/__tests__/utils/vfs.js index 85e968a..7dd3e17 100644 --- a/__tests__/utils/vfs.js +++ b/__tests__/utils/vfs.js @@ -243,4 +243,27 @@ describe('VFS Utils', () => { test('parseFields - POST w/Form', () => { // TODO }); + + test('assembleQueryData', () => { + const result1 = utils.assembleQueryData({ + 'a': 'b', + 'b': '{"a":"foo"}', + 'c': '{"a":false,"c":null,"d":1,"e":{"a":"foo"}}' + }); + + expect(result1).toEqual({ + a: 'b', + b: { + a: 'foo' + }, + c: { + a: false, + c: null, + d: 1, + e: { + a: 'foo' + } + } + }); + }); }); diff --git a/src/adapters/vfs/system.js b/src/adapters/vfs/system.js index 1469c7d..1a689c5 100644 --- a/src/adapters/vfs/system.js +++ b/src/adapters/vfs/system.js @@ -36,20 +36,35 @@ const chokidar = require('chokidar'); /* * Creates an object readable by client */ -const createFileIter = (core, realRoot, file) => { +const createFileIter = (core, realRoot, file, options = {}) => { const filename = path.basename(file); const realPath = path.join(realRoot, filename); const {mime} = core.make('osjs/vfs'); - const createStat = stat => ({ - isDirectory: stat.isDirectory(), - isFile: stat.isFile(), - mime: stat.isFile() ? mime(realPath) : null, - size: stat.size, - path: file, - filename, - stat - }); + const createStat = async stat => { + let totalSize = 0; + let files = []; + if (stat.isDirectory()) { + files = await fs.readdir(realPath); + if(!options.showHiddenFiles) { + files = files.filter(f => f.substr(0, 1) !== '.'); + } + const promises = files.map(f => fs.stat(path.join(realPath, f))); + const allPromises = await Promise.all(promises); + allPromises.map(s => totalSize += s.size); + } + return ({ + isDirectory: stat.isDirectory(), + isFile: stat.isFile(), + mime: stat.isFile() ? mime(realPath) : null, + size: stat.size, + path: file, + totalCount: files.length, + totalSize: totalSize, + filename, + stat + }); + }; return fs.stat(realPath) .then(createStat) @@ -184,9 +199,21 @@ module.exports = (core) => { Promise.resolve(getRealPath(core, options.session, vfs.mount, file)) .then(realPath => { return fs.access(realPath, fs.F_OK) - .then(() => createFileIter(core, path.dirname(realPath), realPath)); + .then(() => createFileIter(core, path.dirname(realPath), realPath, options)); }), + /** + * Get vfs capabilities + * @param {String} file The optional file path from client + * @param {Object} [options={}] Options + * @return {Object} + */ + capabilities: vfs => (file, options = {}) => + Promise.resolve({ + sort:false, + pagination:false + }), + /** * Reads directory * @param {String} root The file path from client diff --git a/src/utils/vfs.js b/src/utils/vfs.js index e4dd10c..9c6d7fc 100644 --- a/src/utils/vfs.js +++ b/src/utils/vfs.js @@ -171,13 +171,30 @@ const mountpointResolver = core => async (path) => { return Object.freeze({mount, adapter}); }; +/* + * Assembles a given object query + */ +const assembleQueryData = (data) => { + const entries = Object + .entries(data) + .map(([k, v]) => { + try { + return [k, JSON.parse(v)]; + } catch (e) { + return [k, v]; + } + }); + + return Object.fromEntries(entries); +}; + /* * Parses URL Body */ const parseGet = req => { const {query} = url.parse(req.url, true); - - return Promise.resolve({fields: query, files: {}}); + const assembledQuery = assembleQueryData(query); + return Promise.resolve({fields: assembledQuery, files: {}}); }; /* @@ -254,5 +271,6 @@ module.exports = { getPrefix, parseFields, errorCodes, - methodArguments + methodArguments, + assembleQueryData }; diff --git a/src/vfs.js b/src/vfs.js index 54d98b6..c4e8fb4 100644 --- a/src/vfs.js +++ b/src/vfs.js @@ -238,6 +238,7 @@ const vfs = core => { realpath: createRequest(requestPath, 'realpath', false), exists: createRequest(requestPath, 'exists', false, respondBoolean), stat: createRequest(requestPath, 'stat', false), + capabilities: createRequest(requestPath, 'capabilities', false), readdir: createRequest(requestPath, 'readdir', false), readfile: createRequest(requestPath, 'readfile', false), writefile: createRequest(requestFile, 'writefile', true, respondNumber), @@ -268,6 +269,7 @@ module.exports = core => { // Then all VFS routes (needs implementation above) router.get('/exists', wrapper(methods.exists)); router.get('/stat', wrapper(methods.stat)); + router.get('/capabilities', wrapper(methods.capabilities)); router.get('/readdir', wrapper(methods.readdir)); router.get('/readfile', wrapper(methods.readfile)); router.post('/writefile', wrapper(methods.writefile));