MCPcopy Create free account
hub / github.com/zenstackhq/zenstack / computeManyToManyRelation

Function computeManyToManyRelation

packages/orm/src/client/query-utils.ts:344–391  ·  view source on GitHub ↗
(schema: SchemaDef, model: string, field: string)

Source from the content-addressed store, hash-verified

342}
343
344function computeManyToManyRelation(schema: SchemaDef, model: string, field: string) {
345 const fieldDef = requireField(schema, model, field);
346 if (!fieldDef.array || !fieldDef.relation?.opposite) {
347 return undefined;
348 }
349
350 // in case the m2m relation field is inherited from a delegate base, get the base model
351 const realModel = fieldDef.originModel ?? model;
352
353 const oppositeFieldDef = requireField(schema, fieldDef.type, fieldDef.relation.opposite);
354 if (oppositeFieldDef.array) {
355 // Prisma's convention for many-to-many relation:
356 // - model are sorted alphabetically by name
357 // - join table is named _<model1>To<model2>, unless an explicit name is provided by `@relation`
358 // - foreign keys are named A and B (based on the order of the model)
359 const sortedModelNames = [realModel, fieldDef.type].sort();
360
361 let orderedFK: [string, string];
362 if (realModel !== fieldDef.type) {
363 // not a self-relation, model name's sort order determines fk order
364 orderedFK = sortedModelNames[0] === realModel ? ['A', 'B'] : ['B', 'A'];
365 } else {
366 // for self-relations, since model names are identical, relation field name's
367 // sort order determines fk order
368 const sortedFieldNames = [field, oppositeFieldDef.name].sort();
369 orderedFK = sortedFieldNames[0] === field ? ['A', 'B'] : ['B', 'A'];
370 }
371
372 const modelIdFields = requireIdFields(schema, realModel);
373 invariant(modelIdFields.length === 1, 'Only single-field ID is supported for many-to-many relation');
374 const otherIdFields = requireIdFields(schema, fieldDef.type);
375 invariant(otherIdFields.length === 1, 'Only single-field ID is supported for many-to-many relation');
376
377 return {
378 parentFkName: orderedFK[0],
379 parentPKName: modelIdFields[0]!,
380 otherModel: fieldDef.type,
381 otherField: fieldDef.relation.opposite,
382 otherFkName: orderedFK[1],
383 otherPKName: otherIdFields[0]!,
384 joinTable: fieldDef.relation.name
385 ? `_${fieldDef.relation.name}`
386 : `_${sortedModelNames[0]}To${sortedModelNames[1]}`,
387 };
388 } else {
389 return undefined;
390 }
391}
392
393/**
394 * Convert filter like `{ id1_id2: { id1: 1, id2: 1 } }` to `{ id1: 1, id2: 1 }`

Callers 1

getManyToManyRelationFunction · 0.85

Calls 3

invariantFunction · 0.90
requireIdFieldsFunction · 0.85
requireFieldFunction · 0.70

Tested by

no test coverage detected