some small updates

This commit is contained in:
Theodor Diaconu 2017-11-30 22:11:25 +02:00
parent 4abcbe777d
commit 324e2b78fd
20 changed files with 125 additions and 102 deletions

5
lib/compose.js Normal file
View file

@ -0,0 +1,5 @@
import deepExtend from 'deep-extend';
export default function (...args) {
return deepExtend({}, ...args);
}

View file

@ -2,7 +2,6 @@ import LinkMany from './linkTypes/linkMany.js';
import LinkManyMeta from './linkTypes/linkManyMeta.js';
import LinkOne from './linkTypes/linkOne.js';
import LinkOneMeta from './linkTypes/linkOneMeta.js';
import LinkResolve from './linkTypes/linkResolve.js';
import {LinkConfigSchema, LinkConfigDefaults} from './config.schema.js';
import smartArguments from './linkTypes/lib/smartArguments';
import dot from 'dot-object';

View file

@ -42,13 +42,6 @@ PostCollection.addLinks({
collection: CategoryCollection,
type: '1'
},
pictures: {
resolve(object) {
return ResolverCollection.find({
resourceId: object._id
}).fetch();
}
},
inversedComment: {
collection: CommentCollection,
inversedBy: 'inversedPost'
@ -90,7 +83,6 @@ describe('Collection Links', function () {
PostCollection.remove({});
CategoryCollection.remove({});
CommentCollection.remove({});
ResolverCollection.remove({});
it('Test Many', function () {
let postId = PostCollection.insert({'text': 'abc'});
@ -254,16 +246,6 @@ describe('Collection Links', function () {
assert.notInclude(post.commentIds, comment._id);
});
it('Tests proper resolver', function () {
let postId = PostCollection.insert({'text': 'abc'});
let uploadId = ResolverCollection.insert({'resourceId': postId});
let post = PostCollection.findOne(postId);
const link = PostCollection.getLink(post, 'pictures');
assert.lengthOf(link.fetch(), 1);
});
it ('Should auto-save object', function () {
let comment = {text: 'abc'};

View file

@ -0,0 +1,39 @@
import {EJSON} from 'meteor/ejson';
/**
* This is a very basic in-memory result caching functionality
*/
export default class BaseResultCacher {
constructor(config = {}) {
this.config = config;
}
/**
* @param queryName
* @param params
* @returns {string}
*/
generateQueryId(queryName, params) {
return `${queryName}::${EJSON.stringify(params)}`;
}
/**
* Dummy function
*/
fetch(cacheId, {query, countCursor}) {
throw 'Not implemented';
}
/**
* @param query
* @param countCursor
* @returns {*}
*/
static fetchData({query, countCursor}) {
if (query) {
return query.fetch();
} else {
return countCursor.count();
}
}
}

View file

@ -1,39 +1,42 @@
import {Meteor} from 'meteor/meteor';
import cloneDeep from 'lodash.clonedeep';
import BaseResultCacher from './BaseResultCacher';
const DEFAULT_TTL = 60000;
/**
* This is a very basic in-memory result caching functionality
*/
export default class MemoryResultCacher {
export default class MemoryResultCacher extends BaseResultCacher {
constructor(config = {}) {
super(config);
this.store = {};
this.config = config;
}
get(cacheId, {
query,
countCursor,
}) {
/**
* @param cacheId
* @param query
* @param countCursor
* @returns {*}
*/
fetch(cacheId, {query, countCursor}) {
const cacheData = this.store[cacheId];
if (cacheData !== undefined) {
return cloneDeep(cacheData);
}
let data;
if (query) {
data = query.fetch();
} else {
data = countCursor.count();
}
this.set(cacheId, data);
const data = BaseResultCacher.fetchData({query, countCursor});
this.storeData(cacheId, data);
return data;
}
set(cacheId, data) {
/**
* @param cacheId
* @param data
*/
storeData(cacheId, data) {
const ttl = this.config.ttl || DEFAULT_TTL;
this.store[cacheId] = cloneDeep(data);

View file

@ -1,5 +0,0 @@
import {EJSON} from 'meteor/ejson';
export default function(queryName, params) {
return `${queryName}::${EJSON.stringify(params)}`;
}

View file

@ -1,8 +1,8 @@
import deepClone from 'lodash.clonedeep';
const specialParameters = ['$body'];
export default class NamedQueryBase {
isNamedQuery = true;
constructor(name, collection, body, options = {}) {
this.queryName = name;
@ -23,6 +23,10 @@ export default class NamedQueryBase {
return `named_query_${this.queryName}`;
}
get isResolver() {
return !!this.resolver;
}
setParams(params) {
this.params = _.extend({}, this.params, params);
@ -34,7 +38,6 @@ export default class NamedQueryBase {
*/
doValidateParams(params) {
params = params || this.params;
params = _.omit(params, ...specialParameters);
const {validateParams} = this.options;
if (!validateParams) return;

View file

@ -2,7 +2,6 @@ import prepareForProcess from '../query/lib/prepareForProcess.js';
import Base from './namedQuery.base';
import deepClone from 'lodash.clonedeep';
import MemoryResultCacher from './cache/MemoryResultCacher';
import generateQueryId from './cache/generateQueryId';
export default class extends Base {
/**
@ -23,8 +22,8 @@ export default class extends Base {
);
if (this.cacher) {
const cacheId = generateQueryId(this.queryName, this.params);
return this.cacher.get(cacheId, {query});
const cacheId = this.cacher.generateQueryId(this.queryName, this.params);
return this.cacher.fetch(cacheId, {query});
}
return query.fetch();
@ -50,9 +49,9 @@ export default class extends Base {
const countCursor = this.getCursorForCounting();
if (this.cacher) {
const cacheId = 'count::' + generateQueryId(this.queryName, this.params);
const cacheId = 'count::' + this.cacher.generateQueryId(this.queryName, this.params);
return this.cacher.get(cacheId, {countCursor});
return this.cacher.fetch(cacheId, {countCursor});
}
return countCursor.count();
@ -105,8 +104,8 @@ export default class extends Base {
};
if (this.cacher) {
const cacheId = generateQueryId(this.queryName, this.params);
return this.cacher.get(cacheId, {query});
const cacheId = this.cacher.generateQueryId(this.queryName, this.params);
return this.cacher.fetch(cacheId, {query});
}
return query.fetch();

View file

@ -11,7 +11,7 @@ function hypernova(collectionNode, userId) {
});
}
export default function hypernovaInit(collectionNode, userId, config = {bypassFirewalls: false}) {
export default function hypernovaInit(collectionNode, userId, config = {bypassFirewalls: false, params: {}}) {
let {filters, options} = applyProps(collectionNode);
const collection = collectionNode.collection;
@ -21,7 +21,7 @@ export default function hypernovaInit(collectionNode, userId, config = {bypassFi
const userIdToPass = (config.bypassFirewalls) ? undefined : userId;
hypernova(collectionNode, userIdToPass);
prepareForDelivery(collectionNode);
prepareForDelivery(collectionNode, params);
return collectionNode.results;
}

View file

@ -81,6 +81,11 @@ export function createNodes(root) {
}
}
/**
* @param body
* @param fieldName
* @param root
*/
export function addFieldNode(body, fieldName, root) {
// it's not a link and not a special variable => we assume it's a field
if (_.isObject(body)) {
@ -94,6 +99,11 @@ export function addFieldNode(body, fieldName, root) {
}
}
/**
* @param collection
* @param body
* @returns {CollectionNode}
*/
export default function (collection, body) {
let root = new CollectionNode(collection, body);
createNodes(root);

View file

@ -7,9 +7,9 @@ import cleanReducerLeftovers from '../reducers/lib/cleanReducerLeftovers';
import sift from 'sift';
import {Minimongo} from 'meteor/minimongo';
export default (node) => {
export default (node, params) => {
snapBackCaches(node);
applyReducers(node);
applyReducers(node, params);
cleanReducerLeftovers(node);
_.each(node.collectionNodes, collectionNode => {
@ -24,8 +24,7 @@ export default (node) => {
storeOneResults(node, node.results);
applyPostFilters(node);
applyPostOptions(node);
node.postFilter();
applyPostFilter(node, params);
}
export function applyPostFilters(node) {
@ -50,6 +49,24 @@ export function applyPostOptions(node) {
}
}
/**
* Optionally applies a post filtering option
*/
function applyPostFilter(node, params) {
if (node.props.$postFilter) {
const filter = node.props.$postFilter;
if (_.isArray(filter)) {
filter.forEach(f => {
node.results = f(node.results, params);
})
} else {
node.results = filter(node.results, params);
}
}
}
export function removeLinkStorages(node, sameLevelResults) {
if (!sameLevelResults) {
return;

View file

@ -39,10 +39,10 @@ function fetch(node, parentObject) {
return results;
}
export default (node) => {
export default (node, params) => {
node.results = fetch(node);
prepareForDelivery(node);
prepareForDelivery(node, params);
return node.results;
}

View file

@ -201,23 +201,6 @@ export default class CollectionNode {
}
}
/**
* Optionally applies a post filtering option
*/
postFilter() {
if (this.props.$postFilter) {
const filter = this.props.$postFilter;
if (_.isArray(filter)) {
filter.forEach(f => {
this.results = f(this.results, this.params);
})
} else {
this.results = filter(this.results, this.params);
}
}
}
/**
* This method verifies whether to remove the linkStorageField form the results
* unless you specify it in your query.

View file

@ -2,6 +2,8 @@ import deepClone from 'lodash.clonedeep';
import {check} from 'meteor/check';
export default class QueryBase {
isGlobalQuery = true;
constructor(collection, body, options = {}) {
this.collection = collection;

View file

@ -181,7 +181,8 @@ export default class Query extends Base {
}
return recursiveFetch(
createGraph(this.collection, body)
createGraph(this.collection, body),
this.params
);
}
}

View file

@ -6,16 +6,16 @@ import Base from './query.base';
export default class Query extends Base {
/**
* Retrieves the data.
* @param options
* @param context
* @returns {*}
*/
fetch(options = {}) {
fetch(context = {}) {
const node = createGraph(
this.collection,
prepareForProcess(this.body, this.params)
);
return hypernova(node, options.userId);
return hypernova(node, context.userId, {params: this.params});
}
/**

View file

@ -1,11 +1,11 @@
export default function applyReducers(root) {
export default function applyReducers(root, params) {
_.each(root.collectionNodes, node => {
applyReducers(node);
applyReducers(node, params);
});
_.each(root.reducerNodes, reducerNode => {
root.results.forEach(result => {
reducerNode.compute(result);
reducerNode.compute(result, params);
});
});
}

View file

@ -43,7 +43,9 @@ function cleanNestedFields(parts, results) {
if (parts.length === 1) {
results.forEach(result => {
delete result[fieldName];
if (fieldName !== '_id') {
delete result[fieldName];
}
});
return;
@ -54,7 +56,9 @@ function cleanNestedFields(parts, results) {
results.forEach(result => {
if (_.keys(result[fieldName]).length === 0) {
delete result[fieldName];
if (fieldName !== '_id') {
delete result[fieldName];
}
}
})
}

View file

@ -21,11 +21,6 @@ Posts.addLinks({
field: 'tagIds',
index: true
},
commentsCount: {
resolve(post) {
return Comments.find({postId: post._id}).count();
}
},
group: {
type: 'one',
collection: Groups,

View file

@ -276,20 +276,6 @@ describe('Hypernova', function () {
})
});
it('Should fetch Resolver links properly', function () {
const data = createQuery({
posts: {
$options: {limit: 5},
commentsCount: 1
}
}).fetch();
assert.lengthOf(data, 5);
_.each(data, post => {
assert.equal(6, post.commentsCount);
})
});
it('Should fetch in depth properly at any given level.', function () {
const data = createQuery({
authors: {