@medplum/cdk 2.1.8 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/config.d.ts +17 -0
- package/package.json +1 -1
- package/src/backend.ts +1 -1
- package/src/config.test.ts +487 -0
- package/src/config.ts +202 -0
- package/src/index.ts +13 -5
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var P=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var F=(c,n)=>{for(var a in n)P(c,a,{get:n[a],enumerable:!0})},x=(c,n,a,e)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of O(n))!M.call(c,o)&&o!==a&&P(c,o,{get:()=>n[o],enumerable:!(e=_(n,o))||e.enumerable});return c};var W=c=>x(P({},"__esModule",{value:!0}),c);var U={};F(U,{BackEnd:()=>A,CloudTrailAlarms:()=>p,FrontEnd:()=>g,MedplumGlobalStack:()=>R,MedplumPrimaryStack:()=>v,MedplumStack:()=>y,Storage:()=>h,awsManagedRules:()=>d,main:()=>B});module.exports=W(U);var E=require("aws-cdk-lib"),G=require("fs"),$=require("path");var S=require("aws-cdk-lib");var t=require("aws-cdk-lib"),N=require("aws-cdk-lib/aws-ecr"),w=require("aws-cdk-lib/aws-rds"),b=require("constructs");var d=[{name:"AWS-AWSManagedRulesCommonRuleSet",priority:10,statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesCommonRuleSet",excludedRules:[{name:"NoUserAgent_HEADER"},{name:"UserAgent_BadBots_HEADER"},{name:"SizeRestrictions_QUERYSTRING"},{name:"SizeRestrictions_Cookie_HEADER"},{name:"SizeRestrictions_BODY"},{name:"SizeRestrictions_URIPATH"},{name:"EC2MetaDataSSRF_BODY"},{name:"EC2MetaDataSSRF_COOKIE"},{name:"EC2MetaDataSSRF_URIPATH"},{name:"EC2MetaDataSSRF_QUERYARGUMENTS"},{name:"GenericLFI_QUERYARGUMENTS"},{name:"GenericLFI_URIPATH"},{name:"GenericLFI_BODY"},{name:"RestrictedExtensions_URIPATH"},{name:"RestrictedExtensions_QUERYARGUMENTS"},{name:"GenericRFI_QUERYARGUMENTS"},{name:"GenericRFI_BODY"},{name:"GenericRFI_URIPATH"},{name:"CrossSiteScripting_COOKIE"},{name:"CrossSiteScripting_QUERYARGUMENTS"},{name:"CrossSiteScripting_BODY"},{name:"CrossSiteScripting_URIPATH"}]}},overrideAction:{count:{}},visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWS-AWSManagedRulesCommonRuleSet"}},{name:"AWS-AWSManagedRulesAmazonIpReputationList",priority:20,statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesAmazonIpReputationList",excludedRules:[{name:"AWSManagedIPReputationList"},{name:"AWSManagedReconnaissanceList"}]}},overrideAction:{count:{}},visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRulesAmazonIpReputationList"}},{name:"AWSManagedRulesSQLiRuleSet",priority:30,visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRulesSQLiRuleSet"},overrideAction:{count:{}},statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesSQLiRuleSet",excludedRules:[{name:"SQLi_QUERYARGUMENTS"},{name:"SQLiExtendedPatterns_QUERYARGUMENTS"},{name:"SQLi_BODY"},{name:"SQLiExtendedPatterns_BODY"},{name:"SQLi_COOKIE"},{name:"SQLi_URIPATH"}]}}},{name:"AWSManagedRuleLinux",priority:40,visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRuleLinux"},overrideAction:{count:{}},statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesLinuxRuleSet",excludedRules:[{name:"LFI_URIPATH"},{name:"LFI_QUERYSTRING"},{name:"LFI_COOKIE"}]}}}];var A=class extends b.Construct{constructor(a,e){super(a,"BackEnd");let o=e.name;if(e.vpcId)this.vpc=t.aws_ec2.Vpc.fromLookup(this,"VPC",{vpcId:e.vpcId});else{let i=new t.aws_logs.LogGroup(this,"VpcFlowLogs",{logGroupName:"/medplum/flowlogs/"+o,removalPolicy:t.RemovalPolicy.DESTROY});this.vpc=new t.aws_ec2.Vpc(this,"VPC",{maxAzs:e.maxAzs,flowLogs:{cloudwatch:{destination:t.aws_ec2.FlowLogDestination.toCloudWatchLogs(i),trafficType:t.aws_ec2.FlowLogTrafficType.ALL}}})}if(this.botLambdaRole=new t.aws_iam.Role(this,"BotLambdaRole",{assumedBy:new t.aws_iam.ServicePrincipal("lambda.amazonaws.com")}),this.rdsSecretsArn=e.rdsSecretsArn,!this.rdsSecretsArn){let i={instanceType:e.rdsInstanceType?new t.aws_ec2.InstanceType(e.rdsInstanceType):void 0,enablePerformanceInsights:!0,isFromLegacyInstanceProps:!0},m;if(e.rdsInstances>1){m=[];for(let u=0;u<e.rdsInstances-1;u++)m.push(w.ClusterInstance.provisioned("Instance"+(u+2),{...i}))}this.rdsCluster=new t.aws_rds.DatabaseCluster(this,"DatabaseCluster",{engine:t.aws_rds.DatabaseClusterEngine.auroraPostgres({version:t.aws_rds.AuroraPostgresEngineVersion.VER_12_9}),credentials:t.aws_rds.Credentials.fromGeneratedSecret("clusteradmin"),defaultDatabaseName:"medplum",storageEncrypted:!0,vpc:this.vpc,vpcSubnets:{subnetType:t.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS},writer:w.ClusterInstance.provisioned("Instance1",{...i}),readers:m,backup:{retention:t.Duration.days(7)},cloudwatchLogsExports:["postgresql"],instanceUpdateBehaviour:t.aws_rds.InstanceUpdateBehaviour.ROLLING}),this.rdsSecretsArn=this.rdsCluster.secret.secretArn}if(this.redisSubnetGroup=new t.aws_elasticache.CfnSubnetGroup(this,"RedisSubnetGroup",{description:"Redis Subnet Group",subnetIds:this.vpc.privateSubnets.map(i=>i.subnetId)}),this.redisSecurityGroup=new t.aws_ec2.SecurityGroup(this,"RedisSecurityGroup",{vpc:this.vpc,description:"Redis Security Group",allowAllOutbound:!1}),this.redisPassword=new t.aws_secretsmanager.Secret(this,"RedisPassword",{generateSecretString:{secretStringTemplate:"{}",generateStringKey:"password",excludeCharacters:"@%*()_+=`~{}|[]\\:\";'?,./"}}),this.redisCluster=new t.aws_elasticache.CfnReplicationGroup(this,"RedisCluster",{engine:"Redis",engineVersion:"6.x",cacheNodeType:e.cacheNodeType??"cache.t2.medium",replicationGroupDescription:"RedisReplicationGroup",authToken:this.redisPassword.secretValueFromJson("password").toString(),transitEncryptionEnabled:!0,atRestEncryptionEnabled:!0,multiAzEnabled:!0,cacheSubnetGroupName:this.redisSubnetGroup.ref,numNodeGroups:1,replicasPerNodeGroup:1,securityGroupIds:[this.redisSecurityGroup.securityGroupId]}),this.redisCluster.node.addDependency(this.redisPassword),this.redisSecrets=new t.aws_secretsmanager.Secret(this,"RedisSecrets",{generateSecretString:{secretStringTemplate:JSON.stringify({host:this.redisCluster.attrPrimaryEndPointAddress,port:this.redisCluster.attrPrimaryEndPointPort,password:this.redisPassword.secretValueFromJson("password").toString(),tls:{}}),generateStringKey:"unused"}}),this.redisSecrets.node.addDependency(this.redisPassword),this.redisSecrets.node.addDependency(this.redisCluster),this.ecsCluster=new t.aws_ecs.Cluster(this,"Cluster",{vpc:this.vpc}),this.taskRolePolicies=new t.aws_iam.PolicyDocument({statements:[new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["logs:CreateLogStream","logs:PutLogEvents"],resources:["arn:aws:logs:*"]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["secretsmanager:GetResourcePolicy","secretsmanager:GetSecretValue","secretsmanager:DescribeSecret","secretsmanager:ListSecrets","secretsmanager:ListSecretVersionIds"],resources:["arn:aws:secretsmanager:*"]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["ssm:GetParametersByPath","ssm:GetParameters","ssm:GetParameter","ssm:DescribeParameters"],resources:["arn:aws:ssm:*"]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["ses:SendEmail","ses:SendRawEmail"],resources:["arn:aws:ses:*"]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:["arn:aws:s3:::*"]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["iam:ListRoles","iam:GetRole","iam:PassRole"],resources:[this.botLambdaRole.roleArn]}),new t.aws_iam.PolicyStatement({effect:t.aws_iam.Effect.ALLOW,actions:["lambda:CreateFunction","lambda:GetFunction","lambda:GetFunctionConfiguration","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:ListLayerVersions","lambda:GetLayerVersion","lambda:InvokeFunction"],resources:["arn:aws:lambda:*"]})]}),this.taskRole=new t.aws_iam.Role(this,"TaskExecutionRole",{assumedBy:new t.aws_iam.ServicePrincipal("ecs-tasks.amazonaws.com"),description:"Medplum Server Task Execution Role",inlinePolicies:{TaskExecutionPolicies:this.taskRolePolicies}}),this.taskDefinition=new t.aws_ecs.FargateTaskDefinition(this,"TaskDefinition",{memoryLimitMiB:e.serverMemory,cpu:e.serverCpu,taskRole:this.taskRole}),this.logGroup=new t.aws_logs.LogGroup(this,"LogGroup",{logGroupName:"/ecs/medplum/"+o,removalPolicy:t.RemovalPolicy.DESTROY}),this.logDriver=new t.aws_ecs.AwsLogDriver({logGroup:this.logGroup,streamPrefix:"Medplum"}),this.serviceContainer=this.taskDefinition.addContainer("MedplumTaskDefinition",{image:this.getContainerImage(e,e.serverImage),command:[e.region==="us-east-1"?`aws:/medplum/${o}/`:`aws:${e.region}:/medplum/${o}/`],logging:this.logDriver}),this.serviceContainer.addPortMappings({containerPort:e.apiPort,hostPort:e.apiPort}),e.additionalContainers)for(let i of e.additionalContainers)this.taskDefinition.addContainer("AdditionalContainer-"+i.name,{containerName:i.name,image:this.getContainerImage(e,i.image),command:i.command,environment:i.environment,logging:this.logDriver});if(this.fargateSecurityGroup=new t.aws_ec2.SecurityGroup(this,"ServiceSecurityGroup",{allowAllOutbound:!0,securityGroupName:"MedplumSecurityGroup",vpc:this.vpc}),this.fargateService=new t.aws_ecs.FargateService(this,"FargateService",{cluster:this.ecsCluster,taskDefinition:this.taskDefinition,assignPublicIp:!1,vpcSubnets:{subnetType:t.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS},desiredCount:e.desiredServerCount,securityGroups:[this.fargateSecurityGroup],healthCheckGracePeriod:t.Duration.minutes(5)}),this.rdsCluster&&this.fargateService.node.addDependency(this.rdsCluster),this.fargateService.node.addDependency(this.redisCluster),this.targetGroup=new t.aws_elasticloadbalancingv2.ApplicationTargetGroup(this,"TargetGroup",{vpc:this.vpc,port:e.apiPort,protocol:t.aws_elasticloadbalancingv2.ApplicationProtocol.HTTP,healthCheck:{path:"/healthcheck",interval:t.Duration.seconds(30),timeout:t.Duration.seconds(3),healthyThresholdCount:2,unhealthyThresholdCount:5},targets:[this.fargateService]}),this.loadBalancer=new t.aws_elasticloadbalancingv2.ApplicationLoadBalancer(this,"LoadBalancer",{vpc:this.vpc,internetFacing:e.apiInternetFacing!==!1,http2Enabled:!0}),e.loadBalancerLoggingBucket&&this.loadBalancer.logAccessLogs(t.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",e.loadBalancerLoggingBucket),e.loadBalancerLoggingPrefix),this.loadBalancer.addListener("HttpsListener",{port:443,certificates:[{certificateArn:e.apiSslCertArn}],sslPolicy:t.aws_elasticloadbalancingv2.SslPolicy.FORWARD_SECRECY_TLS12_RES_GCM,defaultAction:t.aws_elasticloadbalancingv2.ListenerAction.forward([this.targetGroup])}),this.waf=new t.aws_wafv2.CfnWebACL(this,"BackEndWAF",{defaultAction:{allow:{}},scope:"REGIONAL",name:`${e.stackName}-BackEndWAF`,rules:d,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${e.stackName}-BackEndWAF-Metric`,sampledRequestsEnabled:!1}}),this.wafAssociation=new t.aws_wafv2.CfnWebACLAssociation(this,"LoadBalancerAssociation",{resourceArn:this.loadBalancer.loadBalancerArn,webAclArn:this.waf.attrArn}),this.rdsCluster&&this.rdsCluster.connections.allowDefaultPortFrom(this.fargateSecurityGroup),this.redisSecurityGroup.addIngressRule(this.fargateSecurityGroup,t.aws_ec2.Port.tcp(6379)),!e.skipDns){let i=t.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:e.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new t.aws_route53.ARecord(this,"LoadBalancerAliasRecord",{recordName:e.apiDomainName,target:t.aws_route53.RecordTarget.fromAlias(new t.aws_route53_targets.LoadBalancerTarget(this.loadBalancer)),zone:i})}this.regionParameter=new t.aws_ssm.StringParameter(this,"RegionParameter",{tier:t.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${o}/awsRegion`,description:"AWS region",stringValue:e.region}),this.databaseSecretsParameter=new t.aws_ssm.StringParameter(this,"DatabaseSecretsParameter",{tier:t.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${o}/DatabaseSecrets`,description:"Database secrets ARN",stringValue:this.rdsSecretsArn}),this.redisSecretsParameter=new t.aws_ssm.StringParameter(this,"RedisSecretsParameter",{tier:t.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${o}/RedisSecrets`,description:"Redis secrets ARN",stringValue:this.redisSecrets.secretArn}),this.botLambdaRoleParameter=new t.aws_ssm.StringParameter(this,"BotLambdaRoleParameter",{tier:t.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${o}/botLambdaRoleArn`,description:"Bot lambda execution role ARN",stringValue:this.botLambdaRole.roleArn})}getContainerImage(a,e){let i=new RegExp(`^${a.accountNumber}\\.dkr\\.ecr\\.${a.region}\\.amazonaws\\.com/(.*)[:@](.*)$`).exec(e),m=i?.[1],u=i?.[2];if(m&&u){let C=N.Repository.fromRepositoryArn(this,"ServerImageRepo",`arn:aws:ecr:${a.region}:${a.accountNumber}:repository/${m}`);return t.aws_ecs.ContainerImage.fromEcrRepository(C,u)}return t.aws_ecs.ContainerImage.fromRegistry(e)}};var l=require("aws-cdk-lib"),k=require("constructs"),p=class extends k.Construct{constructor(a,e){super(a,"CloudTrailAlarms");if(this.config=e,!e.cloudTrailAlarms)return;e.cloudTrailAlarms.logGroupCreate?(this.logGroup=new l.aws_logs.LogGroup(this,"CloudTrailLogGroup",{logGroupName:e.cloudTrailAlarms.logGroupName,retention:l.aws_logs.RetentionDays.ONE_YEAR}),this.cloudTrail=new l.aws_cloudtrail.Trail(this,"CloudTrail",{sendToCloudWatchLogs:!0,cloudWatchLogGroup:this.logGroup,includeGlobalServiceEvents:!0})):this.logGroup=l.aws_logs.LogGroup.fromLogGroupName(this,"CloudTrailLogGroup",e.cloudTrailAlarms.logGroupName),e.cloudTrailAlarms.snsTopicArn?this.alarmTopic=l.aws_sns.Topic.fromTopicArn(this,"AlarmTopic",e.cloudTrailAlarms.snsTopicArn):this.alarmTopic=new l.aws_sns.Topic(this,"AlarmTopic",{topicName:e.cloudTrailAlarms.snsTopicName});let o=[["UnauthorizedApiCalls","{ ($.errorCode = *UnauthorizedOperation) || ($.errorCode = AccessDenied*) }"],["SignInWithoutMfa","{ ($.eventName = ConsoleLogin) && ($.additionalEventData.MFAUsed != Yes) }"],["RootAccountUsage","{ $.userIdentity.type = Root && $.userIdentity.invokedBy NOT EXISTS && $.eventType != AwsServiceEvent }"],["IamPolicyChanges","{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}"],["CloudTrailConfigurationChanges","{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }"],["SignInFailures",'{ ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") }'],["DisabledCmks","{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }"],["S3PolicyChanges","{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) }"],["ConfigServiceChanges","{($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}"],["SecurityGroupChanges","{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup)}"],["NetworkAclChanges","{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }"],["NetworkGatewayChanges","{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }"],["RouteTableChanges","{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }"],["VpcChanges","{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }"],["OrganizationsChanges","{ ($.eventSource = organizations.amazonaws.com) && (($.eventName = AcceptHandshake) || ($.eventName = AttachPolicy) || ($.eventName = CreateAccount) || ($.eventName = CreateOrganizationalUnit) || ($.eventName = CreatePolicy) || ($.eventName = DeclineHandshake) || ($.eventName = DeleteOrganization) || ($.eventName = DeleteOrganizationalUnit) || ($.eventName = DeletePolicy) || ($.eventName = DetachPolicy) || ($.eventName = DisablePolicyType) || ($.eventName = EnablePolicyType) || ($.eventName = InviteAccountToOrganization) || ($.eventName = LeaveOrganization) || ($.eventName = MoveAccount) || ($.eventName = RemoveAccountFromOrganization) || ($.eventName = UpdatePolicy) || ($.eventName = UpdateOrganizationalUnit)) }"]];for(let[i,m]of o)this.createMetricAlarm(i,m)}createMetricAlarm(a,e){let o=`${this.config.stackName}${a}MetricFilter`,i=`${this.config.stackName}${a}Metric`,m=`${this.config.stackName}Metrics`,u=`${this.config.stackName}${a}Alarm`,C=new l.aws_logs.MetricFilter(this,o,{logGroup:this.logGroup,filterPattern:{logPatternString:e},metricNamespace:m,metricName:i});new l.aws_cloudwatch.Alarm(this,u,{metric:C.metric({}),threshold:1,evaluationPeriods:1,alarmName:u,actionsEnabled:!0,treatMissingData:l.aws_cloudwatch.TreatMissingData.NOT_BREACHING,comparisonOperator:l.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,datapointsToAlarm:1}).addAlarmAction(new l.aws_cloudwatch_actions.SnsAction(this.alarmTopic))}};var r=require("aws-cdk-lib"),L=require("constructs");var I=require("aws-cdk-lib");function f(c,n){let a=new I.aws_iam.PolicyStatement;return a.addActions("s3:GetObject*"),a.addActions("s3:GetBucket*"),a.addActions("s3:List*"),a.addResources(c.bucketArn),a.addResources(`${c.bucketArn}/*`),a.addCanonicalUserPrincipal(n.cloudFrontOriginAccessIdentityS3CanonicalUserId),c.addToResourcePolicy(a),a}var g=class extends L.Construct{constructor(a,e,o){super(a,"FrontEnd");if(o===e.region?this.appBucket=new r.aws_s3.Bucket(this,"AppBucket",{bucketName:e.appDomainName,publicReadAccess:!1,blockPublicAccess:r.aws_s3.BlockPublicAccess.BLOCK_ALL,removalPolicy:r.RemovalPolicy.DESTROY,encryption:r.aws_s3.BucketEncryption.S3_MANAGED,enforceSSL:!0,versioned:!0}):this.appBucket=r.aws_s3.Bucket.fromBucketAttributes(this,"AppBucket",{bucketName:e.appDomainName,region:e.region}),o==="us-east-1"&&(this.responseHeadersPolicy=new r.aws_cloudfront.ResponseHeadersPolicy(this,"ResponseHeadersPolicy",{securityHeadersBehavior:{contentSecurityPolicy:{contentSecurityPolicy:["default-src 'none'","base-uri 'self'","child-src 'self'",`connect-src 'self' ${e.apiDomainName} *.google.com`,"font-src 'self' fonts.gstatic.com","form-action 'self' *.gstatic.com *.google.com","frame-ancestors 'none'","frame-src 'self' *.medplum.com *.gstatic.com *.google.com",`img-src 'self' data: ${e.storageDomainName} *.gstatic.com *.google.com *.googleapis.com`,"manifest-src 'self'",`media-src 'self' ${e.storageDomainName}`,"script-src 'self' *.medplum.com *.gstatic.com *.google.com","style-src 'self' 'unsafe-inline' *.medplum.com *.gstatic.com *.google.com","worker-src 'self' blob: *.gstatic.com *.google.com","upgrade-insecure-requests"].join("; "),override:!0},contentTypeOptions:{override:!0},frameOptions:{frameOption:r.aws_cloudfront.HeadersFrameOption.DENY,override:!0},strictTransportSecurity:{accessControlMaxAge:r.Duration.seconds(63072e3),includeSubdomains:!0,override:!0},xssProtection:{protection:!0,modeBlock:!0,override:!0}}}),this.waf=new r.aws_wafv2.CfnWebACL(this,"FrontEndWAF",{defaultAction:{allow:{}},scope:"CLOUDFRONT",name:`${e.stackName}-FrontEndWAF`,rules:d,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${e.stackName}-FrontEndWAF-Metric`,sampledRequestsEnabled:!1}}),this.apiOriginCachePolicy=new r.aws_cloudfront.CachePolicy(this,"ApiOriginCachePolicy",{cachePolicyName:`${e.stackName}-ApiOriginCachePolicy`,cookieBehavior:r.aws_cloudfront.CacheCookieBehavior.all(),headerBehavior:r.aws_cloudfront.CacheHeaderBehavior.allowList("Authorization","Content-Encoding","Content-Type","If-None-Match","Origin","Referer","User-Agent","X-Medplum"),queryStringBehavior:r.aws_cloudfront.CacheQueryStringBehavior.all()}),this.originAccessIdentity=new r.aws_cloudfront.OriginAccessIdentity(this,"OriginAccessIdentity",{}),this.originAccessPolicyStatement=f(this.appBucket,this.originAccessIdentity),this.distribution=new r.aws_cloudfront.Distribution(this,"AppDistribution",{defaultRootObject:"index.html",defaultBehavior:{origin:new r.aws_cloudfront_origins.S3Origin(this.appBucket,{originAccessIdentity:this.originAccessIdentity}),responseHeadersPolicy:this.responseHeadersPolicy,viewerProtocolPolicy:r.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS},additionalBehaviors:e.appApiProxy?{"/api/*":{origin:new r.aws_cloudfront_origins.HttpOrigin(e.apiDomainName),allowedMethods:r.aws_cloudfront.AllowedMethods.ALLOW_ALL,cachePolicy:this.apiOriginCachePolicy,viewerProtocolPolicy:r.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS}}:void 0,certificate:r.aws_certificatemanager.Certificate.fromCertificateArn(this,"AppCertificate",e.appSslCertArn),domainNames:[e.appDomainName],errorResponses:[{httpStatus:403,responseHttpStatus:200,responsePagePath:"/index.html"},{httpStatus:404,responseHttpStatus:200,responsePagePath:"/index.html"}],webAclId:this.waf.attrArn,logBucket:e.appLoggingBucket?r.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",e.appLoggingBucket):void 0,logFilePrefix:e.appLoggingPrefix}),!e.skipDns)){let i=r.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:e.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new r.aws_route53.ARecord(this,"AppAliasRecord",{recordName:e.appDomainName,target:r.aws_route53.RecordTarget.fromAlias(new r.aws_route53_targets.CloudFrontTarget(this.distribution)),zone:i})}}};var s=require("aws-cdk-lib"),T=require("cdk-serverless-clamscan"),D=require("constructs");var h=class extends D.Construct{constructor(a,e,o){super(a,"Storage");if(o===e.region?(this.storageBucket=new s.aws_s3.Bucket(this,"StorageBucket",{bucketName:e.storageBucketName,publicReadAccess:!1,blockPublicAccess:s.aws_s3.BlockPublicAccess.BLOCK_ALL,encryption:s.aws_s3.BucketEncryption.S3_MANAGED,enforceSSL:!0,versioned:!0}),e.clamscanEnabled&&new T.ServerlessClamscan(this,"ServerlessClamscan",{defsBucketAccessLogsConfig:{logsBucket:s.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",e.clamscanLoggingBucket),logsPrefix:e.clamscanLoggingPrefix}}).addSourceBucket(this.storageBucket)):this.storageBucket=s.aws_s3.Bucket.fromBucketAttributes(this,"StorageBucket",{bucketName:e.storageBucketName,region:e.region}),o==="us-east-1"){let i;if(e.signingKeyId?i=s.aws_cloudfront.PublicKey.fromPublicKeyId(this,"StoragePublicKey",e.signingKeyId):i=new s.aws_cloudfront.PublicKey(this,"StoragePublicKey",{encodedKey:e.storagePublicKey}),this.keyGroup=new s.aws_cloudfront.KeyGroup(this,"StorageKeyGroup",{items:[i]}),this.responseHeadersPolicy=new s.aws_cloudfront.ResponseHeadersPolicy(this,"ResponseHeadersPolicy",{securityHeadersBehavior:{contentSecurityPolicy:{contentSecurityPolicy:"default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors *.medplum.com;",override:!0},contentTypeOptions:{override:!0},frameOptions:{frameOption:s.aws_cloudfront.HeadersFrameOption.DENY,override:!0},referrerPolicy:{referrerPolicy:s.aws_cloudfront.HeadersReferrerPolicy.NO_REFERRER,override:!0},strictTransportSecurity:{accessControlMaxAge:s.Duration.seconds(63072e3),includeSubdomains:!0,override:!0},xssProtection:{protection:!0,modeBlock:!0,override:!0}}}),this.waf=new s.aws_wafv2.CfnWebACL(this,"StorageWAF",{defaultAction:{allow:{}},scope:"CLOUDFRONT",name:`${e.stackName}-StorageWAF`,rules:d,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${e.stackName}-StorageWAF-Metric`,sampledRequestsEnabled:!1}}),this.originAccessIdentity=new s.aws_cloudfront.OriginAccessIdentity(this,"OriginAccessIdentity",{}),this.originAccessPolicyStatement=f(this.storageBucket,this.originAccessIdentity),this.distribution=new s.aws_cloudfront.Distribution(this,"StorageDistribution",{defaultBehavior:{origin:new s.aws_cloudfront_origins.S3Origin(this.storageBucket,{originAccessIdentity:this.originAccessIdentity}),responseHeadersPolicy:this.responseHeadersPolicy,viewerProtocolPolicy:s.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,trustedKeyGroups:[this.keyGroup]},certificate:s.aws_certificatemanager.Certificate.fromCertificateArn(this,"StorageCertificate",e.storageSslCertArn),domainNames:[e.storageDomainName],webAclId:this.waf.attrArn,logBucket:e.storageLoggingBucket?s.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",e.storageLoggingBucket):void 0,logFilePrefix:e.storageLoggingPrefix}),!e.skipDns){let m=s.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:e.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new s.aws_route53.ARecord(this,"StorageAliasRecord",{recordName:e.storageDomainName,target:s.aws_route53.RecordTarget.fromAlias(new s.aws_route53_targets.CloudFrontTarget(this.distribution)),zone:m})}}}};var y=class{constructor(n,a){this.primaryStack=new v(n,a),a.region!=="us-east-1"&&(this.globalStack=new R(n,a),this.globalStack.addDependency(this.primaryStack))}},v=class extends S.Stack{constructor(a,e){super(a,e.stackName,{env:{region:e.region,account:e.accountNumber}});S.Tags.of(this).add("medplum:environment",e.name),this.backEnd=new A(this,e),this.frontEnd=new g(this,e,e.region),this.storage=new h(this,e,e.region),this.cloudTrail=new p(this,e)}},R=class extends S.Stack{constructor(a,e){super(a,e.stackName+"-us-east-1",{env:{region:"us-east-1",account:e.accountNumber}});S.Tags.of(this).add("medplum:environment",e.name),this.frontEnd=new g(this,e,"us-east-1"),this.storage=new h(this,e,"us-east-1"),this.cloudTrail=new p(this,e)}};function B(c){let n=new E.App({context:c}),a=n.node.tryGetContext("config");if(!a){console.log('Missing "config" context variable'),console.log("Usage: cdk deploy -c config=my-config.json");return}let e=JSON.parse((0,G.readFileSync)((0,$.resolve)(a),"utf-8")),o=new y(n,e);console.log("Stack",o.primaryStack.stackId),n.synth()}require.main===module&&B();0&&(module.exports={BackEnd,CloudTrailAlarms,FrontEnd,MedplumGlobalStack,MedplumPrimaryStack,MedplumStack,Storage,awsManagedRules,main});
|
|
1
|
+
"use strict";var z=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var Ne=Object.getOwnPropertyNames;var Oe=Object.prototype.hasOwnProperty;var Le=(e,t)=>{for(var r in t)z(e,r,{get:t[r],enumerable:!0})},$e=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Ne(t))!Oe.call(e,i)&&i!==r&&z(e,i,{get:()=>t[i],enumerable:!(n=De(t,i))||n.enumerable});return e};var Ue=e=>$e(z({},"__esModule",{value:!0}),e);var Lt={};Le(Lt,{BackEnd:()=>M,CloudTrailAlarms:()=>I,FrontEnd:()=>D,MedplumGlobalStack:()=>H,MedplumPrimaryStack:()=>W,MedplumStack:()=>_,Storage:()=>N,awsManagedRules:()=>E,main:()=>ke});module.exports=Ue(Lt);var Pe=require("aws-cdk-lib"),Re=require("fs"),Ee=require("path");var G=require("@aws-sdk/client-ssm");var Me=class{constructor(e,t){this.operator=e,this.child=t}toString(){return`${this.operator}(${this.child.toString()})`}},U=class{constructor(e,t,r){this.operator=e,this.left=t,this.right=r}toString(){return`${this.left.toString()} ${this.operator} ${this.right.toString()}`}},_e=class{constructor(){this.prefixParselets={},this.infixParselets={}}registerInfix(e,t){return this.infixParselets[e]=t,this}registerPrefix(e,t){return this.prefixParselets[e]=t,this}prefix(e,t,r){return this.registerPrefix(e,{parse(n,i){let s=n.consumeAndParse(t);return r(i,s)}})}infixLeft(e,t,r){return this.registerInfix(e,{parse(n,i,s){let a=n.consumeAndParse(t);return r(i,s,a)},precedence:t})}construct(e){return new Be(e,this.prefixParselets,this.infixParselets)}},Be=class{constructor(e,t,r){this.tokens=e,this.prefixParselets=t,this.infixParselets=r}hasMore(){return this.tokens.length>0}match(e){return this.peek()?.id!==e?!1:(this.consume(),!0)}consumeAndParse(e=1/0){let t=this.consume(),r=this.prefixParselets[t.id];if(!r)throw Error(`Parse error at "${t.value}" (line ${t.line}, column ${t.column}). No matching prefix parselet.`);let n=r.parse(this,t);for(;e>this.getPrecedence();){let i=this.consume();n=this.getInfixParselet(i).parse(this,n,i)}return n}getPrecedence(){let e=this.peek();if(!e)return 1/0;let t=this.getInfixParselet(e);return t?t.precedence:1/0}consume(e,t){if(!this.tokens.length)throw Error("Cant consume unknown more tokens.");if(e&&this.peek()?.id!==e){let r=this.peek();throw Error(`Expected ${e} but got "${r.id}" at line ${r.line} column ${r.column}.`)}if(t&&this.peek()?.value!==t){let r=this.peek();throw Error(`Expected "${t}" but got "${r.value}" at line ${r.line} column ${r.column}.`)}return this.tokens.shift()}peek(){return this.tokens.length>0?this.tokens[0]:void 0}removeComments(){this.tokens=this.tokens.filter(e=>e.id!=="Comment")}getInfixParselet(e){return this.infixParselets[e.id==="Symbol"?e.value:e.id]}};function Fe(e,t){let r=new Date(e);r.setUTCHours(0,0,0,0);let n=t?new Date(t):new Date;n.setUTCHours(0,0,0,0);let i=r.getUTCFullYear(),s=r.getUTCMonth(),a=r.getUTCDate(),c=n.getUTCFullYear(),m=n.getUTCMonth(),L=n.getUTCDate(),B=c-i;(m<s||m===s&&L<a)&&B--;let te=c*12+m-(i*12+s);L<a&&te--;let Ie=Math.floor((n.getTime()-r.getTime())/(1e3*60*60*24));return{years:B,months:te,days:Ie}}function oe(e){if(e==null)return!0;let t=typeof e;return t==="string"&&e===""||t==="object"&&Object.keys(e).length===0}var je=[];for(let e=0;e<256;e++)je.push(e.toString(16).padStart(2,"0"));function ae(e){return e.charAt(0).toUpperCase()+e.substring(1)}function Ge(e){let t=e.max&&e.max===Number.MAX_SAFE_INTEGER?Number.POSITIVE_INFINITY:e.max;return{path:"",description:"",type:e.type??[],min:e.min??0,max:t??1,isArray:!!t&&t>1,constraints:[]}}function qe(e){let t=Object.create(null);for(let[r,n]of Object.entries(e))t[r]={name:r,elements:Object.fromEntries(Object.entries(n.elements).map(([i,s])=>[i,Ge(s)])),constraints:[],innerTypes:[]};return t}var We={Element:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]}}},BackboneElement:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]}}},Address:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},use:{type:[{code:"code"}]},type:{type:[{code:"code"}]},text:{type:[{code:"string"}]},line:{max:9007199254740991,type:[{code:"string"}]},city:{type:[{code:"string"}]},district:{type:[{code:"string"}]},state:{type:[{code:"string"}]},postalCode:{type:[{code:"string"}]},country:{type:[{code:"string"}]},period:{type:[{code:"Period"}]}}},Age:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},Annotation:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},"author[x]":{type:[{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Practitioner","http://hl7.org/fhir/StructureDefinition/Patient","http://hl7.org/fhir/StructureDefinition/RelatedPerson","http://hl7.org/fhir/StructureDefinition/Organization"]},{code:"string"}]},time:{type:[{code:"dateTime"}]},text:{min:1,type:[{code:"markdown"}]}}},Attachment:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},contentType:{type:[{code:"code"}]},language:{type:[{code:"code"}]},data:{type:[{code:"base64Binary"}]},url:{type:[{code:"url"}]},size:{type:[{code:"unsignedInt"}]},hash:{type:[{code:"base64Binary"}]},title:{type:[{code:"string"}]},creation:{type:[{code:"dateTime"}]}}},CodeableConcept:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},coding:{max:9007199254740991,type:[{code:"Coding"}]},text:{type:[{code:"string"}]}}},Coding:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},system:{type:[{code:"uri"}]},version:{type:[{code:"string"}]},code:{type:[{code:"code"}]},display:{type:[{code:"string"}]},userSelected:{type:[{code:"boolean"}]}}},ContactDetail:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},name:{type:[{code:"string"}]},telecom:{max:9007199254740991,type:[{code:"ContactPoint"}]}}},ContactPoint:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},system:{type:[{code:"code"}]},value:{type:[{code:"string"}]},use:{type:[{code:"code"}]},rank:{type:[{code:"positiveInt"}]},period:{type:[{code:"Period"}]}}},Contributor:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},type:{min:1,type:[{code:"code"}]},name:{min:1,type:[{code:"string"}]},contact:{max:9007199254740991,type:[{code:"ContactDetail"}]}}},Count:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},DataRequirement:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},type:{min:1,type:[{code:"code"}]},profile:{max:9007199254740991,type:[{code:"canonical",targetProfile:["http://hl7.org/fhir/StructureDefinition/StructureDefinition"]}]},"subject[x]":{type:[{code:"CodeableConcept"},{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Group"]}]},mustSupport:{max:9007199254740991,type:[{code:"string"}]},codeFilter:{max:9007199254740991,type:[{code:"DataRequirementCodeFilter"}]},dateFilter:{max:9007199254740991,type:[{code:"DataRequirementDateFilter"}]},limit:{type:[{code:"positiveInt"}]},sort:{max:9007199254740991,type:[{code:"DataRequirementSort"}]}}},Distance:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},Dosage:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},sequence:{type:[{code:"integer"}]},text:{type:[{code:"string"}]},additionalInstruction:{max:9007199254740991,type:[{code:"CodeableConcept"}]},patientInstruction:{type:[{code:"string"}]},timing:{type:[{code:"Timing"}]},"asNeeded[x]":{type:[{code:"boolean"},{code:"CodeableConcept"}]},site:{type:[{code:"CodeableConcept"}]},route:{type:[{code:"CodeableConcept"}]},method:{type:[{code:"CodeableConcept"}]},doseAndRate:{max:9007199254740991,type:[{code:"DosageDoseAndRate"}]},maxDosePerPeriod:{type:[{code:"Ratio"}]},maxDosePerAdministration:{type:[{code:"Quantity"}]},maxDosePerLifetime:{type:[{code:"Quantity"}]}}},Duration:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},ElementDefinition:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},path:{min:1,type:[{code:"string"}]},representation:{max:9007199254740991,type:[{code:"code"}]},sliceName:{type:[{code:"string"}]},sliceIsConstraining:{type:[{code:"boolean"}]},label:{type:[{code:"string"}]},code:{max:9007199254740991,type:[{code:"Coding"}]},slicing:{type:[{code:"ElementDefinitionSlicing"}]},short:{type:[{code:"string"}]},definition:{type:[{code:"markdown"}]},comment:{type:[{code:"markdown"}]},requirements:{type:[{code:"markdown"}]},alias:{max:9007199254740991,type:[{code:"string"}]},min:{type:[{code:"unsignedInt"}]},max:{type:[{code:"string"}]},base:{type:[{code:"ElementDefinitionBase"}]},contentReference:{type:[{code:"uri"}]},type:{max:9007199254740991,type:[{code:"ElementDefinitionType"}]},"defaultValue[x]":{type:[{code:"base64Binary"},{code:"boolean"},{code:"canonical"},{code:"code"},{code:"date"},{code:"dateTime"},{code:"decimal"},{code:"id"},{code:"instant"},{code:"integer"},{code:"markdown"},{code:"oid"},{code:"positiveInt"},{code:"string"},{code:"time"},{code:"unsignedInt"},{code:"uri"},{code:"url"},{code:"uuid"},{code:"Address"},{code:"Age"},{code:"Annotation"},{code:"Attachment"},{code:"CodeableConcept"},{code:"Coding"},{code:"ContactPoint"},{code:"Count"},{code:"Distance"},{code:"Duration"},{code:"HumanName"},{code:"Identifier"},{code:"Money"},{code:"Period"},{code:"Quantity"},{code:"Range"},{code:"Ratio"},{code:"Reference"},{code:"SampledData"},{code:"Signature"},{code:"Timing"},{code:"ContactDetail"},{code:"Contributor"},{code:"DataRequirement"},{code:"Expression"},{code:"ParameterDefinition"},{code:"RelatedArtifact"},{code:"TriggerDefinition"},{code:"UsageContext"},{code:"Dosage"},{code:"Meta"}]},meaningWhenMissing:{type:[{code:"markdown"}]},orderMeaning:{type:[{code:"string"}]},"fixed[x]":{type:[{code:"base64Binary"},{code:"boolean"},{code:"canonical"},{code:"code"},{code:"date"},{code:"dateTime"},{code:"decimal"},{code:"id"},{code:"instant"},{code:"integer"},{code:"markdown"},{code:"oid"},{code:"positiveInt"},{code:"string"},{code:"time"},{code:"unsignedInt"},{code:"uri"},{code:"url"},{code:"uuid"},{code:"Address"},{code:"Age"},{code:"Annotation"},{code:"Attachment"},{code:"CodeableConcept"},{code:"Coding"},{code:"ContactPoint"},{code:"Count"},{code:"Distance"},{code:"Duration"},{code:"HumanName"},{code:"Identifier"},{code:"Money"},{code:"Period"},{code:"Quantity"},{code:"Range"},{code:"Ratio"},{code:"Reference"},{code:"SampledData"},{code:"Signature"},{code:"Timing"},{code:"ContactDetail"},{code:"Contributor"},{code:"DataRequirement"},{code:"Expression"},{code:"ParameterDefinition"},{code:"RelatedArtifact"},{code:"TriggerDefinition"},{code:"UsageContext"},{code:"Dosage"},{code:"Meta"}]},"pattern[x]":{type:[{code:"base64Binary"},{code:"boolean"},{code:"canonical"},{code:"code"},{code:"date"},{code:"dateTime"},{code:"decimal"},{code:"id"},{code:"instant"},{code:"integer"},{code:"markdown"},{code:"oid"},{code:"positiveInt"},{code:"string"},{code:"time"},{code:"unsignedInt"},{code:"uri"},{code:"url"},{code:"uuid"},{code:"Address"},{code:"Age"},{code:"Annotation"},{code:"Attachment"},{code:"CodeableConcept"},{code:"Coding"},{code:"ContactPoint"},{code:"Count"},{code:"Distance"},{code:"Duration"},{code:"HumanName"},{code:"Identifier"},{code:"Money"},{code:"Period"},{code:"Quantity"},{code:"Range"},{code:"Ratio"},{code:"Reference"},{code:"SampledData"},{code:"Signature"},{code:"Timing"},{code:"ContactDetail"},{code:"Contributor"},{code:"DataRequirement"},{code:"Expression"},{code:"ParameterDefinition"},{code:"RelatedArtifact"},{code:"TriggerDefinition"},{code:"UsageContext"},{code:"Dosage"},{code:"Meta"}]},example:{max:9007199254740991,type:[{code:"ElementDefinitionExample"}]},"minValue[x]":{type:[{code:"date"},{code:"dateTime"},{code:"instant"},{code:"time"},{code:"decimal"},{code:"integer"},{code:"positiveInt"},{code:"unsignedInt"},{code:"Quantity"}]},"maxValue[x]":{type:[{code:"date"},{code:"dateTime"},{code:"instant"},{code:"time"},{code:"decimal"},{code:"integer"},{code:"positiveInt"},{code:"unsignedInt"},{code:"Quantity"}]},maxLength:{type:[{code:"integer"}]},condition:{max:9007199254740991,type:[{code:"id"}]},constraint:{max:9007199254740991,type:[{code:"ElementDefinitionConstraint"}]},mustSupport:{type:[{code:"boolean"}]},isModifier:{type:[{code:"boolean"}]},isModifierReason:{type:[{code:"string"}]},isSummary:{type:[{code:"boolean"}]},binding:{type:[{code:"ElementDefinitionBinding"}]},mapping:{max:9007199254740991,type:[{code:"ElementDefinitionMapping"}]}}},Expression:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},description:{type:[{code:"string"}]},name:{type:[{code:"id"}]},language:{min:1,type:[{code:"code"}]},expression:{type:[{code:"string"}]},reference:{type:[{code:"uri"}]}}},Extension:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},url:{min:1,type:[{code:"string"}]},"value[x]":{type:[{code:"base64Binary"},{code:"boolean"},{code:"canonical"},{code:"code"},{code:"date"},{code:"dateTime"},{code:"decimal"},{code:"id"},{code:"instant"},{code:"integer"},{code:"markdown"},{code:"oid"},{code:"positiveInt"},{code:"string"},{code:"time"},{code:"unsignedInt"},{code:"uri"},{code:"url"},{code:"uuid"},{code:"Address"},{code:"Age"},{code:"Annotation"},{code:"Attachment"},{code:"CodeableConcept"},{code:"Coding"},{code:"ContactPoint"},{code:"Count"},{code:"Distance"},{code:"Duration"},{code:"HumanName"},{code:"Identifier"},{code:"Money"},{code:"Period"},{code:"Quantity"},{code:"Range"},{code:"Ratio"},{code:"Reference"},{code:"SampledData"},{code:"Signature"},{code:"Timing"},{code:"ContactDetail"},{code:"Contributor"},{code:"DataRequirement"},{code:"Expression"},{code:"ParameterDefinition"},{code:"RelatedArtifact"},{code:"TriggerDefinition"},{code:"UsageContext"},{code:"Dosage"},{code:"Meta"}]}}},HumanName:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},use:{type:[{code:"code"}]},text:{type:[{code:"string"}]},family:{type:[{code:"string"}]},given:{max:9007199254740991,type:[{code:"string"}]},prefix:{max:9007199254740991,type:[{code:"string"}]},suffix:{max:9007199254740991,type:[{code:"string"}]},period:{type:[{code:"Period"}]}}},Identifier:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},use:{type:[{code:"code"}]},type:{type:[{code:"CodeableConcept"}]},system:{type:[{code:"uri"}]},value:{type:[{code:"string"}]},period:{type:[{code:"Period"}]},assigner:{type:[{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Organization"]}]}}},MarketingStatus:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},country:{min:1,type:[{code:"CodeableConcept"}]},jurisdiction:{type:[{code:"CodeableConcept"}]},status:{min:1,type:[{code:"CodeableConcept"}]},dateRange:{min:1,type:[{code:"Period"}]},restoreDate:{type:[{code:"dateTime"}]}}},Meta:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},versionId:{type:[{code:"id"}]},lastUpdated:{type:[{code:"instant"}]},source:{type:[{code:"uri"}]},profile:{max:9007199254740991,type:[{code:"canonical",targetProfile:["http://hl7.org/fhir/StructureDefinition/StructureDefinition"]}]},security:{max:9007199254740991,type:[{code:"Coding"}]},tag:{max:9007199254740991,type:[{code:"Coding"}]},project:{type:[{code:"uri"}]},author:{type:[{code:"Reference"}]},account:{type:[{code:"Reference"}]},compartment:{max:9007199254740991,type:[{code:"Reference"}]}}},Money:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},currency:{type:[{code:"code"}]}}},Narrative:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},status:{min:1,type:[{code:"code"}]},div:{min:1,type:[{code:"xhtml"}]}}},ParameterDefinition:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},name:{type:[{code:"code"}]},use:{min:1,type:[{code:"code"}]},min:{type:[{code:"integer"}]},max:{type:[{code:"string"}]},documentation:{type:[{code:"string"}]},type:{min:1,type:[{code:"code"}]},profile:{type:[{code:"canonical",targetProfile:["http://hl7.org/fhir/StructureDefinition/StructureDefinition"]}]}}},Period:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},start:{type:[{code:"dateTime"}]},end:{type:[{code:"dateTime"}]}}},Population:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},"age[x]":{type:[{code:"Range"},{code:"CodeableConcept"}]},gender:{type:[{code:"CodeableConcept"}]},race:{type:[{code:"CodeableConcept"}]},physiologicalCondition:{type:[{code:"CodeableConcept"}]}}},ProdCharacteristic:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},height:{type:[{code:"Quantity"}]},width:{type:[{code:"Quantity"}]},depth:{type:[{code:"Quantity"}]},weight:{type:[{code:"Quantity"}]},nominalVolume:{type:[{code:"Quantity"}]},externalDiameter:{type:[{code:"Quantity"}]},shape:{type:[{code:"string"}]},color:{max:9007199254740991,type:[{code:"string"}]},imprint:{max:9007199254740991,type:[{code:"string"}]},image:{max:9007199254740991,type:[{code:"Attachment"}]},scoring:{type:[{code:"CodeableConcept"}]}}},ProductShelfLife:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},identifier:{type:[{code:"Identifier"}]},type:{min:1,type:[{code:"CodeableConcept"}]},period:{min:1,type:[{code:"Quantity"}]},specialPrecautionsForStorage:{max:9007199254740991,type:[{code:"CodeableConcept"}]}}},Quantity:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},Range:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},low:{type:[{code:"Quantity"}]},high:{type:[{code:"Quantity"}]}}},Ratio:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},numerator:{type:[{code:"Quantity"}]},denominator:{type:[{code:"Quantity"}]}}},Reference:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},reference:{type:[{code:"string"}]},type:{type:[{code:"uri"}]},identifier:{type:[{code:"Identifier"}]},display:{type:[{code:"string"}]}}},RelatedArtifact:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},type:{min:1,type:[{code:"code"}]},label:{type:[{code:"string"}]},display:{type:[{code:"string"}]},citation:{type:[{code:"markdown"}]},url:{type:[{code:"url"}]},document:{type:[{code:"Attachment"}]},resource:{type:[{code:"canonical",targetProfile:["http://hl7.org/fhir/StructureDefinition/Resource"]}]}}},SampledData:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},origin:{min:1,type:[{code:"Quantity"}]},period:{min:1,type:[{code:"decimal"}]},factor:{type:[{code:"decimal"}]},lowerLimit:{type:[{code:"decimal"}]},upperLimit:{type:[{code:"decimal"}]},dimensions:{min:1,type:[{code:"positiveInt"}]},data:{type:[{code:"string"}]}}},Signature:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},type:{min:1,max:9007199254740991,type:[{code:"Coding"}]},when:{min:1,type:[{code:"instant"}]},who:{min:1,type:[{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Practitioner","http://hl7.org/fhir/StructureDefinition/PractitionerRole","http://hl7.org/fhir/StructureDefinition/RelatedPerson","http://hl7.org/fhir/StructureDefinition/Patient","http://hl7.org/fhir/StructureDefinition/Device","http://hl7.org/fhir/StructureDefinition/Organization"]}]},onBehalfOf:{type:[{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Practitioner","http://hl7.org/fhir/StructureDefinition/PractitionerRole","http://hl7.org/fhir/StructureDefinition/RelatedPerson","http://hl7.org/fhir/StructureDefinition/Patient","http://hl7.org/fhir/StructureDefinition/Device","http://hl7.org/fhir/StructureDefinition/Organization"]}]},targetFormat:{type:[{code:"code"}]},sigFormat:{type:[{code:"code"}]},data:{type:[{code:"base64Binary"}]}}},SubstanceAmount:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},"amount[x]":{type:[{code:"Quantity"},{code:"Range"},{code:"string"}]},amountType:{type:[{code:"CodeableConcept"}]},amountText:{type:[{code:"string"}]},referenceRange:{type:[{code:"SubstanceAmountReferenceRange"}]}}},Timing:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},event:{max:9007199254740991,type:[{code:"dateTime"}]},repeat:{type:[{code:"TimingRepeat"}]},code:{type:[{code:"CodeableConcept"}]}}},TriggerDefinition:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},type:{min:1,type:[{code:"code"}]},name:{type:[{code:"string"}]},"timing[x]":{type:[{code:"Timing"},{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/Schedule"]},{code:"date"},{code:"dateTime"}]},data:{max:9007199254740991,type:[{code:"DataRequirement"}]},condition:{type:[{code:"Expression"}]}}},UsageContext:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},code:{min:1,type:[{code:"Coding"}]},"value[x]":{min:1,type:[{code:"CodeableConcept"},{code:"Quantity"},{code:"Range"},{code:"Reference",targetProfile:["http://hl7.org/fhir/StructureDefinition/PlanDefinition","http://hl7.org/fhir/StructureDefinition/ResearchStudy","http://hl7.org/fhir/StructureDefinition/InsurancePlan","http://hl7.org/fhir/StructureDefinition/HealthcareService","http://hl7.org/fhir/StructureDefinition/Group","http://hl7.org/fhir/StructureDefinition/Location","http://hl7.org/fhir/StructureDefinition/Organization"]}]}}},MoneyQuantity:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},SimpleQuantity:{elements:{id:{type:[{code:"string"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},value:{type:[{code:"decimal"}]},comparator:{max:0,type:[{code:"code"}]},unit:{type:[{code:"string"}]},system:{type:[{code:"uri"}]},code:{type:[{code:"code"}]}}},MetadataResource:{elements:{id:{type:[{code:"string"}]},meta:{type:[{code:"Meta"}]},implicitRules:{type:[{code:"uri"}]},language:{type:[{code:"code"}]},text:{type:[{code:"Narrative"}]},contained:{max:9007199254740991,type:[{code:"Resource"}]},extension:{max:9007199254740991,type:[{code:"Extension"}]},modifierExtension:{max:9007199254740991,type:[{code:"Extension"}]},url:{type:[{code:"uri"}]},version:{type:[{code:"string"}]},name:{type:[{code:"string"}]},title:{type:[{code:"string"}]},status:{min:1,type:[{code:"code"}]},experimental:{type:[{code:"boolean"}]},date:{type:[{code:"dateTime"}]},publisher:{type:[{code:"string"}]},contact:{max:9007199254740991,type:[{code:"ContactDetail"}]},description:{type:[{code:"markdown"}]},useContext:{max:9007199254740991,type:[{code:"UsageContext"}]},jurisdiction:{max:9007199254740991,type:[{code:"CodeableConcept"}]}}},IdentityProvider:{elements:{authorizeUrl:{min:1,type:[{code:"string"}]},tokenUrl:{min:1,type:[{code:"string"}]},userInfoUrl:{min:1,type:[{code:"string"}]},clientId:{min:1,type:[{code:"string"}]},clientSecret:{min:1,type:[{code:"string"}]},useSubject:{type:[{code:"boolean"}]}}}};function u(e){return[{type:l.boolean,value:e}]}function R(e){return e==null?{type:"undefined",value:void 0}:Number.isSafeInteger(e)?{type:l.integer,value:e}:typeof e=="number"?{type:l.decimal,value:e}:typeof e=="boolean"?{type:l.boolean,value:e}:typeof e=="string"?{type:l.string,value:e}:v(e)?{type:l.Quantity,value:e}:j(e)?{type:e.resourceType,value:e}:{type:l.BackboneElement,value:e}}function A(e){return e.length===0?!1:!!e[0].value}function C(e,t){if(e.length!==0){if(e.length===1&&(!t||e[0].type===t))return e[0];throw new Error(`Expected singleton of type ${t}, but found ${JSON.stringify(e)}`)}}function He(e,t){if(!e.value)return;let r=et(e.type,t);return r?ze(e,t,r):Qe(e,t)}function ze(e,t,r){let n=r.type;if(!n||n.length===0)return;let i,s="undefined";if(n.length===1)i=e.value[t],s=n[0].code;else for(let c of n){let m=t.replace("[x]","")+ae(c.code);if(m in e.value){i=e.value[m],s=c.code;break}}let a=e.value["_"+t];if(a&&(Array.isArray(i)?i=i.map((c,m)=>a[m]?se(c??{},a[m]):c):i=se(i??{},a)),!oe(i))return(s==="Element"||s==="BackboneElement")&&(s=r.type[0].code),Array.isArray(i)?i.map(c=>re(c,s)):re(i,s)}function re(e,t){return t==="Resource"&&j(e)&&(t=e.resourceType),{type:t,value:e}}function Qe(e,t){let r=e.value;if(!r||typeof r!="object")return;let n;if(t in r)n=r[t];else for(let i in l){let s=t+ae(i);if(s in r){n=r[s];break}}if(!oe(n))return Array.isArray(n)?n.map(R):R(n)}function ce(e){let t=[];for(let r of e){let n=!1;for(let i of t)if(A(de(r,i))){n=!0;break}n||t.push(r)}return t}function ue(e){return u(!A(e))}function le(e,t){return e.length===0||t.length===0?[]:e.length!==t.length?u(!1):u(e.every((r,n)=>A(de(r,t[n]))))}function de(e,t){let r=e.value?.valueOf(),n=t.value?.valueOf();return typeof r=="number"&&typeof n=="number"?u(Math.abs(r-n)<1e-8):v(r)&&v(n)?u(me(r,n)):u(typeof r=="object"&&typeof n=="object"?Q(e,t):r===n)}function pe(e,t){return e.length===0&&t.length===0?u(!0):e.length!==t.length?u(!1):(e.sort(ne),t.sort(ne),u(e.every((r,n)=>A(Ve(r,t[n])))))}function Ve(e,t){let{type:r,value:n}=e,{type:i,value:s}=t,a=n?.valueOf(),c=s?.valueOf();return typeof a=="number"&&typeof c=="number"?u(Math.abs(a-c)<.01):v(a)&&v(c)?u(me(a,c)):u(r==="Coding"&&i==="Coding"?typeof a!="object"||typeof c!="object"?!1:a.code===c.code&&a.system===c.system:typeof a=="object"&&typeof c=="object"?Q({...a,id:void 0},{...c,id:void 0}):typeof a=="string"&&typeof c=="string"?a.toLowerCase()===c.toLowerCase():a===c)}function ne(e,t){let r=e.value?.valueOf(),n=t.value?.valueOf();return typeof r=="number"&&typeof n=="number"?r-n:typeof r=="string"&&typeof n=="string"?r.localeCompare(n):0}function he(e,t){let{value:r}=e;if(r==null)return!1;switch(t){case"Boolean":return typeof r=="boolean";case"Decimal":case"Integer":return typeof r=="number";case"Date":return typeof r=="string"&&!!/^\d{4}(-\d{2}(-\d{2})?)?/.exec(r);case"DateTime":return typeof r=="string"&&!!/^\d{4}(-\d{2}(-\d{2})?)?T/.exec(r);case"Time":return typeof r=="string"&&!!/^T\d/.exec(r);case"Period":return Ye(r);case"Quantity":return v(r);default:return typeof r=="object"&&r?.resourceType===t}}function Ye(e){return!!(e&&typeof e=="object"&&"start"in e)}function v(e){return!!(e&&typeof e=="object"&&"value"in e&&typeof e.value=="number")}function me(e,t){return Math.abs(e.value-t.value)<.01&&(e.unit===t.unit||e.code===t.code||e.unit===t.code||e.code===t.unit)}function Q(e,t){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let i of r){let s=e[i],a=t[i];if(ie(s)&&ie(a)){if(!Q(s,a))return!1}else if(s!==a)return!1}return!0}function ie(e){return e!==null&&typeof e=="object"}function se(e,t){return delete t.__proto__,delete t.constructor,Object.assign(e,t)}function V(e,t){return{resourceType:"OperationOutcome",issue:[{severity:"error",code:"invalid",details:{text:e},expression:t?[t]:void 0}]}}function P(e){return{resourceType:"OperationOutcome",issue:[{severity:"error",code:"structure",details:{text:e}}]}}var T=class extends Error{constructor(e,t){super(Je(e)),this.outcome=e,this.cause=t}};function Je(e){let t=e.issue?.map(Ke)??[];return t.length>0?t.join("; "):"Unknown error"}function Ke(e){let t;return e.details?.text?e.diagnostics?t=`${e.details.text} (${e.diagnostics})`:t=e.details.text:e.diagnostics?t=e.diagnostics:t="Unknown error",e.expression?.length&&(t+=` (${e.expression.join(", ")})`),t}var Xe=qe(We);function Ze(e){return Xe[e]}var l={Address:"Address",Age:"Age",Annotation:"Annotation",Attachment:"Attachment",BackboneElement:"BackboneElement",CodeableConcept:"CodeableConcept",Coding:"Coding",ContactDetail:"ContactDetail",ContactPoint:"ContactPoint",Contributor:"Contributor",Count:"Count",DataRequirement:"DataRequirement",Distance:"Distance",Dosage:"Dosage",Duration:"Duration",Expression:"Expression",Extension:"Extension",HumanName:"HumanName",Identifier:"Identifier",MarketingStatus:"MarketingStatus",Meta:"Meta",Money:"Money",Narrative:"Narrative",ParameterDefinition:"ParameterDefinition",Period:"Period",Population:"Population",ProdCharacteristic:"ProdCharacteristic",ProductShelfLife:"ProductShelfLife",Quantity:"Quantity",Range:"Range",Ratio:"Ratio",Reference:"Reference",RelatedArtifact:"RelatedArtifact",SampledData:"SampledData",Signature:"Signature",SubstanceAmount:"SubstanceAmount",SystemString:"http://hl7.org/fhirpath/System.String",Timing:"Timing",TriggerDefinition:"TriggerDefinition",UsageContext:"UsageContext",base64Binary:"base64Binary",boolean:"boolean",canonical:"canonical",code:"code",date:"date",dateTime:"dateTime",decimal:"decimal",id:"id",instant:"instant",integer:"integer",markdown:"markdown",oid:"oid",positiveInt:"positiveInt",string:"string",time:"time",unsignedInt:"unsignedInt",uri:"uri",url:"url",uuid:"uuid"};function et(e,t){let r=Ze(e);if(r)return r.elements[t]??r.elements[t+"[x]"]}function j(e){return!!(e&&typeof e=="object"&&"resourceType"in e)}function F(e){if(e.startsWith("T"))return e+"T00:00:00.000Z".substring(e.length);if(e.length<=10)return e;try{return new Date(e).toISOString()}catch{return e}}var $=()=>[],y={empty:(e,t)=>u(t.length===0),exists:(e,t,r)=>u(r?t.filter(n=>A(r.eval(e,[n]))).length>0:t.length>0),all:(e,t,r)=>u(t.every(n=>A(r.eval(e,[n])))),allTrue:(e,t)=>{for(let r of t)if(!r.value)return u(!1);return u(!0)},anyTrue:(e,t)=>{for(let r of t)if(r.value)return u(!0);return u(!1)},allFalse:(e,t)=>{for(let r of t)if(r.value)return u(!1);return u(!0)},anyFalse:(e,t)=>{for(let r of t)if(!r.value)return u(!0);return u(!1)},subsetOf:$,supersetOf:$,count:(e,t)=>[{type:l.integer,value:t.length}],distinct:(e,t)=>{let r=[];for(let n of t)r.some(i=>i.value===n.value)||r.push(n);return r},isDistinct:(e,t)=>u(t.length===y.distinct(e,t).length),where:(e,t,r)=>t.filter(n=>A(r.eval(e,[n]))),select:(e,t,r)=>t.map(n=>r.eval(e,[n])).flat(),repeat:$,ofType:(e,t,r)=>t.filter(n=>n.type===r.name),single:(e,t)=>{if(t.length>1)throw new Error("Expected input length one for single()");return t.length===0?[]:t.slice(0,1)},first:(e,t)=>t.length===0?[]:t.slice(0,1),last:(e,t)=>t.length===0?[]:t.slice(t.length-1,t.length),tail:(e,t)=>t.length===0?[]:t.slice(1,t.length),skip:(e,t,r)=>{let n=r.eval(e,t)[0]?.value;if(typeof n!="number")throw new Error("Expected a number for skip(num)");return n>=t.length?[]:n<=0?t:t.slice(n,t.length)},take:(e,t,r)=>{let n=r.eval(e,t)[0]?.value;if(typeof n!="number")throw new Error("Expected a number for take(num)");return n>=t.length?t:n<=0?[]:t.slice(0,n)},intersect:(e,t,r)=>{if(!r)return t;let n=r.eval(e,t),i=[];for(let s of t)!i.some(a=>a.value===s.value)&&n.some(a=>a.value===s.value)&&i.push(s);return i},exclude:(e,t,r)=>{if(!r)return t;let n=r.eval(e,t),i=[];for(let s of t)n.some(a=>a.value===s.value)||i.push(s);return i},union:(e,t,r)=>{if(!r)return t;let n=r.eval(e,t);return ce([...t,...n])},combine:(e,t,r)=>{if(!r)return t;let n=r.eval(e,t);return[...t,...n]},htmlChecks:(e,t,r)=>[R(!0)],iif:(e,t,r,n,i)=>{let s=r.eval(e,t);if(s.length>1||s.length===1&&typeof s[0].value!="boolean")throw new Error("Expected criterion to evaluate to a Boolean");return A(s)?n.eval(e,t):i?i.eval(e,t):[]},toBoolean:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);if(typeof r=="boolean")return[{type:l.boolean,value:r}];if(typeof r=="number"&&(r===0||r===1))return u(!!r);if(typeof r=="string"){let n=r.toLowerCase();if(["true","t","yes","y","1","1.0"].includes(n))return u(!0);if(["false","f","no","n","0","0.0"].includes(n))return u(!1)}return[]},convertsToBoolean:(e,t)=>t.length===0?[]:u(y.toBoolean(e,t).length===1),toInteger:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return typeof r=="number"?[{type:l.integer,value:r}]:typeof r=="string"&&/^[+-]?\d+$/.exec(r)?[{type:l.integer,value:parseInt(r,10)}]:typeof r=="boolean"?[{type:l.integer,value:r?1:0}]:[]},convertsToInteger:(e,t)=>t.length===0?[]:u(y.toInteger(e,t).length===1),toDate:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return typeof r=="string"&&/^\d{4}(-\d{2}(-\d{2})?)?/.exec(r)?[{type:l.date,value:F(r)}]:[]},convertsToDate:(e,t)=>t.length===0?[]:u(y.toDate(e,t).length===1),toDateTime:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return typeof r=="string"&&/^\d{4}(-\d{2}(-\d{2})?)?/.exec(r)?[{type:l.dateTime,value:F(r)}]:[]},convertsToDateTime:(e,t)=>t.length===0?[]:u(y.toDateTime(e,t).length===1),toDecimal:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return typeof r=="number"?[{type:l.decimal,value:r}]:typeof r=="string"&&/^-?\d{1,9}(\.\d{1,9})?$/.exec(r)?[{type:l.decimal,value:parseFloat(r)}]:typeof r=="boolean"?[{type:l.decimal,value:r?1:0}]:[]},convertsToDecimal:(e,t)=>t.length===0?[]:u(y.toDecimal(e,t).length===1),toQuantity:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return v(r)?[{type:l.Quantity,value:r}]:typeof r=="number"?[{type:l.Quantity,value:{value:r,unit:"1"}}]:typeof r=="string"&&/^-?\d{1,9}(\.\d{1,9})?/.exec(r)?[{type:l.Quantity,value:{value:parseFloat(r),unit:"1"}}]:typeof r=="boolean"?[{type:l.Quantity,value:{value:r?1:0,unit:"1"}}]:[]},convertsToQuantity:(e,t)=>t.length===0?[]:u(y.toQuantity(e,t).length===1),toString:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);return r==null?[]:v(r)?[{type:l.string,value:`${r.value} '${r.unit}'`}]:[{type:l.string,value:r.toString()}]},convertsToString:(e,t)=>t.length===0?[]:u(y.toString(e,t).length===1),toTime:(e,t)=>{if(t.length===0)return[];let[{value:r}]=b(t,1);if(typeof r=="string"){let n=/^T?(\d{2}(:\d{2}(:\d{2})?)?)/.exec(r);if(n)return[{type:l.time,value:F("T"+n[1])}]}return[]},convertsToTime:(e,t)=>t.length===0?[]:u(y.toTime(e,t).length===1),indexOf:(e,t,r)=>g((n,i)=>n.indexOf(i),e,t,r),substring:(e,t,r,n)=>g((i,s,a)=>{let c=s,m=a?c+a:i.length;return c<0||c>=i.length?void 0:i.substring(c,m)},e,t,r,n),startsWith:(e,t,r)=>g((n,i)=>n.startsWith(i),e,t,r),endsWith:(e,t,r)=>g((n,i)=>n.endsWith(i),e,t,r),contains:(e,t,r)=>g((n,i)=>n.includes(i),e,t,r),upper:(e,t)=>g(r=>r.toUpperCase(),e,t),lower:(e,t)=>g(r=>r.toLowerCase(),e,t),replace:(e,t,r,n)=>g((i,s,a)=>i.replaceAll(s,a),e,t,r,n),matches:(e,t,r)=>g((n,i)=>!!new RegExp(i).exec(n),e,t,r),replaceMatches:(e,t,r,n)=>g((i,s,a)=>i.replaceAll(s,a),e,t,r,n),length:(e,t)=>g(r=>r.length,e,t),toChars:(e,t)=>g(r=>r?r.split(""):void 0,e,t),abs:(e,t)=>x(Math.abs,e,t),ceiling:(e,t)=>x(Math.ceil,e,t),exp:(e,t)=>x(Math.exp,e,t),floor:(e,t)=>x(Math.floor,e,t),ln:(e,t)=>x(Math.log,e,t),log:(e,t,r)=>x((n,i)=>Math.log(n)/Math.log(i),e,t,r),power:(e,t,r)=>x(Math.pow,e,t,r),round:(e,t)=>x(Math.round,e,t),sqrt:(e,t)=>x(Math.sqrt,e,t),truncate:(e,t)=>x(r=>r|0,e,t),children:$,descendants:$,trace:(e,t,r)=>(console.log("trace",t,r),t),now:()=>[{type:l.dateTime,value:new Date().toISOString()}],timeOfDay:()=>[{type:l.time,value:new Date().toISOString().substring(11)}],today:()=>[{type:l.date,value:new Date().toISOString().substring(0,10)}],between:(e,t,r,n,i)=>{let s=y.toDateTime(e,r.eval(e,t));if(s.length===0)throw new Error("Invalid start date");let a=y.toDateTime(e,n.eval(e,t));if(a.length===0)throw new Error("Invalid end date");let c=i.eval(e,t)[0]?.value;if(c!=="years"&&c!=="months"&&c!=="days")throw new Error("Invalid units");let m=Fe(s[0].value,a[0].value);return[{type:l.Quantity,value:{value:m[c],unit:c}}]},is:(e,t,r)=>{let n="";return r instanceof Y?n=r.name:r instanceof fe&&(n=r.left.name+"."+r.right.name),n?t.map(i=>({type:l.boolean,value:he(i,n)})):[]},not:(e,t)=>y.toBoolean(e,t).map(r=>({type:l.boolean,value:!r.value})),resolve:(e,t)=>t.map(r=>{let n=r.value,i;if(typeof n=="string")i=n;else if(typeof n=="object"){let s=n;if(s.resource)return R(s.resource);s.reference?i=s.reference:s.type&&s.identifier&&(i=`${s.type}?identifier=${s.identifier.system}|${s.identifier.value}`)}if(i?.includes("?")){let[s]=i.split("?");return{type:s,value:{resourceType:s}}}if(i?.includes("/")){let[s,a]=i.split("/");return{type:s,value:{resourceType:s,id:a}}}return{type:l.BackboneElement,value:void 0}}).filter(r=>!!r.value),as:(e,t)=>t,type:(e,t)=>t.map(({value:r})=>typeof r=="boolean"?{type:l.BackboneElement,value:{namespace:"System",name:"Boolean"}}:typeof r=="number"?{type:l.BackboneElement,value:{namespace:"System",name:"Integer"}}:j(r)?{type:l.BackboneElement,value:{namespace:"FHIR",name:r.resourceType}}:{type:l.BackboneElement,value:null}),conformsTo:(e,t,r)=>{let n=r.eval(e,t)[0].value;if(!n.startsWith("http://hl7.org/fhir/StructureDefinition/"))throw new Error("Expected a StructureDefinition URL");let i=n.replace("http://hl7.org/fhir/StructureDefinition/","");return t.map(s=>({type:l.boolean,value:s.value?.resourceType===i}))}};function g(e,t,r,...n){if(r.length===0)return[];let[{value:i}]=b(r,1);if(typeof i!="string")throw new Error("String function cannot be called with non-string");let s=e(i,...n.map(a=>a?.eval(t,r)[0]?.value));return s===void 0?[]:Array.isArray(s)?s.map(R):[R(s)]}function x(e,t,r,...n){if(r.length===0)return[];let[{value:i}]=b(r,1),s=v(i),a=s?i.value:i;if(typeof a!="number")throw new Error("Math function cannot be called with non-number");let c=e(a,...n.map(B=>B.eval(t,r)[0]?.value)),m=s?l.Quantity:r[0].type,L=s?{...i,value:c}:c;return[{type:m,value:L}]}function b(e,t){if(e.length!==t)throw new Error(`Expected ${t} arguments`);for(let r of e)if(r==null)throw new Error("Expected non-null argument");return e}var k=class{constructor(e){this.value=e}eval(){return[this.value]}toString(){let e=this.value.value;return typeof e=="string"?`'${e}'`:e.toString()}},Y=class{constructor(e){this.name=e}eval(e,t){if(this.name==="$this")return t;if(this.name.startsWith("%")){let r=e.variables[this.name.slice(1)];if(!r)throw new Error(`Undefined variable ${this.name}`);return[r]}return t.flatMap(r=>this.evalValue(r)).filter(r=>r?.value!==void 0)}evalValue(e){let t=e.value;if(!(!t||typeof t!="object"))return j(t)&&t.resourceType===this.name?e:He(e,this.name)}toString(){return this.name}},tt=class{eval(){return[]}toString(){return"{}"}},rt=class extends Me{constructor(e,t,r){super(e,t),this.impl=r}eval(e,t){return this.impl(this.child.eval(e,t))}toString(){return this.operator+this.child.toString()}},nt=class extends U{constructor(e,t){super("as",e,t)}eval(e,t){return y.ofType(e,this.left.eval(e,t),this.right)}},S=class extends U{},w=class extends S{constructor(e,t,r,n){super(e,t,r),this.impl=n}eval(e,t){let r=this.left.eval(e,t);if(r.length!==1)return[];let n=this.right.eval(e,t);if(n.length!==1)return[];let i=r[0].value,s=n[0].value,a=v(i)?i.value:i,c=v(s)?s.value:s,m=this.impl(a,c);return typeof m=="boolean"?u(m):v(i)?[{type:l.Quantity,value:{...i,value:m}}]:[R(m)]}},it=class extends U{constructor(e,t){super("&",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t),i=[...r,...n];return i.length>0&&i.every(s=>typeof s.value=="string")?[{type:l.string,value:i.map(s=>s.value).join("")}]:i}},st=class extends S{constructor(e,t){super("contains",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return u(r.some(i=>i.value===n[0].value))}},ot=class extends S{constructor(e,t){super("in",e,t)}eval(e,t){let r=C(this.left.eval(e,t)),n=this.right.eval(e,t);return r?u(n.some(i=>i.value===r.value)):[]}},fe=class extends U{constructor(e,t){super(".",e,t)}eval(e,t){return this.right.eval(e,this.left.eval(e,t))}toString(){return`${this.left.toString()}.${this.right.toString()}`}},at=class extends U{constructor(e,t){super("|",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return ce([...r,...n])}},ct=class extends S{constructor(e,t){super("=",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return le(r,n)}},ut=class extends S{constructor(e,t){super("!=",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return ue(le(r,n))}},lt=class extends S{constructor(e,t){super("~",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return pe(r,n)}},dt=class extends S{constructor(e,t){super("!~",e,t)}eval(e,t){let r=this.left.eval(e,t),n=this.right.eval(e,t);return ue(pe(r,n))}},pt=class extends S{constructor(e,t){super("is",e,t)}eval(e,t){let r=this.left.eval(e,t);if(r.length!==1)return[];let n=this.right.name;return u(he(r[0],n))}},ht=class extends S{constructor(e,t){super("and",e,t)}eval(e,t){let r=C(this.left.eval(e,t),"boolean"),n=C(this.right.eval(e,t),"boolean");return r?.value===!0&&n?.value===!0?u(!0):r?.value===!1||n?.value===!1?u(!1):[]}},mt=class extends S{constructor(e,t){super("or",e,t)}eval(e,t){let r=C(this.left.eval(e,t),"boolean"),n=C(this.right.eval(e,t),"boolean");return r?.value===!1&&n?.value===!1?u(!1):r?.value||n?.value?u(!0):[]}},ft=class extends S{constructor(e,t){super("xor",e,t)}eval(e,t){let r=C(this.left.eval(e,t),"boolean"),n=C(this.right.eval(e,t),"boolean");return!r||!n?[]:u(r.value!==n.value)}},yt=class extends S{constructor(e,t){super("implies",e,t)}eval(e,t){let r=C(this.left.eval(e,t),"boolean"),n=C(this.right.eval(e,t),"boolean");return n?.value===!0||r?.value===!1?u(!0):!r||!n?[]:u(!1)}},gt=class{constructor(e,t){this.name=e,this.args=t}eval(e,t){let r=y[this.name];if(!r)throw new Error("Unrecognized function: "+this.name);return r(e,t,...this.args)}toString(){return`${this.name}(${this.args.map(e=>e.toString()).join(", ")})`}},vt=class{constructor(e,t){this.left=e,this.expr=t}eval(e,t){let r=this.expr.eval(e,t);if(r.length!==1)return[];let n=r[0].value;if(typeof n!="number")throw new Error("Invalid indexer expression: should return integer}");let i=this.left.eval(e,t);return n in i?[i[n]]:[]}toString(){return`${this.left.toString()}[${this.expr.toString()}]`}};var ye=["!=","!~","<=",">=","{}","->"];var p={FunctionCall:0,Dot:1,Indexer:2,UnaryAdd:3,UnarySubtract:3,Multiply:4,Divide:4,IntegerDivide:4,Modulo:4,Add:5,Subtract:5,Ampersand:5,Is:6,As:6,Union:7,GreaterThan:8,GreaterThanOrEquals:8,LessThan:8,LessThanOrEquals:8,Equals:9,Equivalent:9,NotEquals:9,NotEquivalent:9,In:10,Contains:10,And:11,Xor:12,Or:12,Implies:13,Arrow:100,Semicolon:200},St={parse(e){let t=e.consumeAndParse();if(!e.match(")"))throw new Error("Parse error: expected `)` got `"+e.peek()?.value+"`");return t}},wt={parse(e,t){let r=e.consumeAndParse();if(!e.match("]"))throw new Error("Parse error: expected `]`");return new vt(t,r)},precedence:p.Indexer},xt={parse(e,t){if(!(t instanceof Y))throw new Error("Unexpected parentheses");let r=[];for(;!e.match(")");)r.push(e.consumeAndParse()),e.match(",");return new gt(t.name,r)},precedence:p.FunctionCall};function bt(e){let t=e.split(" "),r=parseFloat(t[0]),n=t[1];return n?.startsWith("'")&&n.endsWith("'")?n=n.substring(1,n.length-1):n="{"+n+"}",{value:r,unit:n}}function J(){return new _e().registerPrefix("String",{parse:(e,t)=>new k({type:l.string,value:t.value})}).registerPrefix("DateTime",{parse:(e,t)=>new k({type:l.dateTime,value:F(t.value)})}).registerPrefix("Quantity",{parse:(e,t)=>new k({type:l.Quantity,value:bt(t.value)})}).registerPrefix("Number",{parse:(e,t)=>new k({type:l.decimal,value:parseFloat(t.value)})}).registerPrefix("true",{parse:()=>new k({type:l.boolean,value:!0})}).registerPrefix("false",{parse:()=>new k({type:l.boolean,value:!1})}).registerPrefix("Symbol",{parse:(e,t)=>new Y(t.value)}).registerPrefix("{}",{parse:()=>new tt}).registerPrefix("(",St).registerInfix("[",wt).registerInfix("(",xt).prefix("+",p.UnaryAdd,(e,t)=>new rt("+",t,r=>r)).prefix("-",p.UnarySubtract,(e,t)=>new w("-",t,t,(r,n)=>-n)).infixLeft(".",p.Dot,(e,t,r)=>new fe(e,r)).infixLeft("/",p.Divide,(e,t,r)=>new w("/",e,r,(n,i)=>n/i)).infixLeft("*",p.Multiply,(e,t,r)=>new w("*",e,r,(n,i)=>n*i)).infixLeft("+",p.Add,(e,t,r)=>new w("+",e,r,(n,i)=>n+i)).infixLeft("-",p.Subtract,(e,t,r)=>new w("-",e,r,(n,i)=>n-i)).infixLeft("|",p.Union,(e,t,r)=>new at(e,r)).infixLeft("=",p.Equals,(e,t,r)=>new ct(e,r)).infixLeft("!=",p.NotEquals,(e,t,r)=>new ut(e,r)).infixLeft("~",p.Equivalent,(e,t,r)=>new lt(e,r)).infixLeft("!~",p.NotEquivalent,(e,t,r)=>new dt(e,r)).infixLeft("<",p.LessThan,(e,t,r)=>new w("<",e,r,(n,i)=>n<i)).infixLeft("<=",p.LessThanOrEquals,(e,t,r)=>new w("<=",e,r,(n,i)=>n<=i)).infixLeft(">",p.GreaterThan,(e,t,r)=>new w(">",e,r,(n,i)=>n>i)).infixLeft(">=",p.GreaterThanOrEquals,(e,t,r)=>new w(">=",e,r,(n,i)=>n>=i)).infixLeft("&",p.Ampersand,(e,t,r)=>new it(e,r)).infixLeft("and",p.And,(e,t,r)=>new ht(e,r)).infixLeft("as",p.As,(e,t,r)=>new nt(e,r)).infixLeft("contains",p.Contains,(e,t,r)=>new st(e,r)).infixLeft("div",p.Divide,(e,t,r)=>new w("div",e,r,(n,i)=>n/i|0)).infixLeft("in",p.In,(e,t,r)=>new ot(e,r)).infixLeft("is",p.Is,(e,t,r)=>new pt(e,r)).infixLeft("mod",p.Modulo,(e,t,r)=>new w("mod",e,r,(n,i)=>n%i)).infixLeft("or",p.Or,(e,t,r)=>new mt(e,r)).infixLeft("xor",p.Xor,(e,t,r)=>new ft(e,r)).infixLeft("implies",p.Implies,(e,t,r)=>new yt(e,r))}var Ut=J();var Tt=(e=>(e.BOOLEAN="BOOLEAN",e.NUMBER="NUMBER",e.QUANTITY="QUANTITY",e.TEXT="TEXT",e.REFERENCE="REFERENCE",e.CANONICAL="CANONICAL",e.DATE="DATE",e.DATETIME="DATETIME",e.PERIOD="PERIOD",e.UUID="UUID",e))(Tt||{});var Ct=(e=>(e.EQUALS="eq",e.NOT_EQUALS="ne",e.GREATER_THAN="gt",e.LESS_THAN="lt",e.GREATER_THAN_OR_EQUALS="ge",e.LESS_THAN_OR_EQUALS="le",e.STARTS_AFTER="sa",e.ENDS_BEFORE="eb",e.APPROXIMATELY="ap",e.CONTAINS="contains",e.EXACT="exact",e.TEXT="text",e.NOT="not",e.ABOVE="above",e.BELOW="below",e.IN="in",e.NOT_IN="not-in",e.OF_TYPE="of-type",e.MISSING="missing",e.IDENTIFIER="identifier",e.ITERATE="iterate",e))(Ct||{});var At=(e=>(e.READ="read",e.VREAD="vread",e.UPDATE="update",e.PATCH="patch",e.DELETE="delete",e.HISTORY="history",e.HISTORY_INSTANCE="history-instance",e.HISTORY_TYPE="history-type",e.HISTORY_SYSTEM="history-system",e.CREATE="create",e.SEARCH="search",e.SEARCH_TYPE="search-type",e.SEARCH_SYSTEM="search-system",e.SEARCH_COMPARTMENT="search-compartment",e.CAPABILITIES="capabilities",e.TRANSACTION="transaction",e.BATCH="batch",e.OPERATION="operation",e))(At||{});var Pt={CSS:"text/css",FAVICON:"image/vnd.microsoft.icon",FHIR_JSON:"application/fhir+json",FORM_URL_ENCODED:"application/x-www-form-urlencoded",HL7_V2:"x-application/hl7-v2+er7",HTML:"text/html",JAVASCRIPT:"text/javascript",JSON:"application/json",JSON_PATCH:"application/json-patch+json",PNG:"image/png",SVG:"image/svg+xml",TEXT:"text/plain",TYPESCRIPT:"text/typescript"};var Rt;Rt=Symbol.toStringTag;var Mt=Pt.FHIR_JSON+", */*; q=0.1";var Et=(e=>(e.ClientCredentials="client_credentials",e.AuthorizationCode="authorization_code",e.RefreshToken="refresh_token",e.JwtBearer="urn:ietf:params:oauth:grant-type:jwt-bearer",e.TokenExchange="urn:ietf:params:oauth:grant-type:token-exchange",e))(Et||{}),kt=(e=>(e.AccessToken="urn:ietf:params:oauth:token-type:access_token",e.RefreshToken="urn:ietf:params:oauth:token-type:refresh_token",e.IdToken="urn:ietf:params:oauth:token-type:id_token",e.Saml1Token="urn:ietf:params:oauth:token-type:saml1",e.Saml2Token="urn:ietf:params:oauth:token-type:saml2",e))(kt||{}),It=(e=>(e.JwtBearer="urn:ietf:params:oauth:client-assertion-type:jwt-bearer",e))(It||{});var _t=[...ye,"->","<<",">>"];var Bt=J().registerInfix("->",{precedence:p.Arrow}).registerInfix(";",{precedence:p.Semicolon});var Ft=[...ye,"eq","ne","co"];var jt=J();var X=["string","boolean","number"],K={},Z=class{constructor(t){let{region:r}=t;if(!r)throw new T(P("'region' must be defined as a string literal in config."));K[r]||(K[r]=new G.SSMClient({region:r})),this.config=t,this.clients={ssm:K[r]}}async fetchParameterStoreSecret(t){let n=(await this.clients.ssm.send(new G.GetParameterCommand({Name:t,WithDecryption:!0}))).Parameter;if(!n)throw new T(V(`Key '${t}' not found. Make sure your key is correct and that it is defined in your Parameter Store.`));let i=n.Value;if(!i)throw new T(V(`Key '${t}' found but has no value. Make sure your key is correct and that it is defined in your Parameter Store.`));return i}async fetchExternalSecret(t){Ot(t);let{system:r,key:n,type:i}=t,s;switch(r){case"aws_ssm_parameter_store":{s=await this.fetchParameterStoreSecret(n);break}default:throw new T(P(`Unknown system '${r}' for ExternalSecret. Unable to fetch the secret for key '${n}'.`))}return Dt(n,s,i)}async normalizeInfraConfigArray(t){let r=t[0],n;if(typeof r!="object"&&r!==null||ge(r)){n=new Array(t.length);for(let i=0;i<t.length;i++){let s=t[i];if(typeof s!="object"){n[i]=s;continue}let a=await this.fetchExternalSecret(s);n[i]=a}}else{n=new Array(t.length);for(let i=0;i<t.length;i++)n[i]=await this.normalizeObjectInInfraConfig(t[i])}return n}async normalizeValueForKey(t,r){let n=t[r];typeof n!="object"?t[r]=n:ge(n)?t[r]=await this.fetchExternalSecret(n):Array.isArray(n)&&n.length?t[r]=await this.normalizeInfraConfigArray(n):typeof n=="object"&&(t[r]=await this.normalizeObjectInInfraConfig(n))}async normalizeObjectInInfraConfig(t){let r={...t};for(let n of Object.keys(r))await this.normalizeValueForKey(r,n);return r}async normalizeConfig(){return this.normalizeObjectInInfraConfig(this.config)}};function Dt(e,t,r){let n=typeof t;if(!X.includes(n))throw new T(P(`Invalid value found for type; expected either ${X.join(", or")} but got ${n}`));if(n===r)return t;if(n==="string"&&r==="boolean"){let i=t.toLowerCase();if(i!=="true"&&i!=="false")throw new T(P(`Invalid value found for key '${e}'; expected boolean value but got '${t}'`));return i==="true"}else if(n==="string"&&r==="number"){let i=parseInt(t,10);if(Number.isNaN(i))throw new T(P(`Invalid value found for key '${e}'; expected integer value but got '${t}'`));return i}else throw new T(P(`Invalid value found for type; expected ${r} value but got value of type ${n}`))}function ge(e){return typeof e=="object"&&typeof e.system=="string"&&typeof e.key=="string"&&typeof e.type=="string"}function Nt(e){return typeof e=="object"&&typeof e.system=="string"&&typeof e.key=="string"&&X.includes(e.type)}function Ot(e){if(!Nt(e))throw new T(P("obj is not a valid `ExternalSecret`, must contain a valid `system`, `key`, and `type` prop."))}async function ve(e){return new Z(e).normalizeConfig()}var O=require("aws-cdk-lib");var o=require("aws-cdk-lib"),Se=require("aws-cdk-lib/aws-ecr"),ee=require("aws-cdk-lib/aws-rds"),we=require("constructs");var E=[{name:"AWS-AWSManagedRulesCommonRuleSet",priority:10,statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesCommonRuleSet",excludedRules:[{name:"NoUserAgent_HEADER"},{name:"UserAgent_BadBots_HEADER"},{name:"SizeRestrictions_QUERYSTRING"},{name:"SizeRestrictions_Cookie_HEADER"},{name:"SizeRestrictions_BODY"},{name:"SizeRestrictions_URIPATH"},{name:"EC2MetaDataSSRF_BODY"},{name:"EC2MetaDataSSRF_COOKIE"},{name:"EC2MetaDataSSRF_URIPATH"},{name:"EC2MetaDataSSRF_QUERYARGUMENTS"},{name:"GenericLFI_QUERYARGUMENTS"},{name:"GenericLFI_URIPATH"},{name:"GenericLFI_BODY"},{name:"RestrictedExtensions_URIPATH"},{name:"RestrictedExtensions_QUERYARGUMENTS"},{name:"GenericRFI_QUERYARGUMENTS"},{name:"GenericRFI_BODY"},{name:"GenericRFI_URIPATH"},{name:"CrossSiteScripting_COOKIE"},{name:"CrossSiteScripting_QUERYARGUMENTS"},{name:"CrossSiteScripting_BODY"},{name:"CrossSiteScripting_URIPATH"}]}},overrideAction:{count:{}},visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWS-AWSManagedRulesCommonRuleSet"}},{name:"AWS-AWSManagedRulesAmazonIpReputationList",priority:20,statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesAmazonIpReputationList",excludedRules:[{name:"AWSManagedIPReputationList"},{name:"AWSManagedReconnaissanceList"}]}},overrideAction:{count:{}},visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRulesAmazonIpReputationList"}},{name:"AWSManagedRulesSQLiRuleSet",priority:30,visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRulesSQLiRuleSet"},overrideAction:{count:{}},statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesSQLiRuleSet",excludedRules:[{name:"SQLi_QUERYARGUMENTS"},{name:"SQLiExtendedPatterns_QUERYARGUMENTS"},{name:"SQLi_BODY"},{name:"SQLiExtendedPatterns_BODY"},{name:"SQLi_COOKIE"},{name:"SQLi_URIPATH"}]}}},{name:"AWSManagedRuleLinux",priority:40,visibilityConfig:{sampledRequestsEnabled:!0,cloudWatchMetricsEnabled:!0,metricName:"AWSManagedRuleLinux"},overrideAction:{count:{}},statement:{managedRuleGroupStatement:{vendorName:"AWS",name:"AWSManagedRulesLinuxRuleSet",excludedRules:[{name:"LFI_URIPATH"},{name:"LFI_QUERYSTRING"},{name:"LFI_COOKIE"}]}}}];var M=class extends we.Construct{constructor(r,n){super(r,"BackEnd");let i=n.name;if(n.vpcId)this.vpc=o.aws_ec2.Vpc.fromLookup(this,"VPC",{vpcId:n.vpcId});else{let s=new o.aws_logs.LogGroup(this,"VpcFlowLogs",{logGroupName:"/medplum/flowlogs/"+i,removalPolicy:o.RemovalPolicy.DESTROY});this.vpc=new o.aws_ec2.Vpc(this,"VPC",{maxAzs:n.maxAzs,flowLogs:{cloudwatch:{destination:o.aws_ec2.FlowLogDestination.toCloudWatchLogs(s),trafficType:o.aws_ec2.FlowLogTrafficType.ALL}}})}if(this.botLambdaRole=new o.aws_iam.Role(this,"BotLambdaRole",{assumedBy:new o.aws_iam.ServicePrincipal("lambda.amazonaws.com")}),this.rdsSecretsArn=n.rdsSecretsArn,!this.rdsSecretsArn){let s={instanceType:n.rdsInstanceType?new o.aws_ec2.InstanceType(n.rdsInstanceType):void 0,enablePerformanceInsights:!0,isFromLegacyInstanceProps:!0},a;if(n.rdsInstances>1){a=[];for(let c=0;c<n.rdsInstances-1;c++)a.push(ee.ClusterInstance.provisioned("Instance"+(c+2),{...s}))}this.rdsCluster=new o.aws_rds.DatabaseCluster(this,"DatabaseCluster",{engine:o.aws_rds.DatabaseClusterEngine.auroraPostgres({version:o.aws_rds.AuroraPostgresEngineVersion.VER_12_9}),credentials:o.aws_rds.Credentials.fromGeneratedSecret("clusteradmin"),defaultDatabaseName:"medplum",storageEncrypted:!0,vpc:this.vpc,vpcSubnets:{subnetType:o.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS},writer:ee.ClusterInstance.provisioned("Instance1",{...s}),readers:a,backup:{retention:o.Duration.days(7)},cloudwatchLogsExports:["postgresql"],instanceUpdateBehaviour:o.aws_rds.InstanceUpdateBehaviour.ROLLING}),this.rdsSecretsArn=this.rdsCluster.secret.secretArn}if(this.redisSubnetGroup=new o.aws_elasticache.CfnSubnetGroup(this,"RedisSubnetGroup",{description:"Redis Subnet Group",subnetIds:this.vpc.privateSubnets.map(s=>s.subnetId)}),this.redisSecurityGroup=new o.aws_ec2.SecurityGroup(this,"RedisSecurityGroup",{vpc:this.vpc,description:"Redis Security Group",allowAllOutbound:!1}),this.redisPassword=new o.aws_secretsmanager.Secret(this,"RedisPassword",{generateSecretString:{secretStringTemplate:"{}",generateStringKey:"password",excludeCharacters:"@%*()_+=`~{}|[]\\:\";'?,./"}}),this.redisCluster=new o.aws_elasticache.CfnReplicationGroup(this,"RedisCluster",{engine:"Redis",engineVersion:"6.x",cacheNodeType:n.cacheNodeType??"cache.t2.medium",replicationGroupDescription:"RedisReplicationGroup",authToken:this.redisPassword.secretValueFromJson("password").toString(),transitEncryptionEnabled:!0,atRestEncryptionEnabled:!0,multiAzEnabled:!0,cacheSubnetGroupName:this.redisSubnetGroup.ref,numNodeGroups:1,replicasPerNodeGroup:1,securityGroupIds:[this.redisSecurityGroup.securityGroupId]}),this.redisCluster.node.addDependency(this.redisPassword),this.redisSecrets=new o.aws_secretsmanager.Secret(this,"RedisSecrets",{generateSecretString:{secretStringTemplate:JSON.stringify({host:this.redisCluster.attrPrimaryEndPointAddress,port:this.redisCluster.attrPrimaryEndPointPort,password:this.redisPassword.secretValueFromJson("password").toString(),tls:{}}),generateStringKey:"unused"}}),this.redisSecrets.node.addDependency(this.redisPassword),this.redisSecrets.node.addDependency(this.redisCluster),this.ecsCluster=new o.aws_ecs.Cluster(this,"Cluster",{vpc:this.vpc}),this.taskRolePolicies=new o.aws_iam.PolicyDocument({statements:[new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["logs:CreateLogStream","logs:PutLogEvents"],resources:["arn:aws:logs:*"]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["secretsmanager:GetResourcePolicy","secretsmanager:GetSecretValue","secretsmanager:DescribeSecret","secretsmanager:ListSecrets","secretsmanager:ListSecretVersionIds"],resources:["arn:aws:secretsmanager:*"]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["ssm:GetParametersByPath","ssm:GetParameters","ssm:GetParameter","ssm:DescribeParameters"],resources:["arn:aws:ssm:*"]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["ses:SendEmail","ses:SendRawEmail"],resources:["arn:aws:ses:*"]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["s3:ListBucket","s3:GetObject","s3:PutObject","s3:DeleteObject"],resources:["arn:aws:s3:::*"]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["iam:ListRoles","iam:GetRole","iam:PassRole"],resources:[this.botLambdaRole.roleArn]}),new o.aws_iam.PolicyStatement({effect:o.aws_iam.Effect.ALLOW,actions:["lambda:CreateFunction","lambda:GetFunction","lambda:GetFunctionConfiguration","lambda:UpdateFunctionCode","lambda:UpdateFunctionConfiguration","lambda:ListLayerVersions","lambda:GetLayerVersion","lambda:InvokeFunction"],resources:["arn:aws:lambda:*"]})]}),this.taskRole=new o.aws_iam.Role(this,"TaskExecutionRole",{assumedBy:new o.aws_iam.ServicePrincipal("ecs-tasks.amazonaws.com"),description:"Medplum Server Task Execution Role",inlinePolicies:{TaskExecutionPolicies:this.taskRolePolicies}}),this.taskDefinition=new o.aws_ecs.FargateTaskDefinition(this,"TaskDefinition",{memoryLimitMiB:n.serverMemory,cpu:n.serverCpu,taskRole:this.taskRole}),this.logGroup=new o.aws_logs.LogGroup(this,"LogGroup",{logGroupName:"/ecs/medplum/"+i,removalPolicy:o.RemovalPolicy.DESTROY}),this.logDriver=new o.aws_ecs.AwsLogDriver({logGroup:this.logGroup,streamPrefix:"Medplum"}),this.serviceContainer=this.taskDefinition.addContainer("MedplumTaskDefinition",{image:this.getContainerImage(n,n.serverImage),command:[n.region==="us-east-1"?`aws:/medplum/${i}/`:`aws:${n.region}:/medplum/${i}/`],logging:this.logDriver}),this.serviceContainer.addPortMappings({containerPort:n.apiPort,hostPort:n.apiPort}),n.additionalContainers)for(let s of n.additionalContainers)this.taskDefinition.addContainer("AdditionalContainer-"+s.name,{containerName:s.name,image:this.getContainerImage(n,s.image),command:s.command,environment:s.environment,logging:this.logDriver});if(this.fargateSecurityGroup=new o.aws_ec2.SecurityGroup(this,"ServiceSecurityGroup",{allowAllOutbound:!0,securityGroupName:"MedplumSecurityGroup",vpc:this.vpc}),this.fargateService=new o.aws_ecs.FargateService(this,"FargateService",{cluster:this.ecsCluster,taskDefinition:this.taskDefinition,assignPublicIp:!1,vpcSubnets:{subnetType:o.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS},desiredCount:n.desiredServerCount,securityGroups:[this.fargateSecurityGroup],healthCheckGracePeriod:o.Duration.minutes(5)}),this.rdsCluster&&this.fargateService.node.addDependency(this.rdsCluster),this.fargateService.node.addDependency(this.redisCluster),this.targetGroup=new o.aws_elasticloadbalancingv2.ApplicationTargetGroup(this,"TargetGroup",{vpc:this.vpc,port:n.apiPort,protocol:o.aws_elasticloadbalancingv2.ApplicationProtocol.HTTP,healthCheck:{path:"/healthcheck",interval:o.Duration.seconds(30),timeout:o.Duration.seconds(3),healthyThresholdCount:2,unhealthyThresholdCount:5},targets:[this.fargateService]}),this.loadBalancer=new o.aws_elasticloadbalancingv2.ApplicationLoadBalancer(this,"LoadBalancer",{vpc:this.vpc,internetFacing:n.apiInternetFacing!==!1,http2Enabled:!0}),n.loadBalancerLoggingBucket&&this.loadBalancer.logAccessLogs(o.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",n.loadBalancerLoggingBucket),n.loadBalancerLoggingPrefix),this.loadBalancer.addListener("HttpsListener",{port:443,certificates:[{certificateArn:n.apiSslCertArn}],sslPolicy:o.aws_elasticloadbalancingv2.SslPolicy.FORWARD_SECRECY_TLS12_RES_GCM,defaultAction:o.aws_elasticloadbalancingv2.ListenerAction.forward([this.targetGroup])}),this.waf=new o.aws_wafv2.CfnWebACL(this,"BackEndWAF",{defaultAction:{allow:{}},scope:"REGIONAL",name:`${n.stackName}-BackEndWAF`,rules:E,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${n.stackName}-BackEndWAF-Metric`,sampledRequestsEnabled:!1}}),this.wafAssociation=new o.aws_wafv2.CfnWebACLAssociation(this,"LoadBalancerAssociation",{resourceArn:this.loadBalancer.loadBalancerArn,webAclArn:this.waf.attrArn}),this.rdsCluster&&this.rdsCluster.connections.allowDefaultPortFrom(this.fargateSecurityGroup),this.redisSecurityGroup.addIngressRule(this.fargateSecurityGroup,o.aws_ec2.Port.tcp(6379)),!n.skipDns){let s=o.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:n.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new o.aws_route53.ARecord(this,"LoadBalancerAliasRecord",{recordName:n.apiDomainName,target:o.aws_route53.RecordTarget.fromAlias(new o.aws_route53_targets.LoadBalancerTarget(this.loadBalancer)),zone:s})}this.regionParameter=new o.aws_ssm.StringParameter(this,"RegionParameter",{tier:o.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${i}/awsRegion`,description:"AWS region",stringValue:n.region}),this.databaseSecretsParameter=new o.aws_ssm.StringParameter(this,"DatabaseSecretsParameter",{tier:o.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${i}/DatabaseSecrets`,description:"Database secrets ARN",stringValue:this.rdsSecretsArn}),this.redisSecretsParameter=new o.aws_ssm.StringParameter(this,"RedisSecretsParameter",{tier:o.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${i}/RedisSecrets`,description:"Redis secrets ARN",stringValue:this.redisSecrets.secretArn}),this.botLambdaRoleParameter=new o.aws_ssm.StringParameter(this,"BotLambdaRoleParameter",{tier:o.aws_ssm.ParameterTier.STANDARD,parameterName:`/medplum/${i}/botLambdaRoleArn`,description:"Bot lambda execution role ARN",stringValue:this.botLambdaRole.roleArn})}getContainerImage(r,n){let s=new RegExp(`^${r.accountNumber}\\.dkr\\.ecr\\.${r.region}\\.amazonaws\\.com/(.*)[:@](.*)$`).exec(n),a=s?.[1],c=s?.[2];if(a&&c){let m=Se.Repository.fromRepositoryArn(this,"ServerImageRepo",`arn:aws:ecr:${r.region}:${r.accountNumber}:repository/${a}`);return o.aws_ecs.ContainerImage.fromEcrRepository(m,c)}return o.aws_ecs.ContainerImage.fromRegistry(n)}};var f=require("aws-cdk-lib"),xe=require("constructs"),I=class extends xe.Construct{constructor(r,n){super(r,"CloudTrailAlarms");if(this.config=n,!n.cloudTrailAlarms)return;n.cloudTrailAlarms.logGroupCreate?(this.logGroup=new f.aws_logs.LogGroup(this,"CloudTrailLogGroup",{logGroupName:n.cloudTrailAlarms.logGroupName,retention:f.aws_logs.RetentionDays.ONE_YEAR}),this.cloudTrail=new f.aws_cloudtrail.Trail(this,"CloudTrail",{sendToCloudWatchLogs:!0,cloudWatchLogGroup:this.logGroup,includeGlobalServiceEvents:!0})):this.logGroup=f.aws_logs.LogGroup.fromLogGroupName(this,"CloudTrailLogGroup",n.cloudTrailAlarms.logGroupName),n.cloudTrailAlarms.snsTopicArn?this.alarmTopic=f.aws_sns.Topic.fromTopicArn(this,"AlarmTopic",n.cloudTrailAlarms.snsTopicArn):this.alarmTopic=new f.aws_sns.Topic(this,"AlarmTopic",{topicName:n.cloudTrailAlarms.snsTopicName});let i=[["UnauthorizedApiCalls","{ ($.errorCode = *UnauthorizedOperation) || ($.errorCode = AccessDenied*) }"],["SignInWithoutMfa","{ ($.eventName = ConsoleLogin) && ($.additionalEventData.MFAUsed != Yes) }"],["RootAccountUsage","{ $.userIdentity.type = Root && $.userIdentity.invokedBy NOT EXISTS && $.eventType != AwsServiceEvent }"],["IamPolicyChanges","{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}"],["CloudTrailConfigurationChanges","{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }"],["SignInFailures",'{ ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") }'],["DisabledCmks","{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }"],["S3PolicyChanges","{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) }"],["ConfigServiceChanges","{($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}"],["SecurityGroupChanges","{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup)}"],["NetworkAclChanges","{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }"],["NetworkGatewayChanges","{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }"],["RouteTableChanges","{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }"],["VpcChanges","{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }"],["OrganizationsChanges","{ ($.eventSource = organizations.amazonaws.com) && (($.eventName = AcceptHandshake) || ($.eventName = AttachPolicy) || ($.eventName = CreateAccount) || ($.eventName = CreateOrganizationalUnit) || ($.eventName = CreatePolicy) || ($.eventName = DeclineHandshake) || ($.eventName = DeleteOrganization) || ($.eventName = DeleteOrganizationalUnit) || ($.eventName = DeletePolicy) || ($.eventName = DetachPolicy) || ($.eventName = DisablePolicyType) || ($.eventName = EnablePolicyType) || ($.eventName = InviteAccountToOrganization) || ($.eventName = LeaveOrganization) || ($.eventName = MoveAccount) || ($.eventName = RemoveAccountFromOrganization) || ($.eventName = UpdatePolicy) || ($.eventName = UpdateOrganizationalUnit)) }"]];for(let[s,a]of i)this.createMetricAlarm(s,a)}createMetricAlarm(r,n){let i=`${this.config.stackName}${r}MetricFilter`,s=`${this.config.stackName}${r}Metric`,a=`${this.config.stackName}Metrics`,c=`${this.config.stackName}${r}Alarm`,m=new f.aws_logs.MetricFilter(this,i,{logGroup:this.logGroup,filterPattern:{logPatternString:n},metricNamespace:a,metricName:s});new f.aws_cloudwatch.Alarm(this,c,{metric:m.metric({}),threshold:1,evaluationPeriods:1,alarmName:c,actionsEnabled:!0,treatMissingData:f.aws_cloudwatch.TreatMissingData.NOT_BREACHING,comparisonOperator:f.aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,datapointsToAlarm:1}).addAlarmAction(new f.aws_cloudwatch_actions.SnsAction(this.alarmTopic))}};var d=require("aws-cdk-lib"),Te=require("constructs");var be=require("aws-cdk-lib");function q(e,t){let r=new be.aws_iam.PolicyStatement;return r.addActions("s3:GetObject*"),r.addActions("s3:GetBucket*"),r.addActions("s3:List*"),r.addResources(e.bucketArn),r.addResources(`${e.bucketArn}/*`),r.addCanonicalUserPrincipal(t.cloudFrontOriginAccessIdentityS3CanonicalUserId),e.addToResourcePolicy(r),r}var D=class extends Te.Construct{constructor(r,n,i){super(r,"FrontEnd");if(i===n.region?this.appBucket=new d.aws_s3.Bucket(this,"AppBucket",{bucketName:n.appDomainName,publicReadAccess:!1,blockPublicAccess:d.aws_s3.BlockPublicAccess.BLOCK_ALL,removalPolicy:d.RemovalPolicy.DESTROY,encryption:d.aws_s3.BucketEncryption.S3_MANAGED,enforceSSL:!0,versioned:!0}):this.appBucket=d.aws_s3.Bucket.fromBucketAttributes(this,"AppBucket",{bucketName:n.appDomainName,region:n.region}),i==="us-east-1"&&(this.responseHeadersPolicy=new d.aws_cloudfront.ResponseHeadersPolicy(this,"ResponseHeadersPolicy",{securityHeadersBehavior:{contentSecurityPolicy:{contentSecurityPolicy:["default-src 'none'","base-uri 'self'","child-src 'self'",`connect-src 'self' ${n.apiDomainName} *.google.com`,"font-src 'self' fonts.gstatic.com","form-action 'self' *.gstatic.com *.google.com","frame-ancestors 'none'","frame-src 'self' *.medplum.com *.gstatic.com *.google.com",`img-src 'self' data: ${n.storageDomainName} *.gstatic.com *.google.com *.googleapis.com`,"manifest-src 'self'",`media-src 'self' ${n.storageDomainName}`,"script-src 'self' *.medplum.com *.gstatic.com *.google.com","style-src 'self' 'unsafe-inline' *.medplum.com *.gstatic.com *.google.com","worker-src 'self' blob: *.gstatic.com *.google.com","upgrade-insecure-requests"].join("; "),override:!0},contentTypeOptions:{override:!0},frameOptions:{frameOption:d.aws_cloudfront.HeadersFrameOption.DENY,override:!0},strictTransportSecurity:{accessControlMaxAge:d.Duration.seconds(63072e3),includeSubdomains:!0,override:!0},xssProtection:{protection:!0,modeBlock:!0,override:!0}}}),this.waf=new d.aws_wafv2.CfnWebACL(this,"FrontEndWAF",{defaultAction:{allow:{}},scope:"CLOUDFRONT",name:`${n.stackName}-FrontEndWAF`,rules:E,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${n.stackName}-FrontEndWAF-Metric`,sampledRequestsEnabled:!1}}),this.apiOriginCachePolicy=new d.aws_cloudfront.CachePolicy(this,"ApiOriginCachePolicy",{cachePolicyName:`${n.stackName}-ApiOriginCachePolicy`,cookieBehavior:d.aws_cloudfront.CacheCookieBehavior.all(),headerBehavior:d.aws_cloudfront.CacheHeaderBehavior.allowList("Authorization","Content-Encoding","Content-Type","If-None-Match","Origin","Referer","User-Agent","X-Medplum"),queryStringBehavior:d.aws_cloudfront.CacheQueryStringBehavior.all()}),this.originAccessIdentity=new d.aws_cloudfront.OriginAccessIdentity(this,"OriginAccessIdentity",{}),this.originAccessPolicyStatement=q(this.appBucket,this.originAccessIdentity),this.distribution=new d.aws_cloudfront.Distribution(this,"AppDistribution",{defaultRootObject:"index.html",defaultBehavior:{origin:new d.aws_cloudfront_origins.S3Origin(this.appBucket,{originAccessIdentity:this.originAccessIdentity}),responseHeadersPolicy:this.responseHeadersPolicy,viewerProtocolPolicy:d.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS},additionalBehaviors:n.appApiProxy?{"/api/*":{origin:new d.aws_cloudfront_origins.HttpOrigin(n.apiDomainName),allowedMethods:d.aws_cloudfront.AllowedMethods.ALLOW_ALL,cachePolicy:this.apiOriginCachePolicy,viewerProtocolPolicy:d.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS}}:void 0,certificate:d.aws_certificatemanager.Certificate.fromCertificateArn(this,"AppCertificate",n.appSslCertArn),domainNames:[n.appDomainName],errorResponses:[{httpStatus:403,responseHttpStatus:200,responsePagePath:"/index.html"},{httpStatus:404,responseHttpStatus:200,responsePagePath:"/index.html"}],webAclId:this.waf.attrArn,logBucket:n.appLoggingBucket?d.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",n.appLoggingBucket):void 0,logFilePrefix:n.appLoggingPrefix}),!n.skipDns)){let s=d.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:n.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new d.aws_route53.ARecord(this,"AppAliasRecord",{recordName:n.appDomainName,target:d.aws_route53.RecordTarget.fromAlias(new d.aws_route53_targets.CloudFrontTarget(this.distribution)),zone:s})}}};var h=require("aws-cdk-lib"),Ce=require("cdk-serverless-clamscan"),Ae=require("constructs");var N=class extends Ae.Construct{constructor(r,n,i){super(r,"Storage");if(i===n.region?(this.storageBucket=new h.aws_s3.Bucket(this,"StorageBucket",{bucketName:n.storageBucketName,publicReadAccess:!1,blockPublicAccess:h.aws_s3.BlockPublicAccess.BLOCK_ALL,encryption:h.aws_s3.BucketEncryption.S3_MANAGED,enforceSSL:!0,versioned:!0}),n.clamscanEnabled&&new Ce.ServerlessClamscan(this,"ServerlessClamscan",{defsBucketAccessLogsConfig:{logsBucket:h.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",n.clamscanLoggingBucket),logsPrefix:n.clamscanLoggingPrefix}}).addSourceBucket(this.storageBucket)):this.storageBucket=h.aws_s3.Bucket.fromBucketAttributes(this,"StorageBucket",{bucketName:n.storageBucketName,region:n.region}),i==="us-east-1"){let s;if(n.signingKeyId?s=h.aws_cloudfront.PublicKey.fromPublicKeyId(this,"StoragePublicKey",n.signingKeyId):s=new h.aws_cloudfront.PublicKey(this,"StoragePublicKey",{encodedKey:n.storagePublicKey}),this.keyGroup=new h.aws_cloudfront.KeyGroup(this,"StorageKeyGroup",{items:[s]}),this.responseHeadersPolicy=new h.aws_cloudfront.ResponseHeadersPolicy(this,"ResponseHeadersPolicy",{securityHeadersBehavior:{contentSecurityPolicy:{contentSecurityPolicy:"default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors *.medplum.com;",override:!0},contentTypeOptions:{override:!0},frameOptions:{frameOption:h.aws_cloudfront.HeadersFrameOption.DENY,override:!0},referrerPolicy:{referrerPolicy:h.aws_cloudfront.HeadersReferrerPolicy.NO_REFERRER,override:!0},strictTransportSecurity:{accessControlMaxAge:h.Duration.seconds(63072e3),includeSubdomains:!0,override:!0},xssProtection:{protection:!0,modeBlock:!0,override:!0}}}),this.waf=new h.aws_wafv2.CfnWebACL(this,"StorageWAF",{defaultAction:{allow:{}},scope:"CLOUDFRONT",name:`${n.stackName}-StorageWAF`,rules:E,visibilityConfig:{cloudWatchMetricsEnabled:!0,metricName:`${n.stackName}-StorageWAF-Metric`,sampledRequestsEnabled:!1}}),this.originAccessIdentity=new h.aws_cloudfront.OriginAccessIdentity(this,"OriginAccessIdentity",{}),this.originAccessPolicyStatement=q(this.storageBucket,this.originAccessIdentity),this.distribution=new h.aws_cloudfront.Distribution(this,"StorageDistribution",{defaultBehavior:{origin:new h.aws_cloudfront_origins.S3Origin(this.storageBucket,{originAccessIdentity:this.originAccessIdentity}),responseHeadersPolicy:this.responseHeadersPolicy,viewerProtocolPolicy:h.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,trustedKeyGroups:[this.keyGroup]},certificate:h.aws_certificatemanager.Certificate.fromCertificateArn(this,"StorageCertificate",n.storageSslCertArn),domainNames:[n.storageDomainName],webAclId:this.waf.attrArn,logBucket:n.storageLoggingBucket?h.aws_s3.Bucket.fromBucketName(this,"LoggingBucket",n.storageLoggingBucket):void 0,logFilePrefix:n.storageLoggingPrefix}),!n.skipDns){let a=h.aws_route53.HostedZone.fromLookup(this,"Zone",{domainName:n.domainName.split(".").slice(-2).join(".")});this.dnsRecord=new h.aws_route53.ARecord(this,"StorageAliasRecord",{recordName:n.storageDomainName,target:h.aws_route53.RecordTarget.fromAlias(new h.aws_route53_targets.CloudFrontTarget(this.distribution)),zone:a})}}}};var _=class{constructor(t,r){this.primaryStack=new W(t,r),r.region!=="us-east-1"&&(this.globalStack=new H(t,r),this.globalStack.addDependency(this.primaryStack))}},W=class extends O.Stack{constructor(r,n){super(r,n.stackName,{env:{region:n.region,account:n.accountNumber}});O.Tags.of(this).add("medplum:environment",n.name),this.backEnd=new M(this,n),this.frontEnd=new D(this,n,n.region),this.storage=new N(this,n,n.region),this.cloudTrail=new I(this,n)}},H=class extends O.Stack{constructor(r,n){super(r,n.stackName+"-us-east-1",{env:{region:"us-east-1",account:n.accountNumber}});O.Tags.of(this).add("medplum:environment",n.name),this.frontEnd=new D(this,n,"us-east-1"),this.storage=new N(this,n,"us-east-1"),this.cloudTrail=new I(this,n)}};function ke(e){let t=new Pe.App({context:e}),r=t.node.tryGetContext("config");if(!r){console.log('Missing "config" context variable'),console.log("Usage: cdk deploy -c config=my-config.json");return}let n=JSON.parse((0,Re.readFileSync)((0,Ee.resolve)(r),"utf-8"));ve(n).then(i=>{let s=new _(t,i);console.log("Stack",s.primaryStack.stackId),t.synth()}).catch(i=>{console.error(i),process.exit(1)})}require.main===module&&ke();0&&(module.exports={BackEnd,CloudTrailAlarms,FrontEnd,MedplumGlobalStack,MedplumPrimaryStack,MedplumStack,Storage,awsManagedRules,main});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|