From 324e2b78fde132a3466c751ee9437059894ef375 Mon Sep 17 00:00:00 2001 From: Theodor Diaconu Date: Thu, 30 Nov 2017 22:11:25 +0200 Subject: [PATCH] some small updates --- lib/compose.js | 5 +++ lib/links/linker.js | 1 - lib/links/tests/main.js | 18 --------- lib/namedQuery/cache/BaseResultCacher.js | 39 +++++++++++++++++++ lib/namedQuery/cache/MemoryResultCacher.js | 33 +++++++++------- lib/namedQuery/cache/generateQueryId.js | 5 --- lib/namedQuery/namedQuery.base.js | 9 +++-- lib/namedQuery/namedQuery.server.js | 13 +++---- lib/query/hypernova/hypernova.js | 4 +- lib/query/lib/createGraph.js | 10 +++++ lib/query/lib/prepareForDelivery.js | 25 ++++++++++-- lib/query/lib/recursiveFetch.js | 4 +- lib/query/nodes/collectionNode.js | 17 -------- lib/query/query.base.js | 2 + lib/query/query.client.js | 3 +- lib/query/query.server.js | 6 +-- lib/query/reducers/lib/applyReducers.js | 6 +-- .../reducers/lib/cleanReducerLeftovers.js | 8 +++- lib/query/testing/bootstrap/posts/links.js | 5 --- lib/query/testing/server.test.js | 14 ------- 20 files changed, 125 insertions(+), 102 deletions(-) create mode 100644 lib/compose.js create mode 100644 lib/namedQuery/cache/BaseResultCacher.js delete mode 100644 lib/namedQuery/cache/generateQueryId.js diff --git a/lib/compose.js b/lib/compose.js new file mode 100644 index 0000000..5a71760 --- /dev/null +++ b/lib/compose.js @@ -0,0 +1,5 @@ +import deepExtend from 'deep-extend'; + +export default function (...args) { + return deepExtend({}, ...args); +} \ No newline at end of file diff --git a/lib/links/linker.js b/lib/links/linker.js index 2bf2552..8f5de88 100644 --- a/lib/links/linker.js +++ b/lib/links/linker.js @@ -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'; diff --git a/lib/links/tests/main.js b/lib/links/tests/main.js index 2889952..940f458 100644 --- a/lib/links/tests/main.js +++ b/lib/links/tests/main.js @@ -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'}; diff --git a/lib/namedQuery/cache/BaseResultCacher.js b/lib/namedQuery/cache/BaseResultCacher.js new file mode 100644 index 0000000..fcbae77 --- /dev/null +++ b/lib/namedQuery/cache/BaseResultCacher.js @@ -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(); + } + } +} diff --git a/lib/namedQuery/cache/MemoryResultCacher.js b/lib/namedQuery/cache/MemoryResultCacher.js index 141f81e..ae432ec 100644 --- a/lib/namedQuery/cache/MemoryResultCacher.js +++ b/lib/namedQuery/cache/MemoryResultCacher.js @@ -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); diff --git a/lib/namedQuery/cache/generateQueryId.js b/lib/namedQuery/cache/generateQueryId.js deleted file mode 100644 index ce3f423..0000000 --- a/lib/namedQuery/cache/generateQueryId.js +++ /dev/null @@ -1,5 +0,0 @@ -import {EJSON} from 'meteor/ejson'; - -export default function(queryName, params) { - return `${queryName}::${EJSON.stringify(params)}`; -} \ No newline at end of file diff --git a/lib/namedQuery/namedQuery.base.js b/lib/namedQuery/namedQuery.base.js index d8a1555..913c32f 100644 --- a/lib/namedQuery/namedQuery.base.js +++ b/lib/namedQuery/namedQuery.base.js @@ -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; diff --git a/lib/namedQuery/namedQuery.server.js b/lib/namedQuery/namedQuery.server.js index 3eb7d5c..4b39499 100644 --- a/lib/namedQuery/namedQuery.server.js +++ b/lib/namedQuery/namedQuery.server.js @@ -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(); diff --git a/lib/query/hypernova/hypernova.js b/lib/query/hypernova/hypernova.js index 8448623..5cf7fd9 100644 --- a/lib/query/hypernova/hypernova.js +++ b/lib/query/hypernova/hypernova.js @@ -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; } diff --git a/lib/query/lib/createGraph.js b/lib/query/lib/createGraph.js index 3007cab..c00cf4d 100644 --- a/lib/query/lib/createGraph.js +++ b/lib/query/lib/createGraph.js @@ -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); diff --git a/lib/query/lib/prepareForDelivery.js b/lib/query/lib/prepareForDelivery.js index 5e5fb4b..a76c768 100644 --- a/lib/query/lib/prepareForDelivery.js +++ b/lib/query/lib/prepareForDelivery.js @@ -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; diff --git a/lib/query/lib/recursiveFetch.js b/lib/query/lib/recursiveFetch.js index f56df6d..54813aa 100644 --- a/lib/query/lib/recursiveFetch.js +++ b/lib/query/lib/recursiveFetch.js @@ -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; } diff --git a/lib/query/nodes/collectionNode.js b/lib/query/nodes/collectionNode.js index 6b8ee23..88fb8a0 100644 --- a/lib/query/nodes/collectionNode.js +++ b/lib/query/nodes/collectionNode.js @@ -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. diff --git a/lib/query/query.base.js b/lib/query/query.base.js index 84dfd9a..8690770 100644 --- a/lib/query/query.base.js +++ b/lib/query/query.base.js @@ -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; diff --git a/lib/query/query.client.js b/lib/query/query.client.js index 81685ad..4b706a7 100644 --- a/lib/query/query.client.js +++ b/lib/query/query.client.js @@ -181,7 +181,8 @@ export default class Query extends Base { } return recursiveFetch( - createGraph(this.collection, body) + createGraph(this.collection, body), + this.params ); } } diff --git a/lib/query/query.server.js b/lib/query/query.server.js index d750713..6b9f303 100644 --- a/lib/query/query.server.js +++ b/lib/query/query.server.js @@ -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}); } /** diff --git a/lib/query/reducers/lib/applyReducers.js b/lib/query/reducers/lib/applyReducers.js index 92371b7..980692b 100644 --- a/lib/query/reducers/lib/applyReducers.js +++ b/lib/query/reducers/lib/applyReducers.js @@ -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); }); }); } \ No newline at end of file diff --git a/lib/query/reducers/lib/cleanReducerLeftovers.js b/lib/query/reducers/lib/cleanReducerLeftovers.js index ce85749..a8bda76 100644 --- a/lib/query/reducers/lib/cleanReducerLeftovers.js +++ b/lib/query/reducers/lib/cleanReducerLeftovers.js @@ -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]; + } } }) } diff --git a/lib/query/testing/bootstrap/posts/links.js b/lib/query/testing/bootstrap/posts/links.js index bdad11b..42afdb5 100644 --- a/lib/query/testing/bootstrap/posts/links.js +++ b/lib/query/testing/bootstrap/posts/links.js @@ -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, diff --git a/lib/query/testing/server.test.js b/lib/query/testing/server.test.js index a92afaa..c7f2532 100644 --- a/lib/query/testing/server.test.js +++ b/lib/query/testing/server.test.js @@ -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: {