@grapi/server
Version:
Grapi Schema Generator For GraphQL Server
215 lines (214 loc) • 10.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRelation = void 0;
const constants_1 = require("../../constants");
const lodash_1 = require("../../lodash");
const relationField_1 = __importDefault(require("../relationField"));
const types_1 = require("./types");
const createDefaultRelationName = (relationConfig) => {
const sourceName = relationConfig.source.getNamings().capitalSingular;
const targetName = relationConfig.target.getNamings().capitalSingular;
return `${sourceName}And${targetName}On${relationConfig.sourceField}`;
};
var toRelation;
(function (toRelation) {
toRelation["one"] = "1";
toRelation["many"] = "*";
})(toRelation || (toRelation = {}));
const configModelRelation = (sourceModel, targetModel, sourceFieldName, targetFieldName, relationType, metadata, name) => {
return {
name,
metadata,
type: relationType,
source: sourceModel, target: targetModel,
sourceField: sourceFieldName, targetField: targetFieldName
};
};
const configRelation = (sourceSide, targetSide, metadata, name, relationType) => {
return configModelRelation(sourceSide.sourceModel, sourceSide.targetModel, sourceSide.fieldName, targetSide.fieldName, relationType, metadata, name);
};
const configRelationField = (relationField, relationType, relationShip) => {
relationField.setRelationType(relationType);
relationField.setRelation(relationShip);
};
const configRelationFields = (sourceField, targetField, relationSource, relationTarget, relationType) => {
configRelationField(sourceField, relationType, relationSource);
configRelationField(targetField, relationType, relationTarget);
};
const createRelation = (models) => {
const findModel = (name) => models.find(model => model.getName() === name);
const modelRelations = [];
const relationTable = {};
const relationsWithName = {};
models.forEach(model => {
relationTable[model.getName()] = {};
(0, lodash_1.forEach)(model.getFields(), (field, fieldName) => {
if (!(field instanceof relationField_1.default)) {
return;
}
const relationToModel = field.getRelationTo();
const relationToModelName = relationToModel.getName();
const relationField = {
type: field.isList() ? toRelation.many : toRelation.one,
fieldName,
field,
sourceModel: model,
targetModel: relationToModel,
};
const relationName = (0, lodash_1.get)(field.getRelationConfig(), 'name') ||
(0, lodash_1.get)(field.getMetadata('relation'), 'name');
if (relationName) {
field.setRelationName(relationName);
if (!relationsWithName[relationName]) {
relationsWithName[relationName] = { sourceSide: relationField };
}
else if (relationsWithName[relationName]) {
relationsWithName[relationName].targetSide = relationField;
}
return;
}
const targetRelation = relationTable[model.getName()][relationToModelName];
if (!targetRelation) {
relationTable[model.getName()][relationToModelName] = [];
}
relationTable[model.getName()][relationToModelName].push(relationField);
});
});
(0, lodash_1.forEach)(relationsWithName, ({ sourceSide, targetSide }, name) => {
let relation;
const sourceField = sourceSide.field;
const targetField = (0, lodash_1.get)(targetSide, `field`);
if (!targetSide) {
configRelationField(sourceField, (sourceSide.type === toRelation.one) ? types_1.RelationType.uniOneToOne : types_1.RelationType.uniOneToMany, (sourceSide.type === toRelation.one) ? types_1.RelationShip.OneToOne : types_1.RelationShip.OneToMany);
const metadata = sourceField.getMetadata(constants_1.RELATION_DIRECTIVE_NAME);
relation = {
name,
type: sourceField.getRelationType(),
source: sourceSide.sourceModel,
target: sourceSide.targetModel,
sourceField: sourceSide.fieldName,
metadata: (0, lodash_1.get)(metadata, constants_1.RELATION_WITH) ? (0, lodash_1.mapValues)(sourceField.getRelationConfig(), (value) => {
if (value instanceof Object) {
return value.key;
}
return value;
}) : metadata
};
modelRelations.push(relation);
return;
}
const relationConfig = sourceField.getRelationConfig();
const relationFields = {};
if (sourceSide.type === toRelation.one && targetSide.type === toRelation.one) {
relationFields.relation = types_1.RelationShip.OneToOne;
relationFields.type = types_1.RelationType.biOneToOne;
relation = configRelation(sourceSide, targetSide, relationConfig, name, types_1.RelationType.biOneToOne);
}
else if (sourceSide.type === toRelation.one && targetSide.type === toRelation.many) {
relationFields.relation = types_1.RelationShip.OneToMany;
relationFields.type = types_1.RelationType.biOneToMany;
relation = configModelRelation(sourceSide.targetModel, targetSide.targetModel, targetSide.fieldName, sourceSide.fieldName, types_1.RelationType.biOneToMany, relationConfig, name);
}
else if (sourceSide.type === toRelation.many && targetSide.type === toRelation.one) {
relationFields.relation = types_1.RelationShip.OneToMany;
relationFields.type = types_1.RelationType.biOneToMany;
relation = configModelRelation(sourceSide.sourceModel, targetSide.sourceModel, sourceSide.fieldName, targetSide.fieldName, types_1.RelationType.biOneToMany, relationConfig, name);
}
else if (sourceSide.type === toRelation.many && targetSide.type === toRelation.many) {
relationFields.relation = types_1.RelationShip.ManyToMany;
relationFields.type = types_1.RelationType.biManyToMany;
relation = configRelation(sourceSide, targetSide, relationConfig, name, types_1.RelationType.biManyToMany);
}
else {
throw new Error(`unknown relation type from ${sourceSide.type} to ${targetSide.type}`);
}
configRelationFields(sourceField, targetField, relationFields.relation, relationFields.relation, relationFields.type);
modelRelations.push(relation);
});
(0, lodash_1.forEach)(relationTable, (toRelationMap, fromModelName) => {
(0, lodash_1.forEach)(toRelationMap, (fields, toModelName) => {
const otherSideFields = (0, lodash_1.get)(relationTable, [toModelName, fromModelName]);
fields.forEach(({ type, field, fieldName, built }) => {
if (built) {
return;
}
let relationConfig;
const fromModel = findModel(fromModelName);
const toModel = findModel(toModelName);
if (!otherSideFields || (0, lodash_1.size)(otherSideFields) > 1) {
relationConfig = {
type: (type === toRelation.one) ? types_1.RelationType.uniOneToOne : types_1.RelationType.uniOneToMany,
source: fromModel,
target: toModel,
sourceField: fieldName,
metadata: field.getMetadata(constants_1.RELATION_DIRECTIVE_NAME),
};
const uniRelationName = createDefaultRelationName(relationConfig);
field.setRelationName(uniRelationName);
modelRelations.push({
name: uniRelationName,
...relationConfig,
});
return;
}
const otherSide = otherSideFields[0];
if (type === toRelation.one && otherSide.type === toRelation.one) {
relationConfig = {
type: types_1.RelationType.biOneToOne,
source: fromModel,
target: toModel,
sourceField: fieldName,
targetField: otherSide.fieldName,
metadata: field.getRelationConfig(),
};
}
else if (type === toRelation.one && otherSide.type === toRelation.many) {
relationConfig = {
type: types_1.RelationType.biOneToMany,
source: toModel,
target: fromModel,
sourceField: otherSide.fieldName,
targetField: fieldName,
metadata: field.getRelationConfig(),
};
}
else if (type === toRelation.many && otherSide.type === toRelation.one) {
relationConfig = {
type: types_1.RelationType.biOneToMany,
source: fromModel,
target: toModel,
sourceField: fieldName,
targetField: otherSide.fieldName,
metadata: field.getRelationConfig(),
};
}
else if (type === toRelation.many && otherSide.type === toRelation.many) {
relationConfig = {
type: types_1.RelationType.biManyToMany,
source: fromModel,
target: toModel,
sourceField: fieldName,
targetField: otherSide.fieldName,
metadata: field.getRelationConfig(),
};
}
else {
throw new Error(`unknown relation type from ${type} to ${otherSide.type}`);
}
otherSide.built = true;
const relationName = createDefaultRelationName(relationConfig);
field.setRelationName(relationName);
otherSide.field.setRelationName(relationName);
modelRelations.push({
name: relationName,
...relationConfig,
});
});
});
});
return modelRelations;
};
exports.createRelation = createRelation;