@medplum/fhir-router 2.0.20 → 2.0.22

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.
@@ -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, DEFAULT_SEARCH_COUNT, 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, isResourceType, notFound, created, deepClone, matchesSearchRequest, evalFhirPath } from '@medplum/core';
2
2
  import DataLoader from 'dataloader';
3
3
  import { applyPatch } from 'rfc6902';
4
4
 
@@ -6,7 +6,6 @@ import { applyPatch } from 'rfc6902';
6
6
  * Processes a FHIR batch request.
7
7
  *
8
8
  * See: https://www.hl7.org/fhir/http.html#transaction
9
- *
10
9
  * @param router The FHIR router.
11
10
  * @param repo The FHIR repository.
12
11
  * @param bundle The input bundle.
@@ -34,8 +33,6 @@ class BatchProcessor {
34
33
  }
35
34
  /**
36
35
  * Processes a FHIR batch request.
37
- * @param repo The FHIR repository.
38
- * @param bundle The input bundle.
39
36
  * @returns The bundle response.
40
37
  */
41
38
  async processBatch() {
@@ -13376,6 +13373,12 @@ const typeCache = {
13376
13373
  'http://hl7.org/fhirpath/System.String': GraphQLString,
13377
13374
  'http://hl7.org/fhirpath/System.Time': GraphQLString,
13378
13375
  };
13376
+ const outputTypeCache = {
13377
+ ...typeCache,
13378
+ };
13379
+ const inputTypeCache = {
13380
+ ...typeCache,
13381
+ };
13379
13382
  /**
13380
13383
  * Cache of "introspection" query results.
13381
13384
  * Common case is the standard schema query from GraphiQL and Insomnia.
@@ -13391,8 +13394,12 @@ let rootSchema;
13391
13394
  * Handles FHIR GraphQL requests.
13392
13395
  *
13393
13396
  * See: https://www.hl7.org/fhir/graphql.html
13397
+ * @param req The request details.
13398
+ * @param repo The current user FHIR repository.
13399
+ * @param router The router for router options.
13400
+ * @returns The response.
13394
13401
  */
13395
- async function graphqlHandler(req, repo) {
13402
+ async function graphqlHandler(req, repo, router) {
13396
13403
  const { query, operationName, variables } = req.body;
13397
13404
  if (!query) {
13398
13405
  return [badRequest('Must provide query.')];
@@ -13411,7 +13418,7 @@ async function graphqlHandler(req, repo) {
13411
13418
  return [invalidRequest(validationErrors)];
13412
13419
  }
13413
13420
  const introspection = isIntrospectionQuery(query);
13414
- if (introspection) {
13421
+ if (introspection && !router.options?.introspectionEnabled) {
13415
13422
  return [forbidden];
13416
13423
  }
13417
13424
  const dataLoader = new DataLoader((keys) => repo.readReferences(keys));
@@ -13433,7 +13440,6 @@ async function graphqlHandler(req, repo) {
13433
13440
  * Introspection queries ask for the schema, which is expensive.
13434
13441
  *
13435
13442
  * See: https://graphql.org/learn/introspection/
13436
- *
13437
13443
  * @param query The GraphQL query.
13438
13444
  * @returns True if the query is an introspection query.
13439
13445
  */
@@ -13450,15 +13456,16 @@ function buildRootSchema() {
13450
13456
  // First, create placeholder types
13451
13457
  // We need this first for circular dependencies
13452
13458
  for (const resourceType of getResourceTypes()) {
13453
- typeCache[resourceType] = buildGraphQLType(resourceType);
13459
+ outputTypeCache[resourceType] = buildGraphQLOutputType(resourceType);
13454
13460
  }
13455
13461
  // Next, fill in all of the type properties
13456
13462
  const fields = {};
13463
+ const mutationFields = {};
13457
13464
  for (const resourceType of getResourceTypes()) {
13458
- const graphQLType = getGraphQLType(resourceType);
13465
+ const graphQLOutputType = getGraphQLOutputType(resourceType);
13459
13466
  // Get resource by ID
13460
13467
  fields[resourceType] = {
13461
- type: graphQLType,
13468
+ type: graphQLOutputType,
13462
13469
  args: {
13463
13470
  id: {
13464
13471
  type: new GraphQLNonNull(GraphQLID),
@@ -13469,38 +13476,71 @@ function buildRootSchema() {
13469
13476
  };
13470
13477
  // Search resource by search parameters
13471
13478
  fields[resourceType + 'List'] = {
13472
- type: new GraphQLList(graphQLType),
13479
+ type: new GraphQLList(graphQLOutputType),
13473
13480
  args: buildSearchArgs(resourceType),
13474
13481
  resolve: resolveBySearch,
13475
13482
  };
13476
13483
  // FHIR GraphQL Connection API
13477
13484
  fields[resourceType + 'Connection'] = {
13478
- type: buildConnectionType(resourceType, graphQLType),
13485
+ type: buildConnectionType(resourceType, graphQLOutputType),
13479
13486
  args: buildSearchArgs(resourceType),
13480
13487
  resolve: resolveByConnectionApi,
13481
13488
  };
13489
+ // Mutation API
13490
+ mutationFields[resourceType + 'Create'] = {
13491
+ type: graphQLOutputType,
13492
+ args: buildCreateArgs(resourceType),
13493
+ resolve: resolveByCreate,
13494
+ };
13495
+ mutationFields[resourceType + 'Update'] = {
13496
+ type: graphQLOutputType,
13497
+ args: buildUpdateArgs(resourceType),
13498
+ resolve: resolveByUpdate,
13499
+ };
13500
+ mutationFields[resourceType + 'Delete'] = {
13501
+ type: graphQLOutputType,
13502
+ args: {
13503
+ id: {
13504
+ type: new GraphQLNonNull(GraphQLID),
13505
+ description: resourceType + ' ID',
13506
+ },
13507
+ },
13508
+ resolve: resolveByDelete,
13509
+ };
13482
13510
  }
13483
13511
  return new GraphQLSchema({
13484
13512
  query: new GraphQLObjectType({
13485
13513
  name: 'QueryType',
13486
13514
  fields,
13487
13515
  }),
13516
+ mutation: new GraphQLObjectType({
13517
+ name: 'MutationType',
13518
+ fields: mutationFields,
13519
+ }),
13488
13520
  });
13489
13521
  }
13490
- function getGraphQLType(resourceType) {
13491
- let result = typeCache[resourceType];
13522
+ function getGraphQLOutputType(inputType) {
13523
+ let result = outputTypeCache[inputType];
13492
13524
  if (!result) {
13493
- result = buildGraphQLType(resourceType);
13494
- typeCache[resourceType] = result;
13525
+ result = buildGraphQLOutputType(inputType);
13526
+ outputTypeCache[inputType] = result;
13495
13527
  }
13496
13528
  return result;
13497
13529
  }
13498
- function buildGraphQLType(resourceType) {
13530
+ function getGraphQLInputType(inputType, nameSuffix) {
13531
+ let result = inputTypeCache[inputType];
13532
+ if (!result) {
13533
+ result = buildGraphQLInputType(inputType, nameSuffix);
13534
+ inputTypeCache[inputType] = result;
13535
+ }
13536
+ return result;
13537
+ }
13538
+ function buildGraphQLOutputType(resourceType) {
13499
13539
  if (resourceType === 'ResourceList') {
13500
13540
  return new GraphQLUnionType({
13501
13541
  name: 'ResourceList',
13502
13542
  types: () => getResourceTypes()
13503
- .map(getGraphQLType)
13543
+ .map(getGraphQLOutputType)
13504
13544
  .filter((t) => !!t),
13505
13545
  resolveType: resolveTypeByReference,
13506
13546
  });
@@ -13509,16 +13549,37 @@ function buildGraphQLType(resourceType) {
13509
13549
  return new GraphQLObjectType({
13510
13550
  name: resourceType,
13511
13551
  description: schema.description,
13512
- fields: () => buildGraphQLFields(resourceType),
13552
+ fields: () => buildGraphQLOutputFields(resourceType),
13513
13553
  });
13514
13554
  }
13515
- function buildGraphQLFields(resourceType) {
13555
+ function buildGraphQLInputType(resourceType, nameSuffix) {
13556
+ const schema = getResourceTypeSchema(resourceType);
13557
+ return new GraphQLInputObjectType({
13558
+ name: resourceType + nameSuffix,
13559
+ description: schema.description,
13560
+ fields: () => buildGraphQLInputFields(resourceType, nameSuffix),
13561
+ });
13562
+ }
13563
+ function buildGraphQLOutputFields(resourceType) {
13516
13564
  const fields = {};
13517
- buildPropertyFields(resourceType, fields);
13565
+ buildOutputPropertyFields(resourceType, fields);
13518
13566
  buildReverseLookupFields(resourceType, fields);
13519
13567
  return fields;
13520
13568
  }
13521
- function buildPropertyFields(resourceType, fields) {
13569
+ function buildGraphQLInputFields(resourceType, nameSuffix) {
13570
+ const fields = {};
13571
+ // Add resourceType field for root resource
13572
+ if (isResourceType(resourceType)) {
13573
+ const propertyFieldConfig = {
13574
+ description: 'The type of resource',
13575
+ type: GraphQLString,
13576
+ };
13577
+ fields['resourceType'] = propertyFieldConfig;
13578
+ }
13579
+ buildInputPropertyFields(resourceType, fields, nameSuffix);
13580
+ return fields;
13581
+ }
13582
+ function buildOutputPropertyFields(resourceType, fields) {
13522
13583
  const schema = getResourceTypeSchema(resourceType);
13523
13584
  const properties = schema.properties;
13524
13585
  if (isResourceTypeSchema(schema)) {
@@ -13530,25 +13591,35 @@ function buildPropertyFields(resourceType, fields) {
13530
13591
  if (resourceType === 'Reference') {
13531
13592
  fields.resource = {
13532
13593
  description: 'Reference',
13533
- type: getGraphQLType('ResourceList'),
13594
+ type: getGraphQLOutputType('ResourceList'),
13534
13595
  resolve: resolveByReference,
13535
13596
  };
13536
13597
  }
13537
13598
  for (const key of Object.keys(properties)) {
13538
13599
  const elementDefinition = getElementDefinition(resourceType, key);
13539
13600
  for (const type of elementDefinition.type) {
13540
- buildPropertyField(fields, key, elementDefinition, type);
13601
+ buildOutputPropertyField(fields, key, elementDefinition, type);
13602
+ }
13603
+ }
13604
+ }
13605
+ function buildInputPropertyFields(resourceType, fields, nameSuffix) {
13606
+ const schema = getResourceTypeSchema(resourceType);
13607
+ const properties = schema.properties;
13608
+ for (const key of Object.keys(properties)) {
13609
+ const elementDefinition = getElementDefinition(resourceType, key);
13610
+ for (const type of elementDefinition.type) {
13611
+ buildInputPropertyField(fields, key, elementDefinition, type, nameSuffix);
13541
13612
  }
13542
13613
  }
13543
13614
  }
13544
- function buildPropertyField(fields, key, elementDefinition, elementDefinitionType) {
13615
+ function buildOutputPropertyField(fields, key, elementDefinition, elementDefinitionType) {
13545
13616
  let typeName = elementDefinitionType.code;
13546
13617
  if (typeName === 'Element' || typeName === 'BackboneElement') {
13547
13618
  typeName = buildTypeName(elementDefinition.path?.split('.'));
13548
13619
  }
13549
13620
  const fieldConfig = {
13550
13621
  description: elementDefinition.short,
13551
- type: getPropertyType(elementDefinition, typeName),
13622
+ type: getOutputPropertyType(elementDefinition, typeName),
13552
13623
  resolve: resolveField,
13553
13624
  };
13554
13625
  if (elementDefinition.max === '*') {
@@ -13557,6 +13628,21 @@ function buildPropertyField(fields, key, elementDefinition, elementDefinitionTyp
13557
13628
  const propertyName = key.replace('[x]', capitalize(elementDefinitionType.code));
13558
13629
  fields[propertyName] = fieldConfig;
13559
13630
  }
13631
+ function buildInputPropertyField(fields, key, elementDefinition, elementDefinitionType, nameSuffix) {
13632
+ let typeName = elementDefinitionType.code;
13633
+ if (typeName === 'Element' || typeName === 'BackboneElement') {
13634
+ typeName = buildTypeName(elementDefinition.path?.split('.'));
13635
+ }
13636
+ const fieldConfig = {
13637
+ description: elementDefinition.short,
13638
+ type: getGraphQLInputType(typeName, nameSuffix),
13639
+ };
13640
+ if (elementDefinition.max === '*') {
13641
+ fieldConfig.type = new GraphQLList(getGraphQLInputType(typeName, nameSuffix));
13642
+ }
13643
+ const propertyName = key.replace('[x]', capitalize(elementDefinitionType.code));
13644
+ fields[propertyName] = fieldConfig;
13645
+ }
13560
13646
  /**
13561
13647
  * Builds field arguments for a list property.
13562
13648
  *
@@ -13567,7 +13653,6 @@ function buildPropertyField(fields, key, elementDefinition, elementDefinitionTyp
13567
13653
  * 4. All properties of the list element type.
13568
13654
  *
13569
13655
  * See: https://hl7.org/fhir/R4/graphql.html#list
13570
- *
13571
13656
  * @param fieldTypeName The type name of the field.
13572
13657
  * @returns The arguments for the field.
13573
13658
  */
@@ -13652,13 +13737,12 @@ function buildListPropertyFieldArg(fieldArgs, fieldKey, elementDefinition, eleme
13652
13737
  * (except that the "id" argument is prohibited here as nonsensical).
13653
13738
  *
13654
13739
  * See: https://www.hl7.org/fhir/graphql.html#reverse
13655
- *
13656
13740
  * @param resourceType The resource type to build fields for.
13657
13741
  * @param fields The fields object to add fields to.
13658
13742
  */
13659
13743
  function buildReverseLookupFields(resourceType, fields) {
13660
13744
  for (const childResourceType of getResourceTypes()) {
13661
- const childGraphQLType = getGraphQLType(childResourceType);
13745
+ const childGraphQLType = getGraphQLOutputType(childResourceType);
13662
13746
  const childSearchParams = getSearchParameters(childResourceType);
13663
13747
  const enumValues = {};
13664
13748
  let count = 0;
@@ -13724,8 +13808,30 @@ function buildSearchArgs(resourceType) {
13724
13808
  }
13725
13809
  return args;
13726
13810
  }
13727
- function getPropertyType(elementDefinition, typeName) {
13728
- const graphqlType = getGraphQLType(typeName);
13811
+ function buildCreateArgs(resourceType) {
13812
+ const args = {
13813
+ res: {
13814
+ type: getGraphQLInputType(resourceType, 'Create'),
13815
+ description: resourceType + ' Create',
13816
+ },
13817
+ };
13818
+ return args;
13819
+ }
13820
+ function buildUpdateArgs(resourceType) {
13821
+ const args = {
13822
+ id: {
13823
+ type: new GraphQLNonNull(GraphQLID),
13824
+ description: resourceType + ' ID',
13825
+ },
13826
+ res: {
13827
+ type: getGraphQLInputType(resourceType, 'Update'),
13828
+ description: resourceType + ' Update',
13829
+ },
13830
+ };
13831
+ return args;
13832
+ }
13833
+ function getOutputPropertyType(elementDefinition, typeName) {
13834
+ const graphqlType = getGraphQLOutputType(typeName);
13729
13835
  if (elementDefinition.max === '*') {
13730
13836
  return new GraphQLList(graphqlType);
13731
13837
  }
@@ -13764,7 +13870,6 @@ function buildConnectionType(resourceType, resourceGraphQLType) {
13764
13870
  * @param ctx The GraphQL context.
13765
13871
  * @param info The GraphQL resolve info. This includes the schema, and additional field details.
13766
13872
  * @returns Promise to read the resoures for the query.
13767
- * @implements {GraphQLFieldResolver}
13768
13873
  */
13769
13874
  async function resolveBySearch(source, args, ctx, info) {
13770
13875
  const fieldName = info.fieldName;
@@ -13782,7 +13887,6 @@ async function resolveBySearch(source, args, ctx, info) {
13782
13887
  * @param ctx The GraphQL context.
13783
13888
  * @param info The GraphQL resolve info. This includes the schema, and additional field details.
13784
13889
  * @returns Promise to read the resoures for the query.
13785
- * @implements {GraphQLFieldResolver}
13786
13890
  */
13787
13891
  async function resolveByConnectionApi(source, args, ctx, info) {
13788
13892
  const fieldName = info.fieldName;
@@ -13812,7 +13916,6 @@ async function resolveByConnectionApi(source, args, ctx, info) {
13812
13916
  * @param ctx The GraphQL context.
13813
13917
  * @param info The GraphQL resolve info. This includes the schema, and additional field details.
13814
13918
  * @returns Promise to read the resoure for the query.
13815
- * @implements {GraphQLFieldResolver}
13816
13919
  */
13817
13920
  async function resolveById(_source, args, ctx, info) {
13818
13921
  try {
@@ -13829,7 +13932,6 @@ async function resolveById(_source, args, ctx, info) {
13829
13932
  * @param _args The GraphQL search arguments.
13830
13933
  * @param ctx The GraphQL context.
13831
13934
  * @returns Promise to read the resoure(s) for the query.
13832
- * @implements {GraphQLFieldResolver}
13833
13935
  */
13834
13936
  async function resolveByReference(source, _args, ctx) {
13835
13937
  try {
@@ -13844,14 +13946,13 @@ async function resolveByReference(source, _args, ctx) {
13844
13946
  * When loading a resource via reference, GraphQL needs to know the type of the resource.
13845
13947
  * @param resource The loaded resource.
13846
13948
  * @returns The GraphQL type of the resource.
13847
- * @implements {GraphQLTypeResolver}
13848
13949
  */
13849
13950
  function resolveTypeByReference(resource) {
13850
13951
  const resourceType = resource?.resourceType;
13851
13952
  if (!resourceType) {
13852
13953
  return undefined;
13853
13954
  }
13854
- return getGraphQLType(resourceType).name;
13955
+ return getGraphQLOutputType(resourceType).name;
13855
13956
  }
13856
13957
  /**
13857
13958
  * GraphQL resolver for fields.
@@ -13862,7 +13963,6 @@ function resolveTypeByReference(resource) {
13862
13963
  * @param _ctx The GraphQL context.
13863
13964
  * @param info The GraphQL resolve info. This includes the field name.
13864
13965
  * @returns Promise to read the resoure for the query.
13865
- * @implements {GraphQLFieldResolver}
13866
13966
  */
13867
13967
  async function resolveField(source, args, _ctx, info) {
13868
13968
  const fieldValue = source?.[info.fieldName];
@@ -13885,6 +13985,68 @@ async function resolveField(source, args, _ctx, info) {
13885
13985
  }
13886
13986
  return array;
13887
13987
  }
13988
+ /**
13989
+ * GraphQL resolver function for create requests.
13990
+ * The field name should end with "Create" (i.e., "PatientCreate" for updating a Patient).
13991
+ * The args should include the data to be created for the specified resource type.
13992
+ * @param _source The source/root object. In the case of creates, this is typically not used and is thus ignored.
13993
+ * @param args The GraphQL arguments, containing the new data for the resource.
13994
+ * @param ctx The GraphQL context. This includes the repository where resources are stored.
13995
+ * @param info The GraphQL resolve info. This includes the schema, field details, and other query-specific information.
13996
+ * @returns A Promise that resolves to the created resource, or undefined if the resource could not be found or updated.
13997
+ */
13998
+ async function resolveByCreate(_source, args, ctx, info) {
13999
+ const fieldName = info.fieldName;
14000
+ // 'Create.length'=== 6 && 'Update.length' === 6
14001
+ const resourceType = fieldName.substring(0, fieldName.length - 6);
14002
+ const resourceArgs = args.res;
14003
+ if (resourceArgs.resourceType !== resourceType) {
14004
+ return [badRequest('Invalid resourceType')];
14005
+ }
14006
+ const resource = await ctx.repo.createResource(resourceArgs);
14007
+ return resource;
14008
+ }
14009
+ // Mutation Resolvers
14010
+ /**
14011
+ * GraphQL resolver function for update requests.
14012
+ * The field name should end with "Update" (i.e., "PatientUpdate" for updating a Patient).
14013
+ * The args should include the data to be updated for the specified resource type.
14014
+ * @param _source The source/root object. In the case of updates, this is typically not used and is thus ignored.
14015
+ * @param args The GraphQL arguments, containing the new data for the resource.
14016
+ * @param ctx The GraphQL context. This includes the repository where resources are stored.
14017
+ * @param info The GraphQL resolve info. This includes the schema, field details, and other query-specific information.
14018
+ * @returns A Promise that resolves to the updated resource, or undefined if the resource could not be found or updated.
14019
+ */
14020
+ async function resolveByUpdate(_source, args, ctx, info) {
14021
+ const fieldName = info.fieldName;
14022
+ // 'Create.length'=== 6 && 'Update.length' === 6
14023
+ const resourceType = fieldName.substring(0, fieldName.length - 6);
14024
+ const resourceArgs = args.res;
14025
+ const resourceId = args.id;
14026
+ if (resourceArgs.resourceType !== resourceType) {
14027
+ return [badRequest('Invalid resourceType')];
14028
+ }
14029
+ if (resourceId !== resourceArgs.id) {
14030
+ return [badRequest('Incorrect ID')];
14031
+ }
14032
+ const resource = await ctx.repo.updateResource(resourceArgs);
14033
+ return resource;
14034
+ }
14035
+ /**
14036
+ * GraphQL resolver function for delete requests.
14037
+ * The field name should end with "Delete" (e.g., "PatientDelete" for deleting a Patient).
14038
+ * The args should include the ID of the resource to be deleted.
14039
+ * @param _source The source/root object. In the case of deletions, this is typically not used and is thus ignored.
14040
+ * @param args The GraphQL arguments, containing the ID of the resource to be deleted.
14041
+ * @param ctx The GraphQL context. This includes the repository where resources are stored.
14042
+ * @param info The GraphQL resolve info. This includes the schema, field details, and other query-specific information.
14043
+ * @returns A Promise that resolves when the resource has been deleted. No value is returned.
14044
+ */
14045
+ async function resolveByDelete(_source, args, ctx, info) {
14046
+ const fieldName = info.fieldName;
14047
+ const resourceType = fieldName.substring(0, fieldName.length - 'Delete'.length);
14048
+ await ctx.repo.deleteResource(resourceType, args.id);
14049
+ }
13888
14050
  function parseSearchArgs(resourceType, source, args) {
13889
14051
  let referenceFilter = undefined;
13890
14052
  if (source) {
@@ -14109,8 +14271,9 @@ async function patchResource(req, repo) {
14109
14271
  return [allOk, resource];
14110
14272
  }
14111
14273
  class FhirRouter {
14112
- constructor() {
14274
+ constructor(options = {}) {
14113
14275
  this.router = new Router();
14276
+ this.options = options;
14114
14277
  this.router.add('POST', '', batch);
14115
14278
  this.router.add('GET', ':resourceType', search);
14116
14279
  this.router.add('POST', ':resourceType/_search', searchByPost);
@@ -14130,7 +14293,12 @@ class FhirRouter {
14130
14293
  }
14131
14294
  const { handler, params } = result;
14132
14295
  req.params = params;
14133
- return handler(req, repo, this);
14296
+ try {
14297
+ return await handler(req, repo, this);
14298
+ }
14299
+ catch (err) {
14300
+ return [normalizeOperationOutcome(err)];
14301
+ }
14134
14302
  }
14135
14303
  }
14136
14304
 
@@ -14143,7 +14311,6 @@ class BaseRepository {
14143
14311
  * The return value is the resource, if available; otherwise, undefined.
14144
14312
  *
14145
14313
  * See FHIR search for full details: https://www.hl7.org/fhir/search.html
14146
- *
14147
14314
  * @param searchRequest The FHIR search request.
14148
14315
  * @returns Promise to the first search result or undefined.
14149
14316
  */
@@ -14159,7 +14326,6 @@ class BaseRepository {
14159
14326
  * The return value is an array of resources.
14160
14327
  *
14161
14328
  * See FHIR search for full details: https://www.hl7.org/fhir/search.html
14162
- *
14163
14329
  * @param searchRequest The FHIR search request.
14164
14330
  * @returns Promise to the array of search results.
14165
14331
  */