Skip to content
Closed
68 changes: 67 additions & 1 deletion __tests__/utils/vfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ describe('VFS Utils', () => {
const parser = utils.parseFields();

return expect(parser({
url: '/foo/?bar=baz&jazz=bass',
url: '/foo/?bar.s=baz&jazz.s=bass',
method: 'get'
}))
.resolves
Expand Down Expand Up @@ -243,4 +243,70 @@ describe('VFS Utils', () => {
test('parseFields - POST w/Form', () => {
// TODO
});

test('assembleQueryData', () => {
const result1 = utils.assembleQueryData({
'a.s': 'b',
'b.a.s': 'foo',
'b.b.a.s': 'foo',
'b.b.b.s': 'foo',
'b.b.c.s': 'foo',
'b.b.d.s': 'foo',
'b.b.e.s': 'foo',
'c.n': 'null',
'd.b': 'true',
'e.i': '1',
'f.u': 'undefined'
});

const result2 = utils.assembleQueryData({
'a.0.s': 'foo',
'a.1.s': 'foo',
'b.0.s': 'foo',
'b.1.s': 'foo',
'b.a.s': 'foo',
'c.a.s': 'foo',
'c.b.0.s': 'foo',
'c.b.1.s': 'foo',
'c.c.0.s': 'foo',
'c.c.1.s': 'foo',
'c.c.a.s': 'foo',
});

expect(result1).toEqual({
a: 'b',
b: {
a: 'foo',
b: {
a: 'foo',
b: 'foo',
c: 'foo',
d: 'foo',
e: 'foo'
}
},
c: null,
d: true,
e: 1,
f: undefined
});

expect(result2).toEqual({
a: ['foo', 'foo'],
b:{
'0': 'foo',
'1': 'foo',
'a': 'foo',
},
c: {
a: 'foo',
b: ['foo', 'foo'],
c: {
'0': 'foo',
'1': 'foo',
'a': 'foo'
}
}
});
});
});
52 changes: 49 additions & 3 deletions src/utils/vfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ const errorCodes = {
EACCES: 401
};

/**
* A map of data types
*/
const typeMap = {
i: str => parseInt(str, 10),
s: str => str,
b: str => str === 'true',
u: str => undefined,
n: str => null
};

/**
* Gets prefix of a VFS path
*/
Expand Down Expand Up @@ -171,13 +182,47 @@ const mountpointResolver = core => async (path) => {
return Object.freeze({mount, adapter});
};

/*
* Assembles a given object query
*/
const assembleQueryData = (object) => {
const assembled = {};
const keys = Object.keys(object);

for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const dots = key.split('.');
const type = dots[dots.length - 1];
dots.pop();

let last = assembled;
let parent = null;
for (let j = 0; j < dots.length; j++) {
const dot = dots[j];
if (j >= dots.length - 1) {
if (!/^\d+$/.test(dot) && Array.isArray(last)) {
last = Object.fromEntries(last.map((value, i) => [i, value]));
parent[dots[j - 1]] = last;
}
last[dot] = typeMap[type](object[key]);
} else {
last[dot] = last[dot] || (/^\d+$/.test(dots[j + 1]) ? [] : {});
}

parent = last;
last = last[dot];
}
}
return assembled;
};

/*
* 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: {}});
};

/*
Expand Down Expand Up @@ -254,5 +299,6 @@ module.exports = {
getPrefix,
parseFields,
errorCodes,
methodArguments
methodArguments,
assembleQueryData
};