UNPKG

graphql-compose-mongoose

Version:

Plugin for `graphql-compose` which derive a graphql types from a mongoose model.

160 lines (131 loc) 5.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getIndexesFromModel = getIndexesFromModel; exports.getUniqueIndexes = getUniqueIndexes; exports.extendByReversedIndexes = extendByReversedIndexes; exports.getIndexedFieldNamesForGraphQL = getIndexedFieldNamesForGraphQL; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function isSpecificIndex(idx) { let hasSpecialIndex = false; Object.keys(idx).forEach(k => { if (typeof idx[k] !== 'number' && typeof idx[k] !== 'boolean') { hasSpecialIndex = true; } }); return hasSpecialIndex; } /* * Get mongoose model, and return array of fields with indexes. * MongooseModel -> [ { _id: 1 }, { name: 1, surname: -1 } ] */ function getIndexesFromModel(mongooseModel, opts = {}) { const extractCompound = opts.extractCompound === undefined ? true : Boolean(opts.extractCompound); const skipSpecificIndexes = opts.skipSpecificIndexes === undefined ? true : Boolean(opts.skipSpecificIndexes); const indexedFields = []; // add _id field if existed if (mongooseModel.schema.paths._id) { indexedFields.push({ _id: 1 }); } // scan all fields on index presence [MONGOOSE FIELDS LEVEL INDEX] Object.keys(mongooseModel.schema.paths).forEach(name => { if (mongooseModel.schema.paths[name]._index) { indexedFields.push({ [name]: 1 }); // ASC by default } }); // scan compound and special indexes [MONGOOSE SCHEMA LEVEL INDEXES] if (Array.isArray(mongooseModel.schema._indexes)) { mongooseModel.schema._indexes.forEach(idxData => { const partialIndexes = {}; const idxFields = idxData[0]; if (!skipSpecificIndexes || !isSpecificIndex(idxFields)) { if (!extractCompound) { indexedFields.push(idxFields); } else { // extract partial indexes from compound index // { name: 1, age: 1, salary: 1} -> [{name:1}, {name:1, age:1}, {name:1, age:1, salary:1}] Object.keys(idxFields).forEach(fieldName => { partialIndexes[fieldName] = idxFields[fieldName]; indexedFields.push(_objectSpread({}, partialIndexes)); }); } } }); } // filter duplicates const tmp = []; const result = indexedFields.filter(val => { const asString = JSON.stringify(val); if (tmp.indexOf(asString) > -1) return false; tmp.push(asString); return true; }); return result; } function getUniqueIndexes(mongooseModel) { const indexedFields = []; // add _id field if existed if (mongooseModel.schema.paths._id) { indexedFields.push({ _id: 1 }); } // scan all fields on index presence [MONGOOSE FIELDS LEVEL INDEX] Object.keys(mongooseModel.schema.paths).forEach(name => { if (mongooseModel.schema.paths[name]._index && mongooseModel.schema.paths[name]._index.unique) { indexedFields.push({ [name]: 1 }); // ASC by default } }); // scan compound and special indexes [MONGOOSE SCHEMA LEVEL INDEXES] if (Array.isArray(mongooseModel.schema._indexes)) { mongooseModel.schema._indexes.forEach(idxData => { const idxFields = idxData[0]; const idxCfg = idxData[1]; if (idxCfg.unique && !isSpecificIndex(idxFields)) { indexedFields.push(idxFields); } }); } return indexedFields; } function extendByReversedIndexes(indexes, opts = {}) { const reversedFirst = opts.reversedFirst === undefined ? false : Boolean(opts.reversedFirst); const result = []; indexes.forEach(indexObj => { let hasSpecificIndex = false; // https://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-on-multiple-fields const reversedIndexObj = _objectSpread({}, indexObj); Object.keys(reversedIndexObj).forEach(f => { if (reversedIndexObj[f] === 1) reversedIndexObj[f] = -1;else if (reversedIndexObj[f] === -1) reversedIndexObj[f] = 1;else hasSpecificIndex = true; }); if (reversedFirst) { if (!hasSpecificIndex) { result.push(reversedIndexObj); } result.push(indexObj); } else { result.push(indexObj); if (!hasSpecificIndex) { result.push(reversedIndexObj); } } }); return result; } function getIndexedFieldNamesForGraphQL(model) { const indexes = getIndexesFromModel(model); const fieldNames = []; indexes.forEach(indexData => { const keys = Object.keys(indexData); const clearedName = keys[0].replace(/[^_a-zA-Z0-9]/i, '__'); fieldNames.push(clearedName); }); // filter duplicates const uniqueNames = []; const result = fieldNames.filter(val => { if (uniqueNames.indexOf(val) > -1) return false; uniqueNames.push(val); return true; }); return result; }