@openhi/constructs 0.0.140 → 0.0.142
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.mts +16 -5
- package/lib/index.d.ts +45 -5
- package/lib/index.js +25 -6
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +25 -6
- package/lib/index.mjs.map +1 -1
- package/lib/rest-api-lambda.handler.js +400 -379
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +400 -379
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -9868,13 +9868,17 @@ function parseDateSearchValue(raw) {
|
|
|
9868
9868
|
return { prefix: "eq", value: raw };
|
|
9869
9869
|
}
|
|
9870
9870
|
function flatJsonbExtract(jsonbPath) {
|
|
9871
|
-
const
|
|
9872
|
-
if (
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9871
|
+
const topLevel = /^\$\.([A-Za-z_][A-Za-z0-9_]*)$/.exec(jsonbPath);
|
|
9872
|
+
if (topLevel) {
|
|
9873
|
+
return `resource->>'${topLevel[1]}'`;
|
|
9874
|
+
}
|
|
9875
|
+
const nested = /^\$\.([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/.exec(jsonbPath);
|
|
9876
|
+
if (nested) {
|
|
9877
|
+
return `resource->'${nested[1]}'->>'${nested[2]}'`;
|
|
9876
9878
|
}
|
|
9877
|
-
|
|
9879
|
+
throw new Error(
|
|
9880
|
+
`Generic date predicate requires a scalar JSONPath like "$.fieldName" or "$.field.subfield"; received "${jsonbPath}".`
|
|
9881
|
+
);
|
|
9878
9882
|
}
|
|
9879
9883
|
function emitDatePredicate(opts) {
|
|
9880
9884
|
const { jsonbPath, rawValue, paramName } = opts;
|
|
@@ -10282,6 +10286,53 @@ var APPOINTMENT_SEARCH_PARAMETERS = [
|
|
|
10282
10286
|
{ code: "slot", type: "reference", jsonbPath: "$.slot[*]" }
|
|
10283
10287
|
];
|
|
10284
10288
|
|
|
10289
|
+
// src/data/search/registry/encounter-search-parameters.ts
|
|
10290
|
+
var ENCOUNTER_SEARCH_PARAMETERS = [
|
|
10291
|
+
{ code: "status", type: "token", jsonbPath: "$.status" },
|
|
10292
|
+
{ code: "class", type: "token", jsonbPath: "$.class" },
|
|
10293
|
+
{ code: "type", type: "token", jsonbPath: "$.type[*]" },
|
|
10294
|
+
{ code: "subject", type: "reference", jsonbPath: "$.subject" },
|
|
10295
|
+
{ code: "patient", type: "reference", jsonbPath: "$.subject" },
|
|
10296
|
+
{
|
|
10297
|
+
code: "participant",
|
|
10298
|
+
type: "reference",
|
|
10299
|
+
jsonbPath: "$.participant[*].individual"
|
|
10300
|
+
},
|
|
10301
|
+
{ code: "date", type: "date", jsonbPath: "$.period.start" },
|
|
10302
|
+
{
|
|
10303
|
+
code: "service-provider",
|
|
10304
|
+
type: "reference",
|
|
10305
|
+
jsonbPath: "$.serviceProvider"
|
|
10306
|
+
},
|
|
10307
|
+
{ code: "appointment", type: "reference", jsonbPath: "$.appointment[*]" },
|
|
10308
|
+
{
|
|
10309
|
+
code: "episode-of-care",
|
|
10310
|
+
type: "reference",
|
|
10311
|
+
jsonbPath: "$.episodeOfCare[*]"
|
|
10312
|
+
}
|
|
10313
|
+
];
|
|
10314
|
+
|
|
10315
|
+
// src/data/search/registry/observation-search-parameters.ts
|
|
10316
|
+
var OBSERVATION_SEARCH_PARAMETERS = [
|
|
10317
|
+
{ code: "status", type: "token", jsonbPath: "$.status" },
|
|
10318
|
+
{ code: "category", type: "token", jsonbPath: "$.category[*]" },
|
|
10319
|
+
{ code: "code", type: "token", jsonbPath: "$.code" },
|
|
10320
|
+
{ code: "subject", type: "reference", jsonbPath: "$.subject" },
|
|
10321
|
+
{ code: "patient", type: "reference", jsonbPath: "$.subject" },
|
|
10322
|
+
{ code: "encounter", type: "reference", jsonbPath: "$.encounter" },
|
|
10323
|
+
{ code: "performer", type: "reference", jsonbPath: "$.performer[*]" },
|
|
10324
|
+
{ code: "date", type: "date", jsonbPath: "$.effectiveDateTime" },
|
|
10325
|
+
{
|
|
10326
|
+
code: "value-string",
|
|
10327
|
+
type: "string",
|
|
10328
|
+
jsonbPath: "$.valueString",
|
|
10329
|
+
modifiers: ["exact", "contains", "missing", "not"]
|
|
10330
|
+
},
|
|
10331
|
+
{ code: "identifier", type: "token", jsonbPath: "$.identifier[*]" },
|
|
10332
|
+
{ code: "based-on", type: "reference", jsonbPath: "$.basedOn[*]" },
|
|
10333
|
+
{ code: "part-of", type: "reference", jsonbPath: "$.partOf[*]" }
|
|
10334
|
+
];
|
|
10335
|
+
|
|
10285
10336
|
// src/data/search/registry/patient-search-parameters.ts
|
|
10286
10337
|
var PATIENT_SEARCH_PARAMETERS = [
|
|
10287
10338
|
{ code: "gender", type: "token", jsonbPath: "$.gender" },
|
|
@@ -10319,10 +10370,39 @@ var PATIENT_SEARCH_PARAMETERS = [
|
|
|
10319
10370
|
}
|
|
10320
10371
|
];
|
|
10321
10372
|
|
|
10373
|
+
// src/data/search/registry/procedure-search-parameters.ts
|
|
10374
|
+
var PROCEDURE_SEARCH_PARAMETERS = [
|
|
10375
|
+
{ code: "status", type: "token", jsonbPath: "$.status" },
|
|
10376
|
+
{ code: "category", type: "token", jsonbPath: "$.category" },
|
|
10377
|
+
{ code: "code", type: "token", jsonbPath: "$.code" },
|
|
10378
|
+
{ code: "subject", type: "reference", jsonbPath: "$.subject" },
|
|
10379
|
+
{ code: "patient", type: "reference", jsonbPath: "$.subject" },
|
|
10380
|
+
{ code: "encounter", type: "reference", jsonbPath: "$.encounter" },
|
|
10381
|
+
{
|
|
10382
|
+
code: "performer",
|
|
10383
|
+
type: "reference",
|
|
10384
|
+
jsonbPath: "$.performer[*].actor"
|
|
10385
|
+
},
|
|
10386
|
+
{ code: "date", type: "date", jsonbPath: "$.performedDateTime" },
|
|
10387
|
+
{ code: "location", type: "reference", jsonbPath: "$.location" },
|
|
10388
|
+
{ code: "identifier", type: "token", jsonbPath: "$.identifier[*]" },
|
|
10389
|
+
{ code: "based-on", type: "reference", jsonbPath: "$.basedOn[*]" },
|
|
10390
|
+
{ code: "part-of", type: "reference", jsonbPath: "$.partOf[*]" },
|
|
10391
|
+
{ code: "reason-code", type: "token", jsonbPath: "$.reasonCode[*]" },
|
|
10392
|
+
{
|
|
10393
|
+
code: "reason-reference",
|
|
10394
|
+
type: "reference",
|
|
10395
|
+
jsonbPath: "$.reasonReference[*]"
|
|
10396
|
+
}
|
|
10397
|
+
];
|
|
10398
|
+
|
|
10322
10399
|
// src/data/search/registry/resolver.ts
|
|
10323
10400
|
var STATIC_SEARCH_PARAMETER_MAP = {
|
|
10324
10401
|
Appointment: APPOINTMENT_SEARCH_PARAMETERS,
|
|
10325
|
-
|
|
10402
|
+
Encounter: ENCOUNTER_SEARCH_PARAMETERS,
|
|
10403
|
+
Observation: OBSERVATION_SEARCH_PARAMETERS,
|
|
10404
|
+
Patient: PATIENT_SEARCH_PARAMETERS,
|
|
10405
|
+
Procedure: PROCEDURE_SEARCH_PARAMETERS
|
|
10326
10406
|
};
|
|
10327
10407
|
var defaultSearchParameterResolver = (resourceType, _tenantId) => STATIC_SEARCH_PARAMETER_MAP[resourceType] ?? [];
|
|
10328
10408
|
function getRegisteredSearchParameters(resourceType) {
|
|
@@ -17973,353 +18053,108 @@ async function listEncountersOperation(params) {
|
|
|
17973
18053
|
);
|
|
17974
18054
|
}
|
|
17975
18055
|
|
|
17976
|
-
// src/data/
|
|
17977
|
-
var
|
|
17978
|
-
|
|
17979
|
-
"
|
|
17980
|
-
|
|
17981
|
-
"le",
|
|
17982
|
-
"sa",
|
|
17983
|
-
"eb"
|
|
17984
|
-
];
|
|
17985
|
-
function isPeriodSearchPrefix(s) {
|
|
17986
|
-
return PERIOD_SEARCH_PREFIXES.includes(s);
|
|
17987
|
-
}
|
|
17988
|
-
var PERIOD_START = "resource->'period'->>'start'";
|
|
17989
|
-
var PERIOD_END = "resource->'period'->>'end'";
|
|
17990
|
-
var HAS_ANY_BOUND_GUARD = `(${PERIOD_START} IS NOT NULL OR ${PERIOD_END} IS NOT NULL)`;
|
|
17991
|
-
function buildSinglePredicateSql(prefix, paramName) {
|
|
17992
|
-
switch (prefix) {
|
|
17993
|
-
case "gt":
|
|
17994
|
-
return `(${PERIOD_END} IS NULL OR ${PERIOD_END} > :${paramName})`;
|
|
17995
|
-
case "lt":
|
|
17996
|
-
return `(${PERIOD_START} IS NULL OR ${PERIOD_START} < :${paramName})`;
|
|
17997
|
-
case "ge":
|
|
17998
|
-
return `(${PERIOD_END} IS NULL OR ${PERIOD_END} >= :${paramName})`;
|
|
17999
|
-
case "le":
|
|
18000
|
-
return `(${PERIOD_START} IS NULL OR ${PERIOD_START} <= :${paramName})`;
|
|
18001
|
-
case "sa":
|
|
18002
|
-
return `(${PERIOD_START} IS NOT NULL AND ${PERIOD_START} > :${paramName})`;
|
|
18003
|
-
case "eb":
|
|
18004
|
-
return `(${PERIOD_END} IS NOT NULL AND ${PERIOD_END} < :${paramName})`;
|
|
18005
|
-
}
|
|
18006
|
-
}
|
|
18007
|
-
function periodConstraintParamName(index) {
|
|
18008
|
-
return `periodConstraint${index}`;
|
|
18009
|
-
}
|
|
18010
|
-
function buildPeriodSearchPredicateSql(constraints) {
|
|
18011
|
-
if (constraints.length === 0) {
|
|
18012
|
-
return [];
|
|
18013
|
-
}
|
|
18014
|
-
const fragments = constraints.map(
|
|
18015
|
-
(c, i) => buildSinglePredicateSql(c.prefix, periodConstraintParamName(i))
|
|
18016
|
-
);
|
|
18017
|
-
fragments.push(HAS_ANY_BOUND_GUARD);
|
|
18018
|
-
return fragments;
|
|
18019
|
-
}
|
|
18020
|
-
function buildPeriodSearchPredicateParams(constraints) {
|
|
18021
|
-
return constraints.map((c, i) => ({
|
|
18022
|
-
name: periodConstraintParamName(i),
|
|
18023
|
-
value: c.value
|
|
18024
|
-
}));
|
|
18025
|
-
}
|
|
18026
|
-
|
|
18027
|
-
// src/data/operations/data/encounter/encounter-search-by-date-operation.ts
|
|
18028
|
-
var DEFAULT_LIMIT2 = 100;
|
|
18029
|
-
function buildSearchEncountersByDateSql(opts) {
|
|
18030
|
-
const periodPredicates = buildPeriodSearchPredicateSql(
|
|
18031
|
-
opts.periodConstraints
|
|
18032
|
-
);
|
|
18033
|
-
const lines = [
|
|
18034
|
-
"SELECT resource_id AS id, resource",
|
|
18035
|
-
"FROM resources",
|
|
18036
|
-
"WHERE tenant_id = :tenantId",
|
|
18037
|
-
" AND workspace_id = :workspaceId",
|
|
18038
|
-
" AND resource_type = 'Encounter'",
|
|
18039
|
-
" AND deleted_at IS NULL"
|
|
18040
|
-
];
|
|
18041
|
-
for (const fragment of periodPredicates) {
|
|
18042
|
-
lines.push(` AND ${fragment}`);
|
|
18043
|
-
}
|
|
18044
|
-
lines.push("ORDER BY last_updated DESC");
|
|
18045
|
-
lines.push("LIMIT :limit;");
|
|
18046
|
-
return lines.join("\n");
|
|
18047
|
-
}
|
|
18048
|
-
async function searchEncountersByDateOperation(params) {
|
|
18049
|
-
const { context, periodConstraints } = params;
|
|
18050
|
-
if (periodConstraints.length === 0) {
|
|
18051
|
-
throw new Error(
|
|
18052
|
-
"searchEncountersByDateOperation requires at least one periodConstraint"
|
|
18053
|
-
);
|
|
18054
|
-
}
|
|
18055
|
-
const { tenantId, workspaceId } = context;
|
|
18056
|
-
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
18057
|
-
const limit = params.limit ?? DEFAULT_LIMIT2;
|
|
18058
|
-
const sql = buildSearchEncountersByDateSql({ periodConstraints });
|
|
18059
|
-
const queryParams = [
|
|
18060
|
-
{ name: "tenantId", value: tenantId },
|
|
18061
|
-
{ name: "workspaceId", value: workspaceId },
|
|
18062
|
-
{ name: "limit", value: limit },
|
|
18063
|
-
...buildPeriodSearchPredicateParams(periodConstraints)
|
|
18064
|
-
];
|
|
18065
|
-
const rows = await runner.query(sql, queryParams);
|
|
18066
|
-
const entries = rows.map((row) => ({
|
|
18067
|
-
id: row.id,
|
|
18068
|
-
resource: {
|
|
18069
|
-
...row.resource,
|
|
18070
|
-
id: row.id
|
|
18071
|
-
}
|
|
18072
|
-
}));
|
|
18073
|
-
return { entries, total: entries.length };
|
|
18056
|
+
// src/data/rest-api/routes/data/encounter/encounter-list-route.ts
|
|
18057
|
+
var ENCOUNTER_RESOURCE_TYPE = "Encounter";
|
|
18058
|
+
function stripModifier2(key) {
|
|
18059
|
+
const idx = key.indexOf(":");
|
|
18060
|
+
return idx === -1 ? key : key.slice(0, idx);
|
|
18074
18061
|
}
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
var DEFAULT_LIMIT3 = 100;
|
|
18078
|
-
function buildSearchEncountersByParticipantSql(opts) {
|
|
18079
|
-
const periodPredicates = buildPeriodSearchPredicateSql(
|
|
18080
|
-
opts?.periodConstraints ?? []
|
|
18081
|
-
);
|
|
18082
|
-
const lines = [
|
|
18083
|
-
"SELECT resource_id AS id, resource",
|
|
18084
|
-
"FROM resources",
|
|
18085
|
-
"WHERE tenant_id = :tenantId",
|
|
18086
|
-
" AND workspace_id = :workspaceId",
|
|
18087
|
-
" AND resource_type = 'Encounter'",
|
|
18088
|
-
" AND deleted_at IS NULL",
|
|
18089
|
-
` AND ${REFERENCE_CONTAINMENT_SQL_FRAGMENT}`
|
|
18090
|
-
];
|
|
18091
|
-
for (const fragment of periodPredicates) {
|
|
18092
|
-
lines.push(` AND ${fragment}`);
|
|
18093
|
-
}
|
|
18094
|
-
lines.push("ORDER BY last_updated DESC");
|
|
18095
|
-
lines.push("LIMIT :limit;");
|
|
18096
|
-
return lines.join("\n");
|
|
18062
|
+
function isResultParameter2(key) {
|
|
18063
|
+
return key.startsWith("_");
|
|
18097
18064
|
}
|
|
18098
|
-
|
|
18099
|
-
|
|
18100
|
-
|
|
18101
|
-
|
|
18102
|
-
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
18103
|
-
const limit = params.limit ?? DEFAULT_LIMIT3;
|
|
18104
|
-
const { containmentRelative, containmentUrn } = buildReferenceContainmentPayload({
|
|
18105
|
-
shape: {
|
|
18106
|
-
kind: "array-of-objects",
|
|
18107
|
-
field: "participant",
|
|
18108
|
-
subfield: "individual"
|
|
18109
|
-
},
|
|
18110
|
-
reference: participantReference,
|
|
18111
|
-
tenantId,
|
|
18112
|
-
workspaceId
|
|
18065
|
+
function sendInvalidSearch4002(res, diagnostics) {
|
|
18066
|
+
return res.status(400).json({
|
|
18067
|
+
resourceType: "OperationOutcome",
|
|
18068
|
+
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
18113
18069
|
});
|
|
18114
|
-
const sql = buildSearchEncountersByParticipantSql({ periodConstraints });
|
|
18115
|
-
const queryParams = [
|
|
18116
|
-
{ name: "tenantId", value: tenantId },
|
|
18117
|
-
{ name: "workspaceId", value: workspaceId },
|
|
18118
|
-
{ name: "containmentRelative", value: containmentRelative },
|
|
18119
|
-
{ name: "containmentUrn", value: containmentUrn },
|
|
18120
|
-
{ name: "limit", value: limit },
|
|
18121
|
-
...buildPeriodSearchPredicateParams(periodConstraints)
|
|
18122
|
-
];
|
|
18123
|
-
const rows = await runner.query(sql, queryParams);
|
|
18124
|
-
const entries = rows.map((row) => ({
|
|
18125
|
-
id: row.id,
|
|
18126
|
-
resource: {
|
|
18127
|
-
...row.resource,
|
|
18128
|
-
id: row.id
|
|
18129
|
-
}
|
|
18130
|
-
}));
|
|
18131
|
-
return { entries, total: entries.length };
|
|
18132
18070
|
}
|
|
18133
|
-
|
|
18134
|
-
|
|
18135
|
-
|
|
18136
|
-
|
|
18137
|
-
|
|
18138
|
-
opts?.periodConstraints ?? []
|
|
18139
|
-
);
|
|
18140
|
-
const lines = [
|
|
18141
|
-
"SELECT resource_id AS id, resource",
|
|
18142
|
-
"FROM resources",
|
|
18143
|
-
"WHERE tenant_id = :tenantId",
|
|
18144
|
-
" AND workspace_id = :workspaceId",
|
|
18145
|
-
" AND resource_type = 'Encounter'",
|
|
18146
|
-
" AND deleted_at IS NULL",
|
|
18147
|
-
" AND (resource @> :containmentRelative::jsonb",
|
|
18148
|
-
" OR resource @> :containmentUrn::jsonb)"
|
|
18149
|
-
];
|
|
18150
|
-
for (const fragment of periodPredicates) {
|
|
18151
|
-
lines.push(` AND ${fragment}`);
|
|
18152
|
-
}
|
|
18153
|
-
lines.push("ORDER BY last_updated DESC");
|
|
18154
|
-
lines.push("LIMIT :limit;");
|
|
18155
|
-
return lines.join("\n");
|
|
18156
|
-
}
|
|
18157
|
-
async function searchEncountersByPatientOperation(params) {
|
|
18158
|
-
const { context, patientId } = params;
|
|
18159
|
-
const periodConstraints = params.periodConstraints ?? [];
|
|
18160
|
-
const { tenantId, workspaceId } = context;
|
|
18161
|
-
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
18162
|
-
const limit = params.limit ?? DEFAULT_LIMIT4;
|
|
18163
|
-
const containmentRelative = JSON.stringify({
|
|
18164
|
-
subject: { reference: `Patient/${patientId}` }
|
|
18165
|
-
});
|
|
18166
|
-
const containmentUrn = JSON.stringify({
|
|
18167
|
-
subject: {
|
|
18168
|
-
reference: buildOpenHiResourceUrn({
|
|
18169
|
-
tenantId,
|
|
18170
|
-
workspaceId,
|
|
18171
|
-
resourceType: "Patient",
|
|
18172
|
-
resourceId: patientId
|
|
18173
|
-
})
|
|
18174
|
-
}
|
|
18175
|
-
});
|
|
18176
|
-
const sql = buildSearchEncountersByPatientSql({ periodConstraints });
|
|
18177
|
-
const queryParams = [
|
|
18178
|
-
{ name: "tenantId", value: tenantId },
|
|
18179
|
-
{ name: "workspaceId", value: workspaceId },
|
|
18180
|
-
{ name: "containmentRelative", value: containmentRelative },
|
|
18181
|
-
{ name: "containmentUrn", value: containmentUrn },
|
|
18182
|
-
{ name: "limit", value: limit },
|
|
18183
|
-
...buildPeriodSearchPredicateParams(periodConstraints)
|
|
18184
|
-
];
|
|
18185
|
-
const rows = await runner.query(sql, queryParams);
|
|
18186
|
-
const entries = rows.map((row) => ({
|
|
18187
|
-
id: row.id,
|
|
18188
|
-
resource: {
|
|
18189
|
-
...row.resource,
|
|
18190
|
-
id: row.id
|
|
18071
|
+
function extractSearchParamKeys2(query) {
|
|
18072
|
+
const out = [];
|
|
18073
|
+
for (const rawKey of Object.keys(query)) {
|
|
18074
|
+
if (isResultParameter2(rawKey)) {
|
|
18075
|
+
continue;
|
|
18191
18076
|
}
|
|
18192
|
-
|
|
18193
|
-
return { entries, total: entries.length };
|
|
18194
|
-
}
|
|
18195
|
-
|
|
18196
|
-
// src/data/rest-api/routes/data/encounter/encounter-list-route.ts
|
|
18197
|
-
function singleStringQueryParam(req, name) {
|
|
18198
|
-
const v = req.query[name];
|
|
18199
|
-
if (typeof v !== "string") {
|
|
18200
|
-
return void 0;
|
|
18077
|
+
out.push({ rawKey, code: stripModifier2(rawKey) });
|
|
18201
18078
|
}
|
|
18202
|
-
|
|
18203
|
-
return trimmed === "" ? void 0 : trimmed;
|
|
18079
|
+
return out;
|
|
18204
18080
|
}
|
|
18205
|
-
function
|
|
18206
|
-
|
|
18081
|
+
function buildUnknownParamDiagnostics2(unknownCodes) {
|
|
18082
|
+
const validCodes = getRegisteredSearchParameters(ENCOUNTER_RESOURCE_TYPE).map((p) => p.code).sort().join(", ");
|
|
18083
|
+
const codes = unknownCodes.join(", ");
|
|
18084
|
+
const isPlural = unknownCodes.length !== 1;
|
|
18085
|
+
return [
|
|
18086
|
+
`Unknown search ${isPlural ? "parameters" : "parameter"} for Encounter: ${codes}.`,
|
|
18087
|
+
`Valid codes: ${validCodes}.`
|
|
18088
|
+
].join(" ");
|
|
18207
18089
|
}
|
|
18208
|
-
function
|
|
18209
|
-
const
|
|
18210
|
-
|
|
18211
|
-
|
|
18212
|
-
}
|
|
18213
|
-
|
|
18214
|
-
|
|
18215
|
-
for (const v of values) {
|
|
18216
|
-
if (typeof v !== "string") {
|
|
18217
|
-
return { error: "Each ?date= value must be a string." };
|
|
18218
|
-
}
|
|
18219
|
-
const trimmed = v.trim();
|
|
18220
|
-
if (trimmed === "") {
|
|
18221
|
-
return { error: "?date= value must not be empty." };
|
|
18222
|
-
}
|
|
18223
|
-
const prefix = trimmed.slice(0, 2);
|
|
18224
|
-
const datetime = trimmed.slice(2);
|
|
18225
|
-
if (!isPeriodSearchPrefix(prefix)) {
|
|
18226
|
-
return {
|
|
18227
|
-
error: `Unsupported ?date= prefix in "${trimmed}". Supported prefixes: ${PERIOD_SEARCH_PREFIXES.join(", ")}.`
|
|
18228
|
-
};
|
|
18090
|
+
function findMalformedReference2(query, searchParamKeys) {
|
|
18091
|
+
const referenceCodes = new Set(
|
|
18092
|
+
getRegisteredSearchParameters(ENCOUNTER_RESOURCE_TYPE).filter((p) => p.type === "reference").map((p) => p.code)
|
|
18093
|
+
);
|
|
18094
|
+
for (const { rawKey, code } of searchParamKeys) {
|
|
18095
|
+
if (!referenceCodes.has(code)) {
|
|
18096
|
+
continue;
|
|
18229
18097
|
}
|
|
18230
|
-
|
|
18231
|
-
|
|
18098
|
+
const raw = query[rawKey];
|
|
18099
|
+
const values = typeof raw === "string" ? raw.split(",") : Array.isArray(raw) ? raw.flatMap((v) => v.split(",")) : [];
|
|
18100
|
+
for (const v of values) {
|
|
18101
|
+
const trimmed = v.trim();
|
|
18102
|
+
if (trimmed.length === 0) {
|
|
18103
|
+
continue;
|
|
18104
|
+
}
|
|
18105
|
+
if (parseTypedReference(trimmed) === void 0) {
|
|
18106
|
+
return { rawKey, value: trimmed };
|
|
18107
|
+
}
|
|
18232
18108
|
}
|
|
18233
|
-
out.push({ prefix, value: datetime });
|
|
18234
18109
|
}
|
|
18235
|
-
return
|
|
18236
|
-
}
|
|
18237
|
-
function sendInvalidSearch4002(res, diagnostics) {
|
|
18238
|
-
return res.status(400).json({
|
|
18239
|
-
resourceType: "OperationOutcome",
|
|
18240
|
-
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
18241
|
-
});
|
|
18110
|
+
return void 0;
|
|
18242
18111
|
}
|
|
18243
18112
|
async function listEncountersRoute(req, res) {
|
|
18244
|
-
const
|
|
18245
|
-
|
|
18246
|
-
|
|
18247
|
-
if (
|
|
18248
|
-
return
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
|
|
18113
|
+
const searchParamKeys = extractSearchParamKeys2(
|
|
18114
|
+
req.query
|
|
18115
|
+
);
|
|
18116
|
+
if (searchParamKeys.length === 0) {
|
|
18117
|
+
return handleListRoute({
|
|
18118
|
+
req,
|
|
18119
|
+
res,
|
|
18120
|
+
basePath: BASE_PATH.ENCOUNTER,
|
|
18121
|
+
listOperation: listEncountersOperation,
|
|
18122
|
+
errorLogContext: "GET /Encounter list error:"
|
|
18123
|
+
});
|
|
18124
|
+
}
|
|
18125
|
+
const registered = getRegisteredSearchParameters(ENCOUNTER_RESOURCE_TYPE);
|
|
18126
|
+
const validCodes = new Set(registered.map((p) => p.code));
|
|
18127
|
+
const unknownCodes = searchParamKeys.map((k) => k.code).filter((code) => !validCodes.has(code));
|
|
18128
|
+
if (unknownCodes.length > 0) {
|
|
18252
18129
|
return sendInvalidSearch4002(
|
|
18253
18130
|
res,
|
|
18254
|
-
|
|
18131
|
+
buildUnknownParamDiagnostics2([...new Set(unknownCodes)])
|
|
18255
18132
|
);
|
|
18256
18133
|
}
|
|
18257
|
-
|
|
18258
|
-
|
|
18259
|
-
|
|
18260
|
-
|
|
18261
|
-
|
|
18262
|
-
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18266
|
-
const result = await searchEncountersByParticipantOperation({
|
|
18267
|
-
context: ctx,
|
|
18268
|
-
participantReference: participantRef,
|
|
18269
|
-
periodConstraints
|
|
18270
|
-
});
|
|
18271
|
-
const bundle = buildSearchsetBundle(BASE_PATH.ENCOUNTER, result.entries);
|
|
18272
|
-
return res.json(bundle);
|
|
18273
|
-
} catch (err) {
|
|
18274
|
-
return sendOperationOutcome500(
|
|
18275
|
-
res,
|
|
18276
|
-
err,
|
|
18277
|
-
"GET /Encounter?participant= search error:"
|
|
18278
|
-
);
|
|
18279
|
-
}
|
|
18280
|
-
}
|
|
18281
|
-
if (patientId !== void 0) {
|
|
18282
|
-
const ctx = req.openhiContext;
|
|
18283
|
-
try {
|
|
18284
|
-
const result = await searchEncountersByPatientOperation({
|
|
18285
|
-
context: ctx,
|
|
18286
|
-
patientId,
|
|
18287
|
-
periodConstraints
|
|
18288
|
-
});
|
|
18289
|
-
const bundle = buildSearchsetBundle(BASE_PATH.ENCOUNTER, result.entries);
|
|
18290
|
-
return res.json(bundle);
|
|
18291
|
-
} catch (err) {
|
|
18292
|
-
return sendOperationOutcome500(
|
|
18293
|
-
res,
|
|
18294
|
-
err,
|
|
18295
|
-
"GET /Encounter?patient= search error:"
|
|
18296
|
-
);
|
|
18297
|
-
}
|
|
18134
|
+
const malformedRef = findMalformedReference2(
|
|
18135
|
+
req.query,
|
|
18136
|
+
searchParamKeys
|
|
18137
|
+
);
|
|
18138
|
+
if (malformedRef !== void 0) {
|
|
18139
|
+
return sendInvalidSearch4002(
|
|
18140
|
+
res,
|
|
18141
|
+
`?${malformedRef.rawKey} must be a typed reference like "Practitioner/<id>"; got "${malformedRef.value}".`
|
|
18142
|
+
);
|
|
18298
18143
|
}
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
|
|
18311
|
-
|
|
18312
|
-
"GET /Encounter?date= search error:"
|
|
18313
|
-
);
|
|
18314
|
-
}
|
|
18144
|
+
const ctx = req.openhiContext;
|
|
18145
|
+
try {
|
|
18146
|
+
const result = await genericSearchOperation({
|
|
18147
|
+
resourceType: ENCOUNTER_RESOURCE_TYPE,
|
|
18148
|
+
tenantId: ctx.tenantId,
|
|
18149
|
+
workspaceId: ctx.workspaceId,
|
|
18150
|
+
query: req.query,
|
|
18151
|
+
resolver: defaultSearchParameterResolver
|
|
18152
|
+
});
|
|
18153
|
+
const bundle = buildSearchsetBundle(BASE_PATH.ENCOUNTER, result.entries);
|
|
18154
|
+
return res.json(bundle);
|
|
18155
|
+
} catch (err) {
|
|
18156
|
+
return sendOperationOutcome500(res, err, "GET /Encounter search error:");
|
|
18315
18157
|
}
|
|
18316
|
-
return handleListRoute({
|
|
18317
|
-
req,
|
|
18318
|
-
res,
|
|
18319
|
-
basePath: BASE_PATH.ENCOUNTER,
|
|
18320
|
-
listOperation: listEncountersOperation,
|
|
18321
|
-
errorLogContext: "GET /Encounter list error:"
|
|
18322
|
-
});
|
|
18323
18158
|
}
|
|
18324
18159
|
|
|
18325
18160
|
// src/data/operations/data/encounter/encounter-update-operation.ts
|
|
@@ -29034,15 +28869,108 @@ async function listObservationsOperation(params) {
|
|
|
29034
28869
|
}
|
|
29035
28870
|
|
|
29036
28871
|
// src/data/rest-api/routes/data/observation/observation-list-route.ts
|
|
29037
|
-
|
|
29038
|
-
|
|
29039
|
-
|
|
29040
|
-
|
|
29041
|
-
|
|
29042
|
-
|
|
29043
|
-
|
|
28872
|
+
var OBSERVATION_RESOURCE_TYPE = "Observation";
|
|
28873
|
+
function stripModifier3(key) {
|
|
28874
|
+
const idx = key.indexOf(":");
|
|
28875
|
+
return idx === -1 ? key : key.slice(0, idx);
|
|
28876
|
+
}
|
|
28877
|
+
function isResultParameter3(key) {
|
|
28878
|
+
return key.startsWith("_");
|
|
28879
|
+
}
|
|
28880
|
+
function sendInvalidSearch4003(res, diagnostics) {
|
|
28881
|
+
return res.status(400).json({
|
|
28882
|
+
resourceType: "OperationOutcome",
|
|
28883
|
+
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
29044
28884
|
});
|
|
29045
28885
|
}
|
|
28886
|
+
function extractSearchParamKeys3(query) {
|
|
28887
|
+
const out = [];
|
|
28888
|
+
for (const rawKey of Object.keys(query)) {
|
|
28889
|
+
if (isResultParameter3(rawKey)) {
|
|
28890
|
+
continue;
|
|
28891
|
+
}
|
|
28892
|
+
out.push({ rawKey, code: stripModifier3(rawKey) });
|
|
28893
|
+
}
|
|
28894
|
+
return out;
|
|
28895
|
+
}
|
|
28896
|
+
function buildUnknownParamDiagnostics3(unknownCodes) {
|
|
28897
|
+
const validCodes = getRegisteredSearchParameters(OBSERVATION_RESOURCE_TYPE).map((p) => p.code).sort().join(", ");
|
|
28898
|
+
const codes = unknownCodes.join(", ");
|
|
28899
|
+
const isPlural = unknownCodes.length !== 1;
|
|
28900
|
+
return [
|
|
28901
|
+
`Unknown search ${isPlural ? "parameters" : "parameter"} for Observation: ${codes}.`,
|
|
28902
|
+
`Valid codes: ${validCodes}.`
|
|
28903
|
+
].join(" ");
|
|
28904
|
+
}
|
|
28905
|
+
function findMalformedReference3(query, searchParamKeys) {
|
|
28906
|
+
const referenceCodes = new Set(
|
|
28907
|
+
getRegisteredSearchParameters(OBSERVATION_RESOURCE_TYPE).filter((p) => p.type === "reference").map((p) => p.code)
|
|
28908
|
+
);
|
|
28909
|
+
for (const { rawKey, code } of searchParamKeys) {
|
|
28910
|
+
if (!referenceCodes.has(code)) {
|
|
28911
|
+
continue;
|
|
28912
|
+
}
|
|
28913
|
+
const raw = query[rawKey];
|
|
28914
|
+
const values = typeof raw === "string" ? raw.split(",") : Array.isArray(raw) ? raw.flatMap((v) => v.split(",")) : [];
|
|
28915
|
+
for (const v of values) {
|
|
28916
|
+
const trimmed = v.trim();
|
|
28917
|
+
if (trimmed.length === 0) {
|
|
28918
|
+
continue;
|
|
28919
|
+
}
|
|
28920
|
+
if (parseTypedReference(trimmed) === void 0) {
|
|
28921
|
+
return { rawKey, value: trimmed };
|
|
28922
|
+
}
|
|
28923
|
+
}
|
|
28924
|
+
}
|
|
28925
|
+
return void 0;
|
|
28926
|
+
}
|
|
28927
|
+
async function listObservationsRoute(req, res) {
|
|
28928
|
+
const searchParamKeys = extractSearchParamKeys3(
|
|
28929
|
+
req.query
|
|
28930
|
+
);
|
|
28931
|
+
if (searchParamKeys.length === 0) {
|
|
28932
|
+
return handleListRoute({
|
|
28933
|
+
req,
|
|
28934
|
+
res,
|
|
28935
|
+
basePath: BASE_PATH.OBSERVATION,
|
|
28936
|
+
listOperation: listObservationsOperation,
|
|
28937
|
+
errorLogContext: "GET /Observation list error:"
|
|
28938
|
+
});
|
|
28939
|
+
}
|
|
28940
|
+
const registered = getRegisteredSearchParameters(OBSERVATION_RESOURCE_TYPE);
|
|
28941
|
+
const validCodes = new Set(registered.map((p) => p.code));
|
|
28942
|
+
const unknownCodes = searchParamKeys.map((k) => k.code).filter((code) => !validCodes.has(code));
|
|
28943
|
+
if (unknownCodes.length > 0) {
|
|
28944
|
+
return sendInvalidSearch4003(
|
|
28945
|
+
res,
|
|
28946
|
+
buildUnknownParamDiagnostics3([...new Set(unknownCodes)])
|
|
28947
|
+
);
|
|
28948
|
+
}
|
|
28949
|
+
const malformedRef = findMalformedReference3(
|
|
28950
|
+
req.query,
|
|
28951
|
+
searchParamKeys
|
|
28952
|
+
);
|
|
28953
|
+
if (malformedRef !== void 0) {
|
|
28954
|
+
return sendInvalidSearch4003(
|
|
28955
|
+
res,
|
|
28956
|
+
`?${malformedRef.rawKey} must be a typed reference like "Practitioner/<id>"; got "${malformedRef.value}".`
|
|
28957
|
+
);
|
|
28958
|
+
}
|
|
28959
|
+
const ctx = req.openhiContext;
|
|
28960
|
+
try {
|
|
28961
|
+
const result = await genericSearchOperation({
|
|
28962
|
+
resourceType: OBSERVATION_RESOURCE_TYPE,
|
|
28963
|
+
tenantId: ctx.tenantId,
|
|
28964
|
+
workspaceId: ctx.workspaceId,
|
|
28965
|
+
query: req.query,
|
|
28966
|
+
resolver: defaultSearchParameterResolver
|
|
28967
|
+
});
|
|
28968
|
+
const bundle = buildSearchsetBundle(BASE_PATH.OBSERVATION, result.entries);
|
|
28969
|
+
return res.json(bundle);
|
|
28970
|
+
} catch (err) {
|
|
28971
|
+
return sendOperationOutcome500(res, err, "GET /Observation search error:");
|
|
28972
|
+
}
|
|
28973
|
+
}
|
|
29046
28974
|
|
|
29047
28975
|
// src/data/operations/data/observation/observation-update-operation.ts
|
|
29048
28976
|
async function updateObservationOperation(params) {
|
|
@@ -30053,30 +29981,30 @@ async function listPatientsOperation(params) {
|
|
|
30053
29981
|
|
|
30054
29982
|
// src/data/rest-api/routes/data/patient/patient-list-route.ts
|
|
30055
29983
|
var PATIENT_RESOURCE_TYPE = "Patient";
|
|
30056
|
-
function
|
|
29984
|
+
function stripModifier4(key) {
|
|
30057
29985
|
const idx = key.indexOf(":");
|
|
30058
29986
|
return idx === -1 ? key : key.slice(0, idx);
|
|
30059
29987
|
}
|
|
30060
|
-
function
|
|
29988
|
+
function isResultParameter4(key) {
|
|
30061
29989
|
return key.startsWith("_");
|
|
30062
29990
|
}
|
|
30063
|
-
function
|
|
29991
|
+
function sendInvalidSearch4004(res, diagnostics) {
|
|
30064
29992
|
return res.status(400).json({
|
|
30065
29993
|
resourceType: "OperationOutcome",
|
|
30066
29994
|
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
30067
29995
|
});
|
|
30068
29996
|
}
|
|
30069
|
-
function
|
|
29997
|
+
function extractSearchParamKeys4(query) {
|
|
30070
29998
|
const out = [];
|
|
30071
29999
|
for (const rawKey of Object.keys(query)) {
|
|
30072
|
-
if (
|
|
30000
|
+
if (isResultParameter4(rawKey)) {
|
|
30073
30001
|
continue;
|
|
30074
30002
|
}
|
|
30075
|
-
out.push({ rawKey, code:
|
|
30003
|
+
out.push({ rawKey, code: stripModifier4(rawKey) });
|
|
30076
30004
|
}
|
|
30077
30005
|
return out;
|
|
30078
30006
|
}
|
|
30079
|
-
function
|
|
30007
|
+
function buildUnknownParamDiagnostics4(unknownCodes) {
|
|
30080
30008
|
const validCodes = getRegisteredSearchParameters(PATIENT_RESOURCE_TYPE).map((p) => p.code).sort().join(", ");
|
|
30081
30009
|
const codes = unknownCodes.join(", ");
|
|
30082
30010
|
const isPlural = unknownCodes.length !== 1;
|
|
@@ -30085,7 +30013,7 @@ function buildUnknownParamDiagnostics2(unknownCodes) {
|
|
|
30085
30013
|
`Valid codes: ${validCodes}.`
|
|
30086
30014
|
].join(" ");
|
|
30087
30015
|
}
|
|
30088
|
-
function
|
|
30016
|
+
function findMalformedReference4(query, searchParamKeys) {
|
|
30089
30017
|
const referenceCodes = new Set(
|
|
30090
30018
|
getRegisteredSearchParameters(PATIENT_RESOURCE_TYPE).filter((p) => p.type === "reference").map((p) => p.code)
|
|
30091
30019
|
);
|
|
@@ -30108,7 +30036,7 @@ function findMalformedReference2(query, searchParamKeys) {
|
|
|
30108
30036
|
return void 0;
|
|
30109
30037
|
}
|
|
30110
30038
|
async function listPatientsRoute(req, res) {
|
|
30111
|
-
const searchParamKeys =
|
|
30039
|
+
const searchParamKeys = extractSearchParamKeys4(
|
|
30112
30040
|
req.query
|
|
30113
30041
|
);
|
|
30114
30042
|
if (searchParamKeys.length === 0) {
|
|
@@ -30124,17 +30052,17 @@ async function listPatientsRoute(req, res) {
|
|
|
30124
30052
|
const validCodes = new Set(registered.map((p) => p.code));
|
|
30125
30053
|
const unknownCodes = searchParamKeys.map((k) => k.code).filter((code) => !validCodes.has(code));
|
|
30126
30054
|
if (unknownCodes.length > 0) {
|
|
30127
|
-
return
|
|
30055
|
+
return sendInvalidSearch4004(
|
|
30128
30056
|
res,
|
|
30129
|
-
|
|
30057
|
+
buildUnknownParamDiagnostics4([...new Set(unknownCodes)])
|
|
30130
30058
|
);
|
|
30131
30059
|
}
|
|
30132
|
-
const malformedRef =
|
|
30060
|
+
const malformedRef = findMalformedReference4(
|
|
30133
30061
|
req.query,
|
|
30134
30062
|
searchParamKeys
|
|
30135
30063
|
);
|
|
30136
30064
|
if (malformedRef !== void 0) {
|
|
30137
|
-
return
|
|
30065
|
+
return sendInvalidSearch4004(
|
|
30138
30066
|
res,
|
|
30139
30067
|
`?${malformedRef.rawKey} must be a typed reference like "Practitioner/<id>"; got "${malformedRef.value}".`
|
|
30140
30068
|
);
|
|
@@ -31508,15 +31436,108 @@ async function listProceduresOperation(params) {
|
|
|
31508
31436
|
}
|
|
31509
31437
|
|
|
31510
31438
|
// src/data/rest-api/routes/data/procedure/procedure-list-route.ts
|
|
31511
|
-
|
|
31512
|
-
|
|
31513
|
-
|
|
31514
|
-
|
|
31515
|
-
|
|
31516
|
-
|
|
31517
|
-
|
|
31439
|
+
var PROCEDURE_RESOURCE_TYPE = "Procedure";
|
|
31440
|
+
function stripModifier5(key) {
|
|
31441
|
+
const idx = key.indexOf(":");
|
|
31442
|
+
return idx === -1 ? key : key.slice(0, idx);
|
|
31443
|
+
}
|
|
31444
|
+
function isResultParameter5(key) {
|
|
31445
|
+
return key.startsWith("_");
|
|
31446
|
+
}
|
|
31447
|
+
function sendInvalidSearch4005(res, diagnostics) {
|
|
31448
|
+
return res.status(400).json({
|
|
31449
|
+
resourceType: "OperationOutcome",
|
|
31450
|
+
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
31518
31451
|
});
|
|
31519
31452
|
}
|
|
31453
|
+
function extractSearchParamKeys5(query) {
|
|
31454
|
+
const out = [];
|
|
31455
|
+
for (const rawKey of Object.keys(query)) {
|
|
31456
|
+
if (isResultParameter5(rawKey)) {
|
|
31457
|
+
continue;
|
|
31458
|
+
}
|
|
31459
|
+
out.push({ rawKey, code: stripModifier5(rawKey) });
|
|
31460
|
+
}
|
|
31461
|
+
return out;
|
|
31462
|
+
}
|
|
31463
|
+
function buildUnknownParamDiagnostics5(unknownCodes) {
|
|
31464
|
+
const validCodes = getRegisteredSearchParameters(PROCEDURE_RESOURCE_TYPE).map((p) => p.code).sort().join(", ");
|
|
31465
|
+
const codes = unknownCodes.join(", ");
|
|
31466
|
+
const isPlural = unknownCodes.length !== 1;
|
|
31467
|
+
return [
|
|
31468
|
+
`Unknown search ${isPlural ? "parameters" : "parameter"} for Procedure: ${codes}.`,
|
|
31469
|
+
`Valid codes: ${validCodes}.`
|
|
31470
|
+
].join(" ");
|
|
31471
|
+
}
|
|
31472
|
+
function findMalformedReference5(query, searchParamKeys) {
|
|
31473
|
+
const referenceCodes = new Set(
|
|
31474
|
+
getRegisteredSearchParameters(PROCEDURE_RESOURCE_TYPE).filter((p) => p.type === "reference").map((p) => p.code)
|
|
31475
|
+
);
|
|
31476
|
+
for (const { rawKey, code } of searchParamKeys) {
|
|
31477
|
+
if (!referenceCodes.has(code)) {
|
|
31478
|
+
continue;
|
|
31479
|
+
}
|
|
31480
|
+
const raw = query[rawKey];
|
|
31481
|
+
const values = typeof raw === "string" ? raw.split(",") : Array.isArray(raw) ? raw.flatMap((v) => v.split(",")) : [];
|
|
31482
|
+
for (const v of values) {
|
|
31483
|
+
const trimmed = v.trim();
|
|
31484
|
+
if (trimmed.length === 0) {
|
|
31485
|
+
continue;
|
|
31486
|
+
}
|
|
31487
|
+
if (parseTypedReference(trimmed) === void 0) {
|
|
31488
|
+
return { rawKey, value: trimmed };
|
|
31489
|
+
}
|
|
31490
|
+
}
|
|
31491
|
+
}
|
|
31492
|
+
return void 0;
|
|
31493
|
+
}
|
|
31494
|
+
async function listProceduresRoute(req, res) {
|
|
31495
|
+
const searchParamKeys = extractSearchParamKeys5(
|
|
31496
|
+
req.query
|
|
31497
|
+
);
|
|
31498
|
+
if (searchParamKeys.length === 0) {
|
|
31499
|
+
return handleListRoute({
|
|
31500
|
+
req,
|
|
31501
|
+
res,
|
|
31502
|
+
basePath: BASE_PATH.PROCEDURE,
|
|
31503
|
+
listOperation: listProceduresOperation,
|
|
31504
|
+
errorLogContext: "GET /Procedure list error:"
|
|
31505
|
+
});
|
|
31506
|
+
}
|
|
31507
|
+
const registered = getRegisteredSearchParameters(PROCEDURE_RESOURCE_TYPE);
|
|
31508
|
+
const validCodes = new Set(registered.map((p) => p.code));
|
|
31509
|
+
const unknownCodes = searchParamKeys.map((k) => k.code).filter((code) => !validCodes.has(code));
|
|
31510
|
+
if (unknownCodes.length > 0) {
|
|
31511
|
+
return sendInvalidSearch4005(
|
|
31512
|
+
res,
|
|
31513
|
+
buildUnknownParamDiagnostics5([...new Set(unknownCodes)])
|
|
31514
|
+
);
|
|
31515
|
+
}
|
|
31516
|
+
const malformedRef = findMalformedReference5(
|
|
31517
|
+
req.query,
|
|
31518
|
+
searchParamKeys
|
|
31519
|
+
);
|
|
31520
|
+
if (malformedRef !== void 0) {
|
|
31521
|
+
return sendInvalidSearch4005(
|
|
31522
|
+
res,
|
|
31523
|
+
`?${malformedRef.rawKey} must be a typed reference like "Practitioner/<id>"; got "${malformedRef.value}".`
|
|
31524
|
+
);
|
|
31525
|
+
}
|
|
31526
|
+
const ctx = req.openhiContext;
|
|
31527
|
+
try {
|
|
31528
|
+
const result = await genericSearchOperation({
|
|
31529
|
+
resourceType: PROCEDURE_RESOURCE_TYPE,
|
|
31530
|
+
tenantId: ctx.tenantId,
|
|
31531
|
+
workspaceId: ctx.workspaceId,
|
|
31532
|
+
query: req.query,
|
|
31533
|
+
resolver: defaultSearchParameterResolver
|
|
31534
|
+
});
|
|
31535
|
+
const bundle = buildSearchsetBundle(BASE_PATH.PROCEDURE, result.entries);
|
|
31536
|
+
return res.json(bundle);
|
|
31537
|
+
} catch (err) {
|
|
31538
|
+
return sendOperationOutcome500(res, err, "GET /Procedure search error:");
|
|
31539
|
+
}
|
|
31540
|
+
}
|
|
31520
31541
|
|
|
31521
31542
|
// src/data/operations/data/procedure/procedure-update-operation.ts
|
|
31522
31543
|
async function updateProcedureOperation(params) {
|
|
@@ -33972,7 +33993,7 @@ async function listSchedulesOperation(params) {
|
|
|
33972
33993
|
}
|
|
33973
33994
|
|
|
33974
33995
|
// src/data/operations/data/schedule/schedule-search-by-actor-operation.ts
|
|
33975
|
-
var
|
|
33996
|
+
var DEFAULT_LIMIT2 = 100;
|
|
33976
33997
|
function buildSearchSchedulesByActorSql() {
|
|
33977
33998
|
return [
|
|
33978
33999
|
"SELECT resource_id AS id, resource",
|
|
@@ -33990,7 +34011,7 @@ async function searchSchedulesByActorOperation(params) {
|
|
|
33990
34011
|
const { context, actorReference } = params;
|
|
33991
34012
|
const { tenantId, workspaceId } = context;
|
|
33992
34013
|
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
33993
|
-
const limit = params.limit ??
|
|
34014
|
+
const limit = params.limit ?? DEFAULT_LIMIT2;
|
|
33994
34015
|
const { containmentRelative, containmentUrn } = buildReferenceContainmentPayload({
|
|
33995
34016
|
shape: { kind: "array-of-references", field: "actor" },
|
|
33996
34017
|
reference: actorReference,
|
|
@@ -34016,7 +34037,7 @@ async function searchSchedulesByActorOperation(params) {
|
|
|
34016
34037
|
}
|
|
34017
34038
|
|
|
34018
34039
|
// src/data/rest-api/routes/data/schedule/schedule-list-route.ts
|
|
34019
|
-
function
|
|
34040
|
+
function singleStringQueryParam(req, name) {
|
|
34020
34041
|
const v = req.query[name];
|
|
34021
34042
|
if (typeof v !== "string") {
|
|
34022
34043
|
return void 0;
|
|
@@ -34024,17 +34045,17 @@ function singleStringQueryParam2(req, name) {
|
|
|
34024
34045
|
const trimmed = v.trim();
|
|
34025
34046
|
return trimmed === "" ? void 0 : trimmed;
|
|
34026
34047
|
}
|
|
34027
|
-
function
|
|
34048
|
+
function sendInvalidSearch4006(res, diagnostics) {
|
|
34028
34049
|
return res.status(400).json({
|
|
34029
34050
|
resourceType: "OperationOutcome",
|
|
34030
34051
|
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
34031
34052
|
});
|
|
34032
34053
|
}
|
|
34033
34054
|
async function listSchedulesRoute(req, res) {
|
|
34034
|
-
const actorRef =
|
|
34055
|
+
const actorRef = singleStringQueryParam(req, "actor");
|
|
34035
34056
|
if (actorRef !== void 0) {
|
|
34036
34057
|
if (parseTypedReference(actorRef) === void 0) {
|
|
34037
|
-
return
|
|
34058
|
+
return sendInvalidSearch4006(
|
|
34038
34059
|
res,
|
|
34039
34060
|
`?actor must be a typed reference like "Practitioner/<id>"; got "${actorRef}".`
|
|
34040
34061
|
);
|
|
@@ -37736,7 +37757,7 @@ async function listTasksOperation(params) {
|
|
|
37736
37757
|
}
|
|
37737
37758
|
|
|
37738
37759
|
// src/data/operations/data/task/task-search-by-owner-operation.ts
|
|
37739
|
-
var
|
|
37760
|
+
var DEFAULT_LIMIT3 = 100;
|
|
37740
37761
|
function buildSearchTasksByOwnerSql() {
|
|
37741
37762
|
return [
|
|
37742
37763
|
"SELECT resource_id AS id, resource",
|
|
@@ -37754,7 +37775,7 @@ async function searchTasksByOwnerOperation(params) {
|
|
|
37754
37775
|
const { context, ownerReference } = params;
|
|
37755
37776
|
const { tenantId, workspaceId } = context;
|
|
37756
37777
|
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
37757
|
-
const limit = params.limit ??
|
|
37778
|
+
const limit = params.limit ?? DEFAULT_LIMIT3;
|
|
37758
37779
|
const { containmentRelative, containmentUrn } = buildReferenceContainmentPayload({
|
|
37759
37780
|
shape: { kind: "scalar", field: "owner" },
|
|
37760
37781
|
reference: ownerReference,
|
|
@@ -37780,7 +37801,7 @@ async function searchTasksByOwnerOperation(params) {
|
|
|
37780
37801
|
}
|
|
37781
37802
|
|
|
37782
37803
|
// src/data/operations/data/task/task-search-by-requester-operation.ts
|
|
37783
|
-
var
|
|
37804
|
+
var DEFAULT_LIMIT4 = 100;
|
|
37784
37805
|
function buildSearchTasksByRequesterSql() {
|
|
37785
37806
|
return [
|
|
37786
37807
|
"SELECT resource_id AS id, resource",
|
|
@@ -37798,7 +37819,7 @@ async function searchTasksByRequesterOperation(params) {
|
|
|
37798
37819
|
const { context, requesterReference } = params;
|
|
37799
37820
|
const { tenantId, workspaceId } = context;
|
|
37800
37821
|
const runner = params.runner ?? getDefaultPostgresQueryRunner();
|
|
37801
|
-
const limit = params.limit ??
|
|
37822
|
+
const limit = params.limit ?? DEFAULT_LIMIT4;
|
|
37802
37823
|
const { containmentRelative, containmentUrn } = buildReferenceContainmentPayload({
|
|
37803
37824
|
shape: { kind: "scalar", field: "requester" },
|
|
37804
37825
|
reference: requesterReference,
|
|
@@ -37824,7 +37845,7 @@ async function searchTasksByRequesterOperation(params) {
|
|
|
37824
37845
|
}
|
|
37825
37846
|
|
|
37826
37847
|
// src/data/rest-api/routes/data/task/task-list-route.ts
|
|
37827
|
-
function
|
|
37848
|
+
function singleStringQueryParam2(req, name) {
|
|
37828
37849
|
const v = req.query[name];
|
|
37829
37850
|
if (typeof v !== "string") {
|
|
37830
37851
|
return void 0;
|
|
@@ -37832,24 +37853,24 @@ function singleStringQueryParam3(req, name) {
|
|
|
37832
37853
|
const trimmed = v.trim();
|
|
37833
37854
|
return trimmed === "" ? void 0 : trimmed;
|
|
37834
37855
|
}
|
|
37835
|
-
function
|
|
37856
|
+
function sendInvalidSearch4007(res, diagnostics) {
|
|
37836
37857
|
return res.status(400).json({
|
|
37837
37858
|
resourceType: "OperationOutcome",
|
|
37838
37859
|
issue: [{ severity: "error", code: "invalid", diagnostics }]
|
|
37839
37860
|
});
|
|
37840
37861
|
}
|
|
37841
37862
|
async function listTasksRoute(req, res) {
|
|
37842
|
-
const ownerRef =
|
|
37843
|
-
const requesterRef =
|
|
37863
|
+
const ownerRef = singleStringQueryParam2(req, "owner");
|
|
37864
|
+
const requesterRef = singleStringQueryParam2(req, "requester");
|
|
37844
37865
|
if (ownerRef !== void 0 && requesterRef !== void 0) {
|
|
37845
|
-
return
|
|
37866
|
+
return sendInvalidSearch4007(
|
|
37846
37867
|
res,
|
|
37847
37868
|
"?owner= and ?requester= cannot be combined on the same request."
|
|
37848
37869
|
);
|
|
37849
37870
|
}
|
|
37850
37871
|
if (ownerRef !== void 0) {
|
|
37851
37872
|
if (parseTypedReference(ownerRef) === void 0) {
|
|
37852
|
-
return
|
|
37873
|
+
return sendInvalidSearch4007(
|
|
37853
37874
|
res,
|
|
37854
37875
|
`?owner must be a typed reference like "Practitioner/<id>"; got "${ownerRef}".`
|
|
37855
37876
|
);
|
|
@@ -37872,7 +37893,7 @@ async function listTasksRoute(req, res) {
|
|
|
37872
37893
|
}
|
|
37873
37894
|
if (requesterRef !== void 0) {
|
|
37874
37895
|
if (parseTypedReference(requesterRef) === void 0) {
|
|
37875
|
-
return
|
|
37896
|
+
return sendInvalidSearch4007(
|
|
37876
37897
|
res,
|
|
37877
37898
|
`?requester must be a typed reference like "Practitioner/<id>"; got "${requesterRef}".`
|
|
37878
37899
|
);
|