@openhi/constructs 0.0.69 → 0.0.71

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.d.ts CHANGED
@@ -6,12 +6,15 @@ import { IGraphqlApi, GraphqlApi, GraphqlApiProps } from 'aws-cdk-lib/aws-appsyn
6
6
  import { UserPool, UserPoolProps, UserPoolClient, UserPoolClientProps, UserPoolDomain, UserPoolDomainProps, IUserPool, IUserPoolClient, IUserPoolDomain } from 'aws-cdk-lib/aws-cognito';
7
7
  import { Key, KeyProps, IKey } from 'aws-cdk-lib/aws-kms';
8
8
  import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
9
+ import * as kinesis from 'aws-cdk-lib/aws-kinesis';
10
+ import * as kinesisfirehose from 'aws-cdk-lib/aws-kinesisfirehose';
11
+ import * as s3 from 'aws-cdk-lib/aws-s3';
12
+ import { IBucket, BucketProps } from 'aws-cdk-lib/aws-s3';
9
13
  import { Table, TableProps, ITable } from 'aws-cdk-lib/aws-dynamodb';
10
14
  import { EventBus, EventBusProps, IEventBus } from 'aws-cdk-lib/aws-events';
11
15
  import { HostedZone, HostedZoneProps, IHostedZone, HostedZoneAttributes } from 'aws-cdk-lib/aws-route53';
12
16
  import { StringParameterProps, StringParameter } from 'aws-cdk-lib/aws-ssm';
13
17
  import { Distribution, DistributionProps } from 'aws-cdk-lib/aws-cloudfront';
14
- import { IBucket, BucketProps } from 'aws-cdk-lib/aws-s3';
15
18
  import { IFunction } from 'aws-cdk-lib/aws-lambda';
16
19
 
17
20
  /*******************************************************************************
@@ -513,6 +516,31 @@ declare class PreTokenGenerationLambda extends Construct {
513
516
  constructor(scope: Construct);
514
517
  }
515
518
 
519
+ interface DataStoreHistoricalArchiveProps {
520
+ /**
521
+ * Kinesis stream that receives DynamoDB item-level changes (table Kinesis destination).
522
+ */
523
+ readonly kinesisStream: kinesis.IStream;
524
+ /**
525
+ * Removal policy for the archive bucket and related resources.
526
+ */
527
+ readonly removalPolicy: RemovalPolicy;
528
+ /**
529
+ * Short hash for unique stream/bucket naming within the deployment.
530
+ */
531
+ readonly stackHash: string;
532
+ }
533
+ /**
534
+ * DynamoDB change stream → Kinesis → Firehose → S3 with a transform Lambda for
535
+ * scope filtering and dynamic partitioning (ADR 2026-03-11-02).
536
+ */
537
+ declare class DataStoreHistoricalArchive extends Construct {
538
+ readonly archiveBucket: s3.Bucket;
539
+ readonly deliveryStream: kinesisfirehose.IDeliveryStream;
540
+ readonly transformFunction: NodejsFunction;
541
+ constructor(scope: Construct, id: string, props: DataStoreHistoricalArchiveProps);
542
+ }
543
+
516
544
  /**
517
545
  * @see sites/www-docs/content/packages/@openhi/constructs/components/dynamodb/dynamo-db-data-store.md
518
546
  */
@@ -536,6 +564,9 @@ interface DynamoDbDataStoreProps extends Omit<TableProps, "tableName" | "removal
536
564
  *
537
565
  * Primary key: PK (String), SK (String).
538
566
  * GSIs: GSI1 (reverse reference), GSI2 (identifier lookup), GSI3 (facility ops), GSI4 (resource type list).
567
+ *
568
+ * For historical archive to S3, pass `kinesisStream` and `stream` (e.g.
569
+ * `StreamViewType.NEW_AND_OLD_IMAGES`) on the table props per ADR 2026-03-11-02.
539
570
  */
540
571
  declare class DynamoDbDataStore extends Table {
541
572
  constructor(scope: Construct, id: string, props?: DynamoDbDataStoreProps);
@@ -976,6 +1007,14 @@ declare class OpenHiDataService extends OpenHiService {
976
1007
  * from other stacks to obtain an ITable reference by name.
977
1008
  */
978
1009
  readonly dataStore: ITable;
1010
+ /**
1011
+ * Kinesis stream receiving DynamoDB item-level changes for the data store table.
1012
+ */
1013
+ readonly dataStoreChangeStream: kinesis.IStream;
1014
+ /**
1015
+ * S3 historical archive pipeline (Kinesis → Firehose → S3) per ADR 2026-03-11-02.
1016
+ */
1017
+ readonly dataStoreHistoricalArchive: DataStoreHistoricalArchive;
979
1018
  constructor(ohEnv: OpenHiEnvironment, props?: OpenHiDataServiceProps);
980
1019
  /**
981
1020
  * Creates the data event bus.
@@ -1016,5 +1055,5 @@ declare class OpenHiGraphqlService extends OpenHiService {
1016
1055
  protected createRootGraphqlApi(): RootGraphqlApi;
1017
1056
  }
1018
1057
 
1019
- export { ChildHostedZone, CognitoUserPool, CognitoUserPoolClient, CognitoUserPoolDomain, CognitoUserPoolKmsKey, DataEventBus, DiscoverableStringParameter, DynamoDbDataStore, OpenHiApp, OpenHiAuthService, OpenHiDataService, OpenHiEnvironment, OpenHiGlobalService, OpenHiGraphqlService, OpenHiRestApiService, OpenHiService, OpenHiStage, OpsEventBus, PreTokenGenerationLambda, REST_API_BASE_URL_SSM_NAME, RootGraphqlApi, RootHostedZone, RootHttpApi, RootWildcardCertificate, STATIC_HOSTING_SERVICE_TYPE, StaticHosting, getDynamoDbDataStoreTableName };
1020
- export type { BuildParameterNameProps, ChildHostedZoneProps, DiscoverableStringParameterProps, DynamoDbDataStoreProps, OpenHiAppProps, OpenHiAuthServiceProps, OpenHiDataServiceProps, OpenHiEnvironmentProps, OpenHiGlobalServiceProps, OpenHiGraphqlServiceProps, OpenHiRestApiServiceProps, OpenHiServiceProps, OpenHiServiceType, OpenHiStageProps, RootGraphqlApiProps, RootHttpApiProps, StaticHostingProps };
1058
+ export { ChildHostedZone, CognitoUserPool, CognitoUserPoolClient, CognitoUserPoolDomain, CognitoUserPoolKmsKey, DataEventBus, DataStoreHistoricalArchive, DiscoverableStringParameter, DynamoDbDataStore, OpenHiApp, OpenHiAuthService, OpenHiDataService, OpenHiEnvironment, OpenHiGlobalService, OpenHiGraphqlService, OpenHiRestApiService, OpenHiService, OpenHiStage, OpsEventBus, PreTokenGenerationLambda, REST_API_BASE_URL_SSM_NAME, RootGraphqlApi, RootHostedZone, RootHttpApi, RootWildcardCertificate, STATIC_HOSTING_SERVICE_TYPE, StaticHosting, getDynamoDbDataStoreTableName };
1059
+ export type { BuildParameterNameProps, ChildHostedZoneProps, DataStoreHistoricalArchiveProps, DiscoverableStringParameterProps, DynamoDbDataStoreProps, OpenHiAppProps, OpenHiAuthServiceProps, OpenHiDataServiceProps, OpenHiEnvironmentProps, OpenHiGlobalServiceProps, OpenHiGraphqlServiceProps, OpenHiRestApiServiceProps, OpenHiServiceProps, OpenHiServiceType, OpenHiStageProps, RootGraphqlApiProps, RootHttpApiProps, StaticHostingProps };
package/lib/index.js CHANGED
@@ -99,6 +99,7 @@ __export(src_exports, {
99
99
  CognitoUserPoolDomain: () => CognitoUserPoolDomain,
100
100
  CognitoUserPoolKmsKey: () => CognitoUserPoolKmsKey,
101
101
  DataEventBus: () => DataEventBus,
102
+ DataStoreHistoricalArchive: () => DataStoreHistoricalArchive,
102
103
  DiscoverableStringParameter: () => DiscoverableStringParameter,
103
104
  DynamoDbDataStore: () => DynamoDbDataStore,
104
105
  OpenHiApp: () => OpenHiApp,
@@ -695,6 +696,86 @@ var PreTokenGenerationLambda = class extends import_constructs.Construct {
695
696
  }
696
697
  };
697
698
 
699
+ // src/components/dynamodb/data-store-historical-archive.ts
700
+ var import_node_fs2 = __toESM(require("fs"));
701
+ var import_node_path2 = __toESM(require("path"));
702
+ var import_aws_cdk_lib6 = require("aws-cdk-lib");
703
+ var kinesisfirehose = __toESM(require("aws-cdk-lib/aws-kinesisfirehose"));
704
+ var import_aws_lambda2 = require("aws-cdk-lib/aws-lambda");
705
+ var import_aws_lambda_nodejs2 = require("aws-cdk-lib/aws-lambda-nodejs");
706
+ var s3 = __toESM(require("aws-cdk-lib/aws-s3"));
707
+ var import_constructs2 = require("constructs");
708
+ var HANDLER_NAME2 = "firehose-archive-transform.handler.js";
709
+ function resolveHandlerEntry2(dirname) {
710
+ const sameDir = import_node_path2.default.join(dirname, HANDLER_NAME2);
711
+ if (import_node_fs2.default.existsSync(sameDir)) {
712
+ return sameDir;
713
+ }
714
+ return import_node_path2.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME2);
715
+ }
716
+ var DataStoreHistoricalArchive = class extends import_constructs2.Construct {
717
+ constructor(scope, id, props) {
718
+ super(scope, id);
719
+ this.archiveBucket = new s3.Bucket(this, "ArchiveBucket", {
720
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
721
+ encryption: s3.BucketEncryption.S3_MANAGED,
722
+ enforceSSL: true,
723
+ removalPolicy: props.removalPolicy,
724
+ autoDeleteObjects: props.removalPolicy === import_aws_cdk_lib6.RemovalPolicy.DESTROY,
725
+ versioned: true
726
+ });
727
+ this.transformFunction = new import_aws_lambda_nodejs2.NodejsFunction(this, "FirehoseTransform", {
728
+ entry: resolveHandlerEntry2(__dirname),
729
+ runtime: import_aws_lambda2.Runtime.NODEJS_LATEST,
730
+ memorySize: 512,
731
+ timeout: import_aws_cdk_lib6.Duration.minutes(1),
732
+ description: "Firehose transform: filter CURRENT resource rows, S3 dynamic partition keys",
733
+ bundling: {
734
+ minify: true,
735
+ sourceMap: false
736
+ }
737
+ });
738
+ const processor = new kinesisfirehose.LambdaFunctionProcessor(
739
+ this.transformFunction,
740
+ {
741
+ bufferInterval: import_aws_cdk_lib6.Duration.seconds(60),
742
+ bufferSize: import_aws_cdk_lib6.Size.mebibytes(3),
743
+ retries: 3
744
+ }
745
+ );
746
+ const destination = new kinesisfirehose.S3Bucket(this.archiveBucket, {
747
+ compression: kinesisfirehose.Compression.GZIP,
748
+ bufferingInterval: import_aws_cdk_lib6.Duration.seconds(300),
749
+ // Firehose requires SizeInMBs ≥ 64 when dynamic partitioning is enabled.
750
+ bufferingSize: import_aws_cdk_lib6.Size.mebibytes(64),
751
+ processors: [processor],
752
+ errorOutputPrefix: "errors/!{firehose:error-output-type}/!{timestamp:yyyy/MM/dd/HH}/",
753
+ loggingConfig: new kinesisfirehose.EnableLogging()
754
+ });
755
+ this.deliveryStream = new kinesisfirehose.DeliveryStream(
756
+ this,
757
+ "ArchiveDeliveryStream",
758
+ {
759
+ deliveryStreamName: `openhi-dstore-arch-${props.stackHash}`,
760
+ source: new kinesisfirehose.KinesisStreamSource(props.kinesisStream),
761
+ destination
762
+ }
763
+ );
764
+ const cfn = this.deliveryStream.node.defaultChild;
765
+ cfn.addPropertyOverride(
766
+ "ExtendedS3DestinationConfiguration.DynamicPartitioningConfiguration",
767
+ {
768
+ Enabled: true,
769
+ RetryOptions: { DurationInSeconds: 300 }
770
+ }
771
+ );
772
+ cfn.addPropertyOverride(
773
+ "ExtendedS3DestinationConfiguration.Prefix",
774
+ "!{partitionKeyFromLambda:tenantId}/!{partitionKeyFromLambda:workspaceId}/!{partitionKeyFromLambda:resourceType}/!{partitionKeyFromLambda:resourceId}/!{partitionKeyFromLambda:version}/"
775
+ );
776
+ }
777
+ };
778
+
698
779
  // src/components/dynamodb/dynamo-db-data-store.ts
699
780
  var import_aws_dynamodb = require("aws-cdk-lib/aws-dynamodb");
700
781
  function getDynamoDbDataStoreTableName(scope) {
@@ -817,7 +898,7 @@ var OpsEventBus = class _OpsEventBus extends import_aws_events2.EventBus {
817
898
  };
818
899
 
819
900
  // src/components/route-53/child-hosted-zone.ts
820
- var import_aws_cdk_lib6 = require("aws-cdk-lib");
901
+ var import_aws_cdk_lib7 = require("aws-cdk-lib");
821
902
  var import_aws_route53 = require("aws-cdk-lib/aws-route53");
822
903
  var ChildHostedZone = class extends import_aws_route53.HostedZone {
823
904
  constructor(scope, id, props) {
@@ -826,7 +907,7 @@ var ChildHostedZone = class extends import_aws_route53.HostedZone {
826
907
  zone: props.parentHostedZone,
827
908
  recordName: this.zoneName,
828
909
  values: this.hostedZoneNameServers || [],
829
- ttl: import_aws_cdk_lib6.Duration.minutes(5)
910
+ ttl: import_aws_cdk_lib7.Duration.minutes(5)
830
911
  });
831
912
  }
832
913
  };
@@ -836,8 +917,8 @@ var ChildHostedZone = class extends import_aws_route53.HostedZone {
836
917
  ChildHostedZone.SSM_PARAM_NAME = "CHILDHOSTEDZONE";
837
918
 
838
919
  // src/components/route-53/root-hosted-zone.ts
839
- var import_constructs2 = require("constructs");
840
- var RootHostedZone = class extends import_constructs2.Construct {
920
+ var import_constructs3 = require("constructs");
921
+ var RootHostedZone = class extends import_constructs3.Construct {
841
922
  };
842
923
 
843
924
  // src/components/static-hosting/static-hosting.ts
@@ -845,9 +926,9 @@ var import_aws_cloudfront = require("aws-cdk-lib/aws-cloudfront");
845
926
  var import_aws_cloudfront_origins = require("aws-cdk-lib/aws-cloudfront-origins");
846
927
  var import_aws_s3 = require("aws-cdk-lib/aws-s3");
847
928
  var import_core = require("aws-cdk-lib/core");
848
- var import_constructs3 = require("constructs");
929
+ var import_constructs4 = require("constructs");
849
930
  var STATIC_HOSTING_SERVICE_TYPE = "website";
850
- var _StaticHosting = class _StaticHosting extends import_constructs3.Construct {
931
+ var _StaticHosting = class _StaticHosting extends import_constructs4.Construct {
851
932
  constructor(scope, id, props = {}) {
852
933
  super(scope, id);
853
934
  const stack = OpenHiService.of(scope);
@@ -1158,6 +1239,7 @@ var import_core2 = require("aws-cdk-lib/core");
1158
1239
  // src/services/open-hi-data-service.ts
1159
1240
  var import_aws_dynamodb2 = require("aws-cdk-lib/aws-dynamodb");
1160
1241
  var import_aws_events3 = require("aws-cdk-lib/aws-events");
1242
+ var kinesis = __toESM(require("aws-cdk-lib/aws-kinesis"));
1161
1243
  var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1162
1244
  /**
1163
1245
  * Returns the data event bus by name (deterministic per branch). Use from other stacks to obtain an IEventBus reference.
@@ -1193,7 +1275,24 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1193
1275
  this.props = props;
1194
1276
  this.dataEventBus = this.createDataEventBus();
1195
1277
  this.opsEventBus = this.createOpsEventBus();
1278
+ this.dataStoreChangeStream = new kinesis.Stream(
1279
+ this,
1280
+ "data-store-change-stream",
1281
+ {
1282
+ streamName: `openhi-dstore-cdc-${this.branchHash}`,
1283
+ streamMode: kinesis.StreamMode.ON_DEMAND
1284
+ }
1285
+ );
1196
1286
  this.dataStore = this.createDataStore();
1287
+ this.dataStoreHistoricalArchive = new DataStoreHistoricalArchive(
1288
+ this,
1289
+ "data-store-historical-archive",
1290
+ {
1291
+ kinesisStream: this.dataStoreChangeStream,
1292
+ removalPolicy: this.removalPolicy,
1293
+ stackHash: this.stackHash
1294
+ }
1295
+ );
1197
1296
  }
1198
1297
  /**
1199
1298
  * Creates the data event bus.
@@ -1214,59 +1313,62 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1214
1313
  * Override to customize.
1215
1314
  */
1216
1315
  createDataStore() {
1217
- return new DynamoDbDataStore(this, "dynamo-db-data-store");
1316
+ return new DynamoDbDataStore(this, "dynamo-db-data-store", {
1317
+ kinesisStream: this.dataStoreChangeStream,
1318
+ stream: import_aws_dynamodb2.StreamViewType.NEW_AND_OLD_IMAGES
1319
+ });
1218
1320
  }
1219
1321
  };
1220
1322
  _OpenHiDataService.SERVICE_TYPE = "data";
1221
1323
  var OpenHiDataService = _OpenHiDataService;
1222
1324
 
1223
1325
  // src/data/lambda/cors-options-lambda.ts
1224
- var import_node_fs2 = __toESM(require("fs"));
1225
- var import_node_path2 = __toESM(require("path"));
1226
- var import_aws_lambda2 = require("aws-cdk-lib/aws-lambda");
1227
- var import_aws_lambda_nodejs2 = require("aws-cdk-lib/aws-lambda-nodejs");
1228
- var import_constructs4 = require("constructs");
1229
- var HANDLER_NAME2 = "cors-options-lambda.handler.js";
1230
- function resolveHandlerEntry2(dirname) {
1231
- const sameDir = import_node_path2.default.join(dirname, HANDLER_NAME2);
1232
- if (import_node_fs2.default.existsSync(sameDir)) {
1326
+ var import_node_fs3 = __toESM(require("fs"));
1327
+ var import_node_path3 = __toESM(require("path"));
1328
+ var import_aws_lambda3 = require("aws-cdk-lib/aws-lambda");
1329
+ var import_aws_lambda_nodejs3 = require("aws-cdk-lib/aws-lambda-nodejs");
1330
+ var import_constructs5 = require("constructs");
1331
+ var HANDLER_NAME3 = "cors-options-lambda.handler.js";
1332
+ function resolveHandlerEntry3(dirname) {
1333
+ const sameDir = import_node_path3.default.join(dirname, HANDLER_NAME3);
1334
+ if (import_node_fs3.default.existsSync(sameDir)) {
1233
1335
  return sameDir;
1234
1336
  }
1235
- const fromLib = import_node_path2.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME2);
1337
+ const fromLib = import_node_path3.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME3);
1236
1338
  return fromLib;
1237
1339
  }
1238
- var CorsOptionsLambda = class extends import_constructs4.Construct {
1340
+ var CorsOptionsLambda = class extends import_constructs5.Construct {
1239
1341
  constructor(scope, id = "cors-options-lambda") {
1240
1342
  super(scope, id);
1241
- this.lambda = new import_aws_lambda_nodejs2.NodejsFunction(this, "handler", {
1242
- entry: resolveHandlerEntry2(__dirname),
1243
- runtime: import_aws_lambda2.Runtime.NODEJS_LATEST,
1343
+ this.lambda = new import_aws_lambda_nodejs3.NodejsFunction(this, "handler", {
1344
+ entry: resolveHandlerEntry3(__dirname),
1345
+ runtime: import_aws_lambda3.Runtime.NODEJS_LATEST,
1244
1346
  memorySize: 128
1245
1347
  });
1246
1348
  }
1247
1349
  };
1248
1350
 
1249
1351
  // src/data/lambda/rest-api-lambda.ts
1250
- var import_node_fs3 = __toESM(require("fs"));
1251
- var import_node_path3 = __toESM(require("path"));
1252
- var import_aws_lambda3 = require("aws-cdk-lib/aws-lambda");
1253
- var import_aws_lambda_nodejs3 = require("aws-cdk-lib/aws-lambda-nodejs");
1254
- var import_constructs5 = require("constructs");
1255
- var HANDLER_NAME3 = "rest-api-lambda.handler.js";
1256
- function resolveHandlerEntry3(dirname) {
1257
- const sameDir = import_node_path3.default.join(dirname, HANDLER_NAME3);
1258
- if (import_node_fs3.default.existsSync(sameDir)) {
1352
+ var import_node_fs4 = __toESM(require("fs"));
1353
+ var import_node_path4 = __toESM(require("path"));
1354
+ var import_aws_lambda4 = require("aws-cdk-lib/aws-lambda");
1355
+ var import_aws_lambda_nodejs4 = require("aws-cdk-lib/aws-lambda-nodejs");
1356
+ var import_constructs6 = require("constructs");
1357
+ var HANDLER_NAME4 = "rest-api-lambda.handler.js";
1358
+ function resolveHandlerEntry4(dirname) {
1359
+ const sameDir = import_node_path4.default.join(dirname, HANDLER_NAME4);
1360
+ if (import_node_fs4.default.existsSync(sameDir)) {
1259
1361
  return sameDir;
1260
1362
  }
1261
- const fromLib = import_node_path3.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME3);
1363
+ const fromLib = import_node_path4.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME4);
1262
1364
  return fromLib;
1263
1365
  }
1264
- var RestApiLambda = class extends import_constructs5.Construct {
1366
+ var RestApiLambda = class extends import_constructs6.Construct {
1265
1367
  constructor(scope, props) {
1266
1368
  super(scope, "rest-api-lambda");
1267
- this.lambda = new import_aws_lambda_nodejs3.NodejsFunction(this, "handler", {
1268
- entry: resolveHandlerEntry3(__dirname),
1269
- runtime: import_aws_lambda3.Runtime.NODEJS_LATEST,
1369
+ this.lambda = new import_aws_lambda_nodejs4.NodejsFunction(this, "handler", {
1370
+ entry: resolveHandlerEntry4(__dirname),
1371
+ runtime: import_aws_lambda4.Runtime.NODEJS_LATEST,
1270
1372
  memorySize: 1024,
1271
1373
  environment: {
1272
1374
  DYNAMO_TABLE_NAME: props.dynamoTableName,
@@ -1565,6 +1667,7 @@ var OpenHiGraphqlService = _OpenHiGraphqlService;
1565
1667
  CognitoUserPoolDomain,
1566
1668
  CognitoUserPoolKmsKey,
1567
1669
  DataEventBus,
1670
+ DataStoreHistoricalArchive,
1568
1671
  DiscoverableStringParameter,
1569
1672
  DynamoDbDataStore,
1570
1673
  OpenHiApp,