@nsshunt/stsfhirpg 1.1.7 → 1.2.2

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.
@@ -15,7 +15,6 @@ const require$$1$2 = require("tls");
15
15
  const require$$0$7 = require("path");
16
16
  const require$$0$6 = require("stream");
17
17
  const require$$0$5 = require("buffer");
18
- const redis = require("redis");
19
18
  class LuxonError extends Error {
20
19
  }
21
20
  class InvalidDateTimeError extends LuxonError {
@@ -7026,7 +7025,8 @@ class ResourceHelper {
7026
7025
  this.#definitions = {
7027
7026
  resources: {},
7028
7027
  types: {},
7029
- searchParameters: {}
7028
+ searchParametersByUrl: {},
7029
+ searchParametersByResourceType: {}
7030
7030
  };
7031
7031
  }
7032
7032
  __resources.entry.forEach((entry) => {
@@ -7043,25 +7043,22 @@ class ResourceHelper {
7043
7043
  }
7044
7044
  });
7045
7045
  __searchParams.entry.forEach((entry) => {
7046
- this.#definitions.searchParameters[entry.fullUrl] = entry.resource;
7046
+ this.#definitions.searchParametersByUrl[entry.fullUrl] = entry.resource;
7047
7047
  });
7048
+ this._LoadSearchParameters();
7048
7049
  return this.#definitions;
7049
7050
  };
7050
- GetType = (typeName) => {
7051
+ get definitions() {
7051
7052
  if (!this.#definitions) {
7052
7053
  this.#LoadDefinitions();
7053
7054
  }
7054
- if (this.#definitions) {
7055
- const foundType = this.#definitions.types[typeName];
7056
- return foundType;
7057
- }
7058
- return [];
7055
+ return this.#definitions;
7056
+ }
7057
+ GetType = (typeName) => {
7058
+ return this.definitions.types[typeName];
7059
7059
  };
7060
7060
  GetResource = (resourceType) => {
7061
- if (!this.#definitions) {
7062
- this.#LoadDefinitions();
7063
- }
7064
- return this.#definitions.resources[resourceType];
7061
+ return this.definitions.resources[resourceType];
7065
7062
  };
7066
7063
  GetResourceField = (resourceType, fieldPath) => {
7067
7064
  const resource = this.GetResource(resourceType);
@@ -7074,22 +7071,215 @@ class ResourceHelper {
7074
7071
  }
7075
7072
  };
7076
7073
  GetSearchParam = (url) => {
7077
- if (!this.#definitions) {
7078
- this.#LoadDefinitions();
7079
- }
7080
- return this.#definitions.searchParameters[url];
7074
+ return this.definitions.searchParametersByUrl[url];
7081
7075
  };
7082
7076
  GetSearchParams = () => {
7083
- if (!this.#definitions) {
7084
- this.#LoadDefinitions();
7085
- }
7086
- return this.#definitions.searchParameters;
7077
+ return this.definitions.searchParametersByUrl;
7087
7078
  };
7088
7079
  GetSearchParamsByResource = (resource) => {
7089
- if (!this.#definitions) {
7090
- this.#LoadDefinitions();
7080
+ return Object.values(this.definitions.searchParametersByUrl).filter((sp) => sp.base.includes(resource)).map((sp) => sp);
7081
+ };
7082
+ // ------------------------------------------------------------------------------------------------------------------
7083
+ // Remove ( ) when either are present
7084
+ #RemoveOuterParentheses = (input) => {
7085
+ return input.replace(/^\(|\)$/g, "");
7086
+ };
7087
+ // Remove ( ) only when both are present
7088
+ #RemoveSurroundingParentheses = (input) => {
7089
+ return input.replace(/^\((.*)\)$/, "$1").trim();
7090
+ };
7091
+ /*
7092
+
7093
+ NamingSystem derived-from reference NamingSystem.relatedArtifact.where(type='derived-from').resource
7094
+
7095
+ NamingSystem predecessor reference NamingSystem.relatedArtifact.where(type='predecessor').resource
7096
+
7097
+ ClinicalUseDefinition product reference ClinicalUseDefinition.subject.where(resolve() is MedicinalProductDefinition)
7098
+
7099
+ OrganizationAffiliation email token OrganizationAffiliation.contact.telecom.where(system='email')
7100
+ OrganizationAffiliation phone token OrganizationAffiliation.contact.telecom.where(system='phone')
7101
+
7102
+ PackagedProductDefinition biological reference PackagedProductDefinition.packaging.containedItem.item.reference
7103
+ PackagedProductDefinition contained-item reference PackagedProductDefinition.packaging.containedItem.item.reference
7104
+
7105
+ Patient deceased token Patient.deceased.exists() and Patient.deceased != false
7106
+ Practitioner deceased token Practitioner.deceased.exists() and Practitioner.deceased != false
7107
+
7108
+ Location contains special Location.extension('http://hl7.org/fhir/StructureDefinition/location-boundary-geojson').value
7109
+
7110
+ QuestionnaireResponse item-subject reference QuestionnaireResponse.item.where(extension('http://hl7.org/fhir/StructureDefinition/questionnaireresponse-isSubject').exists()).answer.valueReference
7111
+ */
7112
+ ProcessExpressions = (resourceName, SP_EXPRESSION) => {
7113
+ let expressions = [];
7114
+ expressions = SP_EXPRESSION.split("|").map((e) => e.trim());
7115
+ expressions = expressions.map((e) => this.#RemoveSurroundingParentheses(e).trim());
7116
+ if (resourceName !== "") {
7117
+ expressions = expressions.filter((e) => e.split(".")[0].trim().localeCompare(resourceName) === 0);
7091
7118
  }
7092
- return Object.values(this.#definitions.searchParameters).filter((sp) => sp.base.includes(resource)).map((sp) => sp);
7119
+ let original_expressions = [...expressions];
7120
+ expressions = expressions.map((e) => {
7121
+ let capturedTypeOf = void 0;
7122
+ return {
7123
+ path: e.replace(
7124
+ /\.ofType\(([^)]+)\)/g,
7125
+ (_, typeName) => {
7126
+ capturedTypeOf = true;
7127
+ return typeName.charAt(0).toUpperCase() + typeName.slice(1);
7128
+ }
7129
+ ),
7130
+ typeOf: capturedTypeOf
7131
+ };
7132
+ });
7133
+ expressions.forEach((expression) => {
7134
+ try {
7135
+ const sp = expression;
7136
+ if (sp.path.indexOf("exists()") >= 0) {
7137
+ const parts = sp.path.split(" ");
7138
+ const i = parts[0].indexOf("exists()");
7139
+ if (i >= 0) {
7140
+ let fieldExistsEx = parts[0].substring(0, i - 1);
7141
+ let op = parts[1];
7142
+ let fieldTestEx = parts[2];
7143
+ let comparator = parts[3];
7144
+ let value = parts[4];
7145
+ const fieldExistsParts = fieldExistsEx.split(".");
7146
+ let fieldExists = fieldExistsParts.slice(1).join(".");
7147
+ const fieldTestParts = fieldTestEx.split(".");
7148
+ let fieldTest = fieldTestParts.slice(1).join(".");
7149
+ sp.exists = {
7150
+ fieldExists: [`${fieldExists}Boolean`, `${fieldExists}DataTime`],
7151
+ // [x]Boolean or [x]DateTime
7152
+ op,
7153
+ fieldTest: [`${fieldTest}Boolean`, `${fieldTest}DataTime`],
7154
+ comparator,
7155
+ value: [value, void 0]
7156
+ };
7157
+ }
7158
+ }
7159
+ } catch (error) {
7160
+ }
7161
+ });
7162
+ let capturedType;
7163
+ expressions = expressions.map((obj) => {
7164
+ capturedType = void 0;
7165
+ const { path, typeOf, exists } = obj;
7166
+ return {
7167
+ path: path.replace(
7168
+ /\.where\(resolve\(\)\s+is\s+([^)]+)\)/,
7169
+ (_, typeName) => {
7170
+ capturedType = typeName;
7171
+ return "";
7172
+ }
7173
+ ),
7174
+ typeOf,
7175
+ reference: capturedType,
7176
+ exists
7177
+ };
7178
+ });
7179
+ let capturedWhere = void 0;
7180
+ expressions = expressions.map((obj) => {
7181
+ capturedWhere = void 0;
7182
+ const { path, reference, typeOf, exists } = obj;
7183
+ const retVal = {
7184
+ path: path.replace(/([^.]+)\.where\(([^=]+)='([^']+)'\)/g, (_, field, subfield, value) => {
7185
+ capturedWhere = { field, subfield, value };
7186
+ return field;
7187
+ }),
7188
+ typeOf,
7189
+ reference,
7190
+ exists
7191
+ };
7192
+ if (capturedWhere) {
7193
+ capturedWhere.full = `${capturedWhere.field}[*].${capturedWhere.subfield}=${capturedWhere.value}`;
7194
+ retVal.where = capturedWhere;
7195
+ }
7196
+ return retVal;
7197
+ });
7198
+ return {
7199
+ expressions,
7200
+ original_expressions
7201
+ };
7202
+ };
7203
+ _LoadSearchParameters = () => {
7204
+ for (const [key, val] of Object.entries(this.GetSearchParams())) {
7205
+ const { id, url, code, base, type, expression, component, target } = val;
7206
+ for (let i = 0; i < base.length; i++) {
7207
+ const resourceName = base[i];
7208
+ if (!this.#definitions?.searchParametersByResourceType[resourceName]) {
7209
+ this.#definitions.searchParametersByResourceType[resourceName] = {
7210
+ resourceName,
7211
+ params: []
7212
+ };
7213
+ }
7214
+ const SP_ID = id;
7215
+ const SP_NAME = code;
7216
+ const SP_TYPE = type;
7217
+ const SP_URL = url;
7218
+ const SP_TARGET = target;
7219
+ let SP_EXPRESSION = expression;
7220
+ let expressions = [];
7221
+ let original_expressions = [];
7222
+ if (SP_EXPRESSION) {
7223
+ const retVal = this.ProcessExpressions(resourceName, SP_EXPRESSION);
7224
+ expressions = retVal.expressions;
7225
+ original_expressions = retVal.original_expressions;
7226
+ }
7227
+ const record = {
7228
+ SP_ID,
7229
+ SP_NAME,
7230
+ SP_TYPE,
7231
+ SP_URL,
7232
+ SP_TARGET,
7233
+ expressions,
7234
+ original_expressions,
7235
+ SP_DEFINITION: this.GetSearchParam(SP_URL)
7236
+ };
7237
+ for (let i2 = 0; i2 < record.expressions.length; i2++) {
7238
+ const rf = this.GetResourceField(resourceName, record.expressions[i2].path);
7239
+ if (rf) {
7240
+ expressions[i2].RES_FIELD = rf;
7241
+ }
7242
+ }
7243
+ if (component) {
7244
+ record.component = [...component];
7245
+ record.component.forEach((c) => {
7246
+ const retVal = this.ProcessExpressions("", c.expression);
7247
+ c.expressions = retVal.expressions;
7248
+ c.original_expressions = retVal.original_expressions;
7249
+ const def = this.GetSearchParam(c.definition);
7250
+ if (def && def.type) {
7251
+ c.type = def.type;
7252
+ }
7253
+ });
7254
+ }
7255
+ this.#definitions.searchParametersByResourceType[resourceName].params.push(record);
7256
+ }
7257
+ }
7258
+ };
7259
+ GetSearchParamFromResourceTypeUrl = (resourceType, url) => {
7260
+ const filterByNameAndUrl = this.definitions.searchParametersByResourceType[resourceType].params.filter((rt) => rt.SP_URL.localeCompare(url) === 0);
7261
+ if (filterByNameAndUrl.length > 0) {
7262
+ return filterByNameAndUrl[0];
7263
+ }
7264
+ };
7265
+ /*
7266
+ GetSearchParamFromResourceType = (resourceType: string, name: string): ISearchParamRecord | undefined => {
7267
+ const filterByName = this.definitions.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);
7268
+ if (filterByName.length > 0) {
7269
+ return filterByName[0];
7270
+ }
7271
+ }
7272
+
7273
+ GetPathsFromResourceType = (resourceType: string, name: string): string[] => {
7274
+ const filterByName = this.definitions.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);
7275
+ if (filterByName.length > 0) {
7276
+ return filterByName[0].expressions.map(e => e.path)
7277
+ }
7278
+ return [ ];
7279
+ }
7280
+ */
7281
+ GetSearchParamsFromResourceType = (resourceType) => {
7282
+ return this.definitions.searchParametersByResourceType[resourceType].params;
7093
7283
  };
7094
7284
  }
7095
7285
  var ansiStyles = { exports: {} };
@@ -10567,7 +10757,7 @@ class DBSearchIndexComposite extends DBSearchIndexBase {
10567
10757
  searchFieldRecord.component.forEach((searchParamComponentRecord) => {
10568
10758
  components.push([]);
10569
10759
  const url = searchParamComponentRecord.definition;
10570
- const sp = searchIndex.GetSearchParamFromResourceTypeUrl(resource.resourceType, url);
10760
+ const sp = searchIndex.resourceHelper.GetSearchParamFromResourceTypeUrl(resource.resourceType, url);
10571
10761
  if (this.IsDefined(sp)) {
10572
10762
  const tir2 = {
10573
10763
  PID: v4(),
@@ -11222,27 +11412,13 @@ class DBSearchIndex {
11222
11412
  return [];
11223
11413
  }
11224
11414
  };
11225
- ResolveFhirChoiceType = (path) => {
11226
- const match2 = path.match(/^(.+?)\.ofType\((.+?)\)$/);
11227
- if (!match2) {
11228
- return path;
11229
- }
11230
- const base = match2[1];
11231
- const fhirType = match2[2];
11232
- const capitalizedType = fhirType.charAt(0).toUpperCase() + fhirType.slice(1);
11233
- return `${base}${capitalizedType}`;
11234
- };
11235
11415
  GetSearchIndexData = (resource) => {
11236
11416
  try {
11237
- const st = performance.now();
11238
- if (!this.#searchParams) {
11239
- this.LoadSearchParameters();
11240
- }
11417
+ const searchParamRecords = this.resourceHelper.GetSearchParamsFromResourceType(resource.resourceType);
11241
11418
  const searchIndexData = [];
11242
- for (let i = 0; i < this.#searchParams[resource.resourceType].params.length; i++) {
11243
- const searchRecord = this.#searchParams[resource.resourceType].params[i];
11419
+ for (let i = 0; i < searchParamRecords.length; i++) {
11420
+ const searchRecord = searchParamRecords[i];
11244
11421
  try {
11245
- const st2 = performance.now();
11246
11422
  const retVal = this.UpdateIndex(resource, searchRecord);
11247
11423
  if (retVal && retVal.length > 0) {
11248
11424
  searchIndexData.push(...retVal);
@@ -11257,286 +11433,19 @@ class DBSearchIndex {
11257
11433
  return [];
11258
11434
  }
11259
11435
  };
11260
- GetSearchParamFromResourceTypeUrl = (resourceType, url) => {
11261
- if (!this.#searchParams) {
11262
- this.LoadSearchParameters();
11263
- }
11264
- const filterByNameAndUrl = this.#searchParams[resourceType].params.filter((rt) => rt.SP_URL.localeCompare(url) === 0);
11265
- if (filterByNameAndUrl.length > 0) {
11266
- return filterByNameAndUrl[0];
11267
- }
11268
- };
11269
- GetSearchParamFromResourceType = (resourceType, name) => {
11270
- if (!this.#searchParams) {
11271
- this.LoadSearchParameters();
11272
- }
11273
- const filterByName = this.#searchParams[resourceType].params.filter((rt) => rt.SP_NAME.localeCompare(name) === 0);
11274
- if (filterByName.length > 0) {
11275
- return filterByName[0];
11276
- }
11277
- };
11278
- GetPathsFromResourceType = (resourceType, name) => {
11279
- if (!this.#searchParams) {
11280
- this.LoadSearchParameters();
11281
- }
11282
- const filterByName = this.#searchParams[resourceType].params.filter((rt) => rt.SP_NAME.localeCompare(name) === 0);
11283
- if (filterByName.length > 0) {
11284
- return filterByName[0].expressions.map((e) => e.path);
11285
- }
11286
- return [];
11287
- };
11288
- // Remove ( ) when either are present
11289
- #RemoveOuterParentheses = (input) => {
11290
- return input.replace(/^\(|\)$/g, "");
11291
- };
11292
- // Remove ( ) only when both are present
11293
- #RemoveSurroundingParentheses = (input) => {
11294
- return input.replace(/^\((.*)\)$/, "$1").trim();
11295
- };
11296
11436
  /*
11297
-
11298
- NamingSystem derived-from reference NamingSystem.relatedArtifact.where(type='derived-from').resource
11299
-
11300
- NamingSystem predecessor reference NamingSystem.relatedArtifact.where(type='predecessor').resource
11301
-
11302
- ClinicalUseDefinition product reference ClinicalUseDefinition.subject.where(resolve() is MedicinalProductDefinition)
11303
-
11304
- OrganizationAffiliation email token OrganizationAffiliation.contact.telecom.where(system='email')
11305
- OrganizationAffiliation phone token OrganizationAffiliation.contact.telecom.where(system='phone')
11306
-
11307
- PackagedProductDefinition biological reference PackagedProductDefinition.packaging.containedItem.item.reference
11308
- PackagedProductDefinition contained-item reference PackagedProductDefinition.packaging.containedItem.item.reference
11309
-
11310
- Patient deceased token Patient.deceased.exists() and Patient.deceased != false
11311
- Practitioner deceased token Practitioner.deceased.exists() and Practitioner.deceased != false
11312
-
11313
- Location contains special Location.extension('http://hl7.org/fhir/StructureDefinition/location-boundary-geojson').value
11314
-
11315
- QuestionnaireResponse item-subject reference QuestionnaireResponse.item.where(extension('http://hl7.org/fhir/StructureDefinition/questionnaireresponse-isSubject').exists()).answer.valueReference
11316
- */
11317
- ProcessExpressions = (resourceName, SP_EXPRESSION) => {
11318
- let expressions = [];
11319
- expressions = SP_EXPRESSION.split("|").map((e) => e.trim());
11320
- expressions = expressions.map((e) => this.#RemoveSurroundingParentheses(e).trim());
11321
- if (resourceName !== "") {
11322
- expressions = expressions.filter((e) => e.split(".")[0].trim().localeCompare(resourceName) === 0);
11323
- }
11324
- let original_expressions = [...expressions];
11325
- expressions = expressions.map((e) => {
11326
- let capturedTypeOf = void 0;
11327
- return {
11328
- path: e.replace(
11329
- /\.ofType\(([^)]+)\)/g,
11330
- (_, typeName) => {
11331
- capturedTypeOf = true;
11332
- return typeName.charAt(0).toUpperCase() + typeName.slice(1);
11333
- }
11334
- ),
11335
- typeOf: capturedTypeOf
11336
- };
11337
- });
11338
- expressions.forEach((expression) => {
11339
- try {
11340
- const sp = expression;
11341
- if (sp.path.indexOf("exists()") >= 0) {
11342
- const parts = sp.path.split(" ");
11343
- const i = parts[0].indexOf("exists()");
11344
- if (i >= 0) {
11345
- let fieldExistsEx = parts[0].substring(0, i - 1);
11346
- let op = parts[1];
11347
- let fieldTestEx = parts[2];
11348
- let comparator = parts[3];
11349
- let value = parts[4];
11350
- const fieldExistsParts = fieldExistsEx.split(".");
11351
- let fieldExists = fieldExistsParts.slice(1).join(".");
11352
- const fieldTestParts = fieldTestEx.split(".");
11353
- let fieldTest = fieldTestParts.slice(1).join(".");
11354
- sp.exists = {
11355
- fieldExists: [`${fieldExists}Boolean`, `${fieldExists}DataTime`],
11356
- // [x]Boolean or [x]DateTime
11357
- op,
11358
- fieldTest: [`${fieldTest}Boolean`, `${fieldTest}DataTime`],
11359
- comparator,
11360
- value: [value, void 0]
11361
- };
11362
- }
11363
- }
11364
- } catch (error) {
11437
+ GetSearchParamFromResourceTypeUrl = (resourceType: string, url: string): ISearchParamRecord | undefined => {
11438
+ return this.resourceHelper.GetSearchParamFromResourceTypeUrl(resourceType, url);
11365
11439
  }
11366
- });
11367
- let capturedType;
11368
- expressions = expressions.map((obj) => {
11369
- capturedType = void 0;
11370
- const { path, typeOf, exists } = obj;
11371
- return {
11372
- path: path.replace(
11373
- /\.where\(resolve\(\)\s+is\s+([^)]+)\)/,
11374
- (_, typeName) => {
11375
- capturedType = typeName;
11376
- return "";
11377
- }
11378
- ),
11379
- typeOf,
11380
- reference: capturedType,
11381
- exists
11382
- };
11383
- });
11384
- let capturedWhere = void 0;
11385
- expressions = expressions.map((obj) => {
11386
- capturedWhere = void 0;
11387
- const { path, reference, typeOf, exists } = obj;
11388
- const retVal = {
11389
- path: path.replace(/([^.]+)\.where\(([^=]+)='([^']+)'\)/g, (_, field, subfield, value) => {
11390
- capturedWhere = { field, subfield, value };
11391
- return field;
11392
- }),
11393
- typeOf,
11394
- reference,
11395
- exists
11396
- };
11397
- if (capturedWhere) {
11398
- capturedWhere.full = `${capturedWhere.field}[*].${capturedWhere.subfield}=${capturedWhere.value}`;
11399
- retVal.where = capturedWhere;
11400
- }
11401
- return retVal;
11402
- });
11403
- return {
11404
- expressions,
11405
- original_expressions
11406
- };
11407
- };
11408
- LoadSearchParameters = () => {
11409
- const searchParamData = {};
11410
- for (const [key, val] of Object.entries(this.resourceHelper.GetSearchParams())) {
11411
- const { id, url, code, base, type, expression, component, target } = val;
11412
- for (let i = 0; i < base.length; i++) {
11413
- const resourceName = base[i];
11414
- if (!searchParamData[resourceName]) {
11415
- searchParamData[resourceName] = {
11416
- resourceName,
11417
- params: []
11418
- };
11419
- }
11420
- const SP_ID = id;
11421
- const SP_NAME = code;
11422
- const SP_TYPE = type;
11423
- const SP_URL = url;
11424
- const SP_TARGET = target;
11425
- let SP_EXPRESSION = expression;
11426
- let expressions = [];
11427
- let original_expressions = [];
11428
- if (SP_EXPRESSION) {
11429
- const retVal = this.ProcessExpressions(resourceName, SP_EXPRESSION);
11430
- expressions = retVal.expressions;
11431
- original_expressions = retVal.original_expressions;
11432
- }
11433
- const record = {
11434
- SP_ID,
11435
- SP_NAME,
11436
- SP_TYPE,
11437
- SP_URL,
11438
- SP_TARGET,
11439
- expressions,
11440
- original_expressions,
11441
- SP_DEFINITION: this.resourceHelper.GetSearchParam(SP_URL)
11442
- };
11443
- for (let i2 = 0; i2 < record.expressions.length; i2++) {
11444
- const rf = this.resourceHelper.GetResourceField(resourceName, record.expressions[i2].path);
11445
- if (rf) {
11446
- expressions[i2].RES_FIELD = rf;
11447
- }
11448
- }
11449
- if (component) {
11450
- record.component = [...component];
11451
- record.component.forEach((c) => {
11452
- const retVal = this.ProcessExpressions("", c.expression);
11453
- c.expressions = retVal.expressions;
11454
- c.original_expressions = retVal.original_expressions;
11455
- const def = this.resourceHelper.GetSearchParam(c.definition);
11456
- if (def && def.type) {
11457
- c.type = def.type;
11458
- }
11459
- });
11460
- }
11461
- searchParamData[resourceName].params.push(record);
11462
- }
11463
- }
11464
- this.#searchParams = searchParamData;
11465
- return searchParamData;
11466
- };
11467
- /*
11468
-
11469
-
11470
- for (const [resourceName,val] of Object.entries(searchParams)) {
11471
-
11472
- const patientSearchList: Record<string, any> = (val as any).resourceSpecific;
11473
-
11474
- for (const [key2,val2] of Object.entries(patientSearchList)) {
11475
-
11476
- const SP_ID = val2.id;
11477
- const SP_NAME = key2;
11478
- const SP_TYPE = val2.type;
11479
- const SP_URL = val2.url;
11480
- let SP_EXPRESSION: string = val2.expression;
11481
- let expressions: any[] = [];
11482
- let original_expressions: any[] = [];
11483
- if (SP_EXPRESSION) {
11484
- const retVal = this.ProcessExpressions(resourceName, SP_EXPRESSION);
11485
- expressions = retVal.expressions;
11486
- original_expressions = retVal.original_expressions;
11487
- }
11488
11440
 
11489
- if (!searchParamData[resourceName]) {
11490
- searchParamData[resourceName] = {
11491
- resourceName,
11492
- params: [ ]
11493
- }
11494
- }
11495
-
11496
- // GetResourceField
11497
-
11498
- const record: ISearchParamRecord = {
11499
- SP_ID,
11500
- SP_NAME,
11501
- SP_TYPE,
11502
- SP_URL,
11503
- expressions,
11504
- original_expressions,
11505
- SP_DEFINITION: this.resourceHelper.GetSearchParam(SP_URL)
11506
- };
11507
-
11508
- for (let i=0; i < record.expressions.length; i++) {
11509
- //console.log(record.expressions[i]);
11510
- const rf = this.resourceHelper.GetResourceField(resourceName, record.expressions[i].path);
11511
- if (rf) {
11512
- expressions[i].RES_FIELD = rf;
11513
- }
11514
- }
11515
-
11516
- if (val2.component) {
11517
- record.component = [ ...val2.component ];
11518
- (record.component as any[]).forEach(c => {
11519
- //c.SP_RAW_PATHS = (c.expression.split('|') as any[]).map(rp => rp.trim());
11520
- //c.SP_PATHS = (c.SP_RAW_PATHS as any[]).map(rawPath => this.ResolveFhirChoiceType(rawPath));
11521
- const retVal = this.ProcessExpressions('', c.expression);
11522
- c.expressions = retVal.expressions;
11523
- c.original_expressions = retVal.original_expressions;
11524
- const def = this.resourceHelper.GetSearchParam(c.definition);
11525
- if (def && def.type) {
11526
- c.type = def.type
11527
- }
11528
- })
11529
- }
11530
-
11531
- searchParamData[resourceName].params.push(record);
11532
- }
11533
- }
11534
-
11535
- this.#searchParams = searchParamData;
11441
+ GetSearchParamFromResourceType = (resourceType: string, name: string): ISearchParamRecord | undefined => {
11442
+ return this.resourceHelper.GetSearchParamFromResourceType(resourceType, name);
11443
+ }
11536
11444
 
11537
- return searchParamData;
11445
+ GetPathsFromResourceType = (resourceType: string, name: string): string[] => {
11446
+ return this.resourceHelper.GetPathsFromResourceType(resourceType, name);
11538
11447
  }
11539
- */
11448
+ */
11540
11449
  }
11541
11450
  var lib$1 = { exports: {} };
11542
11451
  var defaults = { exports: {} };
@@ -18945,229 +18854,10 @@ class PGFhirAccessLayer extends tinyEmitterExports.TinyEmitter {
18945
18854
  }
18946
18855
  };
18947
18856
  }
18948
- const RELEASE_SCRIPT = `
18949
- if redis.call("get", KEYS[1]) == ARGV[1] then
18950
- return redis.call("del", KEYS[1])
18951
- else
18952
- return 0
18953
- end
18954
- `;
18955
- const RENEW_SCRIPT = `
18956
- if redis.call("get", KEYS[1]) == ARGV[1] then
18957
- return redis.call("pexpire", KEYS[1], ARGV[2])
18958
- else
18959
- return 0
18960
- end
18961
- `;
18962
- class RedisDistributedLock {
18963
- client;
18964
- ttlMs;
18965
- heartbeatMs;
18966
- keyPrefix;
18967
- constructor(client2, options) {
18968
- this.client = client2;
18969
- this.ttlMs = options?.ttlMs ?? 3e4;
18970
- this.heartbeatMs = options?.heartbeatMs ?? Math.floor(this.ttlMs / 3);
18971
- this.keyPrefix = options?.keyPrefix ?? "lock:";
18972
- if (this.ttlMs <= 0) {
18973
- throw new Error("ttlMs must be > 0");
18974
- }
18975
- if (this.heartbeatMs <= 0) {
18976
- throw new Error("heartbeatMs must be > 0");
18977
- }
18978
- if (this.heartbeatMs >= this.ttlMs) {
18979
- throw new Error("heartbeatMs should be less than ttlMs");
18980
- }
18981
- }
18982
- buildKey(name) {
18983
- return `${this.keyPrefix}${name}`;
18984
- }
18985
- async acquire(name, ttlMs) {
18986
- const key = this.buildKey(name);
18987
- const token = require$$0.randomUUID();
18988
- const effectiveTtlMs = ttlMs ?? this.ttlMs;
18989
- const result2 = await this.client.set(key, token, {
18990
- NX: true,
18991
- PX: effectiveTtlMs
18992
- });
18993
- if (result2 !== "OK") {
18994
- return null;
18995
- }
18996
- return {
18997
- key,
18998
- token,
18999
- ttlMs: effectiveTtlMs
19000
- };
19001
- }
19002
- async release(lock) {
19003
- const result2 = await this.client.eval(RELEASE_SCRIPT, {
19004
- keys: [lock.key],
19005
- arguments: [lock.token]
19006
- });
19007
- return Number(result2) === 1;
19008
- }
19009
- async renew(lock, ttlMs) {
19010
- const effectiveTtlMs = ttlMs ?? lock.ttlMs;
19011
- const result2 = await this.client.eval(RENEW_SCRIPT, {
19012
- keys: [lock.key],
19013
- arguments: [lock.token, String(effectiveTtlMs)]
19014
- });
19015
- return Number(result2) === 1;
19016
- }
19017
- async isOwner(lock) {
19018
- const currentValue = await this.client.get(lock.key);
19019
- return currentValue === lock.token;
19020
- }
19021
- async runExclusive(name, task, options) {
19022
- const lock = await this.acquire(name, options?.ttlMs);
19023
- if (!lock) {
19024
- if (options?.onLockNotAcquired) {
19025
- await options.onLockNotAcquired();
19026
- }
19027
- return { acquired: false };
19028
- }
19029
- let timer = null;
19030
- let stopped = false;
19031
- let renewalError = null;
19032
- const autoRenew = options?.autoRenew ?? false;
19033
- const heartbeatMs = options?.heartbeatMs ?? this.heartbeatMs;
19034
- const stopHeartbeat = () => {
19035
- stopped = true;
19036
- if (timer) {
19037
- clearInterval(timer);
19038
- timer = null;
19039
- }
19040
- };
19041
- if (autoRenew) {
19042
- timer = setInterval(async () => {
19043
- if (stopped) {
19044
- return;
19045
- }
19046
- try {
19047
- const ok = await this.renew(lock, lock.ttlMs);
19048
- if (!ok) {
19049
- renewalError = new Error(
19050
- `Lost lock ownership while renewing "${lock.key}"`
19051
- );
19052
- stopHeartbeat();
19053
- }
19054
- } catch (err) {
19055
- renewalError = err instanceof Error ? err : new Error(String(err));
19056
- stopHeartbeat();
19057
- }
19058
- }, heartbeatMs).unref();
19059
- }
19060
- try {
19061
- const result2 = await task();
19062
- if (renewalError) {
19063
- throw renewalError;
19064
- }
19065
- return { acquired: true, result: result2 };
19066
- } finally {
19067
- stopHeartbeat();
19068
- try {
19069
- await this.release(lock);
19070
- } catch {
19071
- }
19072
- }
19073
- }
19074
- }
19075
- class SearchParameterManager {
19076
- redis;
19077
- EnsureSearchParameterDataLoaded = async (name, loadFn, options) => {
19078
- if (!this.redis) {
19079
- const redisUrl = stsconfig.goptions.imRedisMessageProcessorUrl;
19080
- console.log(`SearchParameterManager(): redis trying to connect ...`);
19081
- this.redis = redis.createClient({
19082
- url: redisUrl
19083
- });
19084
- await this.redis.connect();
19085
- console.log(`SearchParameterManager(): redis connected`);
19086
- }
19087
- try {
19088
- const pollIntervalMs = options?.pollIntervalMs ?? 250;
19089
- const lockTtlMs = options?.lockTtlMs ?? 3e4;
19090
- const autoRenew = options?.autoRenew ?? true;
19091
- const heartbeatMs = options?.heartbeatMs ?? 1e4;
19092
- const completeTtlSeconds = options?.completeTtlSeconds;
19093
- const timeoutMs = options?.timeoutMs;
19094
- const completeKey = `fhir:searchparam:${name}:complete`;
19095
- const startedAt = Date.now();
19096
- const lockManager = new RedisDistributedLock(this.redis, {
19097
- ttlMs: 3e4,
19098
- heartbeatMs: 1e4,
19099
- keyPrefix: "lock:"
19100
- });
19101
- while (true) {
19102
- if (typeof timeoutMs === "number" && timeoutMs > 0) {
19103
- const elapsedMs = Date.now() - startedAt;
19104
- if (elapsedMs >= timeoutMs) {
19105
- throw new Error(
19106
- `Timed out waiting for search param "${name}" to be loaded`
19107
- );
19108
- }
19109
- }
19110
- try {
19111
- const alreadyComplete = await this.redis.get(completeKey);
19112
- if (alreadyComplete) {
19113
- console.log(`ensureSearchParamLoaded():alreadyComplete: PID: [${process.pid}] data loaded: [${alreadyComplete}]`);
19114
- return;
19115
- }
19116
- } catch (error) {
19117
- console.error(error);
19118
- throw error;
19119
- }
19120
- const runResult = await lockManager.runExclusive(
19121
- `fhir:searchparam:${name}`,
19122
- async () => {
19123
- console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] lock acquired`);
19124
- const completeAfterLock = await this.redis.get(completeKey);
19125
- if (completeAfterLock) {
19126
- console.log(`ensureSearchParamLoaded():completeAfterLock: PID: [${process.pid}] data loaded: [${completeAfterLock}]`);
19127
- return;
19128
- }
19129
- await loadFn();
19130
- const completeValue = JSON.stringify({
19131
- loaded: true,
19132
- loadedAt: (/* @__PURE__ */ new Date()).toLocaleString(),
19133
- name,
19134
- workerPid: process.pid
19135
- });
19136
- console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] data loaded: [${completeValue}]`);
19137
- if (typeof completeTtlSeconds === "number" && completeTtlSeconds > 0) {
19138
- await this.redis.set(completeKey, completeValue, {
19139
- EX: completeTtlSeconds
19140
- });
19141
- } else {
19142
- await this.redis.set(completeKey, completeValue);
19143
- }
19144
- },
19145
- {
19146
- ttlMs: lockTtlMs,
19147
- autoRenew,
19148
- heartbeatMs
19149
- }
19150
- );
19151
- if (runResult.acquired) {
19152
- return;
19153
- }
19154
- console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] Did not get lock`);
19155
- await stsutils.Sleep(pollIntervalMs);
19156
- }
19157
- } finally {
19158
- if (this.redis) {
19159
- this.redis.close();
19160
- console.log(`SearchParameterManager(): redis closed`);
19161
- }
19162
- }
19163
- };
19164
- }
19165
18857
  exports.DBSearchIndex = DBSearchIndex;
19166
18858
  exports.FHIRDateUtils = FHIRDateUtils;
19167
18859
  exports.PGFhirAccessLayer = PGFhirAccessLayer;
19168
- exports.RedisDistributedLock = RedisDistributedLock;
19169
18860
  exports.ResourceHelper = ResourceHelper;
19170
- exports.SearchParameterManager = SearchParameterManager;
19171
18861
  exports.hashReferenceParam = hashReferenceParam;
19172
18862
  exports.hashStringParam = hashStringParam;
19173
18863
  exports.hashTokenParam = hashTokenParam;