@medplum/fhir-router 2.0.17 → 2.0.18
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/dist/cjs/index.cjs +72 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/cjs/index.min.cjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.min.mjs.map +1 -1
- package/dist/esm/index.mjs +73 -2
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OperationOutcomeError, badRequest, normalizeOperationOutcome, parseSearchUrl, getReferenceString, resolveId, getStatus, isOk, allOk, LRUCache, forbidden, getResourceTypes, getResourceTypeSchema, isResourceTypeSchema, getElementDefinition, buildTypeName, capitalize, isLowerCase, globalSchema, getSearchParameters, toJsBoolean, evalFhirPathTyped, toTypedValue, Operator, parseSearchRequest, notFound, created, deepClone, matchesSearchRequest, evalFhirPath } from '@medplum/core';
|
|
1
|
+
import { OperationOutcomeError, badRequest, normalizeOperationOutcome, parseSearchUrl, getReferenceString, resolveId, getStatus, isOk, allOk, LRUCache, forbidden, getResourceTypes, getResourceTypeSchema, isResourceTypeSchema, getElementDefinition, buildTypeName, capitalize, isLowerCase, globalSchema, getSearchParameters, DEFAULT_SEARCH_COUNT, toJsBoolean, evalFhirPathTyped, toTypedValue, Operator, parseSearchRequest, notFound, created, deepClone, matchesSearchRequest, evalFhirPath } from '@medplum/core';
|
|
2
2
|
import DataLoader from 'dataloader';
|
|
3
3
|
import { applyPatch } from 'rfc6902';
|
|
4
4
|
|
|
@@ -13473,6 +13473,12 @@ function buildRootSchema() {
|
|
|
13473
13473
|
args: buildSearchArgs(resourceType),
|
|
13474
13474
|
resolve: resolveBySearch,
|
|
13475
13475
|
};
|
|
13476
|
+
// FHIR GraphQL Connection API
|
|
13477
|
+
fields[resourceType + 'Connection'] = {
|
|
13478
|
+
type: buildConnectionType(resourceType, graphQLType),
|
|
13479
|
+
args: buildSearchArgs(resourceType),
|
|
13480
|
+
resolve: resolveByConnectionApi,
|
|
13481
|
+
};
|
|
13476
13482
|
}
|
|
13477
13483
|
return new GraphQLSchema({
|
|
13478
13484
|
query: new GraphQLObjectType({
|
|
@@ -13725,6 +13731,30 @@ function getPropertyType(elementDefinition, typeName) {
|
|
|
13725
13731
|
}
|
|
13726
13732
|
return graphqlType;
|
|
13727
13733
|
}
|
|
13734
|
+
function buildConnectionType(resourceType, resourceGraphQLType) {
|
|
13735
|
+
return new GraphQLObjectType({
|
|
13736
|
+
name: resourceType + 'Connection',
|
|
13737
|
+
fields: {
|
|
13738
|
+
count: { type: GraphQLInt },
|
|
13739
|
+
offset: { type: GraphQLInt },
|
|
13740
|
+
pageSize: { type: GraphQLInt },
|
|
13741
|
+
first: { type: GraphQLString },
|
|
13742
|
+
previous: { type: GraphQLString },
|
|
13743
|
+
next: { type: GraphQLString },
|
|
13744
|
+
last: { type: GraphQLString },
|
|
13745
|
+
edges: {
|
|
13746
|
+
type: new GraphQLList(new GraphQLObjectType({
|
|
13747
|
+
name: resourceType + 'ConnectionEdge',
|
|
13748
|
+
fields: {
|
|
13749
|
+
mode: { type: GraphQLString },
|
|
13750
|
+
score: { type: GraphQLFloat },
|
|
13751
|
+
resource: { type: resourceGraphQLType },
|
|
13752
|
+
},
|
|
13753
|
+
})),
|
|
13754
|
+
},
|
|
13755
|
+
},
|
|
13756
|
+
});
|
|
13757
|
+
}
|
|
13728
13758
|
/**
|
|
13729
13759
|
* GraphQL data loader for search requests.
|
|
13730
13760
|
* The field name should always end with "List" (i.e., "Patient" search uses "PatientList").
|
|
@@ -13738,11 +13768,41 @@ function getPropertyType(elementDefinition, typeName) {
|
|
|
13738
13768
|
*/
|
|
13739
13769
|
async function resolveBySearch(source, args, ctx, info) {
|
|
13740
13770
|
const fieldName = info.fieldName;
|
|
13741
|
-
const resourceType = fieldName.substring(0, fieldName.length -
|
|
13771
|
+
const resourceType = fieldName.substring(0, fieldName.length - 'List'.length);
|
|
13742
13772
|
const searchRequest = parseSearchArgs(resourceType, source, args);
|
|
13743
13773
|
const bundle = await ctx.repo.search(searchRequest);
|
|
13744
13774
|
return bundle.entry?.map((e) => e.resource);
|
|
13745
13775
|
}
|
|
13776
|
+
/**
|
|
13777
|
+
* GraphQL data loader for search requests.
|
|
13778
|
+
* The field name should always end with "List" (i.e., "Patient" search uses "PatientList").
|
|
13779
|
+
* The search args should be FHIR search parameters.
|
|
13780
|
+
* @param source The source/root. This should always be null for our top level readers.
|
|
13781
|
+
* @param args The GraphQL search arguments.
|
|
13782
|
+
* @param ctx The GraphQL context.
|
|
13783
|
+
* @param info The GraphQL resolve info. This includes the schema, and additional field details.
|
|
13784
|
+
* @returns Promise to read the resoures for the query.
|
|
13785
|
+
* @implements {GraphQLFieldResolver}
|
|
13786
|
+
*/
|
|
13787
|
+
async function resolveByConnectionApi(source, args, ctx, info) {
|
|
13788
|
+
const fieldName = info.fieldName;
|
|
13789
|
+
const resourceType = fieldName.substring(0, fieldName.length - 'Connection'.length);
|
|
13790
|
+
const searchRequest = parseSearchArgs(resourceType, source, args);
|
|
13791
|
+
if (isFieldRequested(info, 'count')) {
|
|
13792
|
+
searchRequest.total = 'accurate';
|
|
13793
|
+
}
|
|
13794
|
+
const bundle = await ctx.repo.search(searchRequest);
|
|
13795
|
+
return {
|
|
13796
|
+
count: bundle.total,
|
|
13797
|
+
offset: searchRequest.offset || 0,
|
|
13798
|
+
pageSize: searchRequest.count || DEFAULT_SEARCH_COUNT,
|
|
13799
|
+
edges: bundle.entry?.map((e) => ({
|
|
13800
|
+
mode: e.search?.mode,
|
|
13801
|
+
score: e.search?.score,
|
|
13802
|
+
resource: e.resource,
|
|
13803
|
+
})),
|
|
13804
|
+
};
|
|
13805
|
+
}
|
|
13746
13806
|
/**
|
|
13747
13807
|
* GraphQL data loader for ID requests.
|
|
13748
13808
|
* The field name should always by the resource type.
|
|
@@ -13891,6 +13951,17 @@ const MaxDepthRule = (context) => ({
|
|
|
13891
13951
|
function getDepth(path) {
|
|
13892
13952
|
return path.filter((p) => p === 'selections').length;
|
|
13893
13953
|
}
|
|
13954
|
+
/**
|
|
13955
|
+
* Returns true if the field is requested in the GraphQL query.
|
|
13956
|
+
* @param info The GraphQL resolve info. This includes the field name.
|
|
13957
|
+
* @param fieldName The field name to check.
|
|
13958
|
+
* @returns True if the field is requested in the GraphQL query.
|
|
13959
|
+
*/
|
|
13960
|
+
function isFieldRequested(info, fieldName) {
|
|
13961
|
+
return info.fieldNodes.some((fieldNode) => fieldNode.selectionSet?.selections.some((selection) => {
|
|
13962
|
+
return selection.kind === 'Field' && selection.name.value === fieldName;
|
|
13963
|
+
}));
|
|
13964
|
+
}
|
|
13894
13965
|
/**
|
|
13895
13966
|
* Returns an OperationOutcome for GraphQL errors.
|
|
13896
13967
|
* @param errors Array of GraphQL errors.
|