mongodb-schema
Version:
Infer the probabilistic schema for a MongoDB collection.
98 lines • 3.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertInternalToExpanded = void 0;
const internalToStandard_1 = require("./internalToStandard");
const internalToMongoDB_1 = require("./internalToMongoDB");
const util_1 = require("../util");
const createConvertInternalToExpanded = function () {
const usedDefinitions = new Set();
function getUsedDefinitions() {
const filteredDefinitions = Object.fromEntries(Object.entries(internalToStandard_1.RELAXED_EJSON_DEFINITIONS).filter(([key]) => usedDefinitions.has(key)));
return Object.freeze(filteredDefinitions);
}
function markUsedDefinition(ref) {
usedDefinitions.add(ref.split('/')[2]);
}
function getStandardType(internalType) {
const type = internalToStandard_1.InternalTypeToStandardTypeMap[internalType];
if (!type)
throw new Error(`Encountered unknown type: ${internalType}`);
return { ...type };
}
function getBsonType(internalType) {
const type = internalToMongoDB_1.InternalTypeToBsonTypeMap[internalType];
if (!type)
throw new Error(`Encountered unknown type: ${internalType}`);
return type;
}
async function parseType(type, signal) {
await (0, util_1.allowAbort)(signal);
const schema = {
...getStandardType(type.bsonType),
'x-bsonType': getBsonType(type.bsonType),
'x-metadata': getMetadata(type)
};
if ('values' in type && type.values) {
schema['x-sampleValues'] = type.values;
}
if (schema.$ref)
markUsedDefinition(schema.$ref);
switch (type.bsonType) {
case 'Array':
schema.items = await parseTypes(type.types, signal);
break;
case 'Document':
Object.assign(schema, await parseFields(type.fields, signal));
break;
}
return schema;
}
function getMetadata({ hasDuplicates, probability, count }) {
return {
...(typeof hasDuplicates === 'boolean' ? { hasDuplicates } : {}),
probability,
count
};
}
async function parseTypes(types, signal) {
await (0, util_1.allowAbort)(signal);
const definedTypes = types.filter(type => type.bsonType.toLowerCase() !== 'undefined');
const isSingleType = definedTypes.length === 1;
if (isSingleType) {
return parseType(definedTypes[0], signal);
}
const parsedTypes = await Promise.all(definedTypes.map(type => parseType(type, signal)));
return {
anyOf: parsedTypes
};
}
async function parseFields(fields, signal) {
const required = [];
const properties = {};
for (const field of fields) {
if (field.probability === 1)
required.push(field.name);
properties[field.name] = {
...await parseTypes(field.types, signal),
'x-metadata': getMetadata(field)
};
}
return { required, properties };
}
return async function convert(internalSchema, options = {}) {
const { required, properties } = await parseFields(internalSchema.fields, options.signal);
const schema = {
type: 'object',
'x-bsonType': 'object',
required,
properties,
$defs: getUsedDefinitions()
};
return schema;
};
};
function convertInternalToExpanded(internalSchema, options = {}) {
return createConvertInternalToExpanded()(internalSchema, options);
}
exports.convertInternalToExpanded = convertInternalToExpanded;
//# sourceMappingURL=internalToExpanded.js.map