@openhi/constructs 0.0.77 → 0.0.79

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/index.js CHANGED
@@ -98,6 +98,9 @@ __export(src_exports, {
98
98
  CognitoUserPoolClient: () => CognitoUserPoolClient,
99
99
  CognitoUserPoolDomain: () => CognitoUserPoolDomain,
100
100
  CognitoUserPoolKmsKey: () => CognitoUserPoolKmsKey,
101
+ DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES: () => DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES,
102
+ DATA_STORE_CHANGE_DETAIL_TYPE: () => DATA_STORE_CHANGE_DETAIL_TYPE,
103
+ DATA_STORE_CHANGE_EVENT_SOURCE: () => DATA_STORE_CHANGE_EVENT_SOURCE,
101
104
  DataEventBus: () => DataEventBus,
102
105
  DataStoreHistoricalArchive: () => DataStoreHistoricalArchive,
103
106
  DiscoverableStringParameter: () => DiscoverableStringParameter,
@@ -120,6 +123,7 @@ __export(src_exports, {
120
123
  RootWildcardCertificate: () => RootWildcardCertificate,
121
124
  STATIC_HOSTING_SERVICE_TYPE: () => STATIC_HOSTING_SERVICE_TYPE,
122
125
  StaticHosting: () => StaticHosting,
126
+ buildFhirCurrentResourceChangeDetail: () => buildFhirCurrentResourceChangeDetail,
123
127
  getDynamoDbDataStoreTableName: () => getDynamoDbDataStoreTableName
124
128
  });
125
129
  module.exports = __toCommonJS(src_exports);
@@ -696,6 +700,131 @@ var PreTokenGenerationLambda = class extends import_constructs.Construct {
696
700
  }
697
701
  };
698
702
 
703
+ // src/components/dynamodb/dynamodb-stream-record.ts
704
+ function dynamodbValueToJs(av) {
705
+ if (av.S !== void 0) {
706
+ return av.S;
707
+ }
708
+ if (av.N !== void 0) {
709
+ return av.N.includes(".") ? Number.parseFloat(av.N) : Number.parseInt(av.N, 10);
710
+ }
711
+ if (av.BOOL !== void 0) {
712
+ return av.BOOL;
713
+ }
714
+ if (av.NULL !== void 0) {
715
+ return null;
716
+ }
717
+ if (av.M !== void 0) {
718
+ return dynamodbImageToPlain(av.M);
719
+ }
720
+ if (av.L !== void 0) {
721
+ return av.L.map((x) => dynamodbValueToJs(x));
722
+ }
723
+ if (av.SS !== void 0) {
724
+ return av.SS;
725
+ }
726
+ if (av.NS !== void 0) {
727
+ return av.NS.map(
728
+ (n) => n.includes(".") ? Number.parseFloat(n) : Number.parseInt(n, 10)
729
+ );
730
+ }
731
+ return void 0;
732
+ }
733
+ function dynamodbImageToPlain(image) {
734
+ const out = {};
735
+ for (const [k, v] of Object.entries(image)) {
736
+ out[k] = dynamodbValueToJs(v);
737
+ }
738
+ return out;
739
+ }
740
+
741
+ // src/components/dynamodb/data-store-change-events.ts
742
+ var DATA_STORE_CHANGE_EVENT_SOURCE = "openhi.data.store";
743
+ var DATA_STORE_CHANGE_DETAIL_TYPE = "FhirCurrentResourceChanged";
744
+ var DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES = 250 * 1024;
745
+ var EXCLUDED_CHANGE_DETAIL_KEYS = /* @__PURE__ */ new Set([
746
+ "PK",
747
+ "SK",
748
+ "GSI1PK",
749
+ "GSI1SK",
750
+ "GSI2PK",
751
+ "GSI2SK",
752
+ "GSI3PK",
753
+ "GSI3SK",
754
+ "GSI4PK",
755
+ "GSI4SK",
756
+ /** Full FHIR JSON may contain PII; never list or ship in the bus payload. */
757
+ "resource"
758
+ ]);
759
+ function shallowValueEqual(a, b) {
760
+ return JSON.stringify(a) === JSON.stringify(b);
761
+ }
762
+ function changedNonResourceAttributeNames(oldImage, newImage) {
763
+ if (!oldImage || !newImage) {
764
+ return void 0;
765
+ }
766
+ const names = /* @__PURE__ */ new Set();
767
+ const keys = /* @__PURE__ */ new Set([...Object.keys(oldImage), ...Object.keys(newImage)]);
768
+ for (const k of keys) {
769
+ if (EXCLUDED_CHANGE_DETAIL_KEYS.has(k)) {
770
+ continue;
771
+ }
772
+ if (!shallowValueEqual(oldImage[k], newImage[k])) {
773
+ names.add(k);
774
+ }
775
+ }
776
+ return names.size > 0 ? [...names].sort() : void 0;
777
+ }
778
+ function presentMetadataAttributeNames(image) {
779
+ if (!image) {
780
+ return void 0;
781
+ }
782
+ const names = Object.keys(image).filter(
783
+ (k) => !EXCLUDED_CHANGE_DETAIL_KEYS.has(k)
784
+ );
785
+ return names.length > 0 ? names.sort() : void 0;
786
+ }
787
+ function plainImage(image) {
788
+ if (!image) {
789
+ return void 0;
790
+ }
791
+ return dynamodbImageToPlain(image);
792
+ }
793
+ function buildFhirCurrentResourceChangeDetail(record, keys) {
794
+ const rawName = record.eventName;
795
+ const changeType = rawName === "INSERT" || rawName === "MODIFY" || rawName === "REMOVE" ? rawName : "MODIFY";
796
+ const seq = record.dynamodb?.SequenceNumber;
797
+ const approxEpochSec = record.dynamodb?.ApproximateCreationDateTime;
798
+ const newPlain = plainImage(
799
+ record.dynamodb?.NewImage
800
+ );
801
+ const oldPlain = plainImage(
802
+ record.dynamodb?.OldImage
803
+ );
804
+ let changedAttributeNames;
805
+ if (changeType === "MODIFY") {
806
+ changedAttributeNames = changedNonResourceAttributeNames(
807
+ oldPlain,
808
+ newPlain
809
+ );
810
+ } else if (changeType === "INSERT") {
811
+ changedAttributeNames = presentMetadataAttributeNames(newPlain);
812
+ } else {
813
+ changedAttributeNames = presentMetadataAttributeNames(oldPlain);
814
+ }
815
+ return {
816
+ changeType,
817
+ tenantId: keys.tenantId,
818
+ workspaceId: keys.workspaceId,
819
+ resourceType: keys.resourceType,
820
+ resourceId: keys.resourceId,
821
+ resourceVersion: keys.version,
822
+ ...typeof seq === "string" && seq.length > 0 ? { streamSequenceNumber: seq } : {},
823
+ ...typeof approxEpochSec === "number" && Number.isFinite(approxEpochSec) ? { approximateCreationEpochSec: approxEpochSec } : {},
824
+ ...changedAttributeNames ? { changedAttributeNames } : {}
825
+ };
826
+ }
827
+
699
828
  // src/components/dynamodb/data-store-historical-archive.ts
700
829
  var import_node_fs2 = __toESM(require("fs"));
701
830
  var import_node_path2 = __toESM(require("path"));
@@ -724,17 +853,32 @@ var DataStoreHistoricalArchive = class extends import_constructs2.Construct {
724
853
  autoDeleteObjects: props.removalPolicy === import_aws_cdk_lib6.RemovalPolicy.DESTROY,
725
854
  versioned: true
726
855
  });
856
+ const putEventsFailureDlqBucket = props.dataEventBus ? new s3.Bucket(this, "PutEventsFailureDlq", {
857
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
858
+ encryption: s3.BucketEncryption.S3_MANAGED,
859
+ enforceSSL: true,
860
+ removalPolicy: props.removalPolicy,
861
+ autoDeleteObjects: props.removalPolicy === import_aws_cdk_lib6.RemovalPolicy.DESTROY,
862
+ versioned: false
863
+ }) : void 0;
864
+ this.putEventsFailureDlqBucket = putEventsFailureDlqBucket;
727
865
  this.transformFunction = new import_aws_lambda_nodejs2.NodejsFunction(this, "FirehoseTransform", {
728
866
  entry: resolveHandlerEntry2(__dirname),
729
867
  runtime: import_aws_lambda2.Runtime.NODEJS_LATEST,
730
868
  memorySize: 512,
731
869
  timeout: import_aws_cdk_lib6.Duration.minutes(1),
732
- description: "Firehose transform: filter CURRENT resource rows, S3 dynamic partition keys",
870
+ description: "Firehose transform: filter CURRENT resource rows, S3 keys, EventBridge PutEvents",
871
+ environment: props.dataEventBus && putEventsFailureDlqBucket ? {
872
+ DATA_EVENT_BUS_NAME: props.dataEventBus.eventBusName,
873
+ DATA_STORE_PUT_EVENTS_DLQ_BUCKET: putEventsFailureDlqBucket.bucketName
874
+ } : void 0,
733
875
  bundling: {
734
876
  minify: true,
735
877
  sourceMap: false
736
878
  }
737
879
  });
880
+ props.dataEventBus?.grantPutEventsTo(this.transformFunction);
881
+ putEventsFailureDlqBucket?.grantPut(this.transformFunction);
738
882
  const processor = new kinesisfirehose.LambdaFunctionProcessor(
739
883
  this.transformFunction,
740
884
  {
@@ -1290,7 +1434,8 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1290
1434
  {
1291
1435
  kinesisStream: this.dataStoreChangeStream,
1292
1436
  removalPolicy: this.removalPolicy,
1293
- stackHash: this.stackHash
1437
+ stackHash: this.stackHash,
1438
+ dataEventBus: this.dataEventBus
1294
1439
  }
1295
1440
  );
1296
1441
  }
@@ -1666,6 +1811,9 @@ var OpenHiGraphqlService = _OpenHiGraphqlService;
1666
1811
  CognitoUserPoolClient,
1667
1812
  CognitoUserPoolDomain,
1668
1813
  CognitoUserPoolKmsKey,
1814
+ DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES,
1815
+ DATA_STORE_CHANGE_DETAIL_TYPE,
1816
+ DATA_STORE_CHANGE_EVENT_SOURCE,
1669
1817
  DataEventBus,
1670
1818
  DataStoreHistoricalArchive,
1671
1819
  DiscoverableStringParameter,
@@ -1688,6 +1836,7 @@ var OpenHiGraphqlService = _OpenHiGraphqlService;
1688
1836
  RootWildcardCertificate,
1689
1837
  STATIC_HOSTING_SERVICE_TYPE,
1690
1838
  StaticHosting,
1839
+ buildFhirCurrentResourceChangeDetail,
1691
1840
  getDynamoDbDataStoreTableName
1692
1841
  });
1693
1842
  //# sourceMappingURL=index.js.map