UNPKG

@codemask-labs/nestjs-mongodb

Version:
207 lines 9.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getEntityDropIndexNames = exports.getEntityIndexDescriptions = exports.getEntityIndexes = exports.mergeObjectAndArray = exports.getIndexNameFromKey = exports.getEntitySchemaValidator = exports.getObjectValidator = exports.getPropertyValidator = exports.getBsonType = exports.getEntitiesFromMixedList = exports.getDefaultDataSourceOptions = exports.getConnectionString = exports.getEntityMetadata = exports.getCollectionToken = exports.getDataSourceToken = exports.getClientToken = exports.isEmpty = exports.isDataSourceOptions = void 0; const ramda_1 = require("ramda"); const mongodb_1 = require("mongodb"); const constants_1 = require("./constants"); const metadata_1 = require("./metadata"); const enums_1 = require("./enums"); const isDataSourceOptions = (object) => (0, ramda_1.is)(Object, object) && (0, ramda_1.has)('database', object); exports.isDataSourceOptions = isDataSourceOptions; const isEmpty = (value) => (Array.isArray(value) ? value.length === 0 : Object.keys(value).length === 0); exports.isEmpty = isEmpty; const getClientToken = (connectionName) => `mongo-client:${connectionName ?? constants_1.DEFAULT_CONNECTION_NAME}`; exports.getClientToken = getClientToken; const getDataSourceToken = (connectionName) => `mongo-datasource:${connectionName ?? constants_1.DEFAULT_CONNECTION_NAME}`; exports.getDataSourceToken = getDataSourceToken; const getCollectionToken = (entity, connectionName) => `mongo-entity:${connectionName ?? constants_1.DEFAULT_CONNECTION_NAME}:${entity.name}`; exports.getCollectionToken = getCollectionToken; const getEntityMetadata = (entity) => metadata_1.Metadata.get(entity, constants_1.ENTITY_METADATA); exports.getEntityMetadata = getEntityMetadata; const getConnectionString = (options) => { const host = options.host ?? 'localhost'; const port = options.port ?? 27017; const auth = options.username && options.password ? `${options.username}:${options.password}@` : ''; return `mongodb://${auth}${host}:${port}/${options.database}?authSource=admin`; }; exports.getConnectionString = getConnectionString; const getDefaultDataSourceOptions = (options) => ({ ...options, synchronize: options.synchronize ?? true }); exports.getDefaultDataSourceOptions = getDefaultDataSourceOptions; const getEntitiesFromMixedList = (mixedList = []) => { const entities = Array.isArray(mixedList) ? mixedList : Object.values(mixedList ?? {}); return entities.reduce((acc, entity) => (!metadata_1.Metadata.has(entity, constants_1.ENTITY_WATERMARK) ? acc : [...acc, entity]), []); }; exports.getEntitiesFromMixedList = getEntitiesFromMixedList; const getBsonType = (type) => { switch (type) { case String: return enums_1.BSONType.String; case Number: return enums_1.BSONType.Number; case Boolean: return enums_1.BSONType.Bool; case Date: return enums_1.BSONType.Date; case Array: return enums_1.BSONType.Array; case mongodb_1.ObjectId: return enums_1.BSONType.ObjectId; default: return enums_1.BSONType.Object; } }; exports.getBsonType = getBsonType; const getPropertyValidator = (column) => { const bsonType = (0, exports.getBsonType)(column.type); const isNestedEntity = metadata_1.Metadata.has(column.type, constants_1.NESTED_ENTITY_WATERMARK); if (isNestedEntity && column.options.array) { const metadata = metadata_1.Metadata.get(column.type, constants_1.ENTITY_METADATA); return { bsonType: enums_1.BSONType.Array, additionalProperties: false, items: (0, exports.getObjectValidator)(metadata.entityColumns) }; } if (isNestedEntity) { const metadata = metadata_1.Metadata.get(column.type, constants_1.ENTITY_METADATA); return (0, exports.getObjectValidator)(metadata.entityColumns); } if (column.options.array && column.options.enum) { return { bsonType: enums_1.BSONType.Array, additionalProperties: false, items: { enum: Object.values(column.type) } }; } if (column.options.enum) { return (0, ramda_1.reject)(exports.isEmpty, { enum: Object.values(column.options.enum) }); } if (column.options.array) { return { bsonType: enums_1.BSONType.Array, additionalProperties: false, items: { bsonType } }; } return (0, ramda_1.reject)(ramda_1.isNil, { bsonType }); }; exports.getPropertyValidator = getPropertyValidator; const getObjectValidator = (columns) => (0, ramda_1.reject)(exports.isEmpty, columns.reduce((acc, column) => ({ bsonType: enums_1.BSONType.Object, additionalProperties: false, required: column.options.required ? [...(acc.required ?? []), column.propertyKey] : acc.required, properties: { ...acc.properties, [column.propertyKey]: (0, exports.getPropertyValidator)(column) } }), {})); exports.getObjectValidator = getObjectValidator; const getEntitySchemaValidator = (columns) => ({ $jsonSchema: (0, exports.getObjectValidator)(columns) }); exports.getEntitySchemaValidator = getEntitySchemaValidator; const getIndexNameFromKey = (key) => key.replace(/\.+/g, '_').toUpperCase(); exports.getIndexNameFromKey = getIndexNameFromKey; const mergeObjectAndArray = (left, right) => { if (Array.isArray(left) && Array.isArray(right)) { return (0, ramda_1.concat)(left, right); } if ((0, ramda_1.is)(Object, left) && (0, ramda_1.is)(Object, right)) { return (0, exports.mergeObjectAndArray)(left, right); } return right; }; exports.mergeObjectAndArray = mergeObjectAndArray; const getEntityIndexes = (metadata, stackedKeys = []) => { const columns = metadata.entityColumns; const createIndexOptionMap = metadata.entityOptions.index ?? {}; return columns.reduce((result, column) => { const isNestedEntity = metadata_1.Metadata.has(column.type, constants_1.NESTED_ENTITY_WATERMARK); if (isNestedEntity) { const nestedEntityMetadata = metadata_1.Metadata.get(column.type, constants_1.ENTITY_METADATA); return { ...result, ...(0, exports.getEntityIndexes)(nestedEntityMetadata, [...stackedKeys, column.propertyKey]) }; } if ((0, ramda_1.isNil)(column.options.index)) { return result; } const key = [...stackedKeys, column.propertyKey].join('.'); if ((0, ramda_1.is)(String, column.options.index)) { const { index: indexName } = column.options; if (!createIndexOptionMap[indexName]) { throw new Error(`The index '${indexName}' on property '${column.propertyKey}' in [class ${column.parent.name}] has no index defined. Please add 'index[${indexName}]' in @Entity() or @NestedEntity() options.`); } return (0, ramda_1.mergeDeepWith)(exports.mergeObjectAndArray, result, { [indexName]: { keys: [key], options: createIndexOptionMap[indexName] } }); } if (Array.isArray(column.options.index)) { const { index: indexNames } = column.options; indexNames.forEach(indexName => { if (!createIndexOptionMap[indexName]) { throw new Error(`The index '${indexName}' on property '${column.propertyKey}' in [class ${column.parent.name}] has no index defined. Please add 'index[${indexName}]' in @Entity() or @NestedEntity() options.`); } }); return (0, ramda_1.mergeDeepWith)(exports.mergeObjectAndArray, result, indexNames.reduce((acc, indexName) => (0, ramda_1.mergeDeepWith)(exports.mergeObjectAndArray, acc, { [indexName]: { keys: [key], options: createIndexOptionMap[indexName] } }), {})); } const indexName = (0, exports.getIndexNameFromKey)(key); const { index: createIndexOptions } = column.options; return (0, ramda_1.mergeDeepWith)(exports.mergeObjectAndArray, result, { [indexName]: { keys: [key], options: createIndexOptions } }); }, {}); }; exports.getEntityIndexes = getEntityIndexes; const getEntityIndexDescriptions = (entityIndexes) => Object.entries(entityIndexes).map(([name, { keys, options }]) => ({ name, key: keys.reduce((acc, key) => ({ ...acc, [key]: 1 }), {}), ...options })); exports.getEntityIndexDescriptions = getEntityIndexDescriptions; const getEntityDropIndexNames = (currentIndexDescriptions, entityIndexes) => currentIndexDescriptions.reduce((acc, { name, key: currentIndexKeys, ...currentIndexOptions }) => { if (!name || name === '_id_') { return acc; } const targetEntityIndex = entityIndexes[name]; if (!targetEntityIndex) { return [...acc, name]; } const differenceInKeys = (0, ramda_1.difference)(Object.keys(currentIndexKeys), targetEntityIndex.keys); if (differenceInKeys.length) { return [...acc, name]; } const [differenceInOptions] = (0, ramda_1.difference)([currentIndexOptions], [targetEntityIndex.options]); if (differenceInOptions && Object.keys(differenceInOptions).some(key => key !== 'v')) { return [...acc, name]; } return acc; }, []); exports.getEntityDropIndexNames = getEntityDropIndexNames; //# sourceMappingURL=utils.js.map