Skip to content

Commit 3c23e5f

Browse files
committed
wip
1 parent c514068 commit 3c23e5f

File tree

2 files changed

+100
-11
lines changed

2 files changed

+100
-11
lines changed
Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,98 @@
1-
import { InternalSchema } from '..';
2-
import { ExpandedJSONSchema } from '../types';
1+
import { JSONSchema4TypeName } from 'json-schema';
2+
import { BaseSchemaType, ArraySchemaType, DocumentSchemaType, Schema as InternalSchema, SchemaType, SchemaField } from '../schema-analyzer';
3+
import { type ExpandedJSONSchema } from '../types';
4+
import { InternalTypeToStandardTypeMap, RELAXED_EJSON_DEFINITIONS } from './internalToStandard';
5+
import { InternalTypeToBsonTypeMap } from './internalToMongoDB';
6+
import { allowAbort } from './util';
37

4-
export default function internalSchemaToExpanded(
5-
/* eslint @typescript-eslint/no-unused-vars: 0 */
8+
const getStandardType = (internalType: string) => {
9+
const type = { ...InternalTypeToStandardTypeMap[internalType] };
10+
if (!type) throw new Error(`Encountered unknown type: ${internalType}`);
11+
return type;
12+
};
13+
14+
const getBsonType = (internalType: string) => {
15+
const type = InternalTypeToBsonTypeMap[internalType];
16+
if (!type) throw new Error(`Encountered unknown type: ${internalType}`);
17+
return type;
18+
};
19+
20+
async function parseType(type: SchemaType, signal?: AbortSignal): Promise<ExpandedJSONSchema> {
21+
await allowAbort(signal);
22+
const schema: ExpandedJSONSchema = {
23+
...getStandardType(type.bsonType),
24+
'x-bsonType': getBsonType(type.bsonType),
25+
'x-metadata': getMetadata(type)
26+
};
27+
if ('values' in type && !!type.values) {
28+
schema['x-sampleValues'] = type.values;
29+
}
30+
switch (type.bsonType) {
31+
case 'Array':
32+
schema.items = await parseTypes((type as ArraySchemaType).types);
33+
break;
34+
case 'Document':
35+
Object.assign(schema,
36+
await parseFields((type as DocumentSchemaType).fields, signal)
37+
);
38+
break;
39+
}
40+
41+
return schema;
42+
}
43+
44+
const getMetadata = <TType extends SchemaField | SchemaType>({
45+
hasDuplicates,
46+
probability,
47+
count
48+
}: TType) => ({
49+
...(typeof hasDuplicates === 'boolean' ? { hasDuplicates } : {}),
50+
probability,
51+
count
52+
});
53+
54+
async function parseTypes(types: SchemaType[], signal?: AbortSignal): Promise<ExpandedJSONSchema> {
55+
await allowAbort(signal);
56+
const definedTypes = types.filter(type => type.bsonType.toLowerCase() !== 'undefined');
57+
const isSingleType = definedTypes.length === 1;
58+
if (isSingleType) {
59+
return parseType(definedTypes[0], signal);
60+
}
61+
const parsedTypes = await Promise.all(definedTypes.map(type => parseType(type, signal)));
62+
return {
63+
anyOf: parsedTypes
64+
};
65+
}
66+
67+
async function parseFields(fields: DocumentSchemaType['fields'], signal?: AbortSignal): Promise<{
68+
required: ExpandedJSONSchema['required'],
69+
properties: ExpandedJSONSchema['properties'],
70+
}> {
71+
const required = [];
72+
const properties: ExpandedJSONSchema['properties'] = {};
73+
for (const field of fields) {
74+
if (field.probability === 1) required.push(field.name);
75+
properties[field.name] = {
76+
...await parseTypes(field.types, signal),
77+
'x-metadata': getMetadata(field)
78+
};
79+
}
80+
81+
return { required, properties };
82+
}
83+
84+
export default async function internalSchemaToMongodb(
685
internalSchema: InternalSchema,
786
options: {
887
signal?: AbortSignal
9-
}): Promise<ExpandedJSONSchema> {
10-
// TODO: COMPASS-8702
11-
return Promise.resolve({} as ExpandedJSONSchema);
88+
} = {}): Promise<ExpandedJSONSchema> {
89+
const { required, properties } = await parseFields(internalSchema.fields, options.signal);
90+
const schema: ExpandedJSONSchema = {
91+
type: 'object',
92+
'x-bsonType': 'object',
93+
required,
94+
properties,
95+
$defs: RELAXED_EJSON_DEFINITIONS
96+
};
97+
return schema;
1298
}

src/types.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ export type MongoDBJSONSchema = Pick<StandardJSONSchema, 'title' | 'required' |
1010
}
1111

1212
export type ExpandedJSONSchema = StandardJSONSchema & {
13-
['x-bsonType']: string;
14-
['x-metadata']: {
15-
hasDuplicates: boolean;
13+
['x-bsonType']?: string | string[];
14+
['x-metadata']?: {
15+
hasDuplicates?: boolean;
1616
probability: number;
1717
count: number;
1818
};
19-
['x-sampleValues']: any[];
19+
['x-sampleValues']?: any[];
20+
properties?: Record<string, ExpandedJSONSchema>;
21+
items?: ExpandedJSONSchema | ExpandedJSONSchema[];
22+
anyOf?: ExpandedJSONSchema[];
2023
}
2124

2225
export type AnyIterable<T = any> = Iterable<T> | AsyncIterable<T>;

0 commit comments

Comments
 (0)