@openhi/constructs 0.0.85 → 0.0.87
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/lib/{chunk-SWSN6GDD.mjs → chunk-CEOAGPYY.mjs} +1 -5
- package/lib/chunk-CEOAGPYY.mjs.map +1 -0
- package/lib/chunk-X5MHU7DA.mjs +298 -0
- package/lib/chunk-X5MHU7DA.mjs.map +1 -0
- package/lib/data-store-postgres-replication.handler.d.mts +55 -0
- package/lib/data-store-postgres-replication.handler.d.ts +55 -0
- package/lib/data-store-postgres-replication.handler.js +448 -0
- package/lib/data-store-postgres-replication.handler.js.map +1 -0
- package/lib/data-store-postgres-replication.handler.mjs +313 -0
- package/lib/data-store-postgres-replication.handler.mjs.map +1 -0
- package/lib/firehose-archive-transform.handler.js +0 -4
- package/lib/firehose-archive-transform.handler.js.map +1 -1
- package/lib/firehose-archive-transform.handler.mjs +5 -290
- package/lib/firehose-archive-transform.handler.mjs.map +1 -1
- package/lib/index.d.mts +230 -5
- package/lib/index.d.ts +231 -6
- package/lib/index.js +489 -117
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +468 -97
- package/lib/index.mjs.map +1 -1
- package/lib/post-authentication.handler.d.mts +5 -0
- package/lib/post-authentication.handler.d.ts +5 -0
- package/lib/post-authentication.handler.js +45 -0
- package/lib/post-authentication.handler.js.map +1 -0
- package/lib/post-authentication.handler.mjs +25 -0
- package/lib/post-authentication.handler.mjs.map +1 -0
- package/lib/rest-api-lambda.handler.js +636 -153
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +639 -153
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/package.json +20 -11
- package/scripts/generate-operations.js +2 -2
- package/scripts/generate-routes.js +1 -1
- package/lib/chunk-SWSN6GDD.mjs.map +0 -1
package/lib/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DATA_STORE_CHANGE_DETAIL_TYPE,
|
|
4
4
|
DATA_STORE_CHANGE_EVENT_SOURCE,
|
|
5
5
|
buildFhirCurrentResourceChangeDetail
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CEOAGPYY.mjs";
|
|
7
7
|
import {
|
|
8
8
|
__commonJS,
|
|
9
9
|
__toESM
|
|
@@ -347,6 +347,10 @@ var OpenHiService = class extends Stack {
|
|
|
347
347
|
this.environmentHash = environmentHash;
|
|
348
348
|
this.branchHash = branchHash;
|
|
349
349
|
this.stackHash = stackHash;
|
|
350
|
+
this.node.setContext(
|
|
351
|
+
`availability-zones:account=${account}:region=${region}`,
|
|
352
|
+
[`${region}a`, `${region}b`, `${region}c`]
|
|
353
|
+
);
|
|
350
354
|
Tags.of(this).add(`${appName}:repo-name`, repoName.slice(0, 255));
|
|
351
355
|
Tags.of(this).add(`${appName}:branch-name`, branchName.slice(0, 255));
|
|
352
356
|
Tags.of(this).add(`${appName}:service-type`, id.slice(0, 255));
|
|
@@ -530,6 +534,46 @@ var _RootGraphqlApi = class _RootGraphqlApi extends GraphqlApi {
|
|
|
530
534
|
_RootGraphqlApi.SSM_PARAM_NAME = "ROOT_GRAPHQL_API";
|
|
531
535
|
var RootGraphqlApi = _RootGraphqlApi;
|
|
532
536
|
|
|
537
|
+
// src/components/cognito/cognito-fixture-seeder-client.ts
|
|
538
|
+
import { Duration } from "aws-cdk-lib";
|
|
539
|
+
import {
|
|
540
|
+
UserPoolClient
|
|
541
|
+
} from "aws-cdk-lib/aws-cognito";
|
|
542
|
+
var CognitoFixtureSeederClient = class extends UserPoolClient {
|
|
543
|
+
constructor(scope, props) {
|
|
544
|
+
const { userPool, ...rest } = props;
|
|
545
|
+
super(scope, "fixture-seeder-client", {
|
|
546
|
+
userPool,
|
|
547
|
+
generateSecret: false,
|
|
548
|
+
authFlows: {
|
|
549
|
+
userPassword: true
|
|
550
|
+
},
|
|
551
|
+
// No OAuth flows — the seeder calls Cognito's `InitiateAuth`
|
|
552
|
+
// directly with USER_PASSWORD_AUTH, not through the hosted-UI
|
|
553
|
+
// OAuth grant flows the SPA client uses. `disableOAuth: true`
|
|
554
|
+
// causes CDK to omit `AllowedOAuthFlowsUserPoolClient` entirely;
|
|
555
|
+
// passing an empty `oAuth` block instead still flips that flag on
|
|
556
|
+
// and Cognito rejects the create call for missing flows/scopes.
|
|
557
|
+
disableOAuth: true,
|
|
558
|
+
// Short-lived tokens: a seeder run takes seconds, not hours.
|
|
559
|
+
// 1h access-token validity is the minimum Cognito permits and is
|
|
560
|
+
// plenty for a fixture run.
|
|
561
|
+
accessTokenValidity: Duration.hours(1),
|
|
562
|
+
idTokenValidity: Duration.hours(1),
|
|
563
|
+
refreshTokenValidity: Duration.days(1),
|
|
564
|
+
preventUserExistenceErrors: true,
|
|
565
|
+
...rest
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
/**
|
|
570
|
+
* SSM parameter name suffix used to publish this client's ID for
|
|
571
|
+
* cross-stack lookups. Built into a full parameter name via
|
|
572
|
+
* `buildParameterName` with `serviceType` AUTH (since the auth stack
|
|
573
|
+
* owns this resource).
|
|
574
|
+
*/
|
|
575
|
+
CognitoFixtureSeederClient.SSM_PARAM_NAME = "COGNITO_FIXTURE_SEEDER_CLIENT";
|
|
576
|
+
|
|
533
577
|
// src/components/cognito/cognito-user-pool.ts
|
|
534
578
|
import {
|
|
535
579
|
UserPool,
|
|
@@ -569,8 +613,8 @@ var CognitoUserPool = class extends UserPool {
|
|
|
569
613
|
CognitoUserPool.SSM_PARAM_NAME = "COGNITO_USER_POOL";
|
|
570
614
|
|
|
571
615
|
// src/components/cognito/cognito-user-pool-client.ts
|
|
572
|
-
import { UserPoolClient } from "aws-cdk-lib/aws-cognito";
|
|
573
|
-
var CognitoUserPoolClient = class extends
|
|
616
|
+
import { UserPoolClient as UserPoolClient2 } from "aws-cdk-lib/aws-cognito";
|
|
617
|
+
var CognitoUserPoolClient = class extends UserPoolClient2 {
|
|
574
618
|
constructor(scope, props) {
|
|
575
619
|
super(scope, "user-pool-client", {
|
|
576
620
|
/**
|
|
@@ -629,13 +673,13 @@ var CognitoUserPoolKmsKey = class extends Key {
|
|
|
629
673
|
*/
|
|
630
674
|
CognitoUserPoolKmsKey.SSM_PARAM_NAME = "COGNITO_USER_POOL_KMS_KEY";
|
|
631
675
|
|
|
632
|
-
// src/components/cognito/
|
|
676
|
+
// src/components/cognito/post-authentication-lambda.ts
|
|
633
677
|
import fs from "fs";
|
|
634
678
|
import path from "path";
|
|
635
679
|
import { Runtime } from "aws-cdk-lib/aws-lambda";
|
|
636
680
|
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
637
681
|
import { Construct } from "constructs";
|
|
638
|
-
var HANDLER_NAME = "
|
|
682
|
+
var HANDLER_NAME = "post-authentication.handler.js";
|
|
639
683
|
function resolveHandlerEntry(dirname) {
|
|
640
684
|
const sameDir = path.join(dirname, HANDLER_NAME);
|
|
641
685
|
if (fs.existsSync(sameDir)) {
|
|
@@ -644,9 +688,9 @@ function resolveHandlerEntry(dirname) {
|
|
|
644
688
|
const fromLib = path.join(dirname, "..", "..", "..", "lib", HANDLER_NAME);
|
|
645
689
|
return fromLib;
|
|
646
690
|
}
|
|
647
|
-
var
|
|
691
|
+
var PostAuthenticationLambda = class extends Construct {
|
|
648
692
|
constructor(scope) {
|
|
649
|
-
super(scope, "
|
|
693
|
+
super(scope, "post-authentication-lambda");
|
|
650
694
|
this.lambda = new NodejsFunction(this, "handler", {
|
|
651
695
|
entry: resolveHandlerEntry(__dirname),
|
|
652
696
|
runtime: Runtime.NODEJS_LATEST,
|
|
@@ -655,24 +699,50 @@ var PreTokenGenerationLambda = class extends Construct {
|
|
|
655
699
|
}
|
|
656
700
|
};
|
|
657
701
|
|
|
658
|
-
// src/components/
|
|
702
|
+
// src/components/cognito/pre-token-generation-lambda.ts
|
|
659
703
|
import fs2 from "fs";
|
|
660
704
|
import path2 from "path";
|
|
661
|
-
import { Duration, RemovalPolicy as RemovalPolicy2, Size } from "aws-cdk-lib";
|
|
662
|
-
import * as kinesisfirehose from "aws-cdk-lib/aws-kinesisfirehose";
|
|
663
705
|
import { Runtime as Runtime2 } from "aws-cdk-lib/aws-lambda";
|
|
664
706
|
import { NodejsFunction as NodejsFunction2 } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
665
|
-
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
666
707
|
import { Construct as Construct2 } from "constructs";
|
|
667
|
-
var HANDLER_NAME2 = "
|
|
708
|
+
var HANDLER_NAME2 = "pre-token-generation.handler.js";
|
|
668
709
|
function resolveHandlerEntry2(dirname) {
|
|
669
710
|
const sameDir = path2.join(dirname, HANDLER_NAME2);
|
|
670
711
|
if (fs2.existsSync(sameDir)) {
|
|
671
712
|
return sameDir;
|
|
672
713
|
}
|
|
673
|
-
|
|
714
|
+
const fromLib = path2.join(dirname, "..", "..", "..", "lib", HANDLER_NAME2);
|
|
715
|
+
return fromLib;
|
|
674
716
|
}
|
|
675
|
-
var
|
|
717
|
+
var PreTokenGenerationLambda = class extends Construct2 {
|
|
718
|
+
constructor(scope) {
|
|
719
|
+
super(scope, "pre-token-generation-lambda");
|
|
720
|
+
this.lambda = new NodejsFunction2(this, "handler", {
|
|
721
|
+
entry: resolveHandlerEntry2(__dirname),
|
|
722
|
+
runtime: Runtime2.NODEJS_LATEST,
|
|
723
|
+
memorySize: 1024
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
// src/components/dynamodb/data-store-historical-archive.ts
|
|
729
|
+
import fs3 from "fs";
|
|
730
|
+
import path3 from "path";
|
|
731
|
+
import { Duration as Duration2, RemovalPolicy as RemovalPolicy2, Size } from "aws-cdk-lib";
|
|
732
|
+
import * as kinesisfirehose from "aws-cdk-lib/aws-kinesisfirehose";
|
|
733
|
+
import { Runtime as Runtime3 } from "aws-cdk-lib/aws-lambda";
|
|
734
|
+
import { NodejsFunction as NodejsFunction3 } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
735
|
+
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
736
|
+
import { Construct as Construct3 } from "constructs";
|
|
737
|
+
var HANDLER_NAME3 = "firehose-archive-transform.handler.js";
|
|
738
|
+
function resolveHandlerEntry3(dirname) {
|
|
739
|
+
const sameDir = path3.join(dirname, HANDLER_NAME3);
|
|
740
|
+
if (fs3.existsSync(sameDir)) {
|
|
741
|
+
return sameDir;
|
|
742
|
+
}
|
|
743
|
+
return path3.join(dirname, "..", "..", "..", "lib", HANDLER_NAME3);
|
|
744
|
+
}
|
|
745
|
+
var DataStoreHistoricalArchive = class extends Construct3 {
|
|
676
746
|
constructor(scope, id, props) {
|
|
677
747
|
super(scope, id);
|
|
678
748
|
this.archiveBucket = new s3.Bucket(this, "ArchiveBucket", {
|
|
@@ -692,11 +762,11 @@ var DataStoreHistoricalArchive = class extends Construct2 {
|
|
|
692
762
|
versioned: false
|
|
693
763
|
}) : void 0;
|
|
694
764
|
this.putEventsFailureDlqBucket = putEventsFailureDlqBucket;
|
|
695
|
-
this.transformFunction = new
|
|
696
|
-
entry:
|
|
697
|
-
runtime:
|
|
765
|
+
this.transformFunction = new NodejsFunction3(this, "FirehoseTransform", {
|
|
766
|
+
entry: resolveHandlerEntry3(__dirname),
|
|
767
|
+
runtime: Runtime3.NODEJS_LATEST,
|
|
698
768
|
memorySize: 512,
|
|
699
|
-
timeout:
|
|
769
|
+
timeout: Duration2.minutes(1),
|
|
700
770
|
description: "Firehose transform: filter CURRENT resource rows, S3 keys, EventBridge PutEvents",
|
|
701
771
|
environment: props.dataEventBus && putEventsFailureDlqBucket ? {
|
|
702
772
|
DATA_EVENT_BUS_NAME: props.dataEventBus.eventBusName,
|
|
@@ -712,14 +782,14 @@ var DataStoreHistoricalArchive = class extends Construct2 {
|
|
|
712
782
|
const processor = new kinesisfirehose.LambdaFunctionProcessor(
|
|
713
783
|
this.transformFunction,
|
|
714
784
|
{
|
|
715
|
-
bufferInterval:
|
|
785
|
+
bufferInterval: Duration2.seconds(60),
|
|
716
786
|
bufferSize: Size.mebibytes(3),
|
|
717
787
|
retries: 3
|
|
718
788
|
}
|
|
719
789
|
);
|
|
720
790
|
const destination = new kinesisfirehose.S3Bucket(this.archiveBucket, {
|
|
721
791
|
compression: kinesisfirehose.Compression.GZIP,
|
|
722
|
-
bufferingInterval:
|
|
792
|
+
bufferingInterval: Duration2.seconds(300),
|
|
723
793
|
// Firehose requires SizeInMBs ≥ 64 when dynamic partitioning is enabled.
|
|
724
794
|
bufferingSize: Size.mebibytes(64),
|
|
725
795
|
processors: [processor],
|
|
@@ -789,7 +859,15 @@ var DynamoDbDataStore = class extends Table {
|
|
|
789
859
|
type: AttributeType.STRING
|
|
790
860
|
},
|
|
791
861
|
projectionType: ProjectionType.INCLUDE,
|
|
792
|
-
nonKeyAttributes: [
|
|
862
|
+
nonKeyAttributes: [
|
|
863
|
+
"summary",
|
|
864
|
+
"vid",
|
|
865
|
+
"lastUpdated",
|
|
866
|
+
"createdDate",
|
|
867
|
+
"modifiedDate",
|
|
868
|
+
"createdById",
|
|
869
|
+
"modifiedById"
|
|
870
|
+
]
|
|
793
871
|
});
|
|
794
872
|
this.addGlobalSecondaryIndex({
|
|
795
873
|
indexName: "GSI2",
|
|
@@ -802,32 +880,12 @@ var DynamoDbDataStore = class extends Table {
|
|
|
802
880
|
type: AttributeType.STRING
|
|
803
881
|
},
|
|
804
882
|
projectionType: ProjectionType.INCLUDE,
|
|
805
|
-
nonKeyAttributes: [
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
type: AttributeType.STRING
|
|
812
|
-
},
|
|
813
|
-
sortKey: {
|
|
814
|
-
name: "GSI3SK",
|
|
815
|
-
type: AttributeType.STRING
|
|
816
|
-
},
|
|
817
|
-
projectionType: ProjectionType.INCLUDE,
|
|
818
|
-
nonKeyAttributes: ["resourcePk", "resourceSk"]
|
|
819
|
-
});
|
|
820
|
-
this.addGlobalSecondaryIndex({
|
|
821
|
-
indexName: "GSI4",
|
|
822
|
-
partitionKey: {
|
|
823
|
-
name: "GSI4PK",
|
|
824
|
-
type: AttributeType.STRING
|
|
825
|
-
},
|
|
826
|
-
sortKey: {
|
|
827
|
-
name: "GSI4SK",
|
|
828
|
-
type: AttributeType.STRING
|
|
829
|
-
},
|
|
830
|
-
projectionType: ProjectionType.ALL
|
|
883
|
+
nonKeyAttributes: [
|
|
884
|
+
"id",
|
|
885
|
+
"currentTenant",
|
|
886
|
+
"currentWorkspace",
|
|
887
|
+
"displayName"
|
|
888
|
+
]
|
|
831
889
|
});
|
|
832
890
|
}
|
|
833
891
|
};
|
|
@@ -876,8 +934,172 @@ var OpsEventBus = class _OpsEventBus extends EventBus2 {
|
|
|
876
934
|
}
|
|
877
935
|
};
|
|
878
936
|
|
|
937
|
+
// src/components/postgres/data-store-postgres-replica.ts
|
|
938
|
+
import fs4 from "fs";
|
|
939
|
+
import path4 from "path";
|
|
940
|
+
import { Duration as Duration3, Stack as Stack2 } from "aws-cdk-lib";
|
|
941
|
+
import * as ec2 from "aws-cdk-lib/aws-ec2";
|
|
942
|
+
import { Runtime as Runtime4, StartingPosition } from "aws-cdk-lib/aws-lambda";
|
|
943
|
+
import { KinesisEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
944
|
+
import { NodejsFunction as NodejsFunction4 } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
945
|
+
import * as rds from "aws-cdk-lib/aws-rds";
|
|
946
|
+
import { Construct as Construct4 } from "constructs";
|
|
947
|
+
var HANDLER_NAME4 = "data-store-postgres-replication.handler.js";
|
|
948
|
+
var DEFAULT_DATABASE_NAME = "openhi";
|
|
949
|
+
var SCHEMA_NAME_PATTERN = /^[a-z_][a-z0-9_]{0,62}$/;
|
|
950
|
+
var POSTGRES_REPLICA_CLUSTER_ARN_SSM_NAME = "POSTGRES_REPLICA_CLUSTER_ARN";
|
|
951
|
+
var POSTGRES_REPLICA_SECRET_ARN_SSM_NAME = "POSTGRES_REPLICA_SECRET_ARN";
|
|
952
|
+
var POSTGRES_REPLICA_DATABASE_NAME_SSM_NAME = "POSTGRES_REPLICA_DATABASE_NAME";
|
|
953
|
+
function resolveHandlerEntry4(dirname) {
|
|
954
|
+
const sameDir = path4.join(dirname, HANDLER_NAME4);
|
|
955
|
+
if (fs4.existsSync(sameDir)) {
|
|
956
|
+
return sameDir;
|
|
957
|
+
}
|
|
958
|
+
return path4.join(dirname, "..", "..", "..", "lib", HANDLER_NAME4);
|
|
959
|
+
}
|
|
960
|
+
function getPostgresReplicaSchemaName(branchHash) {
|
|
961
|
+
const candidate = `b_${branchHash.toLowerCase()}`;
|
|
962
|
+
if (!SCHEMA_NAME_PATTERN.test(candidate)) {
|
|
963
|
+
throw new Error(
|
|
964
|
+
`Branch hash ${JSON.stringify(branchHash)} produces an invalid Postgres schema name ${JSON.stringify(candidate)}; expected /[a-z_][a-z0-9_]{0,62}/.`
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
return candidate;
|
|
968
|
+
}
|
|
969
|
+
var DataStorePostgresReplica = class extends Construct4 {
|
|
970
|
+
/**
|
|
971
|
+
* Resolve the cluster ARN published by an upstream {@link DataStorePostgresReplica}.
|
|
972
|
+
* Use from any stack that needs to grant `rds-data:ExecuteStatement` against
|
|
973
|
+
* the cluster.
|
|
974
|
+
*/
|
|
975
|
+
static clusterArnFromConstruct(scope) {
|
|
976
|
+
return DiscoverableStringParameter.valueForLookupName(scope, {
|
|
977
|
+
ssmParamName: POSTGRES_REPLICA_CLUSTER_ARN_SSM_NAME,
|
|
978
|
+
serviceType: "data"
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Resolve the credentials secret ARN published by an upstream
|
|
983
|
+
* {@link DataStorePostgresReplica}. Use from any stack that needs to grant
|
|
984
|
+
* `secretsmanager:GetSecretValue` against the secret.
|
|
985
|
+
*/
|
|
986
|
+
static secretArnFromConstruct(scope) {
|
|
987
|
+
return DiscoverableStringParameter.valueForLookupName(scope, {
|
|
988
|
+
ssmParamName: POSTGRES_REPLICA_SECRET_ARN_SSM_NAME,
|
|
989
|
+
serviceType: "data"
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Resolve the database name published by an upstream
|
|
994
|
+
* {@link DataStorePostgresReplica}.
|
|
995
|
+
*/
|
|
996
|
+
static databaseNameFromConstruct(scope) {
|
|
997
|
+
return DiscoverableStringParameter.valueForLookupName(scope, {
|
|
998
|
+
ssmParamName: POSTGRES_REPLICA_DATABASE_NAME_SSM_NAME,
|
|
999
|
+
serviceType: "data"
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
constructor(scope, id, props) {
|
|
1003
|
+
super(scope, id);
|
|
1004
|
+
this.databaseName = props.databaseName ?? DEFAULT_DATABASE_NAME;
|
|
1005
|
+
this.schemaName = getPostgresReplicaSchemaName(props.branchHash);
|
|
1006
|
+
const region = Stack2.of(this).region;
|
|
1007
|
+
this.vpc = props.vpc ?? new ec2.Vpc(this, "Vpc", {
|
|
1008
|
+
availabilityZones: [`${region}a`, `${region}b`],
|
|
1009
|
+
natGateways: 0,
|
|
1010
|
+
subnetConfiguration: [
|
|
1011
|
+
{
|
|
1012
|
+
name: "isolated",
|
|
1013
|
+
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
|
|
1014
|
+
cidrMask: 24
|
|
1015
|
+
}
|
|
1016
|
+
]
|
|
1017
|
+
});
|
|
1018
|
+
this.cluster = new rds.DatabaseCluster(this, "Cluster", {
|
|
1019
|
+
clusterIdentifier: `openhi-dstore-pg-${props.stackHash}`,
|
|
1020
|
+
engine: rds.DatabaseClusterEngine.auroraPostgres({
|
|
1021
|
+
version: rds.AuroraPostgresEngineVersion.VER_16_4
|
|
1022
|
+
}),
|
|
1023
|
+
vpc: this.vpc,
|
|
1024
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
|
|
1025
|
+
writer: rds.ClusterInstance.serverlessV2("writer"),
|
|
1026
|
+
serverlessV2MinCapacity: props.minCapacity ?? 1,
|
|
1027
|
+
serverlessV2MaxCapacity: props.maxCapacity ?? 2,
|
|
1028
|
+
defaultDatabaseName: this.databaseName,
|
|
1029
|
+
credentials: rds.Credentials.fromGeneratedSecret("openhi_admin"),
|
|
1030
|
+
storageEncrypted: true,
|
|
1031
|
+
removalPolicy: props.removalPolicy,
|
|
1032
|
+
// Phase 2 of ADR 2026-04-17-01: the REST API Lambda queries Postgres
|
|
1033
|
+
// via the RDS Data API (HTTPS) so it can stay out of the cluster's VPC.
|
|
1034
|
+
// Direct `pg` from the replication Lambda continues to work in parallel.
|
|
1035
|
+
enableDataApi: true
|
|
1036
|
+
});
|
|
1037
|
+
this.publishCoordinatesToSsm();
|
|
1038
|
+
this.replicationFunction = new NodejsFunction4(this, "ReplicationFunction", {
|
|
1039
|
+
entry: resolveHandlerEntry4(__dirname),
|
|
1040
|
+
runtime: Runtime4.NODEJS_LATEST,
|
|
1041
|
+
memorySize: 512,
|
|
1042
|
+
timeout: Duration3.minutes(1),
|
|
1043
|
+
vpc: this.vpc,
|
|
1044
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
|
|
1045
|
+
description: "Replicates DynamoDB current-resource changes into the Postgres `resources` JSONB table (ADR 2026-04-17-01).",
|
|
1046
|
+
environment: {
|
|
1047
|
+
OPENHI_PG_HOST: this.cluster.clusterEndpoint.hostname,
|
|
1048
|
+
OPENHI_PG_PORT: this.cluster.clusterEndpoint.port.toString(),
|
|
1049
|
+
OPENHI_PG_DATABASE: this.databaseName,
|
|
1050
|
+
OPENHI_PG_SCHEMA: this.schemaName,
|
|
1051
|
+
OPENHI_PG_SECRET_ARN: this.cluster.secret.secretArn,
|
|
1052
|
+
OPENHI_PG_SSL: "true"
|
|
1053
|
+
},
|
|
1054
|
+
bundling: {
|
|
1055
|
+
minify: true,
|
|
1056
|
+
sourceMap: false,
|
|
1057
|
+
// pg has conditional/optional deps (pg-native, pg-cloudflare) that
|
|
1058
|
+
// historically misbehave when bundled by esbuild; keep it as a real
|
|
1059
|
+
// node_module in the Lambda zip instead.
|
|
1060
|
+
nodeModules: ["pg"]
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
this.cluster.secret.grantRead(this.replicationFunction);
|
|
1064
|
+
this.cluster.connections.allowDefaultPortFrom(this.replicationFunction);
|
|
1065
|
+
this.replicationFunction.addEventSource(
|
|
1066
|
+
new KinesisEventSource(props.kinesisStream, {
|
|
1067
|
+
startingPosition: StartingPosition.LATEST,
|
|
1068
|
+
batchSize: 100,
|
|
1069
|
+
maxBatchingWindow: Duration3.seconds(5),
|
|
1070
|
+
retryAttempts: 10,
|
|
1071
|
+
bisectBatchOnError: true,
|
|
1072
|
+
parallelizationFactor: 2,
|
|
1073
|
+
reportBatchItemFailures: true
|
|
1074
|
+
})
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Publishes the cluster ARN, secret ARN, and database name as discoverable
|
|
1079
|
+
* SSM parameters so the REST API stack (and any future read-side consumer)
|
|
1080
|
+
* can wire RDS Data API access without a direct CDK cross-stack reference.
|
|
1081
|
+
*/
|
|
1082
|
+
publishCoordinatesToSsm() {
|
|
1083
|
+
new DiscoverableStringParameter(this, "cluster-arn-param", {
|
|
1084
|
+
ssmParamName: POSTGRES_REPLICA_CLUSTER_ARN_SSM_NAME,
|
|
1085
|
+
stringValue: this.cluster.clusterArn,
|
|
1086
|
+
description: "ARN of the Aurora Serverless v2 cluster backing the Postgres replication tier (ADR 2026-04-17-01)."
|
|
1087
|
+
});
|
|
1088
|
+
new DiscoverableStringParameter(this, "secret-arn-param", {
|
|
1089
|
+
ssmParamName: POSTGRES_REPLICA_SECRET_ARN_SSM_NAME,
|
|
1090
|
+
stringValue: this.cluster.secret.secretArn,
|
|
1091
|
+
description: "ARN of the Secrets Manager secret with credentials for the Postgres replication tier."
|
|
1092
|
+
});
|
|
1093
|
+
new DiscoverableStringParameter(this, "database-name-param", {
|
|
1094
|
+
ssmParamName: POSTGRES_REPLICA_DATABASE_NAME_SSM_NAME,
|
|
1095
|
+
stringValue: this.databaseName,
|
|
1096
|
+
description: "Database name within the Postgres replication cluster."
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
|
|
879
1101
|
// src/components/route-53/child-hosted-zone.ts
|
|
880
|
-
import { Duration as
|
|
1102
|
+
import { Duration as Duration4 } from "aws-cdk-lib";
|
|
881
1103
|
import {
|
|
882
1104
|
HostedZone,
|
|
883
1105
|
NsRecord
|
|
@@ -889,7 +1111,7 @@ var ChildHostedZone = class extends HostedZone {
|
|
|
889
1111
|
zone: props.parentHostedZone,
|
|
890
1112
|
recordName: this.zoneName,
|
|
891
1113
|
values: this.hostedZoneNameServers || [],
|
|
892
|
-
ttl:
|
|
1114
|
+
ttl: Duration4.minutes(5)
|
|
893
1115
|
});
|
|
894
1116
|
}
|
|
895
1117
|
};
|
|
@@ -899,8 +1121,8 @@ var ChildHostedZone = class extends HostedZone {
|
|
|
899
1121
|
ChildHostedZone.SSM_PARAM_NAME = "CHILDHOSTEDZONE";
|
|
900
1122
|
|
|
901
1123
|
// src/components/route-53/root-hosted-zone.ts
|
|
902
|
-
import { Construct as
|
|
903
|
-
var RootHostedZone = class extends
|
|
1124
|
+
import { Construct as Construct5 } from "constructs";
|
|
1125
|
+
var RootHostedZone = class extends Construct5 {
|
|
904
1126
|
};
|
|
905
1127
|
|
|
906
1128
|
// src/components/static-hosting/static-hosting.ts
|
|
@@ -910,10 +1132,10 @@ import {
|
|
|
910
1132
|
} from "aws-cdk-lib/aws-cloudfront";
|
|
911
1133
|
import { S3BucketOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
|
|
912
1134
|
import { Bucket as Bucket2 } from "aws-cdk-lib/aws-s3";
|
|
913
|
-
import { Duration as
|
|
914
|
-
import { Construct as
|
|
1135
|
+
import { Duration as Duration5 } from "aws-cdk-lib/core";
|
|
1136
|
+
import { Construct as Construct6 } from "constructs";
|
|
915
1137
|
var STATIC_HOSTING_SERVICE_TYPE = "website";
|
|
916
|
-
var _StaticHosting = class _StaticHosting extends
|
|
1138
|
+
var _StaticHosting = class _StaticHosting extends Construct6 {
|
|
917
1139
|
constructor(scope, id, props = {}) {
|
|
918
1140
|
super(scope, id);
|
|
919
1141
|
const stack = OpenHiService.of(scope);
|
|
@@ -931,9 +1153,9 @@ var _StaticHosting = class _StaticHosting extends Construct4 {
|
|
|
931
1153
|
const cachePolicy = new CachePolicy(this, "cache-policy", {
|
|
932
1154
|
cachePolicyName: `static-hosting-10s-${stack.branchHash}`,
|
|
933
1155
|
comment: "Low TTL (10s) for static hosting; no invalidation",
|
|
934
|
-
defaultTtl:
|
|
935
|
-
minTtl:
|
|
936
|
-
maxTtl:
|
|
1156
|
+
defaultTtl: Duration5.seconds(10),
|
|
1157
|
+
minTtl: Duration5.seconds(0),
|
|
1158
|
+
maxTtl: Duration5.seconds(10)
|
|
937
1159
|
});
|
|
938
1160
|
this.distribution = new Distribution(this, "distribution", {
|
|
939
1161
|
defaultBehavior: {
|
|
@@ -965,14 +1187,17 @@ _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ARN = "STATIC_HOSTING_DISTRIBUTION_AR
|
|
|
965
1187
|
var StaticHosting = _StaticHosting;
|
|
966
1188
|
|
|
967
1189
|
// src/services/open-hi-auth-service.ts
|
|
1190
|
+
var import_config4 = __toESM(require_lib());
|
|
968
1191
|
import {
|
|
969
1192
|
LambdaVersion,
|
|
970
1193
|
UserPool as UserPool2,
|
|
971
|
-
UserPoolClient as
|
|
1194
|
+
UserPoolClient as UserPoolClient3,
|
|
972
1195
|
UserPoolDomain as UserPoolDomain2,
|
|
973
1196
|
UserPoolOperation
|
|
974
1197
|
} from "aws-cdk-lib/aws-cognito";
|
|
1198
|
+
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
975
1199
|
import { Key as Key2 } from "aws-cdk-lib/aws-kms";
|
|
1200
|
+
import { Stack as Stack3 } from "aws-cdk-lib/core";
|
|
976
1201
|
var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
977
1202
|
/**
|
|
978
1203
|
* Returns an IUserPool by looking up the Auth stack's User Pool ID from SSM.
|
|
@@ -995,12 +1220,33 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
995
1220
|
serviceType: _OpenHiAuthService.SERVICE_TYPE
|
|
996
1221
|
}
|
|
997
1222
|
);
|
|
998
|
-
return
|
|
1223
|
+
return UserPoolClient3.fromUserPoolClientId(
|
|
999
1224
|
scope,
|
|
1000
1225
|
"user-pool-client",
|
|
1001
1226
|
userPoolClientId
|
|
1002
1227
|
);
|
|
1003
1228
|
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Returns the dedicated fixture-seeder IUserPoolClient by looking up
|
|
1231
|
+
* its ID from SSM. Only non-prod auth stacks publish this parameter
|
|
1232
|
+
* (per the conditional in {@link createFixtureSeederClient}); calling
|
|
1233
|
+
* this against a prod-deployed stack will fail at lookup time.
|
|
1234
|
+
*
|
|
1235
|
+
* Consumed by `OpenHiRestApiService` (in non-prod) so the authorizer
|
|
1236
|
+
* accepts tokens issued by this client, and by the seed-fixtures CLI
|
|
1237
|
+
* to drive USER_PASSWORD_AUTH against this client's ID.
|
|
1238
|
+
*/
|
|
1239
|
+
static fixtureSeederClientFromConstruct(scope) {
|
|
1240
|
+
const clientId = DiscoverableStringParameter.valueForLookupName(scope, {
|
|
1241
|
+
ssmParamName: CognitoFixtureSeederClient.SSM_PARAM_NAME,
|
|
1242
|
+
serviceType: _OpenHiAuthService.SERVICE_TYPE
|
|
1243
|
+
});
|
|
1244
|
+
return UserPoolClient3.fromUserPoolClientId(
|
|
1245
|
+
scope,
|
|
1246
|
+
"fixture-seeder-client",
|
|
1247
|
+
clientId
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1004
1250
|
/**
|
|
1005
1251
|
* Returns an IUserPoolDomain by looking up the Auth stack's User Pool Domain from SSM.
|
|
1006
1252
|
*/
|
|
@@ -1029,9 +1275,12 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
1029
1275
|
this.props = props;
|
|
1030
1276
|
this.userPoolKmsKey = this.createUserPoolKmsKey();
|
|
1031
1277
|
this.preTokenGenerationLambda = this.createPreTokenGenerationLambda();
|
|
1278
|
+
this.postAuthenticationLambda = this.createPostAuthenticationLambda();
|
|
1032
1279
|
this.userPool = this.createUserPool();
|
|
1280
|
+
this.grantPostAuthenticationPermissions();
|
|
1033
1281
|
this.userPoolClient = this.createUserPoolClient();
|
|
1034
1282
|
this.userPoolDomain = this.createUserPoolDomain();
|
|
1283
|
+
this.fixtureSeederClient = this.createFixtureSeederClient();
|
|
1035
1284
|
}
|
|
1036
1285
|
/**
|
|
1037
1286
|
* Creates the KMS key for the Cognito User Pool and exports its ARN to SSM.
|
|
@@ -1055,6 +1304,15 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
1055
1304
|
const construct = new PreTokenGenerationLambda(this);
|
|
1056
1305
|
return construct.lambda;
|
|
1057
1306
|
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Creates the Post Authentication Lambda (Cognito trigger). Calls
|
|
1309
|
+
* AdminUserGlobalSignOut on every sign-in to enforce single-device-per-user
|
|
1310
|
+
* sessions per ADR 2026-03-17-01.
|
|
1311
|
+
*/
|
|
1312
|
+
createPostAuthenticationLambda() {
|
|
1313
|
+
const construct = new PostAuthenticationLambda(this);
|
|
1314
|
+
return construct.lambda;
|
|
1315
|
+
}
|
|
1058
1316
|
/**
|
|
1059
1317
|
* Creates the Cognito User Pool and exports its ID to SSM.
|
|
1060
1318
|
* Look up via {@link OpenHiAuthService.userPoolFromConstruct}.
|
|
@@ -1070,6 +1328,10 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
1070
1328
|
this.preTokenGenerationLambda,
|
|
1071
1329
|
LambdaVersion.V2_0
|
|
1072
1330
|
);
|
|
1331
|
+
userPool.addTrigger(
|
|
1332
|
+
UserPoolOperation.POST_AUTHENTICATION,
|
|
1333
|
+
this.postAuthenticationLambda
|
|
1334
|
+
);
|
|
1073
1335
|
new DiscoverableStringParameter(this, "user-pool-param", {
|
|
1074
1336
|
ssmParamName: CognitoUserPool.SSM_PARAM_NAME,
|
|
1075
1337
|
stringValue: userPool.userPoolId,
|
|
@@ -1077,6 +1339,33 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
1077
1339
|
});
|
|
1078
1340
|
return userPool;
|
|
1079
1341
|
}
|
|
1342
|
+
/**
|
|
1343
|
+
* Grants the Post Authentication Lambda permission to call
|
|
1344
|
+
* `cognito-idp:AdminUserGlobalSignOut`.
|
|
1345
|
+
*
|
|
1346
|
+
* Scoped via `Stack.of(this).formatArn` rather than `userPool.userPoolArn`
|
|
1347
|
+
* because the User Pool registers this Lambda as a Post Authentication
|
|
1348
|
+
* trigger, creating the cycle:
|
|
1349
|
+
* userPool → lambda (trigger ARN) → role policy → userPool ARN.
|
|
1350
|
+
* Using `formatArn` avoids referencing the User Pool resource directly
|
|
1351
|
+
* while still scoping to user pools in this account+region. The Lambda
|
|
1352
|
+
* is invoked only by Cognito with a Cognito-provided `event.userPoolId`,
|
|
1353
|
+
* so the runtime target is constrained by the trigger contract.
|
|
1354
|
+
*/
|
|
1355
|
+
grantPostAuthenticationPermissions() {
|
|
1356
|
+
this.postAuthenticationLambda.addToRolePolicy(
|
|
1357
|
+
new PolicyStatement({
|
|
1358
|
+
actions: ["cognito-idp:AdminUserGlobalSignOut"],
|
|
1359
|
+
resources: [
|
|
1360
|
+
Stack3.of(this).formatArn({
|
|
1361
|
+
service: "cognito-idp",
|
|
1362
|
+
resource: "userpool",
|
|
1363
|
+
resourceName: "*"
|
|
1364
|
+
})
|
|
1365
|
+
]
|
|
1366
|
+
})
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1080
1369
|
/**
|
|
1081
1370
|
* Creates the User Pool Client and exports its ID to SSM (AUTH service type).
|
|
1082
1371
|
* Look up via {@link OpenHiAuthService.userPoolClientFromConstruct}.
|
|
@@ -1093,6 +1382,31 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
|
|
|
1093
1382
|
});
|
|
1094
1383
|
return client;
|
|
1095
1384
|
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Creates the dedicated USER_PASSWORD_AUTH app client for the
|
|
1387
|
+
* `@openhi/seed-fixtures` CLI, **only** in non-prod environments.
|
|
1388
|
+
* Returns `undefined` when this stack is being deployed to a prod
|
|
1389
|
+
* stage so the prod auth stack carries no fixture-seeder code path.
|
|
1390
|
+
*
|
|
1391
|
+
* Operator post-deploy: create a `fixture-seeder` Cognito user with
|
|
1392
|
+
* a service password (manually via console or scripted with
|
|
1393
|
+
* `aws cognito-idp admin-create-user`); the CLI consumes those creds
|
|
1394
|
+
* via env vars to drive `InitiateAuth`.
|
|
1395
|
+
*/
|
|
1396
|
+
createFixtureSeederClient() {
|
|
1397
|
+
if (this.ohEnv.ohStage.stageType === import_config4.OPEN_HI_STAGE.PROD) {
|
|
1398
|
+
return void 0;
|
|
1399
|
+
}
|
|
1400
|
+
const client = new CognitoFixtureSeederClient(this, {
|
|
1401
|
+
userPool: this.userPool
|
|
1402
|
+
});
|
|
1403
|
+
new DiscoverableStringParameter(this, "fixture-seeder-client-param", {
|
|
1404
|
+
ssmParamName: CognitoFixtureSeederClient.SSM_PARAM_NAME,
|
|
1405
|
+
stringValue: client.userPoolClientId,
|
|
1406
|
+
description: "Cognito User Pool Client ID for the OpenHI fixture-seeder CLI (USER_PASSWORD_AUTH; non-prod only); cross-stack reference"
|
|
1407
|
+
});
|
|
1408
|
+
return client;
|
|
1409
|
+
}
|
|
1096
1410
|
/**
|
|
1097
1411
|
* Creates the User Pool Domain (Cognito hosted UI) and exports domain name to SSM.
|
|
1098
1412
|
* Look up via {@link OpenHiAuthService.userPoolDomainFromConstruct}.
|
|
@@ -1224,6 +1538,7 @@ _OpenHiGlobalService.SERVICE_TYPE = "global";
|
|
|
1224
1538
|
var OpenHiGlobalService = _OpenHiGlobalService;
|
|
1225
1539
|
|
|
1226
1540
|
// src/services/open-hi-rest-api-service.ts
|
|
1541
|
+
var import_config5 = __toESM(require_lib());
|
|
1227
1542
|
import {
|
|
1228
1543
|
CorsHttpMethod,
|
|
1229
1544
|
DomainName,
|
|
@@ -1235,14 +1550,14 @@ import {
|
|
|
1235
1550
|
} from "aws-cdk-lib/aws-apigatewayv2";
|
|
1236
1551
|
import { HttpUserPoolAuthorizer } from "aws-cdk-lib/aws-apigatewayv2-authorizers";
|
|
1237
1552
|
import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
|
|
1238
|
-
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
1553
|
+
import { Effect, PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
|
|
1239
1554
|
import {
|
|
1240
1555
|
ARecord,
|
|
1241
1556
|
HostedZone as HostedZone3,
|
|
1242
1557
|
RecordTarget
|
|
1243
1558
|
} from "aws-cdk-lib/aws-route53";
|
|
1244
1559
|
import { ApiGatewayv2DomainProperties } from "aws-cdk-lib/aws-route53-targets";
|
|
1245
|
-
import { Duration as
|
|
1560
|
+
import { Duration as Duration6 } from "aws-cdk-lib/core";
|
|
1246
1561
|
|
|
1247
1562
|
// src/services/open-hi-data-service.ts
|
|
1248
1563
|
import { StreamViewType, Table as Table2 } from "aws-cdk-lib/aws-dynamodb";
|
|
@@ -1288,7 +1603,11 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
|
|
|
1288
1603
|
"data-store-change-stream",
|
|
1289
1604
|
{
|
|
1290
1605
|
streamName: `openhi-dstore-cdc-${this.branchHash}`,
|
|
1291
|
-
streamMode: kinesis.StreamMode.ON_DEMAND
|
|
1606
|
+
streamMode: kinesis.StreamMode.ON_DEMAND,
|
|
1607
|
+
// CDK default for kinesis.Stream is RETAIN, which strands the stream
|
|
1608
|
+
// when a non-prod stack is destroyed. Use the service's policy so
|
|
1609
|
+
// non-prod tears down cleanly while prod retains.
|
|
1610
|
+
removalPolicy: this.removalPolicy
|
|
1292
1611
|
}
|
|
1293
1612
|
);
|
|
1294
1613
|
this.dataStore = this.createDataStore();
|
|
@@ -1302,6 +1621,16 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
|
|
|
1302
1621
|
dataEventBus: this.dataEventBus
|
|
1303
1622
|
}
|
|
1304
1623
|
);
|
|
1624
|
+
this.dataStorePostgresReplica = new DataStorePostgresReplica(
|
|
1625
|
+
this,
|
|
1626
|
+
"data-store-postgres-replica",
|
|
1627
|
+
{
|
|
1628
|
+
kinesisStream: this.dataStoreChangeStream,
|
|
1629
|
+
removalPolicy: this.removalPolicy,
|
|
1630
|
+
stackHash: this.stackHash,
|
|
1631
|
+
branchHash: this.branchHash
|
|
1632
|
+
}
|
|
1633
|
+
);
|
|
1305
1634
|
}
|
|
1306
1635
|
/**
|
|
1307
1636
|
* Creates the data event bus.
|
|
@@ -1332,57 +1661,61 @@ _OpenHiDataService.SERVICE_TYPE = "data";
|
|
|
1332
1661
|
var OpenHiDataService = _OpenHiDataService;
|
|
1333
1662
|
|
|
1334
1663
|
// src/data/lambda/cors-options-lambda.ts
|
|
1335
|
-
import
|
|
1336
|
-
import
|
|
1337
|
-
import { Runtime as
|
|
1338
|
-
import { NodejsFunction as
|
|
1339
|
-
import { Construct as
|
|
1340
|
-
var
|
|
1341
|
-
function
|
|
1342
|
-
const sameDir =
|
|
1343
|
-
if (
|
|
1664
|
+
import fs5 from "fs";
|
|
1665
|
+
import path5 from "path";
|
|
1666
|
+
import { Runtime as Runtime5 } from "aws-cdk-lib/aws-lambda";
|
|
1667
|
+
import { NodejsFunction as NodejsFunction5 } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
1668
|
+
import { Construct as Construct7 } from "constructs";
|
|
1669
|
+
var HANDLER_NAME5 = "cors-options-lambda.handler.js";
|
|
1670
|
+
function resolveHandlerEntry5(dirname) {
|
|
1671
|
+
const sameDir = path5.join(dirname, HANDLER_NAME5);
|
|
1672
|
+
if (fs5.existsSync(sameDir)) {
|
|
1344
1673
|
return sameDir;
|
|
1345
1674
|
}
|
|
1346
|
-
const fromLib =
|
|
1675
|
+
const fromLib = path5.join(dirname, "..", "..", "..", "lib", HANDLER_NAME5);
|
|
1347
1676
|
return fromLib;
|
|
1348
1677
|
}
|
|
1349
|
-
var CorsOptionsLambda = class extends
|
|
1678
|
+
var CorsOptionsLambda = class extends Construct7 {
|
|
1350
1679
|
constructor(scope, id = "cors-options-lambda") {
|
|
1351
1680
|
super(scope, id);
|
|
1352
|
-
this.lambda = new
|
|
1353
|
-
entry:
|
|
1354
|
-
runtime:
|
|
1681
|
+
this.lambda = new NodejsFunction5(this, "handler", {
|
|
1682
|
+
entry: resolveHandlerEntry5(__dirname),
|
|
1683
|
+
runtime: Runtime5.NODEJS_LATEST,
|
|
1355
1684
|
memorySize: 128
|
|
1356
1685
|
});
|
|
1357
1686
|
}
|
|
1358
1687
|
};
|
|
1359
1688
|
|
|
1360
1689
|
// src/data/lambda/rest-api-lambda.ts
|
|
1361
|
-
import
|
|
1362
|
-
import
|
|
1363
|
-
import { Runtime as
|
|
1364
|
-
import { NodejsFunction as
|
|
1365
|
-
import { Construct as
|
|
1366
|
-
var
|
|
1367
|
-
function
|
|
1368
|
-
const sameDir =
|
|
1369
|
-
if (
|
|
1690
|
+
import fs6 from "fs";
|
|
1691
|
+
import path6 from "path";
|
|
1692
|
+
import { Runtime as Runtime6 } from "aws-cdk-lib/aws-lambda";
|
|
1693
|
+
import { NodejsFunction as NodejsFunction6 } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
1694
|
+
import { Construct as Construct8 } from "constructs";
|
|
1695
|
+
var HANDLER_NAME6 = "rest-api-lambda.handler.js";
|
|
1696
|
+
function resolveHandlerEntry6(dirname) {
|
|
1697
|
+
const sameDir = path6.join(dirname, HANDLER_NAME6);
|
|
1698
|
+
if (fs6.existsSync(sameDir)) {
|
|
1370
1699
|
return sameDir;
|
|
1371
1700
|
}
|
|
1372
|
-
const fromLib =
|
|
1701
|
+
const fromLib = path6.join(dirname, "..", "..", "..", "lib", HANDLER_NAME6);
|
|
1373
1702
|
return fromLib;
|
|
1374
1703
|
}
|
|
1375
|
-
var RestApiLambda = class extends
|
|
1704
|
+
var RestApiLambda = class extends Construct8 {
|
|
1376
1705
|
constructor(scope, props) {
|
|
1377
1706
|
super(scope, "rest-api-lambda");
|
|
1378
|
-
this.lambda = new
|
|
1379
|
-
entry:
|
|
1380
|
-
runtime:
|
|
1707
|
+
this.lambda = new NodejsFunction6(this, "handler", {
|
|
1708
|
+
entry: resolveHandlerEntry6(__dirname),
|
|
1709
|
+
runtime: Runtime6.NODEJS_LATEST,
|
|
1381
1710
|
memorySize: 1024,
|
|
1382
1711
|
environment: {
|
|
1383
1712
|
DYNAMO_TABLE_NAME: props.dynamoTableName,
|
|
1384
1713
|
BRANCH_TAG_VALUE: props.branchTagValue,
|
|
1385
|
-
HTTP_API_TAG_VALUE: props.httpApiTagValue
|
|
1714
|
+
HTTP_API_TAG_VALUE: props.httpApiTagValue,
|
|
1715
|
+
OPENHI_PG_CLUSTER_ARN: props.postgresClusterArn,
|
|
1716
|
+
OPENHI_PG_SECRET_ARN: props.postgresSecretArn,
|
|
1717
|
+
OPENHI_PG_DATABASE: props.postgresDatabase,
|
|
1718
|
+
OPENHI_PG_SCHEMA: props.postgresSchema
|
|
1386
1719
|
},
|
|
1387
1720
|
bundling: {
|
|
1388
1721
|
minify: true,
|
|
@@ -1501,11 +1834,36 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
|
|
|
1501
1834
|
*/
|
|
1502
1835
|
createRestApiLambdaAndRoutes(hostedZone, domainName) {
|
|
1503
1836
|
const dataStoreTable = OpenHiDataService.dynamoDbDataStoreFromConstruct(this);
|
|
1837
|
+
const postgresClusterArn = DataStorePostgresReplica.clusterArnFromConstruct(this);
|
|
1838
|
+
const postgresSecretArn = DataStorePostgresReplica.secretArnFromConstruct(this);
|
|
1839
|
+
const postgresDatabase = DataStorePostgresReplica.databaseNameFromConstruct(this);
|
|
1840
|
+
const postgresSchema = getPostgresReplicaSchemaName(this.branchHash);
|
|
1504
1841
|
const { lambda } = new RestApiLambda(this, {
|
|
1505
1842
|
dynamoTableName: dataStoreTable.tableName,
|
|
1506
1843
|
branchTagValue: this.branchName,
|
|
1507
|
-
httpApiTagValue: RootHttpApi.SSM_PARAM_NAME
|
|
1844
|
+
httpApiTagValue: RootHttpApi.SSM_PARAM_NAME,
|
|
1845
|
+
postgresClusterArn,
|
|
1846
|
+
postgresSecretArn,
|
|
1847
|
+
postgresDatabase,
|
|
1848
|
+
postgresSchema
|
|
1508
1849
|
});
|
|
1850
|
+
lambda.addToRolePolicy(
|
|
1851
|
+
new PolicyStatement2({
|
|
1852
|
+
effect: Effect.ALLOW,
|
|
1853
|
+
actions: [
|
|
1854
|
+
"rds-data:ExecuteStatement",
|
|
1855
|
+
"rds-data:BatchExecuteStatement"
|
|
1856
|
+
],
|
|
1857
|
+
resources: [postgresClusterArn]
|
|
1858
|
+
})
|
|
1859
|
+
);
|
|
1860
|
+
lambda.addToRolePolicy(
|
|
1861
|
+
new PolicyStatement2({
|
|
1862
|
+
effect: Effect.ALLOW,
|
|
1863
|
+
actions: ["secretsmanager:GetSecretValue"],
|
|
1864
|
+
resources: [postgresSecretArn]
|
|
1865
|
+
})
|
|
1866
|
+
);
|
|
1509
1867
|
const dynamoActions = [
|
|
1510
1868
|
"dynamodb:GetItem",
|
|
1511
1869
|
"dynamodb:Query",
|
|
@@ -1519,14 +1877,14 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
|
|
|
1519
1877
|
];
|
|
1520
1878
|
dataStoreTable.grant(lambda, ...dynamoActions);
|
|
1521
1879
|
lambda.addToRolePolicy(
|
|
1522
|
-
new
|
|
1880
|
+
new PolicyStatement2({
|
|
1523
1881
|
effect: Effect.ALLOW,
|
|
1524
1882
|
actions: [...dynamoActions],
|
|
1525
1883
|
resources: [`${dataStoreTable.tableArn}/index/*`]
|
|
1526
1884
|
})
|
|
1527
1885
|
);
|
|
1528
1886
|
lambda.addToRolePolicy(
|
|
1529
|
-
new
|
|
1887
|
+
new PolicyStatement2({
|
|
1530
1888
|
effect: Effect.ALLOW,
|
|
1531
1889
|
actions: [
|
|
1532
1890
|
"ssm:GetParameter",
|
|
@@ -1585,10 +1943,16 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
|
|
|
1585
1943
|
createRootHttpApi(domainName) {
|
|
1586
1944
|
const userPool = OpenHiAuthService.userPoolFromConstruct(this);
|
|
1587
1945
|
const userPoolClient = OpenHiAuthService.userPoolClientFromConstruct(this);
|
|
1946
|
+
const userPoolClients = [userPoolClient];
|
|
1947
|
+
if (this.ohEnv.ohStage.stageType !== import_config5.OPEN_HI_STAGE.PROD) {
|
|
1948
|
+
userPoolClients.push(
|
|
1949
|
+
OpenHiAuthService.fixtureSeederClientFromConstruct(this)
|
|
1950
|
+
);
|
|
1951
|
+
}
|
|
1588
1952
|
const cognitoAuthorizer = new HttpUserPoolAuthorizer(
|
|
1589
1953
|
"cognito-authorizer",
|
|
1590
1954
|
userPool,
|
|
1591
|
-
{ userPoolClients
|
|
1955
|
+
{ userPoolClients }
|
|
1592
1956
|
);
|
|
1593
1957
|
const { corsPreflight: cors, ...restRootHttpApiProps } = this.props.rootHttpApiProps ?? {};
|
|
1594
1958
|
const corsPreflight = cors !== void 0 ? {
|
|
@@ -1607,7 +1971,7 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
|
|
|
1607
1971
|
"Authorization"
|
|
1608
1972
|
],
|
|
1609
1973
|
allowCredentials: cors.allowCredentials ?? true,
|
|
1610
|
-
maxAge: cors.maxAge ??
|
|
1974
|
+
maxAge: cors.maxAge ?? Duration6.days(1),
|
|
1611
1975
|
...cors.exposeHeaders !== void 0 && {
|
|
1612
1976
|
exposeHeaders: cors.exposeHeaders
|
|
1613
1977
|
}
|
|
@@ -1673,6 +2037,7 @@ _OpenHiGraphqlService.SERVICE_TYPE = "graphql-api";
|
|
|
1673
2037
|
var OpenHiGraphqlService = _OpenHiGraphqlService;
|
|
1674
2038
|
export {
|
|
1675
2039
|
ChildHostedZone,
|
|
2040
|
+
CognitoFixtureSeederClient,
|
|
1676
2041
|
CognitoUserPool,
|
|
1677
2042
|
CognitoUserPoolClient,
|
|
1678
2043
|
CognitoUserPoolDomain,
|
|
@@ -1682,6 +2047,7 @@ export {
|
|
|
1682
2047
|
DATA_STORE_CHANGE_EVENT_SOURCE,
|
|
1683
2048
|
DataEventBus,
|
|
1684
2049
|
DataStoreHistoricalArchive,
|
|
2050
|
+
DataStorePostgresReplica,
|
|
1685
2051
|
DiscoverableStringParameter,
|
|
1686
2052
|
DynamoDbDataStore,
|
|
1687
2053
|
OpenHiApp,
|
|
@@ -1694,6 +2060,10 @@ export {
|
|
|
1694
2060
|
OpenHiService,
|
|
1695
2061
|
OpenHiStage,
|
|
1696
2062
|
OpsEventBus,
|
|
2063
|
+
POSTGRES_REPLICA_CLUSTER_ARN_SSM_NAME,
|
|
2064
|
+
POSTGRES_REPLICA_DATABASE_NAME_SSM_NAME,
|
|
2065
|
+
POSTGRES_REPLICA_SECRET_ARN_SSM_NAME,
|
|
2066
|
+
PostAuthenticationLambda,
|
|
1697
2067
|
PreTokenGenerationLambda,
|
|
1698
2068
|
REST_API_BASE_URL_SSM_NAME,
|
|
1699
2069
|
RootGraphqlApi,
|
|
@@ -1703,6 +2073,7 @@ export {
|
|
|
1703
2073
|
STATIC_HOSTING_SERVICE_TYPE,
|
|
1704
2074
|
StaticHosting,
|
|
1705
2075
|
buildFhirCurrentResourceChangeDetail,
|
|
1706
|
-
getDynamoDbDataStoreTableName
|
|
2076
|
+
getDynamoDbDataStoreTableName,
|
|
2077
|
+
getPostgresReplicaSchemaName
|
|
1707
2078
|
};
|
|
1708
2079
|
//# sourceMappingURL=index.mjs.map
|