Skip to content
Merged
240 changes: 206 additions & 34 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
".esm-wrapper.mjs"
],
"scripts": {
"test": "nyc mocha --timeout 5000 --colors -r ts-node/register test/*.ts src/**/*.test.ts",
"test": "nyc mocha --timeout 5000 --colors -r ts-node/register test/**/*.ts src/**/*.test.ts",
"test-example-parse-from-file": "ts-node examples/parse-from-file.ts",
"test-example-parse-schema": "ts-node examples/parse-schema.ts",
"test-time": "ts-node ./test/time-testing.ts",
Expand All @@ -60,6 +60,7 @@
"@types/sinon": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"ajv": "^8.17.1",
"bson": "^6.7.0",
"coveralls": "^3.1.1",
"depcheck": "^1.4.3",
Expand Down
10 changes: 10 additions & 0 deletions src/schema-accessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,24 @@ export class InternalSchemaBasedAccessor implements SchemaAccessor {
return this.internalSchema;
}

/**
* Get standard JSON Schema - as per
* https://json-schema.org/draft/2020-12/schema
*/
async getStandardJsonSchema(options: Options = {}): Promise<StandardJSONSchema> {
return this.standardJSONSchema ??= await convertors.internalSchemaToStandard(this.internalSchema, options);
}

/**
* Get MongoDB's $jsonSchema
*/
async getMongoDBJsonSchema(options: Options = {}): Promise<MongoDBJSONSchema> {
return this.mongodbJSONSchema ??= await convertors.internalSchemaToMongoDB(this.internalSchema, options);
}

/**
* Get expanded JSON Schema - with additional properties
*/
async getExpandedJSONSchema(options: Options = {}): Promise<ExpandedJSONSchema> {
return this.ExpandedJSONSchema ??= await convertors.internalSchemaToExpanded(this.internalSchema, options);
}
Expand Down
25 changes: 12 additions & 13 deletions src/schema-convertors/internalToMongoDB.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* Transforms the internal schema to $jsonSchema
*/
import { ArraySchemaType, DocumentSchemaType, Schema as InternalSchema, SchemaType } from '../schema-analyzer';
import { MongoDBJSONSchema } from '../types';
import { allowAbort } from './util';

const InternalTypeToBsonTypeMap: Record<
export const InternalTypeToBsonTypeMap: Record<
SchemaType['name'] | 'Double' | 'BSONSymbol',
string
> = {
Expand Down Expand Up @@ -36,15 +40,6 @@ const convertInternalType = (type: string) => {
return bsonType;
};

async function allowAbort(signal?: AbortSignal) {
return new Promise<void>((resolve, reject) =>
setTimeout(() => {
if (signal?.aborted) return reject(signal?.reason || new Error('Operation aborted'));
resolve();
})
);
}

async function parseType(type: SchemaType, signal?: AbortSignal): Promise<MongoDBJSONSchema> {
await allowAbort(signal);
const schema: MongoDBJSONSchema = {
Expand All @@ -64,6 +59,10 @@ async function parseType(type: SchemaType, signal?: AbortSignal): Promise<MongoD
return schema;
}

function isPlainTypesOnly(types: MongoDBJSONSchema[]): types is { bsonType: string }[] {
return types.every(definition => !!definition.bsonType && Object.keys(definition).length === 1);
}

async function parseTypes(types: SchemaType[], signal?: AbortSignal): Promise<MongoDBJSONSchema> {
await allowAbort(signal);
const definedTypes = types.filter(type => type.bsonType.toLowerCase() !== 'undefined');
Expand All @@ -72,13 +71,13 @@ async function parseTypes(types: SchemaType[], signal?: AbortSignal): Promise<Mo
return parseType(definedTypes[0], signal);
}
const parsedTypes = await Promise.all(definedTypes.map(type => parseType(type, signal)));
if (definedTypes.some(type => ['Document', 'Array'].includes(type.bsonType))) {
if (isPlainTypesOnly(parsedTypes)) {
return {
anyOf: parsedTypes
bsonType: parsedTypes.map(({ bsonType }) => bsonType)
};
}
return {
bsonType: definedTypes.map((type) => convertInternalType(type.bsonType))
anyOf: parsedTypes
};
}

Expand Down
Loading