Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
directive: DirectiveNode,
ctx: TransformerContext
): void => {
const parentTypeName = parent.name.value;
const fieldName = field.name.value;
const args : RelationArguments = getDirectiveArguments(directive);
const numFields = args.fields.length;
// Check that related type exists and that the connected object is annotated with @model.
const relatedTypeName = getBaseType(field.type)
const relatedType = ctx.inputDocument.definitions.find(
d => d.kind === Kind.OBJECT_TYPE_DEFINITION && d.name.value === relatedTypeName
) as ObjectTypeDefinitionNode | undefined
// Get Child object's table.
const tableLogicalID = ModelResourceIDs.ModelTableResourceID(relatedType.name.value);
const tableResource = ctx.getResource(tableLogicalID) as Table;
// Ensure that there is at least one field provided.
if (numFields === 0) {
throw new InvalidDirectiveError('No fields passed in to @connection directive.')
}
// Check that each field provided exists in the parent model and that it is a valid key type (single non-null).
let inputFields : FieldDefinitionNode[] = [];
args.fields.forEach(
item => {
const fieldsArrayLength = inputFields.length;
inputFields[fieldsArrayLength] = parent.fields.find(f => f.name.value === item);
if (!inputFields[fieldsArrayLength]) {
throw new InvalidDirectiveError(item + ' is not a field in ' + parentTypeName)
}
new Map()
)
nonModelArray.forEach(
(value: ObjectTypeDefinitionNode) => {
let nonModelObject = makeNonModelInputObject(value, nonModelArray, ctx)
if (!this.typeExist(nonModelObject.name.value, ctx)) {
ctx.addInput(nonModelObject)
}
}
)
// Create the dynamodb table to hold the @model type
// TODO: Handle types with more than a single "id" hash key
const typeName = def.name.value
const tableLogicalID = ModelResourceIDs.ModelTableResourceID(typeName)
const iamRoleLogicalID = ModelResourceIDs.ModelTableIAMRoleID(typeName)
const dataSourceRoleLogicalID = ModelResourceIDs.ModelTableDataSourceID(typeName)
const deletionPolicy = this.opts.EnableDeletionProtection ?
DeletionPolicy.Retain :
DeletionPolicy.Delete;
ctx.setResource(
tableLogicalID,
this.resources.makeModelTable(typeName, undefined, undefined, deletionPolicy)
)
ctx.mapResourceToStack(stackName, tableLogicalID);
ctx.setResource(
iamRoleLogicalID,
this.resources.makeIAMRole(typeName)
)
ctx.mapResourceToStack(stackName, iamRoleLogicalID);
replacePrimaryKey = (definition: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerContext) => {
const args: KeyArguments = getDirectiveArguments(directive);
const ks = keySchema(args);
const attrDefs = attributeDefinitions(args, definition, ctx);
const tableLogicalID = ModelResourceIDs.ModelTableResourceID(definition.name.value);
const tableResource = ctx.getResource(tableLogicalID);
if (!tableResource) {
throw new InvalidDirectiveError(`The @key directive may only be added to object definitions annotated with @model.`);
} else {
// First remove any attribute definitions in the current primary key.
const existingAttrDefSet = new Set(tableResource.Properties.AttributeDefinitions.map(ad => ad.AttributeName));
for (const existingKey of tableResource.Properties.KeySchema) {
if (existingAttrDefSet.has(existingKey.AttributeName)) {
tableResource.Properties.AttributeDefinitions = tableResource.Properties.AttributeDefinitions.filter(ad => ad.AttributeName !== existingKey.AttributeName);
existingAttrDefSet.delete(existingKey.AttributeName);
}
}
// Then replace the KeySchema and add any new attribute definitions back.
tableResource.Properties.KeySchema = ks;
for (const attr of attrDefs) {
if (!existingAttrDefSet.has(attr.AttributeName)) {
ctx.putType(updated)
}
} else if (leftConnectionIsList) {
// 4. [] to ?
// Store foreign key on the related table and wire up a Query resolver.
// This has no inverse and has limited knowlege of the connection.
if (!connectionAttributeName) {
connectionAttributeName = makeConnectionAttributeName(parentTypeName, fieldName)
}
// Validate the provided key field is legit.
const existingKeyField = relatedType.fields.find(f => f.name.value === connectionAttributeName)
validateKeyField(existingKeyField);
const tableLogicalId = ModelResourceIDs.ModelTableResourceID(relatedTypeName)
const table = ctx.getResource(tableLogicalId) as Table
const updated = this.resources.updateTableForConnection(table, connectionName, connectionAttributeName)
ctx.setResource(tableLogicalId, updated)
const queryResolver = this.resources.makeQueryConnectionResolver(
parentTypeName,
fieldName,
relatedTypeName,
connectionAttributeName,
connectionName,
sortKeyInfo
)
ctx.setResource(ResolverResourceIDs.ResolverResourceID(parentTypeName, fieldName), queryResolver)
this.extendTypeWithConnection(ctx, parent, field, relatedType, sortKeyInfo)
DataSourceName: ModelResourceIDs.ModelTableResourceID(relatedType.name.value),
FieldName: field,
TypeName: type,
RequestMappingTemplate: print(
compoundExpression([
...setup,
DynamoDBMappingTemplate.query(queryArguments)
])
),
ResponseMappingTemplate: print(
compoundExpression([
iff(raw('!$result'), set(ref('result'), ref('ctx.result'))),
raw('$util.toJson($result)')
])
)
}).dependsOn([ResourceConstants.RESOURCES.GraphQLSchemaLogicalID, ModelResourceIDs.ModelTableResourceID(relatedType.name.value)])
}
),
limit: ref('limit'),
nextToken: ifElse(
ref('context.args.nextToken'),
str('$context.args.nextToken'),
nul()
)
}
if (indexName) {
let indexArg = "index";
queryArguments[indexArg] = str(indexName);
}
return new Resolver({
ApiId: Fn.GetAtt(ResourceConstants.RESOURCES.GraphQLAPILogicalID, 'ApiId'),
DataSourceName: ModelResourceIDs.ModelTableResourceID(relatedType.name.value),
FieldName: field,
TypeName: type,
RequestMappingTemplate: print(
compoundExpression([
...setup,
DynamoDBMappingTemplate.query(queryArguments)
])
),
ResponseMappingTemplate: print(
compoundExpression([
iff(raw('!$result'), set(ref('result'), ref('ctx.result'))),
raw('$util.toJson($result)')
])
)
}).dependsOn([ResourceConstants.RESOURCES.GraphQLSchemaLogicalID, ModelResourceIDs.ModelTableResourceID(relatedType.name.value)])
}
private getPrimaryKey(ctx: TransformerContext, typeName: string): string {
const tableResourceID = ModelResourceIDs.ModelTableResourceID(typeName);
const tableResource = ctx.getResource(tableResourceID);
const primaryKeySchemaElement = tableResource.Properties.KeySchema.find((keyElement: any) => keyElement.KeyType === 'HASH');
return primaryKeySchemaElement.AttributeName;
}
}
return new Resolver({
ApiId: Fn.GetAtt(ResourceConstants.RESOURCES.GraphQLAPILogicalID, 'ApiId'),
DataSourceName: ModelResourceIDs.ModelTableResourceID(relatedType),
FieldName: field,
TypeName: type,
RequestMappingTemplate: print(
compoundExpression([
DynamoDBMappingTemplate.getItem({
key: keyObj
})
])
),
ResponseMappingTemplate: print(
ref('util.toJson($context.result)')
)
}).dependsOn([ResourceConstants.RESOURCES.GraphQLSchemaLogicalID, ModelResourceIDs.ModelTableResourceID(relatedType)])
}
public makeDynamoDBStreamEventSourceMapping(typeName: string) {
return new Lambda.EventSourceMapping({
BatchSize: 1,
Enabled: true,
EventSourceArn: Fn.ImportValue(
Fn.Join(
':',
[Fn.Ref(ResourceConstants.PARAMETERS.AppSyncApiId), "GetAtt", ModelResourceIDs.ModelTableResourceID(typeName), "StreamArn"]
)
),
FunctionName: Fn.GetAtt(ResourceConstants.RESOURCES.ElasticsearchStreamingLambdaFunctionLogicalID, 'Arn'),
StartingPosition: 'LATEST'
}).dependsOn([
ResourceConstants.RESOURCES.ElasticsearchStreamingLambdaFunctionLogicalID
])
}