@aws-amplify/appsync-modelgen-plugin
Version:
145 lines • 7.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.addHasManyKey = exports.hasManyHasImplicitKey = exports.getConnectedFieldsForHasMany = exports.processHasManyConnection = void 0;
const constants_1 = require("./constants");
const fieldUtils_1 = require("./fieldUtils");
const fieldUtils_2 = require("./fieldUtils");
const process_connections_1 = require("./process-connections");
const process_connections_v2_1 = require("./process-connections-v2");
function processHasManyConnection(field, model, modelMap, connectionDirective, shouldUseModelNameFieldInHasManyAndBelongsTo, isCustomPKEnabled = false) {
if (!field.isList) {
throw new Error("A field with hasMany must be a list type");
}
const otherSide = modelMap[field.type];
const connectionFields = connectionDirective.arguments.fields || [];
const references = connectionDirective.arguments.references || [];
if (references.length > 0) {
const associatedWithNativeReferences = (0, process_connections_v2_1.getConnectedFieldForReferences)(field, model, otherSide, connectionDirective.name);
const associatedWithFields = references.map((reference) => otherSide.fields.find((field) => reference === field.name));
return {
kind: process_connections_1.CodeGenConnectionType.HAS_MANY,
associatedWith: associatedWithFields[0],
associatedWithFields,
associatedWithNativeReferences,
isConnectingFieldAutoCreated: false,
connectedModel: otherSide,
};
}
const otherSideFields = isCustomPKEnabled
? getConnectedFieldsForHasMany(field, model, otherSide, shouldUseModelNameFieldInHasManyAndBelongsTo)
: [(0, process_connections_v2_1.getConnectedFieldV2)(field, model, otherSide, connectionDirective.name, shouldUseModelNameFieldInHasManyAndBelongsTo)];
const otherSideField = otherSideFields[0];
const isConnectingFieldAutoCreated = connectionFields.length === 0;
return {
kind: process_connections_1.CodeGenConnectionType.HAS_MANY,
associatedWith: otherSideField,
associatedWithFields: otherSideFields,
isConnectingFieldAutoCreated,
connectedModel: otherSide,
};
}
exports.processHasManyConnection = processHasManyConnection;
function getConnectedFieldsForHasMany(field, model, connectedModel, shouldUseModelNameFieldInHasManyAndBelongsTo) {
var _a, _b, _c;
const hasManyDir = (0, fieldUtils_1.getDirective)(field)(constants_1.TransformerV2DirectiveName.HAS_MANY);
if (!hasManyDir) {
throw new Error(`The ${field.name} on model ${model.name} is not connected`);
}
let otherSideConnectedField;
const indexName = hasManyDir.arguments.indexName;
const indexMatchingFields = hasManyDir.arguments.fields;
if (indexMatchingFields) {
let otherSideConnectedDir;
const otherSideFieldDirectives = (0, process_connections_1.flattenFieldDirectives)(connectedModel);
if (indexName) {
otherSideConnectedDir = otherSideFieldDirectives.find(dir => {
return dir.name === constants_1.TransformerV2DirectiveName.INDEX && dir.arguments.name === indexName;
});
if (!otherSideConnectedDir) {
throw new Error(`Error processing @hasMany directive on ${model.name}.${field.name}, @index directive with name ${indexName} was not found in connected model ${connectedModel.name}`);
}
}
else {
otherSideConnectedDir = otherSideFieldDirectives.find(dir => {
return dir.name === constants_1.TransformerV2DirectiveName.PRIMARY_KEY;
});
}
const otherSideConnectedFieldName = (_c = (_a = otherSideConnectedDir === null || otherSideConnectedDir === void 0 ? void 0 : otherSideConnectedDir.fieldName) !== null && _a !== void 0 ? _a : (_b = (0, fieldUtils_1.getOtherSideBelongsToField)(model.name, connectedModel)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : constants_1.DEFAULT_HASH_KEY_FIELD;
otherSideConnectedField = connectedModel.fields
.filter(f => f.type === model.name)
.find(f => f.directives.find(d => (d.name === constants_1.TransformerV2DirectiveName.BELONGS_TO) &&
d.arguments.fields &&
d.arguments.fields[0] === otherSideConnectedFieldName));
if (otherSideConnectedField) {
return [otherSideConnectedField];
}
otherSideConnectedField = connectedModel.fields.find(f => f.name === otherSideConnectedFieldName);
if (!otherSideConnectedField) {
throw new Error(`Can not find key field ${otherSideConnectedFieldName} in ${connectedModel.name}`);
}
return [otherSideConnectedField];
}
if (shouldUseModelNameFieldInHasManyAndBelongsTo) {
otherSideConnectedField = connectedModel.fields
.filter(f => f.type === model.name)
.find(f => f.directives.find(d => d.name === constants_1.TransformerV2DirectiveName.BELONGS_TO));
if (otherSideConnectedField) {
return [otherSideConnectedField];
}
}
return (0, fieldUtils_2.getModelPrimaryKeyComponentFields)(model)
.map(compField => {
const foreignKeyFieldName = (0, process_connections_1.makeConnectionAttributeName)(model.name, field.name, compField.name);
otherSideConnectedField = connectedModel.fields.find(f => f.name === foreignKeyFieldName);
return otherSideConnectedField !== null && otherSideConnectedField !== void 0 ? otherSideConnectedField : {
name: foreignKeyFieldName,
directives: [],
type: compField.type,
isList: false,
isNullable: true,
};
});
}
exports.getConnectedFieldsForHasMany = getConnectedFieldsForHasMany;
function addKeyToModel(model, name, fields) {
model.directives.push({
name: 'key',
arguments: {
name,
fields,
},
});
}
function getConnectionAssociatedFields(hasManyConnection) {
const associatedFields = hasManyConnection.associatedWithFields && hasManyConnection.associatedWithFields.length > 0
? hasManyConnection.associatedWithFields
: [hasManyConnection.associatedWith];
if (associatedFields.length === 0) {
throw new Error('Expected at least one associated field for the hasMany relationship.');
}
return associatedFields;
}
function doesHasManyConnectionHaveCorrespondingBelongsTo(model, hasManyConnection) {
const fieldReferencingParent = hasManyConnection.connectedModel.fields.find(f => f.type === model.name);
if (!fieldReferencingParent) {
return false;
}
return fieldReferencingParent.directives.some(d => d.name === constants_1.TransformerV2DirectiveName.BELONGS_TO);
}
function doesHasManySpecifyIndexName(field) {
return field.directives.some(d => d.name === constants_1.TransformerV2DirectiveName.HAS_MANY && d.arguments.indexName);
}
function hasManyHasImplicitKey(field, model, hasManyConnection) {
const hasCorrespondingBelongsTo = doesHasManyConnectionHaveCorrespondingBelongsTo(model, hasManyConnection);
const hasIndexNameSpecified = doesHasManySpecifyIndexName(field);
return !(hasCorrespondingBelongsTo || hasIndexNameSpecified);
}
exports.hasManyHasImplicitKey = hasManyHasImplicitKey;
function addHasManyKey(field, model, hasManyConnection) {
const associatedFieldNames = getConnectionAssociatedFields(hasManyConnection).map(f => f.name);
const connectedModel = hasManyConnection.connectedModel;
const name = `gsi-${model.name}.${field.name}`;
addKeyToModel(connectedModel, name, associatedFieldNames);
}
exports.addHasManyKey = addHasManyKey;
//# sourceMappingURL=process-has-many.js.map