@woovi/graphql-mongoose-loader
Version:
GraphQL Mongoose Loader helpers
228 lines (227 loc) • 8.69 kB
JavaScript
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
connectionFromMongoCursor: ()=>ConnectionFromMongoCursor,
mongooseLoader: ()=>mongooseLoader,
unbase64: ()=>unbase64,
calculateOffsets: ()=>calculateOffsets,
offsetToCursor: ()=>offsetToCursor,
getPageInfo: ()=>getPageInfo,
base64: ()=>base64,
connectionFromMongoAggregate: ()=>ConnectionFromMongoAggregate,
getOffsetWithDefault: ()=>getOffsetWithDefault,
getTotalCount: ()=>getTotalCount,
cursorToOffset: ()=>cursorToOffset
});
const PREFIX = 'mongo:';
const base64 = (str)=>Buffer.from(str, 'ascii').toString('base64');
const unbase64 = (b64)=>Buffer.from(b64, 'base64').toString('ascii');
const cursorToOffset = (cursor)=>parseInt(unbase64(cursor).substring(PREFIX.length), 10);
const getOffsetWithDefault = (cursor, defaultOffset)=>{
if (null == cursor) return defaultOffset;
const offset = cursorToOffset(cursor);
return isNaN(offset) ? defaultOffset : offset;
};
const offsetToCursor = (offset)=>base64(PREFIX + offset);
const getTotalCount = async ({ cursor, useEstimatedCount = false, lean = true })=>{
const clonedCursor = lean ? cursor.model.find().lean().merge(cursor) : cursor.model.find().merge(cursor);
return useEstimatedCount ? clonedCursor.estimatedDocumentCount() : clonedCursor.countDocuments();
};
const calculateOffsets = ({ args, totalCount })=>{
const { after, before } = args;
let { first, last } = args;
if (!first && !last) first = 10;
if (first && first > 1000) first = 1000;
if (last && last > 1000) last = 1000;
const beforeOffset = getOffsetWithDefault(before || null, totalCount);
const afterOffset = getOffsetWithDefault(after || null, -1);
let startOffset = Math.max(-1, afterOffset) + 1;
let endOffset = Math.min(totalCount, beforeOffset);
if (null != first) endOffset = Math.min(endOffset, startOffset + first);
if (null != last) startOffset = Math.max(startOffset, endOffset - (last || 0));
const skip = Math.max(startOffset, 0);
const safeLimit = Math.max(endOffset - startOffset, 1);
const limitOffset = Math.max(endOffset - startOffset, 0);
return {
first: first || null,
last: last || null,
before: before || null,
after: after || null,
skip,
limit: safeLimit,
beforeOffset,
afterOffset,
startOffset,
endOffset,
startCursorOffset: skip,
endCursorOffset: limitOffset + skip
};
};
function getPageInfo({ edges, totalCount, startCursorOffset, endCursorOffset }) {
const firstEdge = edges[0];
const lastEdge = edges[edges.length - 1];
return {
startCursor: firstEdge ? firstEdge.cursor : null,
endCursor: lastEdge ? lastEdge.cursor : null,
hasPreviousPage: startCursorOffset > 0,
hasNextPage: endCursorOffset < totalCount
};
}
async function connectionFromMongoCursor({ cursor, context, args = {}, loader, raw = false, useEstimatedCount = false, lean = true }) {
const clonedCursor = lean ? cursor.model.find().lean().merge(cursor) : cursor.model.find().merge(cursor);
const totalCount = await getTotalCount({
cursor: clonedCursor,
useEstimatedCount,
lean
});
const { first, last, before, after, skip, limit, beforeOffset, afterOffset, startOffset, endOffset, startCursorOffset, endCursorOffset } = calculateOffsets({
args,
totalCount
});
clonedCursor.skip(skip);
clonedCursor.limit(limit);
const slice = await clonedCursor.select(raw ? {} : {
_id: 1
}).exec();
const edges = slice.map((value, index)=>({
cursor: offsetToCursor(startOffset + index),
node: loader(context, raw ? value : value._id)
}));
return {
edges,
count: totalCount,
endCursorOffset,
startCursorOffset,
pageInfo: getPageInfo({
edges,
before,
after,
first,
last,
afterOffset,
beforeOffset,
startOffset,
endOffset,
totalCount,
startCursorOffset,
endCursorOffset
})
};
}
const ConnectionFromMongoCursor = connectionFromMongoCursor;
const cloneAggregate = (aggregate)=>aggregate._model.aggregate(aggregate.pipeline());
async function connectionFromMongoAggregate({ aggregate, context, args = {}, loader, raw = false, allowDiskUse = false }) {
const clonedAggregate = cloneAggregate(aggregate).allowDiskUse(allowDiskUse);
const resultCount = await cloneAggregate(aggregate).allowDiskUse(allowDiskUse).count('total');
const totalCount = resultCount.length ? resultCount[0].total : 0;
const { first, last, before, after, skip, limit, beforeOffset, afterOffset, startOffset, endOffset, startCursorOffset, endCursorOffset } = calculateOffsets({
args,
totalCount
});
clonedAggregate.skip(skip);
clonedAggregate.limit(limit || 1);
const slice = await (raw ? clonedAggregate : clonedAggregate.project({
_id: 1
}));
const edges = slice.map((value, index)=>({
cursor: offsetToCursor(startOffset + index),
node: loader(context, raw ? value : value._id)
}));
return {
edges,
count: totalCount,
endCursorOffset,
startCursorOffset,
pageInfo: getPageInfo({
edges,
before,
after,
first,
last,
afterOffset,
beforeOffset,
startOffset,
endOffset,
totalCount,
startCursorOffset,
endCursorOffset
})
};
}
const ConnectionFromMongoAggregate = connectionFromMongoAggregate;
function indexResults(results, indexField, cacheKey = cacheKeyFn) {
const indexedResults = new Map();
results.forEach((res)=>{
indexedResults.set(cacheKey(res[indexField]), res);
});
return indexedResults;
}
function normalizeResults(keys, indexField, cacheKey = cacheKeyFn) {
return (results)=>{
const indexedResults = indexResults(results, indexField, cacheKey);
return keys.map((val)=>indexedResults.get(cacheKey(val)) || new Error(`Key not found : ${val}`));
};
}
const cacheKeyFn = (key)=>key.toString();
async function mongooseLoader(model, keys, lean = true, keyField = '_id') {
const results = lean ? await model.find({
[keyField]: {
$in: keys
}
}).lean() : await model.find({
[keyField]: {
$in: keys
}
});
return normalizeResults(keys, keyField, cacheKeyFn)(results);
}
exports.base64 = __webpack_exports__.base64;
exports.calculateOffsets = __webpack_exports__.calculateOffsets;
exports.connectionFromMongoAggregate = __webpack_exports__.connectionFromMongoAggregate;
exports.connectionFromMongoCursor = __webpack_exports__.connectionFromMongoCursor;
exports.cursorToOffset = __webpack_exports__.cursorToOffset;
exports.getOffsetWithDefault = __webpack_exports__.getOffsetWithDefault;
exports.getPageInfo = __webpack_exports__.getPageInfo;
exports.getTotalCount = __webpack_exports__.getTotalCount;
exports.mongooseLoader = __webpack_exports__.mongooseLoader;
exports.offsetToCursor = __webpack_exports__.offsetToCursor;
exports.unbase64 = __webpack_exports__.unbase64;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"base64",
"calculateOffsets",
"connectionFromMongoAggregate",
"connectionFromMongoCursor",
"cursorToOffset",
"getOffsetWithDefault",
"getPageInfo",
"getTotalCount",
"mongooseLoader",
"offsetToCursor",
"unbase64"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
;