@openhi/constructs 0.0.5 → 0.0.6
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 +27 -4
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +27 -4
- package/lib/index.mjs.map +1 -1
- package/lib/rest-api-lambda.handler.js +468 -4
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +472 -4
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/package.json +4 -3
|
@@ -8,7 +8,7 @@ import serverlessExpress from "@codegenie/serverless-express";
|
|
|
8
8
|
// src/data/rest-api/rest-api.ts
|
|
9
9
|
import path from "path";
|
|
10
10
|
import cors from "cors";
|
|
11
|
-
import
|
|
11
|
+
import express3 from "express";
|
|
12
12
|
|
|
13
13
|
// src/data/middleware/open-hi-context.ts
|
|
14
14
|
var STATIC_TENANT_ID = "tenant-1";
|
|
@@ -625,18 +625,486 @@ async function deletePatient(req, res) {
|
|
|
625
625
|
}
|
|
626
626
|
router.delete("/:id", deletePatient);
|
|
627
627
|
|
|
628
|
+
// src/data/rest-api/ohi/Configuration.ts
|
|
629
|
+
import express2 from "express";
|
|
630
|
+
|
|
631
|
+
// src/data/rest-api/ohi/dynamic-configuration.ts
|
|
632
|
+
import {
|
|
633
|
+
DescribeParametersCommand,
|
|
634
|
+
GetParametersCommand,
|
|
635
|
+
SSMClient
|
|
636
|
+
} from "@aws-sdk/client-ssm";
|
|
637
|
+
var BASE_PATH2 = "/ohi/Configuration";
|
|
638
|
+
var TAG_KEY_BRANCH = "openhi:branch-name";
|
|
639
|
+
var TAG_KEY_HTTP_API_PARAM = "openhi:param-name";
|
|
640
|
+
function getSsmDynamicConfigEnvFilter() {
|
|
641
|
+
const branchTagValue = process.env.BRANCH_TAG_VALUE;
|
|
642
|
+
const httpApiTagValue = process.env.HTTP_API_TAG_VALUE;
|
|
643
|
+
if (branchTagValue == null || branchTagValue === "" || httpApiTagValue == null || httpApiTagValue === "") {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
return { branchTagValue, httpApiTagValue };
|
|
647
|
+
}
|
|
648
|
+
async function getDynamicConfigurationEntries(context) {
|
|
649
|
+
const envFilter = getSsmDynamicConfigEnvFilter();
|
|
650
|
+
if (envFilter == null) {
|
|
651
|
+
return getStaticDummyEntry(context);
|
|
652
|
+
}
|
|
653
|
+
const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
|
|
654
|
+
const client3 = new SSMClient({ region });
|
|
655
|
+
try {
|
|
656
|
+
const describeResult = await client3.send(
|
|
657
|
+
new DescribeParametersCommand({
|
|
658
|
+
ParameterFilters: [
|
|
659
|
+
{
|
|
660
|
+
Key: `tag:${TAG_KEY_BRANCH}`,
|
|
661
|
+
Option: "Equals",
|
|
662
|
+
Values: [envFilter.branchTagValue]
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
Key: `tag:${TAG_KEY_HTTP_API_PARAM}`,
|
|
666
|
+
Option: "Equals",
|
|
667
|
+
Values: [envFilter.httpApiTagValue]
|
|
668
|
+
}
|
|
669
|
+
],
|
|
670
|
+
MaxResults: 50
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
const names = (describeResult.Parameters ?? []).map((p) => p.Name).filter((n) => n != null);
|
|
674
|
+
if (names.length === 0) {
|
|
675
|
+
return getStaticDummyEntry(context);
|
|
676
|
+
}
|
|
677
|
+
const parameters = [];
|
|
678
|
+
for (let i = 0; i < names.length; i += 10) {
|
|
679
|
+
const batch = names.slice(i, i + 10);
|
|
680
|
+
const getResult = await client3.send(
|
|
681
|
+
new GetParametersCommand({
|
|
682
|
+
Names: batch,
|
|
683
|
+
WithDecryption: true
|
|
684
|
+
})
|
|
685
|
+
);
|
|
686
|
+
for (const p of getResult.Parameters ?? []) {
|
|
687
|
+
const name = p.Name;
|
|
688
|
+
const value = p.Value;
|
|
689
|
+
if (name != null && value != null) {
|
|
690
|
+
parameters.push({ name, value });
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
const parameterList = parameters.map((p) => {
|
|
695
|
+
const shortName = p.name.includes("/") ? p.name.split("/").slice(-1)[0] : p.name;
|
|
696
|
+
return { name: shortName, valueString: p.value };
|
|
697
|
+
});
|
|
698
|
+
const entry = {
|
|
699
|
+
fullUrl: `${BASE_PATH2}/ssm-dynamic`,
|
|
700
|
+
resource: {
|
|
701
|
+
resourceType: "Configuration",
|
|
702
|
+
id: "ssm-dynamic",
|
|
703
|
+
key: "ssm-dynamic",
|
|
704
|
+
resource: {
|
|
705
|
+
parameter: parameterList
|
|
706
|
+
},
|
|
707
|
+
meta: {
|
|
708
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
709
|
+
versionId: "1"
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
return [entry];
|
|
714
|
+
} catch (err) {
|
|
715
|
+
console.error("getDynamicConfigurationEntries SSM error:", err);
|
|
716
|
+
return getStaticDummyEntry(context);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
function getStaticDummyEntry(_context) {
|
|
720
|
+
const dummy = {
|
|
721
|
+
fullUrl: `${BASE_PATH2}/dynamic-dummy`,
|
|
722
|
+
resource: {
|
|
723
|
+
resourceType: "Configuration",
|
|
724
|
+
id: "dynamic-dummy",
|
|
725
|
+
key: "dynamic-dummy",
|
|
726
|
+
resource: {
|
|
727
|
+
parameter: [
|
|
728
|
+
{
|
|
729
|
+
name: "description",
|
|
730
|
+
valueString: "Statically generated dummy configuration (not from DynamoDB)."
|
|
731
|
+
},
|
|
732
|
+
{ name: "source", valueString: "dynamic-configuration" }
|
|
733
|
+
]
|
|
734
|
+
},
|
|
735
|
+
meta: {
|
|
736
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
737
|
+
versionId: "1"
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
return [dummy];
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// src/data/dynamo/ohi/ohi-data-service.ts
|
|
745
|
+
import { DynamoDBClient as DynamoDBClient2 } from "@aws-sdk/client-dynamodb";
|
|
746
|
+
import { Service as Service2 } from "electrodb";
|
|
747
|
+
|
|
748
|
+
// src/data/dynamo/ohi/Configuration.ts
|
|
749
|
+
import { Entity as Entity2 } from "electrodb";
|
|
750
|
+
var Configuration = new Entity2({
|
|
751
|
+
model: {
|
|
752
|
+
entity: "configuration",
|
|
753
|
+
service: "ohi",
|
|
754
|
+
version: "01"
|
|
755
|
+
},
|
|
756
|
+
attributes: {
|
|
757
|
+
/** Sort key. "CURRENT" for current version; version history in S3. */
|
|
758
|
+
sk: {
|
|
759
|
+
type: "string",
|
|
760
|
+
required: true,
|
|
761
|
+
default: "CURRENT"
|
|
762
|
+
},
|
|
763
|
+
/** Tenant scope. Use "BASELINE" when the config is baseline default (no tenant). */
|
|
764
|
+
tenantId: {
|
|
765
|
+
type: "string",
|
|
766
|
+
required: true,
|
|
767
|
+
default: "BASELINE"
|
|
768
|
+
},
|
|
769
|
+
/** Workspace scope. Use "-" when absent. */
|
|
770
|
+
workspaceId: {
|
|
771
|
+
type: "string",
|
|
772
|
+
required: true,
|
|
773
|
+
default: "-"
|
|
774
|
+
},
|
|
775
|
+
/** User scope. Use "-" when absent. */
|
|
776
|
+
userId: {
|
|
777
|
+
type: "string",
|
|
778
|
+
required: true,
|
|
779
|
+
default: "-"
|
|
780
|
+
},
|
|
781
|
+
/** Role scope. Use "-" when absent. */
|
|
782
|
+
roleId: {
|
|
783
|
+
type: "string",
|
|
784
|
+
required: true,
|
|
785
|
+
default: "-"
|
|
786
|
+
},
|
|
787
|
+
/** Config type (category), e.g. endpoints, branding, display. */
|
|
788
|
+
key: {
|
|
789
|
+
type: "string",
|
|
790
|
+
required: true
|
|
791
|
+
},
|
|
792
|
+
/** FHIR Resource.id; logical id in URL and for the Configuration resource. */
|
|
793
|
+
id: {
|
|
794
|
+
type: "string",
|
|
795
|
+
required: true
|
|
796
|
+
},
|
|
797
|
+
/** Payload as JSON string. JSON.stringify(resource) on write; JSON.parse(item.resource) on read. */
|
|
798
|
+
resource: {
|
|
799
|
+
type: "string",
|
|
800
|
+
required: true
|
|
801
|
+
},
|
|
802
|
+
/** Version id (e.g. ULID). Tracks current version; S3 history key. */
|
|
803
|
+
vid: {
|
|
804
|
+
type: "string",
|
|
805
|
+
required: true
|
|
806
|
+
},
|
|
807
|
+
lastUpdated: {
|
|
808
|
+
type: "string",
|
|
809
|
+
required: true
|
|
810
|
+
},
|
|
811
|
+
deleted: {
|
|
812
|
+
type: "boolean",
|
|
813
|
+
required: false
|
|
814
|
+
},
|
|
815
|
+
bundleId: {
|
|
816
|
+
type: "string",
|
|
817
|
+
required: false
|
|
818
|
+
},
|
|
819
|
+
msgId: {
|
|
820
|
+
type: "string",
|
|
821
|
+
required: false
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
indexes: {
|
|
825
|
+
/** Base table: PK, SK (data store key names). PK is built from tenantId, workspaceId, userId, roleId; SK is built from key and sk. Do not supply PK or SK from outside. */
|
|
826
|
+
record: {
|
|
827
|
+
pk: {
|
|
828
|
+
field: "PK",
|
|
829
|
+
composite: ["tenantId", "workspaceId", "userId", "roleId"],
|
|
830
|
+
template: "OHI#CONFIG#TID#${tenantId}#WID#${workspaceId}#UID#${userId}#RID#${roleId}"
|
|
831
|
+
},
|
|
832
|
+
sk: {
|
|
833
|
+
field: "SK",
|
|
834
|
+
composite: ["key", "sk"],
|
|
835
|
+
template: "KEY#${key}#SK#${sk}"
|
|
836
|
+
}
|
|
837
|
+
},
|
|
838
|
+
/** GSI4 — Resource Type Index: list all Configuration in a tenant or workspace (no scan). Use for "list configs scoped to this tenant" (workspaceId = "-") or "list configs scoped to this workspace". Does not support hierarchical resolution in one query; use base table GetItem in fallback order (user → workspace → tenant → baseline) for that. */
|
|
839
|
+
gsi4: {
|
|
840
|
+
index: "GSI4",
|
|
841
|
+
condition: () => true,
|
|
842
|
+
pk: {
|
|
843
|
+
field: "GSI4PK",
|
|
844
|
+
composite: ["tenantId", "workspaceId"],
|
|
845
|
+
template: "TID#${tenantId}#WID#${workspaceId}#RT#Configuration"
|
|
846
|
+
},
|
|
847
|
+
sk: {
|
|
848
|
+
field: "GSI4SK",
|
|
849
|
+
composite: ["key", "sk"],
|
|
850
|
+
template: "KEY#${key}#SK#${sk}"
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
// src/data/dynamo/ohi/ohi-data-service.ts
|
|
857
|
+
var table2 = process.env.DYNAMO_TABLE_NAME ?? "jesttesttable";
|
|
858
|
+
var client2 = new DynamoDBClient2({
|
|
859
|
+
...process.env.MOCK_DYNAMODB_ENDPOINT && {
|
|
860
|
+
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
861
|
+
sslEnabled: false,
|
|
862
|
+
region: "local"
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
var entities2 = { configuration: Configuration };
|
|
866
|
+
var OhiDataService = new Service2(entities2, { table: table2, client: client2 });
|
|
867
|
+
function getOhiDataService(tableName) {
|
|
868
|
+
return new Service2(entities2, { table: tableName, client: client2 });
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// src/data/rest-api/ohi/Configuration.ts
|
|
872
|
+
var BASE_PATH3 = "/ohi/Configuration";
|
|
873
|
+
var router2 = express2.Router();
|
|
874
|
+
var SK3 = "CURRENT";
|
|
875
|
+
var TABLE_NAME2 = process.env.DYNAMO_TABLE_NAME ?? "jesttesttable";
|
|
876
|
+
async function listConfigurations(req, res) {
|
|
877
|
+
const { tenantId, workspaceId } = req.openhiContext;
|
|
878
|
+
const service = getOhiDataService(TABLE_NAME2);
|
|
879
|
+
try {
|
|
880
|
+
const result = await service.entities.configuration.query.gsi4({ tenantId, workspaceId }).go();
|
|
881
|
+
const dynamoEntries = (result.data ?? []).map((item) => {
|
|
882
|
+
const resource = JSON.parse(decompressResource(item.resource));
|
|
883
|
+
return {
|
|
884
|
+
fullUrl: `${BASE_PATH3}/${item.key}`,
|
|
885
|
+
resource: { ...resource, id: item.id, key: item.key }
|
|
886
|
+
};
|
|
887
|
+
});
|
|
888
|
+
const dynamicEntries = await getDynamicConfigurationEntries({
|
|
889
|
+
tenantId,
|
|
890
|
+
workspaceId
|
|
891
|
+
});
|
|
892
|
+
const entries = [...dynamoEntries, ...dynamicEntries];
|
|
893
|
+
const bundle = {
|
|
894
|
+
resourceType: "Bundle",
|
|
895
|
+
type: "searchset",
|
|
896
|
+
total: entries.length,
|
|
897
|
+
link: [{ relation: "self", url: BASE_PATH3 }],
|
|
898
|
+
entry: entries
|
|
899
|
+
};
|
|
900
|
+
return res.json(bundle);
|
|
901
|
+
} catch (err) {
|
|
902
|
+
console.error("GET /Configuration list error:", err);
|
|
903
|
+
return res.status(500).json({
|
|
904
|
+
resourceType: "OperationOutcome",
|
|
905
|
+
issue: [
|
|
906
|
+
{
|
|
907
|
+
severity: "error",
|
|
908
|
+
code: "exception",
|
|
909
|
+
diagnostics: String(err)
|
|
910
|
+
}
|
|
911
|
+
]
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
router2.get("/", listConfigurations);
|
|
916
|
+
async function getConfigurationByKey(req, res) {
|
|
917
|
+
const key = String(req.params.key);
|
|
918
|
+
const ctx = req.openhiContext;
|
|
919
|
+
const { tenantId, workspaceId, userId } = ctx;
|
|
920
|
+
const roleId = "roleId" in ctx && typeof ctx.roleId === "string" ? ctx.roleId : "-";
|
|
921
|
+
const service = getOhiDataService(TABLE_NAME2);
|
|
922
|
+
try {
|
|
923
|
+
const result = await service.entities.configuration.get({ tenantId, workspaceId, userId, roleId, key, sk: SK3 }).go();
|
|
924
|
+
if (!result.data) {
|
|
925
|
+
return res.status(404).json({
|
|
926
|
+
resourceType: "OperationOutcome",
|
|
927
|
+
issue: [
|
|
928
|
+
{
|
|
929
|
+
severity: "error",
|
|
930
|
+
code: "not-found",
|
|
931
|
+
diagnostics: `Configuration ${key} not found`
|
|
932
|
+
}
|
|
933
|
+
]
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
const resource = JSON.parse(
|
|
937
|
+
decompressResource(result.data.resource)
|
|
938
|
+
);
|
|
939
|
+
return res.json({
|
|
940
|
+
...resource,
|
|
941
|
+
resourceType: "Configuration",
|
|
942
|
+
id: result.data.id,
|
|
943
|
+
key: result.data.key
|
|
944
|
+
});
|
|
945
|
+
} catch (err) {
|
|
946
|
+
console.error("GET Configuration error:", err);
|
|
947
|
+
return res.status(500).json({
|
|
948
|
+
resourceType: "OperationOutcome",
|
|
949
|
+
issue: [
|
|
950
|
+
{
|
|
951
|
+
severity: "error",
|
|
952
|
+
code: "exception",
|
|
953
|
+
diagnostics: String(err)
|
|
954
|
+
}
|
|
955
|
+
]
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
router2.get("/:key", getConfigurationByKey);
|
|
960
|
+
async function createConfiguration(req, res) {
|
|
961
|
+
const ctx = req.openhiContext;
|
|
962
|
+
const {
|
|
963
|
+
tenantId: ctxTenantId,
|
|
964
|
+
workspaceId: ctxWorkspaceId,
|
|
965
|
+
userId: ctxUserId,
|
|
966
|
+
date
|
|
967
|
+
} = ctx;
|
|
968
|
+
const body = req.body;
|
|
969
|
+
const key = body?.key;
|
|
970
|
+
if (!key || typeof key !== "string") {
|
|
971
|
+
return res.status(400).json({
|
|
972
|
+
resourceType: "OperationOutcome",
|
|
973
|
+
issue: [
|
|
974
|
+
{
|
|
975
|
+
severity: "error",
|
|
976
|
+
code: "required",
|
|
977
|
+
diagnostics: "Configuration key is required"
|
|
978
|
+
}
|
|
979
|
+
]
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
const id = body?.id ?? `config-${key}-${Date.now()}`;
|
|
983
|
+
const resourcePayload = body?.resource;
|
|
984
|
+
const resourceStr = typeof resourcePayload === "string" ? resourcePayload : JSON.stringify(resourcePayload ?? {});
|
|
985
|
+
const tenantId = body?.tenantId ?? ctxTenantId;
|
|
986
|
+
const workspaceId = body?.workspaceId ?? ctxWorkspaceId;
|
|
987
|
+
const userId = body?.userId ?? ctxUserId ?? "-";
|
|
988
|
+
const roleId = body?.roleId ?? "-";
|
|
989
|
+
const vid = body?.vid ?? (date.replace(/[-:T.Z]/g, "").slice(0, 12) || Date.now().toString(36));
|
|
990
|
+
const lastUpdated = body?.lastUpdated ?? date;
|
|
991
|
+
const service = getOhiDataService(TABLE_NAME2);
|
|
992
|
+
try {
|
|
993
|
+
await service.entities.configuration.put({
|
|
994
|
+
tenantId,
|
|
995
|
+
workspaceId,
|
|
996
|
+
userId,
|
|
997
|
+
roleId,
|
|
998
|
+
key,
|
|
999
|
+
id,
|
|
1000
|
+
resource: compressResource(resourceStr),
|
|
1001
|
+
vid,
|
|
1002
|
+
lastUpdated,
|
|
1003
|
+
sk: SK3
|
|
1004
|
+
}).go();
|
|
1005
|
+
const config = {
|
|
1006
|
+
resourceType: "Configuration",
|
|
1007
|
+
id,
|
|
1008
|
+
key,
|
|
1009
|
+
resource: typeof resourcePayload === "object" ? resourcePayload : JSON.parse(resourceStr),
|
|
1010
|
+
meta: { lastUpdated, versionId: vid }
|
|
1011
|
+
};
|
|
1012
|
+
return res.status(201).location(`${BASE_PATH3}/${key}`).json(config);
|
|
1013
|
+
} catch (err) {
|
|
1014
|
+
console.error("POST Configuration error:", err);
|
|
1015
|
+
return res.status(500).json({
|
|
1016
|
+
resourceType: "OperationOutcome",
|
|
1017
|
+
issue: [
|
|
1018
|
+
{ severity: "error", code: "exception", diagnostics: String(err) }
|
|
1019
|
+
]
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
router2.post("/", createConfiguration);
|
|
1024
|
+
async function updateConfiguration(req, res) {
|
|
1025
|
+
const key = String(req.params.key);
|
|
1026
|
+
const ctx = req.openhiContext;
|
|
1027
|
+
const { tenantId, workspaceId, userId, date } = ctx;
|
|
1028
|
+
const roleId = "roleId" in ctx && typeof ctx.roleId === "string" ? ctx.roleId : "-";
|
|
1029
|
+
const body = req.body;
|
|
1030
|
+
const resourcePayload = body?.resource;
|
|
1031
|
+
const resourceStr = typeof resourcePayload === "string" ? resourcePayload : JSON.stringify(resourcePayload ?? {});
|
|
1032
|
+
const lastUpdated = body?.lastUpdated ?? date;
|
|
1033
|
+
const service = getOhiDataService(TABLE_NAME2);
|
|
1034
|
+
try {
|
|
1035
|
+
const existing = await service.entities.configuration.get({ tenantId, workspaceId, userId, roleId, key, sk: SK3 }).go();
|
|
1036
|
+
if (!existing.data) {
|
|
1037
|
+
return res.status(404).json({
|
|
1038
|
+
resourceType: "OperationOutcome",
|
|
1039
|
+
issue: [
|
|
1040
|
+
{
|
|
1041
|
+
severity: "error",
|
|
1042
|
+
code: "not-found",
|
|
1043
|
+
diagnostics: `Configuration ${key} not found`
|
|
1044
|
+
}
|
|
1045
|
+
]
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
const nextVid = existing.data.vid != null ? String(Number(existing.data.vid) + 1) : date.replace(/[-:T.Z]/g, "").slice(0, 12) || "2";
|
|
1049
|
+
await service.entities.configuration.patch({ tenantId, workspaceId, userId, roleId, key, sk: SK3 }).set({
|
|
1050
|
+
resource: compressResource(resourceStr),
|
|
1051
|
+
lastUpdated,
|
|
1052
|
+
vid: nextVid
|
|
1053
|
+
}).go();
|
|
1054
|
+
const config = {
|
|
1055
|
+
resourceType: "Configuration",
|
|
1056
|
+
id: existing.data.id,
|
|
1057
|
+
key: existing.data.key,
|
|
1058
|
+
resource: typeof resourcePayload === "object" ? resourcePayload : JSON.parse(resourceStr),
|
|
1059
|
+
meta: { lastUpdated, versionId: nextVid }
|
|
1060
|
+
};
|
|
1061
|
+
return res.json(config);
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
console.error("PUT Configuration error:", err);
|
|
1064
|
+
return res.status(500).json({
|
|
1065
|
+
resourceType: "OperationOutcome",
|
|
1066
|
+
issue: [
|
|
1067
|
+
{ severity: "error", code: "exception", diagnostics: String(err) }
|
|
1068
|
+
]
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
router2.put("/:key", updateConfiguration);
|
|
1073
|
+
async function deleteConfiguration(req, res) {
|
|
1074
|
+
const key = String(req.params.key);
|
|
1075
|
+
const ctx = req.openhiContext;
|
|
1076
|
+
const { tenantId, workspaceId, userId } = ctx;
|
|
1077
|
+
const roleId = "roleId" in ctx && typeof ctx.roleId === "string" ? ctx.roleId : "-";
|
|
1078
|
+
const service = getOhiDataService(TABLE_NAME2);
|
|
1079
|
+
try {
|
|
1080
|
+
await service.entities.configuration.delete({ tenantId, workspaceId, userId, roleId, key, sk: SK3 }).go();
|
|
1081
|
+
return res.status(204).send();
|
|
1082
|
+
} catch (err) {
|
|
1083
|
+
console.error("DELETE Configuration error:", err);
|
|
1084
|
+
return res.status(500).json({
|
|
1085
|
+
resourceType: "OperationOutcome",
|
|
1086
|
+
issue: [
|
|
1087
|
+
{ severity: "error", code: "exception", diagnostics: String(err) }
|
|
1088
|
+
]
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
router2.delete("/:key", deleteConfiguration);
|
|
1093
|
+
|
|
628
1094
|
// src/data/rest-api/rest-api.ts
|
|
629
|
-
var app =
|
|
1095
|
+
var app = express3();
|
|
630
1096
|
app.set("view engine", "ejs");
|
|
631
1097
|
app.set("views", path.join(__dirname, "views"));
|
|
632
1098
|
app.use(cors());
|
|
633
|
-
app.use(
|
|
634
|
-
app.use(
|
|
1099
|
+
app.use(express3.json());
|
|
1100
|
+
app.use(express3.urlencoded({ extended: true }));
|
|
635
1101
|
app.get("/", (_req, res) => {
|
|
636
1102
|
return res.status(200).json({ message: "POC App is running" });
|
|
637
1103
|
});
|
|
638
1104
|
app.use("/ehr", openHiContextMiddleware);
|
|
1105
|
+
app.use("/ohi", openHiContextMiddleware);
|
|
639
1106
|
app.use("/ehr/r4/Patient", router);
|
|
1107
|
+
app.use("/ohi/Configuration", router2);
|
|
640
1108
|
|
|
641
1109
|
// src/data/lambda/rest-api-lambda.handler.ts
|
|
642
1110
|
var handler = serverlessExpress({ app });
|