"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PipelineS3Sync = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const constructs_1 = require("constructs");
class PipelineS3Sync extends constructs_1.Construct {
    constructor(scope, id, props) {
        var _a;
        super(scope, id);
        const patternPairs = props.contentTypePatterns || [];
        // List of all the patterns that have specific content types provided
        // Ex: *.shtml,*.pdf,*.jpe?g
        const allTypePatterns = patternPairs.map(pair => pair.pattern).join(',');
        this.project = new aws_cdk_lib_1.aws_codebuild.PipelineProject(scope, `${id}SyncProject`, {
            description: 'Deploys built web components to bucket',
            timeout: aws_cdk_lib_1.Duration.minutes(10),
            environment: {
                buildImage: aws_cdk_lib_1.aws_codebuild.LinuxBuildImage.STANDARD_7_0,
                privileged: true,
            },
            environmentVariables: {
                // The stack that deploys these needs to export these parameters to the right path. This is necessary
                // since we can't know the distribution id until the pipeline has run to set up the cloudFront!
                DEST_BUCKET: {
                    value: props.bucketParamPath,
                    type: aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.PARAMETER_STORE,
                },
                DISTRIBUTION_ID: {
                    value: props.cloudFrontParamPath,
                    type: aws_cdk_lib_1.aws_codebuild.BuildEnvironmentVariableType.PARAMETER_STORE,
                },
            },
            buildSpec: aws_cdk_lib_1.aws_codebuild.BuildSpec.fromObject({
                phases: {
                    pre_build: {
                        commands: [
                            // Remove existing files from the s3 bucket
                            'aws s3 rm s3://$DEST_BUCKET --recursive',
                        ],
                    },
                    build: {
                        commands: [
                            // Copy new build to the site s3 bucket
                            `cd ${props.subdirectory || '.'}`,
                            'aws s3 cp --recursive . s3://$DEST_BUCKET/ --include "*"' +
                                (allTypePatterns ? ` --exclude "${allTypePatterns}"` : ''),
                        ].concat(patternPairs.map(pair => `aws s3 cp --recursive . s3://$DEST_BUCKET/ \
                  --exclude "*" \
                  --include "${pair.pattern}" \
                  --content-type "${pair.contentType}"`)),
                    },
                    post_build: {
                        commands: ((_a = props.invalidateCache) !== null && _a !== void 0 ? _a : true)
                            ? ['aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*"']
                            : [],
                    },
                },
                version: '0.2',
            }),
        });
        this.project.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            actions: ['cloudFront:CreateInvalidation'],
            resources: ['*'],
        }));
        // We don't know exactly what the bucket's name will be until runtime, but it starts with the stack's name
        this.project.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            actions: ['s3:*'],
            resources: [aws_cdk_lib_1.Fn.sub('arn:aws:s3:::' + props.bucketNamePrefix + '*')],
        }));
        this.project.addToRolePolicy(new aws_cdk_lib_1.aws_iam.PolicyStatement({
            actions: ['ssm:GetParametersByPath', 'ssm:GetParameter', 'ssm:GetParameters'],
            resources: [
                aws_cdk_lib_1.Fn.sub('arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter' + props.bucketParamPath),
                aws_cdk_lib_1.Fn.sub('arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter' + props.cloudFrontParamPath),
            ],
        }));
        this.action = new aws_cdk_lib_1.aws_codepipeline_actions.CodeBuildAction({
            actionName: 'Sync_Build_Files_To_S3',
            input: props.inputBuildArtifact,
            project: this.project,
            runOrder: 2,
        });
    }
}
exports.PipelineS3Sync = PipelineS3Sync;
