mirror of
https://github.com/vale981/grapher
synced 2025-03-05 09:31:42 -05:00
some small updates
This commit is contained in:
parent
4abcbe777d
commit
324e2b78fd
20 changed files with 125 additions and 102 deletions
5
lib/compose.js
Normal file
5
lib/compose.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import deepExtend from 'deep-extend';
|
||||
|
||||
export default function (...args) {
|
||||
return deepExtend({}, ...args);
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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'};
|
||||
|
||||
|
|
39
lib/namedQuery/cache/BaseResultCacher.js
vendored
Normal file
39
lib/namedQuery/cache/BaseResultCacher.js
vendored
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
33
lib/namedQuery/cache/MemoryResultCacher.js
vendored
33
lib/namedQuery/cache/MemoryResultCacher.js
vendored
|
@ -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);
|
||||
|
||||
|
|
5
lib/namedQuery/cache/generateQueryId.js
vendored
5
lib/namedQuery/cache/generateQueryId.js
vendored
|
@ -1,5 +0,0 @@
|
|||
import {EJSON} from 'meteor/ejson';
|
||||
|
||||
export default function(queryName, params) {
|
||||
return `${queryName}::${EJSON.stringify(params)}`;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -181,7 +181,8 @@ export default class Query extends Base {
|
|||
}
|
||||
|
||||
return recursiveFetch(
|
||||
createGraph(this.collection, body)
|
||||
createGraph(this.collection, body),
|
||||
this.params
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Add table
Reference in a new issue