{
  "version": 3,
  "sources": ["../../../src/cdc/handler.ts"],
  "sourcesContent": ["import snakeCase from 'lodash/snakeCase.js';\n\nimport type {\n  ChangeDataCaptureConfig,\n  Model,\n} from '@code-like-a-carpenter/foundation-intermediate-representation';\n\nimport type {\n  AWSIAMPolicy,\n  Resource7,\n} from '../__generated__/json-schemas/serverless-application-model.ts';\nimport type {Config} from '../config.ts';\nimport {combineFragments} from '../fragments/combine-fragments.ts';\nimport {makeKmsKey} from '../fragments/kms-key.ts';\nimport {writeLambda} from '../fragments/lambda.ts';\nimport {filterNull} from '../helpers.ts';\nimport {makeHandlerStack, makeHandlerStackName} from '../stacks/handler.ts';\nimport type {ServerlessApplicationModel} from '../types.ts';\n\n/** generate the dispatcher lambda function */\nexport function makeHandler(\n  config: Config,\n  model: Model,\n  cdc: ChangeDataCaptureConfig,\n  template: string\n): {\n  fragment: ServerlessApplicationModel;\n  stack: ServerlessApplicationModel;\n} {\n  const {\n    table: {tableName},\n  } = model;\n\n  const {\n    directory,\n    event,\n    filename,\n    functionName,\n    memorySize,\n    readableTables,\n    sourceModelName,\n    timeout,\n    nestedStackLocation,\n    writableTables,\n  } = cdc;\n\n  writeLambda(directory, template);\n\n  const stackName = makeHandlerStackName(model, cdc);\n  const qKeyName = 'SharedKmsKey';\n\n  const stack: Resource7 = {\n    Properties: {\n      Location: nestedStackLocation,\n      Parameters: {\n        ...(config.singleQueueKey\n          ? {\n              ExternalKmsMasterKeyId: {\n                'Fn::If': [\n                  'DefineSharedKmsKey',\n                  {Ref: qKeyName},\n                  'AWS::NoValue',\n                ],\n              },\n            }\n          : {}),\n        CodeUri: filename,\n        DetailType: event === 'UPSERT' ? 'INSERT,MODIFY' : event,\n        MemorySize: memorySize,\n        SourceModelName: sourceModelName,\n        StageName: {Ref: 'StageName'},\n        TableArn: {'Fn::GetAtt': [tableName, 'Arn']},\n        // This is the table logical name, not the table name\n        TableName: tableName,\n        TableNames: {\n          'Fn::ToJsonString': Object.fromEntries(\n            [...readableTables, ...writableTables].map((t) => [\n              snakeCase(t).toUpperCase(),\n              {Ref: t},\n            ])\n          ),\n        },\n        Timeout: timeout,\n      },\n    },\n    Type: 'AWS::Serverless::Application',\n  };\n\n  const tableAccessPolicy: AWSIAMPolicy = {\n    Properties: {\n      PolicyDocument: {\n        Statement: [\n          readableTables.length && {\n            Action: [\n              'dynamodb:GetItem',\n              'dynamodb:Scan',\n              'dynamodb:Query',\n              'dynamodb:BatchGetItem',\n              'dynamodb:DescribeTable',\n            ],\n            Effect: 'Allow',\n            Resource: [\n              ...readableTables.map((name) => ({\n                'Fn::GetAtt': [name, 'Arn'],\n              })),\n              ...readableTables.map((name) => ({\n                'Fn::Sub': [\n                  // eslint-disable-next-line no-template-curly-in-string\n                  '${tableArn}/index/*',\n                  {tableArn: {'Fn::GetAtt': [name, 'Arn']}},\n                ],\n              })),\n            ],\n          },\n          writableTables.length && {\n            Action: [\n              'dynamodb:GetItem',\n              'dynamodb:DeleteItem',\n              'dynamodb:PutItem',\n              'dynamodb:Scan',\n              'dynamodb:Query',\n              'dynamodb:UpdateItem',\n              'dynamodb:BatchWriteItem',\n              'dynamodb:BatchGetItem',\n              'dynamodb:DescribeTable',\n              'dynamodb:ConditionCheckItem',\n            ],\n            Effect: 'Allow',\n            Resource: [\n              ...writableTables.map((name) => ({\n                'Fn::GetAtt': [name, 'Arn'],\n              })),\n              ...writableTables.map((name) => ({\n                'Fn::Sub': [\n                  // eslint-disable-next-line no-template-curly-in-string\n                  '${tableArn}/index/*',\n                  {tableArn: {'Fn::GetAtt': [name, 'Arn']}},\n                ],\n              })),\n            ],\n          },\n        ].filter(filterNull),\n        Version: '2012-10-17',\n      },\n      PolicyName: `${functionName}TableAccessPolicy`,\n      Roles: [\n        // @ts-expect-error typedef doesn't include intrinsic functions\n        {'Fn::GetAtt': [stackName, 'Outputs.Role']},\n      ],\n    },\n    Type: 'AWS::IAM::Policy',\n  };\n\n  const tableAccessPolicyName = `${functionName}TableAccessPolicy`;\n\n  const fragment = combineFragments({\n    Conditions: config.singleQueueKey\n      ? {DefineSharedKmsKey: {Condition: 'IsProd'}}\n      : {},\n    Resources: {\n      ...(config.singleQueueKey\n        ? {[qKeyName]: {...makeKmsKey(), Condition: 'DefineSharedKmsKey'}}\n        : {}),\n      [stackName]: stack,\n      ...(readableTables.length || writableTables.length\n        ? {[tableAccessPolicyName]: tableAccessPolicy}\n        : {}),\n    },\n    Transform: ['AWS::LanguageExtensions'],\n  });\n  const handlerStack = makeHandlerStack(config);\n\n  return {fragment, stack: handlerStack};\n}\n"],
  "mappings": "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",
  "names": []
}
