@openhi/constructs 0.0.170 → 0.0.171
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-USNOOCSZ.mjs → chunk-AWAWCRWW.mjs} +2 -2
- package/lib/{chunk-ZXPA6W3G.mjs → chunk-RC7HHZR6.mjs} +3 -3
- package/lib/chunk-RC7HHZR6.mjs.map +1 -0
- package/lib/data-store-postgres-replication.handler.js +6 -6
- package/lib/data-store-postgres-replication.handler.js.map +1 -1
- package/lib/data-store-postgres-replication.handler.mjs +8 -8
- package/lib/data-store-postgres-replication.handler.mjs.map +1 -1
- package/lib/firehose-archive-transform.handler.js +2 -2
- package/lib/firehose-archive-transform.handler.js.map +1 -1
- package/lib/firehose-archive-transform.handler.mjs +2 -2
- package/lib/index.d.mts +6 -2
- package/lib/index.d.ts +6 -2
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1 -1
- package/package.json +1 -1
- package/lib/chunk-ZXPA6W3G.mjs.map +0 -1
- /package/lib/{chunk-USNOOCSZ.mjs.map → chunk-AWAWCRWW.mjs.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DATA_STORE_CHANGE_DETAIL_TYPE,
|
|
4
4
|
buildFhirCurrentResourceChangeDetail,
|
|
5
5
|
dynamodbImageToPlain
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RC7HHZR6.mjs";
|
|
7
7
|
import {
|
|
8
8
|
decompressResource
|
|
9
9
|
} from "./chunk-APVVG7BO.mjs";
|
|
@@ -327,4 +327,4 @@ export {
|
|
|
327
327
|
buildArchivePayload,
|
|
328
328
|
handler
|
|
329
329
|
};
|
|
330
|
-
//# sourceMappingURL=chunk-
|
|
330
|
+
//# sourceMappingURL=chunk-AWAWCRWW.mjs.map
|
|
@@ -87,7 +87,7 @@ function buildFhirCurrentResourceChangeDetail(record, keys) {
|
|
|
87
87
|
const rawName = record.eventName;
|
|
88
88
|
const changeType = rawName === "INSERT" || rawName === "MODIFY" || rawName === "REMOVE" ? rawName : "MODIFY";
|
|
89
89
|
const seq = record.dynamodb?.SequenceNumber;
|
|
90
|
-
const
|
|
90
|
+
const approxEpochMs = record.dynamodb?.ApproximateCreationDateTime;
|
|
91
91
|
const newPlain = plainImage(
|
|
92
92
|
record.dynamodb?.NewImage
|
|
93
93
|
);
|
|
@@ -113,7 +113,7 @@ function buildFhirCurrentResourceChangeDetail(record, keys) {
|
|
|
113
113
|
resourceId: keys.resourceId,
|
|
114
114
|
resourceVersion: keys.version,
|
|
115
115
|
...typeof seq === "string" && seq.length > 0 ? { streamSequenceNumber: seq } : {},
|
|
116
|
-
...typeof
|
|
116
|
+
...typeof approxEpochMs === "number" && Number.isFinite(approxEpochMs) ? { approximateCreationEpochMs: approxEpochMs } : {},
|
|
117
117
|
...changedAttributeNames ? { changedAttributeNames } : {}
|
|
118
118
|
};
|
|
119
119
|
}
|
|
@@ -124,4 +124,4 @@ export {
|
|
|
124
124
|
DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES,
|
|
125
125
|
buildFhirCurrentResourceChangeDetail
|
|
126
126
|
};
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
127
|
+
//# sourceMappingURL=chunk-RC7HHZR6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/dynamodb/dynamodb-stream-record.ts","../src/components/dynamodb/data-store-change-events.ts"],"sourcesContent":["import type { AttributeValue } from \"@aws-sdk/client-dynamodb\";\n\n/**\n * Shape of a DynamoDB change record as delivered inside Kinesis (table stream\n * destination) and decoded by the Firehose transform Lambda.\n */\nexport interface DynamoDbStreamKinesisRecord {\n eventName?: string;\n userIdentity?: unknown;\n dynamodb?: {\n Keys?: Record<string, AttributeValue>;\n NewImage?: Record<string, AttributeValue>;\n OldImage?: Record<string, AttributeValue>;\n SequenceNumber?: string;\n ApproximateCreationDateTime?: number;\n };\n}\n\nexport function dynamodbValueToJs(av: AttributeValue): unknown {\n if (av.S !== undefined) {\n return av.S;\n }\n if (av.N !== undefined) {\n return av.N.includes(\".\")\n ? Number.parseFloat(av.N)\n : Number.parseInt(av.N, 10);\n }\n if (av.BOOL !== undefined) {\n return av.BOOL;\n }\n if (av.NULL !== undefined) {\n return null;\n }\n if (av.M !== undefined) {\n return dynamodbImageToPlain(av.M);\n }\n if (av.L !== undefined) {\n return av.L.map((x: AttributeValue) => dynamodbValueToJs(x));\n }\n if (av.SS !== undefined) {\n return av.SS;\n }\n if (av.NS !== undefined) {\n return av.NS.map((n: string) =>\n n.includes(\".\") ? Number.parseFloat(n) : Number.parseInt(n, 10),\n );\n }\n return undefined;\n}\n\nexport function dynamodbImageToPlain(\n image: Record<string, AttributeValue>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(image)) {\n out[k] = dynamodbValueToJs(v);\n }\n return out;\n}\n","import type { AttributeValue } from \"@aws-sdk/client-dynamodb\";\nimport type { DynamoDbStreamKinesisRecord } from \"./dynamodb-stream-record\";\nimport { dynamodbImageToPlain } from \"./dynamodb-stream-record\";\n\n/**\n * EventBridge envelope constants for data-store CDC (no CDK imports).\n *\n * The bus-`Source` value is intentionally NOT defined here. Per TR-016\n * §Configuration Standards, the canonical per-bus `Source` constants\n * live in `@openhi/workflows` (`OPENHI_DATA_SOURCE = \"openhi.data\"`).\n * Importers should read that symbol directly so producer and consumer\n * never drift from a single source of truth.\n *\n * @see docs/architecture/adr/2026-03-02-01-dynamodb-stream-to-data-event-bus.md\n * @see https://github.com/codedrifters/openhi-planning/blob/main/docs/src/content/docs/requirements/technical-requirements/TR-016-openhi-workflows-envelope-package.md\n */\nexport const DATA_STORE_CHANGE_DETAIL_TYPE = \"FhirCurrentResourceChanged\";\n\n/** AWS PutEvents per-entry detail limit is 256 KiB; stay under for headroom. */\nexport const DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES = 250 * 1024;\n\nconst EXCLUDED_CHANGE_DETAIL_KEYS = new Set([\n \"PK\",\n \"SK\",\n \"GSI1PK\",\n \"GSI1SK\",\n \"GSI2PK\",\n \"GSI2SK\",\n /** Full FHIR JSON may contain PII; never list or ship in the bus payload. */\n \"resource\",\n]);\n\nfunction shallowValueEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\nfunction changedNonResourceAttributeNames(\n oldImage: Record<string, unknown> | undefined,\n newImage: Record<string, unknown> | undefined,\n): string[] | undefined {\n if (!oldImage || !newImage) {\n return undefined;\n }\n const names = new Set<string>();\n const keys = new Set([...Object.keys(oldImage), ...Object.keys(newImage)]);\n for (const k of keys) {\n if (EXCLUDED_CHANGE_DETAIL_KEYS.has(k)) {\n continue;\n }\n if (!shallowValueEqual(oldImage[k], newImage[k])) {\n names.add(k);\n }\n }\n return names.size > 0 ? [...names].sort() : undefined;\n}\n\n/** Non-excluded attribute names present on an item (for INSERT / REMOVE). */\nfunction presentMetadataAttributeNames(\n image: Record<string, unknown> | undefined,\n): string[] | undefined {\n if (!image) {\n return undefined;\n }\n const names = Object.keys(image).filter(\n (k) => !EXCLUDED_CHANGE_DETAIL_KEYS.has(k),\n );\n return names.length > 0 ? names.sort() : undefined;\n}\n\nfunction plainImage(\n image: Record<string, AttributeValue> | undefined,\n): Record<string, unknown> | undefined {\n if (!image) {\n return undefined;\n }\n return dynamodbImageToPlain(image);\n}\n\nexport interface FhirCurrentResourceChangeDetail {\n changeType: \"INSERT\" | \"MODIFY\" | \"REMOVE\";\n tenantId: string;\n workspaceId: string;\n resourceType: string;\n resourceId: string;\n resourceVersion: string;\n streamSequenceNumber?: string;\n /**\n * Milliseconds since UNIX epoch. Mirrors the Kinesis-Data-Streams-for-DynamoDB\n * envelope's `ApproximateCreationDateTime`, which is ms — NOT seconds (the\n * legacy DynamoDB Streams API of the same name was in seconds).\n */\n approximateCreationEpochMs?: number;\n /**\n * MODIFY: attributes whose values differ between old and new images.\n * INSERT / REMOVE: attributes present on the written or removed image (metadata only).\n */\n changedAttributeNames?: string[];\n}\n\nexport function buildFhirCurrentResourceChangeDetail(\n record: DynamoDbStreamKinesisRecord,\n keys: {\n tenantId: string;\n workspaceId: string;\n resourceType: string;\n resourceId: string;\n version: string;\n },\n): FhirCurrentResourceChangeDetail {\n const rawName = record.eventName;\n const changeType =\n rawName === \"INSERT\" || rawName === \"MODIFY\" || rawName === \"REMOVE\"\n ? rawName\n : \"MODIFY\";\n\n const seq = record.dynamodb?.SequenceNumber;\n const approxEpochMs = record.dynamodb?.ApproximateCreationDateTime;\n\n const newPlain = plainImage(\n record.dynamodb?.NewImage as Record<string, AttributeValue> | undefined,\n );\n const oldPlain = plainImage(\n record.dynamodb?.OldImage as Record<string, AttributeValue> | undefined,\n );\n\n let changedAttributeNames: string[] | undefined;\n if (changeType === \"MODIFY\") {\n changedAttributeNames = changedNonResourceAttributeNames(\n oldPlain,\n newPlain,\n );\n } else if (changeType === \"INSERT\") {\n changedAttributeNames = presentMetadataAttributeNames(newPlain);\n } else {\n changedAttributeNames = presentMetadataAttributeNames(oldPlain);\n }\n\n return {\n changeType,\n tenantId: keys.tenantId,\n workspaceId: keys.workspaceId,\n resourceType: keys.resourceType,\n resourceId: keys.resourceId,\n resourceVersion: keys.version,\n ...(typeof seq === \"string\" && seq.length > 0\n ? { streamSequenceNumber: seq }\n : {}),\n ...(typeof approxEpochMs === \"number\" && Number.isFinite(approxEpochMs)\n ? { approximateCreationEpochMs: approxEpochMs }\n : {}),\n ...(changedAttributeNames ? { changedAttributeNames } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1117,7 +1117,7 @@ function decodeKinesisRecord(record) {
|
|
|
1117
1117
|
const json = Buffer.from(record.kinesis.data, "base64").toString("utf8");
|
|
1118
1118
|
return JSON.parse(json);
|
|
1119
1119
|
}
|
|
1120
|
-
function deriveLastUpdated(resource,
|
|
1120
|
+
function deriveLastUpdated(resource, approximateCreationEpochMs) {
|
|
1121
1121
|
if (resource && typeof resource === "object") {
|
|
1122
1122
|
const meta = resource.meta;
|
|
1123
1123
|
const lu = meta?.lastUpdated;
|
|
@@ -1128,8 +1128,8 @@ function deriveLastUpdated(resource, approximateCreationEpochSec) {
|
|
|
1128
1128
|
}
|
|
1129
1129
|
}
|
|
1130
1130
|
}
|
|
1131
|
-
if (typeof
|
|
1132
|
-
return new Date(
|
|
1131
|
+
if (typeof approximateCreationEpochMs === "number" && Number.isFinite(approximateCreationEpochMs)) {
|
|
1132
|
+
return new Date(approximateCreationEpochMs);
|
|
1133
1133
|
}
|
|
1134
1134
|
return /* @__PURE__ */ new Date();
|
|
1135
1135
|
}
|
|
@@ -1147,7 +1147,7 @@ function buildWriteIntent(change, awsRegion) {
|
|
|
1147
1147
|
return { kind: "drop" };
|
|
1148
1148
|
}
|
|
1149
1149
|
const plain = dynamodbImageToPlain(image);
|
|
1150
|
-
const
|
|
1150
|
+
const approxEpochMs = change.dynamodb?.ApproximateCreationDateTime;
|
|
1151
1151
|
if (isRemove) {
|
|
1152
1152
|
return {
|
|
1153
1153
|
kind: "delete",
|
|
@@ -1157,7 +1157,7 @@ function buildWriteIntent(change, awsRegion) {
|
|
|
1157
1157
|
resourceType: keys.resourceType,
|
|
1158
1158
|
resourceId: keys.resourceId,
|
|
1159
1159
|
version: keys.version,
|
|
1160
|
-
deletedAt: deriveLastUpdated(void 0,
|
|
1160
|
+
deletedAt: deriveLastUpdated(void 0, approxEpochMs)
|
|
1161
1161
|
}
|
|
1162
1162
|
};
|
|
1163
1163
|
}
|
|
@@ -1180,7 +1180,7 @@ function buildWriteIntent(change, awsRegion) {
|
|
|
1180
1180
|
resourceType: keys.resourceType,
|
|
1181
1181
|
resourceId: keys.resourceId,
|
|
1182
1182
|
version: keys.version,
|
|
1183
|
-
lastUpdated: deriveLastUpdated(resourceObj,
|
|
1183
|
+
lastUpdated: deriveLastUpdated(resourceObj, approxEpochMs),
|
|
1184
1184
|
resourceJson
|
|
1185
1185
|
}
|
|
1186
1186
|
};
|