Skip to content

Commit 22cd678

Browse files
authored
fix: add relationship fields items and anyOf support COMPASS-9649 (#7161)
1 parent a502609 commit 22cd678

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

packages/compass-data-modeling/src/store/diagram.spec.ts

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
openDiagram,
88
redoEdit,
99
undoEdit,
10+
selectFieldsForCurrentModel,
1011
} from './diagram';
1112
import type {
1213
Edit,
@@ -295,4 +296,150 @@ describe('Data Modeling store', function () {
295296
expect(diagramAfterRedo.edits[0]).to.deep.include(loadedDiagram.edits[0]);
296297
expect(diagramAfterRedo.edits[1]).to.deep.include(edit);
297298
});
299+
300+
describe('selectFieldsForCurrentModel', function () {
301+
it('should select fields from a flat schema', function () {
302+
const edits: MongoDBDataModelDescription['edits'] = [
303+
{
304+
id: 'first-edit',
305+
timestamp: new Date().toISOString(),
306+
type: 'SetModel',
307+
model: {
308+
collections: [
309+
{
310+
ns: 'collection1',
311+
indexes: [],
312+
displayPosition: [0, 0],
313+
shardKey: {},
314+
jsonSchema: {
315+
bsonType: 'object',
316+
properties: {
317+
field1: { bsonType: 'string' },
318+
field2: { bsonType: 'int' },
319+
field3: { bsonType: 'int' },
320+
},
321+
},
322+
},
323+
],
324+
relationships: [],
325+
},
326+
},
327+
];
328+
const selectedFields = selectFieldsForCurrentModel(edits);
329+
330+
expect(selectedFields).to.deep.equal({
331+
collection1: [['field1'], ['field2'], ['field3']],
332+
});
333+
});
334+
335+
it('should select fields from a nested schema', function () {
336+
const edits: MongoDBDataModelDescription['edits'] = [
337+
{
338+
id: 'first-edit',
339+
timestamp: new Date().toISOString(),
340+
type: 'SetModel',
341+
model: {
342+
collections: [
343+
{
344+
ns: 'collection1',
345+
indexes: [],
346+
displayPosition: [0, 0],
347+
shardKey: {},
348+
jsonSchema: {
349+
bsonType: 'object',
350+
properties: {
351+
prop1: { bsonType: 'string' },
352+
// Deeply nested properties
353+
prop2: {
354+
bsonType: 'object',
355+
properties: {
356+
prop2A: { bsonType: 'string' },
357+
prop2B: {
358+
bsonType: 'object',
359+
properties: {
360+
prop2B1: { bsonType: 'string' },
361+
prop2B2: { bsonType: 'int' },
362+
},
363+
},
364+
},
365+
},
366+
// Array of objects
367+
prop3: {
368+
bsonType: 'array',
369+
items: {
370+
bsonType: 'object',
371+
properties: {
372+
prop3A: { bsonType: 'string' },
373+
},
374+
},
375+
},
376+
// Mixed type with objects
377+
prop4: {
378+
anyOf: [
379+
{
380+
bsonType: 'object',
381+
properties: {
382+
prop4A: { bsonType: 'string' },
383+
},
384+
},
385+
{
386+
bsonType: 'object',
387+
properties: {
388+
prop4B: { bsonType: 'string' },
389+
},
390+
},
391+
],
392+
},
393+
// Mixed array with objects
394+
prop5: {
395+
bsonType: 'array',
396+
items: [
397+
{
398+
bsonType: 'object',
399+
properties: {
400+
prop5A: { bsonType: 'string' },
401+
},
402+
},
403+
{
404+
bsonType: 'object',
405+
properties: {
406+
prop5B: { bsonType: 'number' },
407+
},
408+
},
409+
],
410+
},
411+
},
412+
},
413+
},
414+
],
415+
relationships: [],
416+
},
417+
},
418+
];
419+
const selectedFields = selectFieldsForCurrentModel(edits);
420+
421+
expect(selectedFields).to.have.property('collection1');
422+
expect(selectedFields.collection1).to.deep.include(['prop1']);
423+
expect(selectedFields.collection1).to.deep.include(['prop2']);
424+
expect(selectedFields.collection1).to.deep.include(['prop2', 'prop2A']);
425+
expect(selectedFields.collection1).to.deep.include([
426+
'prop2',
427+
'prop2B',
428+
'prop2B1',
429+
]);
430+
expect(selectedFields.collection1).to.deep.include([
431+
'prop2',
432+
'prop2B',
433+
'prop2B2',
434+
]);
435+
expect(selectedFields.collection1).to.deep.include(['prop3']);
436+
expect(selectedFields.collection1).to.deep.include(['prop3', 'prop3A']);
437+
expect(selectedFields.collection1).to.deep.include(['prop4']);
438+
expect(selectedFields.collection1).to.deep.include(['prop4', 'prop4A']);
439+
expect(selectedFields.collection1).to.deep.include(['prop4', 'prop4B']);
440+
expect(selectedFields.collection1).to.deep.include(['prop5']);
441+
expect(selectedFields.collection1).to.deep.include(['prop5', 'prop5A']);
442+
expect(selectedFields.collection1).to.deep.include(['prop5', 'prop5B']);
443+
});
444+
});
298445
});

packages/compass-data-modeling/src/store/diagram.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,19 @@ function extractFields(
610610
parentKey?: string[],
611611
fields: string[][] = []
612612
) {
613+
if ('anyOf' in parentSchema && parentSchema.anyOf) {
614+
for (const schema of parentSchema.anyOf) {
615+
extractFields(schema, parentKey, fields);
616+
}
617+
}
618+
if ('items' in parentSchema && parentSchema.items) {
619+
const items = Array.isArray(parentSchema.items)
620+
? parentSchema.items
621+
: [parentSchema.items];
622+
for (const schema of items) {
623+
extractFields(schema, parentKey, fields);
624+
}
625+
}
613626
if ('properties' in parentSchema && parentSchema.properties) {
614627
for (const [key, value] of Object.entries(parentSchema.properties)) {
615628
const fullKey = parentKey ? [...parentKey, key] : [key];

0 commit comments

Comments
 (0)