Skip to content

feat(gen2-migration): support overriding default resolvers#14769

Draft
dgandhi62 wants to merge 14 commits intogen2-migrationfrom
override-default-resolvers
Draft

feat(gen2-migration): support overriding default resolvers#14769
dgandhi62 wants to merge 14 commits intogen2-migrationfrom
override-default-resolvers

Conversation

@dgandhi62
Copy link
Copy Markdown
Contributor

@dgandhi62 dgandhi62 commented Apr 10, 2026

Input

Query.listBoards.req.vtl

## [Start] Custom List Request - Override to cap results at 50. **
#set( $args = $util.defaultIfNull($ctx.stash.transformedArgs, $ctx.args) )
#set( $limit = $util.defaultIfNull($args.limit, 50) )
## Cap the limit at 50 to keep the board list manageable
#if( $limit > 50 )
  #set( $limit = 50 )
#end
#set( $ListRequest = {
  "version": "2018-05-29",
  "limit": $limit
} )
#if( $args.nextToken )
  #set( $ListRequest.nextToken = $args.nextToken )
#end
#if( !$util.isNullOrEmpty($ctx.stash.authFilter) )
  #set( $filter = $ctx.stash.authFilter )
  #if( !$util.isNullOrEmpty($args.filter) )
    #set( $filter = {
  "and":   [$filter, $args.filter]
} )
  #end
#else
  #if( !$util.isNullOrEmpty($args.filter) )
    #set( $filter = $args.filter )
  #end
#end
#if( !$util.isNullOrEmpty($filter) )
  #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) )
  #if( $util.isNullOrEmpty($filterExpression) )
    $util.error("Unable to process the filter expression", "Unrecognized Filter")
  #end
  #if( !$util.isNullOrBlank($filterExpression.expression) )
    #if( $filterExpression.expressionValues.size() == 0 )
      $util.qr($filterExpression.remove("expressionValues"))
    #end
    #set( $ListRequest.filter = $filterExpression )
  #end
#end
#if( !$util.isNull($ctx.stash.modelQueryExpression) && !$util.isNullOrEmpty($ctx.stash.modelQueryExpression.expression) )
  $util.qr($ListRequest.put("operation", "Query"))
  $util.qr($ListRequest.put("query", $ctx.stash.modelQueryExpression))
  #if( !$util.isNull($args.sortDirection) && $args.sortDirection == "DESC" )
    #set( $ListRequest.scanIndexForward = false )
  #else
    #set( $ListRequest.scanIndexForward = true )
  #end
#else
  $util.qr($ListRequest.put("operation", "Scan"))
#end
#if( !$util.isNull($ctx.stash.metadata.index) )
  #set( $ListRequest.IndexName = $ctx.stash.metadata.index )
#end
$util.toJson($ListRequest)
## [End] Custom List Request. **

Query.listBoards.res.vtl

## [Start] Custom ResponseTemplate - Prepend emoji to board names to prove override is active. **
#if( $ctx.error )
  $util.error($ctx.error.message, $ctx.error.type)
#end

## Add a pin emoji prefix to each board name so it's visible on the frontend
#foreach( $item in $ctx.result.items )
  #if( !$item.name.startsWith("📌 ") )
    $util.qr($item.put("name", "📌 $item.name"))
  #end
#end

$util.toJson($ctx.result)
## [End] Custom ResponseTemplate. **

Output

backend.ts

const __dirname = dirname(fileURLToPath(import.meta.url));
const resolversDir = join(__dirname, 'data/resolvers');
const resolverFiles = readdirSync(resolversDir).filter(
  (f) => f.endsWith('.req.vtl') || f.endsWith('.res.vtl')
);
for (const file of resolverFiles) {
  const parts = file.replace('.req.vtl', '').replace('.res.vtl', '').split('.');
  const [typeName, fieldName] = parts;
  const isRequest = file.endsWith('.req.vtl');
  const functionId = `${typeName}${
    fieldName.charAt(0).toUpperCase() + fieldName.slice(1)
  }DataResolverFn`;
  const pipelineFunction =
    backend.data.resources.cfnResources.cfnFunctionConfigurations[functionId];
  if (pipelineFunction) {
    const templatePath = join(resolversDir, file);
    const vtlTemplate = new assets.Asset(backend.data, `VTLTemplate-${file}`, {
      path: templatePath
    });
    if (isRequest) {
      pipelineFunction.requestMappingTemplateS3Location = vtlTemplate.s3ObjectUrl;
    } else {
      pipelineFunction.responseMappingTemplateS3Location = vtlTemplate.s3ObjectUrl;
    }
  }
}

@dgandhi62 dgandhi62 force-pushed the override-default-resolvers branch from 92d87a9 to 74ac890 Compare April 10, 2026 18:49
…lvers

When a Gen1 project has custom VTL resolver files in
amplify/backend/api/<name>/resolvers/, the DataGenerator now:

- Detects .vtl files in the local resolvers directory
- Copies them to amplify/data/resolvers/ in the Gen2 output
- Generates backend.ts code that reads the VTL files at runtime
  and overrides pipeline function request/response mapping
  templates, replacing S3-based templates with inline content

Supports both .req.vtl (request) and .res.vtl (response)
resolver overrides. The generated for-of loop determines the
resolver type from the filename suffix and overrides the
corresponding mapping template properties.
@dgandhi62 dgandhi62 force-pushed the override-default-resolvers branch from 74ac890 to 7ff85ea Compare April 20, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant