@nsshunt/stsfhirpg 1.2.29 → 1.2.30
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/index.cjs +841 -439
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +841 -439
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/types/fhir-database/dbsearchindexreference.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhiraccesslayer.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhircombo.d.ts +3 -1
- package/types/fhir-database/pg/pgfhircombo.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirdate.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirdate.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirdbparamtypebase.d.ts +11 -0
- package/types/fhir-database/pg/pgfhirdbparamtypebase.d.ts.map +1 -0
- package/types/fhir-database/pg/pgfhirnumber.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirnumber.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirquantity.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirquantity.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirresource.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirresourcelink.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirresourcelink.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirstring.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirstring.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhirtoken.d.ts +3 -1
- package/types/fhir-database/pg/pgfhirtoken.d.ts.map +1 -1
- package/types/fhir-database/pg/pgfhiruri.d.ts +3 -1
- package/types/fhir-database/pg/pgfhiruri.d.ts.map +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["#LoadDefinitions","#searchParametersByResourceTypeKey","#searchParametersByUrlKey","#resourcesKey","#typesKey","#definitions","#loaded","#LoadDefinitions","#RemoveSurroundingParentheses","#ops","#GetValueFromResourceAtPath","#GenerateHashValues","#OutputToken","#warn","#debug","#OutputQuantity","#GetResourceID","#OutputReference","#resourceHelper","#OutputString","#OutputNumber","#OutputURI","#searchIndexBaseRegistry","#debug","#options","#CreatePools","#CreatePool","#AttachInstruments","#pools","#GetPoolKey","#LogDebugMessage","#LogErrorMessage","#UpdateInstruments","#DetachInstruments","#keyPrefix","#observer","#FilterResults","#filterResults","#filterResults","#filterResults","#filterResults","#filterResults","#replacer","#filterResults","#options","#poolManager","#dbSTSResource","#dbSTSResourceVersion","#dbSearchIndex","#dbSTSResourceLink","#dbSTSString","#dbSTSToken","#dbSTSQuantity","#dbSTSNumber","#dbSTSDate","#dbSTSUri","#dbSTSCombo","#transactions","#maxTransactionTime"],"sources":["../src/fhir-utils/fhirDateUtils.ts","../node_modules/xxhash-wasm/esm/xxhash-wasm.js","../__vite-browser-external","../src/fhir-utils/hashUtils.ts","../src/fhir-utils/fhirHashUtils.ts","../src/redisDistributedLock.ts","../src/searchParameterManager.ts","../src/fhir-utils/resourceHelper.ts","../src/fhir-database/dbsearchindexbase.ts","../src/fhir-database/dbsearchindextoken.ts","../src/fhir-database/dbsearchindexcomposite.ts","../src/fhir-database/dbsearchindexdates.ts","../src/fhir-database/dbsearchindexquantity.ts","../src/fhir-database/dbsearchindexreference.ts","../src/fhir-database/dbsearchindexstring.ts","../src/fhir-database/dbsearchindexnumber.ts","../src/fhir-database/dbsearchindexuri.ts","../src/fhir-database/dbsearchregistry.ts","../src/fhir-database/dbsearchindex.ts","../src/fhir-database/pg/pgpoolmanager.ts","../src/fhir-database/pg/pgfhirdbbase.ts","../src/fhir-database/pg/pgfhirresource.ts","../src/fhir-database/pg/pgfhirresourceversion.ts","../src/fhir-database/pg/pgfhirresourcelink.ts","../src/fhir-database/pg/pgfhirstring.ts","../src/fhir-database/pg/pgfhirtoken.ts","../src/fhir-database/pg/pgfhirquantity.ts","../src/fhir-database/pg/pgfhirnumber.ts","../src/fhir-database/pg/pgfhirdate.ts","../src/fhir-database/pg/pgfhiruri.ts","../src/fhir-database/pg/pgfhircombo.ts","../src/fhir-database/pg/pgfhiraccesslayer.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\n/* eslint @typescript-eslint/no-unused-vars: 0 */ // --> OFF\nimport { DateTime } from 'luxon';\n\nexport class FHIRDateUtils {\n static fullDateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n static yearMonthRegex = /^\\d{4}-\\d{2}$/;\n static yearRegex = /^\\d{4}$/;\n\n // Parse FHIR date: YYYY | YYYY-MM | YYYY-MM-DD\n static parseDate(value: string): DateTime | null {\n if (this.yearRegex.test(value)) {\n return DateTime.fromFormat(value, 'yyyy', { zone: 'utc' });\n } else if (this.yearMonthRegex.test(value)) {\n return DateTime.fromFormat(value, 'yyyy-MM', { zone: 'utc' });\n } else if (this.fullDateRegex.test(value)) {\n return DateTime.fromISO(value, { zone: 'utc' });\n } else {\n return null;\n }\n }\n\n // Parse FHIR dateTime\n static parseDateTime(value: string): DateTime | null {\n const dt = DateTime.fromISO(value);\n return dt.isValid ? dt : null;\n }\n\n // Parse FHIR instant (must include timezone per spec)\n static parseInstant(value: string): DateTime | null {\n const dt = DateTime.fromISO(value, { setZone: true });\n return dt.isValid && dt.offset !== null ? dt : null;\n }\n\n // Format DateTime to FHIR date\n static formatDate(dt: DateTime, precision: 'year' | 'month' | 'day' = 'day'): string {\n switch (precision) {\n case 'year': return dt.toFormat('yyyy');\n case 'month': return dt.toFormat('yyyy-MM');\n case 'day':\n default: return dt.toFormat('yyyy-MM-dd');\n }\n }\n\n // Format DateTime to FHIR dateTime\n static formatDateTime(dt: DateTime, includeTimeZone = true): string {\n return includeTimeZone\n ? dt.toISO()!\n : dt.toISO({ includeOffset: false, suppressMilliseconds: true })!;\n }\n\n // Format FHIR instant (must include time + timezone)\n static formatInstant(dt: DateTime): string {\n return dt.toUTC().toISO()!; // Always UTC/Z\n }\n\n // Parse FHIR Period\n static parsePeriod(period: { start?: string; end?: string }): { start: DateTime | null; end: DateTime | null } {\n return {\n start: period.start ? this.parseDateTime(period.start) : null,\n end: period.end ? this.parseDateTime(period.end) : null\n };\n }\n\n // Format Period\n static formatPeriod(start?: DateTime, end?: DateTime): { start?: string; end?: string } {\n const out: any = {};\n if (start) {\n out.start = this.formatDateTime(start);\n }\n if (end) {\n out.end = this.formatDateTime(end);\n }\n return out;\n }\n\n // Very basic Timing parser (expands repeat boundsPeriod only)\n static parseTiming(timing: any): { boundsStart?: DateTime; boundsEnd?: DateTime } {\n if (!timing || !timing.repeat || !timing.repeat.boundsPeriod) {\n return {};\n }\n const { start, end } = timing.repeat.boundsPeriod;\n return {\n boundsStart: start ? this.parseDateTime(start)! : undefined,\n boundsEnd: end ? this.parseDateTime(end)! : undefined\n };\n }\n}\n","const t=new Uint8Array([0,97,115,109,1,0,0,0,1,48,8,96,3,127,127,127,1,127,96,3,127,127,127,0,96,2,127,127,0,96,1,127,1,127,96,3,127,127,126,1,126,96,3,126,127,127,1,126,96,2,127,126,0,96,1,127,1,126,3,11,10,0,0,2,1,3,4,5,6,1,7,5,3,1,0,1,7,85,9,3,109,101,109,2,0,5,120,120,104,51,50,0,0,6,105,110,105,116,51,50,0,2,8,117,112,100,97,116,101,51,50,0,3,8,100,105,103,101,115,116,51,50,0,4,5,120,120,104,54,52,0,5,6,105,110,105,116,54,52,0,7,8,117,112,100,97,116,101,54,52,0,8,8,100,105,103,101,115,116,54,52,0,9,10,251,22,10,242,1,1,4,127,32,0,32,1,106,33,3,32,1,65,16,79,4,127,32,3,65,16,107,33,6,32,2,65,168,136,141,161,2,106,33,3,32,2,65,137,235,208,208,7,107,33,4,32,2,65,207,140,162,142,6,106,33,5,3,64,32,3,32,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,4,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,4,32,2,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,5,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,6,32,0,65,4,106,34,0,79,13,0,11,32,2,65,12,119,32,5,65,18,119,106,32,4,65,7,119,106,32,3,65,1,119,106,5,32,2,65,177,207,217,178,1,106,11,32,1,106,32,0,32,1,65,15,113,16,1,11,146,1,0,32,1,32,2,106,33,2,3,64,32,1,65,4,106,32,2,75,69,4,64,32,0,32,1,40,2,0,65,189,220,202,149,124,108,106,65,17,119,65,175,214,211,190,2,108,33,0,32,1,65,4,106,33,1,12,1,11,11,3,64,32,1,32,2,79,69,4,64,32,0,32,1,45,0,0,65,177,207,217,178,1,108,106,65,11,119,65,177,243,221,241,121,108,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,65,15,118,115,65,247,148,175,175,120,108,34,0,65,13,118,32,0,115,65,189,220,202,149,124,108,34,0,65,16,118,32,0,115,11,63,0,32,0,65,8,106,32,1,65,168,136,141,161,2,106,54,2,0,32,0,65,12,106,32,1,65,137,235,208,208,7,107,54,2,0,32,0,65,16,106,32,1,54,2,0,32,0,65,20,106,32,1,65,207,140,162,142,6,106,54,2,0,11,195,4,1,6,127,32,1,32,2,106,33,6,32,0,65,24,106,33,4,32,0,65,40,106,40,2,0,33,3,32,0,32,0,40,2,0,32,2,106,54,2,0,32,0,65,4,106,34,5,32,5,40,2,0,32,2,65,16,79,32,0,40,2,0,65,16,79,114,114,54,2,0,32,2,32,3,106,65,16,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,40,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,16,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,40,2,0,32,4,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,12,106,34,3,32,3,40,2,0,32,4,65,4,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,16,106,34,3,32,3,40,2,0,32,4,65,8,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,20,106,34,3,32,3,40,2,0,32,4,65,12,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,40,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,32,6,65,16,107,77,4,64,32,6,65,16,107,33,8,32,0,65,8,106,40,2,0,33,2,32,0,65,12,106,40,2,0,33,3,32,0,65,16,106,40,2,0,33,5,32,0,65,20,106,40,2,0,33,7,3,64,32,2,32,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,3,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,5,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,7,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,7,32,8,32,1,65,4,106,34,1,79,13,0,11,32,0,65,8,106,32,2,54,2,0,32,0,65,12,106,32,3,54,2,0,32,0,65,16,106,32,5,54,2,0,32,0,65,20,106,32,7,54,2,0,11,32,1,32,6,73,4,64,32,4,32,1,32,6,32,1,107,34,1,252,10,0,0,32,0,65,40,106,32,1,54,2,0,11,11,97,1,1,127,32,0,65,16,106,40,2,0,33,1,32,0,65,4,106,40,2,0,4,127,32,1,65,12,119,32,0,65,20,106,40,2,0,65,18,119,106,32,0,65,12,106,40,2,0,65,7,119,106,32,0,65,8,106,40,2,0,65,1,119,106,5,32,1,65,177,207,217,178,1,106,11,32,0,40,2,0,106,32,0,65,24,106,32,0,65,40,106,40,2,0,16,1,11,255,3,2,3,126,1,127,32,0,32,1,106,33,6,32,1,65,32,79,4,126,32,6,65,32,107,33,6,32,2,66,214,235,130,238,234,253,137,245,224,0,124,33,3,32,2,66,177,169,172,193,173,184,212,166,61,125,33,4,32,2,66,249,234,208,208,231,201,161,228,225,0,124,33,5,3,64,32,3,32,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,3,32,4,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,4,32,2,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,2,32,5,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,5,32,6,32,0,65,8,106,34,0,79,13,0,11,32,2,66,12,137,32,5,66,18,137,124,32,4,66,7,137,124,32,3,66,1,137,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,2,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,2,66,197,207,217,178,241,229,186,234,39,124,11,32,1,173,124,32,0,32,1,65,31,113,16,6,11,134,2,0,32,1,32,2,106,33,2,3,64,32,2,32,1,65,8,106,79,4,64,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,32,0,133,66,27,137,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,33,0,32,1,65,8,106,33,1,12,1,11,11,32,1,65,4,106,32,2,77,4,64,32,0,32,1,53,2,0,66,135,149,175,175,152,182,222,155,158,127,126,133,66,23,137,66,207,214,211,190,210,199,171,217,66,126,66,249,243,221,241,153,246,153,171,22,124,33,0,32,1,65,4,106,33,1,11,3,64,32,1,32,2,73,4,64,32,0,32,1,49,0,0,66,197,207,217,178,241,229,186,234,39,126,133,66,11,137,66,135,149,175,175,152,182,222,155,158,127,126,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,66,33,136,133,66,207,214,211,190,210,199,171,217,66,126,34,0,32,0,66,29,136,133,66,249,243,221,241,153,246,153,171,22,126,34,0,32,0,66,32,136,133,11,77,0,32,0,65,8,106,32,1,66,214,235,130,238,234,253,137,245,224,0,124,55,3,0,32,0,65,16,106,32,1,66,177,169,172,193,173,184,212,166,61,125,55,3,0,32,0,65,24,106,32,1,55,3,0,32,0,65,32,106,32,1,66,249,234,208,208,231,201,161,228,225,0,124,55,3,0,11,244,4,2,3,127,4,126,32,1,32,2,106,33,5,32,0,65,40,106,33,4,32,0,65,200,0,106,40,2,0,33,3,32,0,32,0,41,3,0,32,2,173,124,55,3,0,32,2,32,3,106,65,32,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,200,0,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,32,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,41,3,0,32,4,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,16,106,34,3,32,3,41,3,0,32,4,65,8,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,24,106,34,3,32,3,41,3,0,32,4,65,16,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,32,106,34,3,32,3,41,3,0,32,4,65,24,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,200,0,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,65,32,106,32,5,77,4,64,32,5,65,32,107,33,2,32,0,65,8,106,41,3,0,33,6,32,0,65,16,106,41,3,0,33,7,32,0,65,24,106,41,3,0,33,8,32,0,65,32,106,41,3,0,33,9,3,64,32,6,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,6,32,7,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,7,32,8,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,8,32,9,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,9,32,2,32,1,65,8,106,34,1,79,13,0,11,32,0,65,8,106,32,6,55,3,0,32,0,65,16,106,32,7,55,3,0,32,0,65,24,106,32,8,55,3,0,32,0,65,32,106,32,9,55,3,0,11,32,1,32,5,73,4,64,32,4,32,1,32,5,32,1,107,34,1,252,10,0,0,32,0,65,200,0,106,32,1,54,2,0,11,11,188,2,1,5,126,32,0,65,24,106,41,3,0,33,1,32,0,41,3,0,34,2,66,32,90,4,126,32,0,65,8,106,41,3,0,34,3,66,1,137,32,0,65,16,106,41,3,0,34,4,66,7,137,124,32,1,66,12,137,32,0,65,32,106,41,3,0,34,5,66,18,137,124,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,1,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,1,66,197,207,217,178,241,229,186,234,39,124,11,32,2,124,32,0,65,40,106,32,2,66,31,131,167,16,6,11]);async function e(){return function(t){const{exports:{mem:e,xxh32:n,xxh64:r,init32:i,update32:a,digest32:o,init64:s,update64:u,digest64:c}}=t;let h=new Uint8Array(e.buffer);function g(t,n){if(e.buffer.byteLength<t+n){const r=Math.ceil((t+n-e.buffer.byteLength)/65536);e.grow(r),h=new Uint8Array(e.buffer)}}function f(t,e,n,r,i,a){g(t);const o=new Uint8Array(t);return h.set(o),n(0,e),o.set(h.subarray(0,t)),{update(e){let n;return h.set(o),\"string\"==typeof e?(g(3*e.length,t),n=w.encodeInto(e,h.subarray(t)).written):(g(e.byteLength,t),h.set(e,t),n=e.byteLength),r(0,t,n),o.set(h.subarray(0,t)),this},digest:()=>(h.set(o),a(i(0)))}}function y(t){return t>>>0}const b=2n**64n-1n;function d(t){return t&b}const w=new TextEncoder,l=0,p=0n;function x(t,e=l){return g(3*t.length,0),y(n(0,w.encodeInto(t,h).written,e))}function L(t,e=p){return g(3*t.length,0),d(r(0,w.encodeInto(t,h).written,e))}return{h32:x,h32ToString:(t,e=l)=>x(t,e).toString(16).padStart(8,\"0\"),h32Raw:(t,e=l)=>(g(t.byteLength,0),h.set(t),y(n(0,t.byteLength,e))),create32:(t=l)=>f(48,t,i,a,o,y),h64:L,h64ToString:(t,e=p)=>L(t,e).toString(16).padStart(16,\"0\"),h64Raw:(t,e=p)=>(g(t.byteLength,0),h.set(t),d(r(0,t.byteLength,e))),create64:(t=p)=>f(88,t,s,u,c,d)}}((await WebAssembly.instantiate(t)).instance)}export{e as default};\n//# sourceMappingURL=xxhash-wasm.js.map\n","module.exports = {}","import { error } from 'node:console';\nimport xxhash from 'xxhash-wasm';\n\nexport type TokenParam = {\n system?: string | null;\n code: string;\n};\n\nexport class HashUtils {\n private static instance: HashUtils;\n\n private HASH_SEED = 0xABCDn;\n private h64?: (input: string, seed?: bigint) => bigint;\n\n static getInstance(): HashUtils {\n if (!HashUtils.instance) {\n HashUtils.instance = new HashUtils();\n }\n return HashUtils.instance;\n }\n\n private constructor() {\n\n }\n\n normalizeStringParam = (input: string): string => {\n return input.trim().replace(/\\s+/g, ' ').toLowerCase();\n }\n\n InitHash = async (): Promise<void> => {\n const api = await xxhash();\n this.h64 = api.h64;\n }\n\n xxhash64Signed(input: string): bigint {\n if (this.h64) {\n return BigInt.asIntN(64, this.h64(input, this.HASH_SEED));\n }\n throw error(`h64 not initialized`);\n }\n\n hashStringParam(input: string, normalize: boolean): bigint {\n if (normalize === true) {\n const normalized = this.normalizeStringParam(input);\n return this.xxhash64Signed(normalized);\n } else {\n return this.xxhash64Signed(input);\n }\n }\n\n hashTokenParam({ system, code }: TokenParam): bigint {\n const combined = (system ?? '') + '|' + code;\n return this.xxhash64Signed(combined);\n }\n\n hashReferenceParam(reference: string): bigint {\n return this.xxhash64Signed(reference);\n }\n\n hashUriParam(uri: string, lowercase = false): bigint {\n return this.xxhash64Signed(lowercase ? uri.toLowerCase() : uri);\n }\n\n}","//import { x64 } from 'murmurhash3js';\nimport xxhash from 'xxhash-wasm';\n\nimport { HashUtils } from './hashUtils.js'\n\nHashUtils.getInstance().InitHash();\n\nconst HASH_SEED = 0xABCDn;\n\nexport type TokenParam = {\n system?: string | null;\n code: string;\n};\n\n//\n// NORMALIZATION HELPERS\n//\n\n/**\n * Normalize string values similar to HAPI FHIR (trim, collapse whitespace, lowercase)\n */\nexport function normalizeStringParam(input: string): string {\n return input.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n\n//\n// HASHING HELPERS\n//\n\nlet h64: (input: string, seed?: bigint) => bigint;\n\nexport async function initHash(): Promise<void> {\n const api = await xxhash();\n h64 = api.h64;\n}\n\nexport function xxhash64Signed(input: string): bigint {\n return BigInt.asIntN(64, h64(input, HASH_SEED));\n}\n\n\n/*\nexport function xxhash64Signed(input: string): bigint {\n const hashHex = xxhash.h64(input, 0xABCD).toString(16).padStart(16, '0');\n const buf = Buffer.from(hashHex, 'hex');\n return buf.readBigInt64BE(0);\n}\n*/\n\n/**\n * Converts first 64 bits of MurmurHash3_x64_128 result into signed BigInt\n */\n\n/*\nexport function murmur64Signed(input: string): bigint {\n //const hex128 = x64.hash128(input);\n const hex128 = xxhash.h64(input, 0xABCD).toString(16);\n const buf = Buffer.from(hex128.slice(0, 16), 'hex');\n return buf.readBigInt64LE(0);\n}\n*/\n\n/**\n * Compute hash for a normalized string search parameter\n */\nexport function hashStringParam(input: string, normalize: boolean): bigint {\n\n return HashUtils.getInstance().hashStringParam(input, normalize);\n\n if (normalize === true) {\n const normalized = normalizeStringParam(input);\n return xxhash64Signed(normalized);\n } else {\n return xxhash64Signed(input);\n }\n}\n\n/**\n * Compute hash for a token search parameter (system|code)\n */\nexport function hashTokenParam({ system, code }: TokenParam): bigint {\n const combined = (system ?? '') + '|' + code;\n return xxhash64Signed(combined);\n}\n\n/**\n * Compute hash for a reference search parameter\n * Case-sensitive and used as-is\n */\nexport function hashReferenceParam(reference: string): bigint {\n return xxhash64Signed(reference);\n}\n\n/**\n * Compute hash for a URI parameter (optionally lowercased)\n */\nexport function hashUriParam(uri: string, lowercase = false): bigint {\n return xxhash64Signed(lowercase ? uri.toLowerCase() : uri);\n}\n","import { createClient, RedisClientType } from 'redis';\nimport { randomUUID } from 'crypto';\n\nexport type AppRedisClient = ReturnType<typeof createClient>;\n\nconst RELEASE_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"del\", KEYS[1])\nelse\n return 0\nend\n`;\n\nconst RENEW_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"pexpire\", KEYS[1], ARGV[2])\nelse\n return 0\nend\n`;\n\nexport interface RedisDistributedLockOptions {\n ttlMs?: number;\n heartbeatMs?: number;\n keyPrefix?: string;\n}\n\nexport interface LockHandle {\n key: string;\n token: string;\n ttlMs: number;\n}\n\nexport class RedisDistributedLock {\n private readonly client: AppRedisClient;\n private readonly ttlMs: number;\n private readonly heartbeatMs: number;\n private readonly keyPrefix: string;\n\n public constructor(\n client: AppRedisClient,\n options?: RedisDistributedLockOptions\n ) {\n this.client = client;\n this.ttlMs = options?.ttlMs ?? 30000;\n this.heartbeatMs = options?.heartbeatMs ?? Math.floor(this.ttlMs / 3);\n this.keyPrefix = options?.keyPrefix ?? 'lock:';\n\n if (this.ttlMs <= 0) {\n throw new Error('ttlMs must be > 0');\n }\n\n if (this.heartbeatMs <= 0) {\n throw new Error('heartbeatMs must be > 0');\n }\n\n if (this.heartbeatMs >= this.ttlMs) {\n throw new Error('heartbeatMs should be less than ttlMs');\n }\n }\n\n private buildKey(name: string): string {\n return `${this.keyPrefix}${name}`;\n }\n\n public async acquire(\n name: string,\n ttlMs?: number\n ): Promise<LockHandle | null> {\n const key = this.buildKey(name);\n const token = randomUUID();\n const effectiveTtlMs = ttlMs ?? this.ttlMs;\n\n const result = await this.client.set(key, token, {\n NX: true,\n PX: effectiveTtlMs\n });\n\n if (result !== 'OK') {\n return null;\n }\n\n return {\n key,\n token,\n ttlMs: effectiveTtlMs\n };\n }\n\n public async release(lock: LockHandle): Promise<boolean> {\n const result = await this.client.eval(RELEASE_SCRIPT, {\n keys: [lock.key],\n arguments: [lock.token]\n });\n\n return Number(result) === 1;\n }\n\n public async renew(lock: LockHandle, ttlMs?: number): Promise<boolean> {\n const effectiveTtlMs = ttlMs ?? lock.ttlMs;\n\n const result = await this.client.eval(RENEW_SCRIPT, {\n keys: [lock.key],\n arguments: [lock.token, String(effectiveTtlMs)]\n });\n\n return Number(result) === 1;\n }\n\n public async isOwner(lock: LockHandle): Promise<boolean> {\n const currentValue = await this.client.get(lock.key);\n return currentValue === lock.token;\n }\n\n public async runExclusive<T>(\n name: string,\n task: () => Promise<T>,\n options?: {\n ttlMs?: number;\n autoRenew?: boolean;\n heartbeatMs?: number;\n onLockNotAcquired?: () => void | Promise<void>;\n }\n ): Promise<{ acquired: true; result: T } | { acquired: false }> {\n const lock = await this.acquire(name, options?.ttlMs);\n\n if (!lock) {\n if (options?.onLockNotAcquired) {\n await options.onLockNotAcquired();\n }\n return { acquired: false };\n }\n\n let timer: NodeJS.Timeout | null = null;\n let stopped = false;\n let renewalError: Error | null = null;\n\n const autoRenew = options?.autoRenew ?? false;\n const heartbeatMs = options?.heartbeatMs ?? this.heartbeatMs;\n\n const stopHeartbeat = (): void => {\n stopped = true;\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n\n if (autoRenew) {\n timer = setInterval(async () => {\n if (stopped) {\n return\n }\n\n try {\n const ok = await this.renew(lock, lock.ttlMs);\n if (!ok) {\n renewalError = new Error(\n `Lost lock ownership while renewing \"${lock.key}\"`\n );\n stopHeartbeat();\n }\n } catch (err) {\n renewalError =\n err instanceof Error ? err : new Error(String(err));\n stopHeartbeat();\n }\n }, heartbeatMs).unref();\n }\n\n try {\n const result = await task();\n\n if (renewalError) {\n throw renewalError;\n }\n\n return { acquired: true, result };\n } finally {\n stopHeartbeat();\n\n try {\n await this.release(lock);\n } catch {\n // Intentionally swallow release errors here.\n // If needed, log them through your own logger.\n }\n }\n }\n}","import { RedisDistributedLock, AppRedisClient } from './redisDistributedLock.js'\nimport { Sleep } from '@nsshunt/stsutils';\nimport { goptions } from '@nsshunt/stsconfig';\nimport { createClient } from 'redis';\n\nimport fs from 'node:fs';\n\nimport { SearchParameter } from '@nsshunt/stsfhirclient'\nimport { IResources } from './fhir-utils/resourceHelper.js'\n\nimport { ISearchParam} from './fhir-utils/commonTypes.js'\n\nconst specPath1: string = './dist/';\nconst specPath2: string = './node_modules/@nsshunt/stsfhirpg/dist/';\n\nconst resourcesPath = 'fhir-spec/profiles-resources.json';\nconst typesPath = 'fhir-spec/profiles-types.json';\nconst searchParamsPath = 'fhir-spec/search-parameters.json';\n\nexport interface ISearchParameterManagerOptions {\n name: string\n pollIntervalMs?: number;\n lockTtlMs?: number;\n autoRenew?: boolean;\n heartbeatMs?: number;\n completeTtlSeconds?: number;\n timeoutMs?: number;\n}\n\nexport class SearchParameterManager {\n private redis?: AppRedisClient;\n private alreadyComplete: string | null = null;\n private options: ISearchParameterManagerOptions;\n private cache: Record<string, any> = { };\n\n constructor(options: ISearchParameterManagerOptions) {\n this.options = options;\n }\n\n EnsureSearchParameterDataLoaded = async (resources: IResources): Promise<string> => {\n if (this.alreadyComplete) {\n return this.alreadyComplete;\n }\n if (!this.redis) {\n const redisUrl = goptions.imRedisMessageProcessorUrl;\n console.log(`SearchParameterManager(): redis trying to connect ...`);\n this.redis = createClient({\n url: redisUrl\n });\n await this.redis.connect();\n console.log(`SearchParameterManager(): redis connected`);\n }\n\n try {\n const pollIntervalMs = this.options?.pollIntervalMs ?? 250;\n const lockTtlMs = this.options?.lockTtlMs ?? 30000;\n const autoRenew = this.options?.autoRenew ?? true;\n const heartbeatMs = this.options?.heartbeatMs ?? 10000;\n const completeTtlSeconds = this.options?.completeTtlSeconds;\n const timeoutMs = this.options?.timeoutMs;\n\n const completeKey = `fhir:searchparam:${this.options.name}:complete`;\n const startedAt = Date.now();\n\n const lockManager = new RedisDistributedLock(this.redis, {\n ttlMs: 30000,\n heartbeatMs: 10000,\n keyPrefix: 'lock:'\n });\n\n while (true) {\n if (typeof timeoutMs === 'number' && timeoutMs > 0) {\n const elapsedMs = Date.now() - startedAt;\n if (elapsedMs >= timeoutMs) {\n throw new Error(\n `Timed out waiting for search param \"${this.options.name}\" to be loaded`\n );\n }\n }\n\n try {\n this.alreadyComplete = await this.redis.get(completeKey);\n if (this.alreadyComplete) {\n console.log(`ensureSearchParamLoaded():alreadyComplete: PID: [${process.pid}] data loaded: [${this.alreadyComplete}]`);\n return this.alreadyComplete;\n }\n } catch (error) {\n console.error(error);\n throw error;\n }\n\n const runResult = await lockManager.runExclusive(\n `fhir:searchparam:${this.options.name}`,\n async () => {\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] lock acquired`);\n this.alreadyComplete = await this.redis!.get(completeKey);\n if (this.alreadyComplete) {\n console.log(`ensureSearchParamLoaded():completeAfterLock: PID: [${process.pid}] data loaded: [${this.alreadyComplete}]`);\n return;\n }\n\n try {\n await this.#LoadDefinitions(resources);\n } catch (error) {\n console.error(error);\n throw error;\n }\n\n const completeValue = JSON.stringify({\n loaded: true,\n loadedAt: new Date().toLocaleString(),\n name: this.options.name,\n workerPid: process.pid\n });\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] data loaded: [${completeValue}]`);\n\n if (typeof completeTtlSeconds === 'number' && completeTtlSeconds > 0) {\n await this.redis!.set(completeKey, completeValue, {\n EX: completeTtlSeconds\n });\n } else {\n await this.redis!.set(completeKey, completeValue);\n }\n this.alreadyComplete = completeValue;\n },\n {\n ttlMs: lockTtlMs,\n autoRenew,\n heartbeatMs\n }\n );\n\n if (runResult.acquired) {\n if (this.alreadyComplete) {\n return this.alreadyComplete;\n } else {\n throw new Error(`EnsureSearchParameterDataLoaded(): runResult.acquired is true but this.alreadyComplete not set`);\n }\n }\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] Did not get lock`);\n\n await Sleep(pollIntervalMs);\n }\n } catch (error) {\n console.error(`SearchParameterManager:EnsureSearchParameterDataLoaded(): Error: [${error}]`);\n throw error;\n }\n }\n\n Stop = async () => {\n if (this.redis) {\n await this.redis.close();\n console.log(`SearchParameterManager(): redis closed`);\n }\n }\n\n #searchParametersByResourceTypeKey = `__stsfhir__searchParametersByResourceType`;\n #searchParametersByUrlKey = `__stsfhir__searchParametersByUrl`;\n #resourcesKey = `__stsfhir__resources`;\n #typesKey = `__stsfhir__types`;\n\n #LoadDefinitions = async (resources: IResources) => {\n console.log('Data Load Starting ...');\n\n for (const [key, value] of Object.entries(resources.searchParametersByResourceType)) {\n await this.redis!.hSet(this.#searchParametersByResourceTypeKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.searchParametersByUrl)) {\n await this.redis!.hSet(this.#searchParametersByUrlKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.resources)) {\n await this.redis!.hSet(this.#resourcesKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.types)) {\n await this.redis!.hSet(this.#typesKey, key, JSON.stringify(value));\n }\n\n console.log('All Done ***********************************************************************************');\n }\n\n GetSearchParamFromResourceType = async (resourceType: string): Promise<ISearchParam> => {\n const key = `${this.#searchParametersByResourceTypeKey}_${resourceType}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#searchParametersByResourceTypeKey, resourceType);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetType = async (typeName: string): Promise<any[]> => {\n const key = `${this.#typesKey}_${typeName}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#typesKey, typeName);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetResource = async (resourceType: string): Promise<any[]> => {\n const key = `${this.#resourcesKey}_${resourceType}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#resourcesKey, resourceType);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetSearchParam = async (url: string): Promise<SearchParameter> => {\n const key = `${this.#searchParametersByUrlKey}_${url}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#searchParametersByUrlKey, url);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n}\n","import fs from 'node:fs';\n\nimport { SearchParameter } from '@nsshunt/stsfhirclient'\n\nimport { ISearchParamRecord, ISearchParams, ISearchParamExpressionRecord,\n ISearchFieldRecord, ISearchParam } from './commonTypes.js'\n\n//import __resources from './../fhir-spec/profiles-resources.json'\n//import __types from './../fhir-spec/profiles-types.json'\n//import __searchParams from './../fhir-spec/search-parameters.json'\n\nimport { SearchParameterManager } from './../searchParameterManager.js'\n\nconst specPath1: string = './dist/';\nconst specPath2: string = './node_modules/@nsshunt/stsfhirpg/dist/';\n\nconst resourcesPath = 'fhir-spec/profiles-resources.json';\nconst typesPath = 'fhir-spec/profiles-types.json';\nconst searchParamsPath = 'fhir-spec/search-parameters.json';\n\n// './node_modules/@nsshunt/stsdatamanagement/dist'\n\nexport interface IResources {\n resources: Record<string, any>\n types: Record<string, any>\n searchParametersByUrl: Record<string, SearchParameter>\n searchParametersByResourceType: Record<string, ISearchParam>\n}\n\nexport class ResourceHelper {\n #definitions: IResources | undefined;\n #loaded: boolean = false;\n private searchParameterManager?: SearchParameterManager;\n\n private static instance: ResourceHelper;\n\n private constructor() {}\n\n static getInstance(): ResourceHelper {\n if (!ResourceHelper.instance) {\n ResourceHelper.instance = new ResourceHelper();\n }\n return ResourceHelper.instance;\n }\n\n Stop = async () => {\n if (this.searchParameterManager) {\n await this.searchParameterManager.Stop();\n }\n this.searchParameterManager = undefined;\n }\n\n #LoadDefinitions = async (): Promise<void> => {\n let usePath = '';\n if (fs.existsSync(`${specPath1}${resourcesPath}`)) {\n usePath = specPath1;\n } else {\n usePath = specPath2;\n }\n const __resources: any = JSON.parse(fs.readFileSync(`${usePath}${resourcesPath}`, 'utf-8'));\n const __types: any = JSON.parse(fs.readFileSync(`${usePath}${typesPath}`, 'utf-8'));\n const __searchParams: any = JSON.parse(fs.readFileSync(`${usePath}${searchParamsPath}`, 'utf-8'));\n\n if (!this.#definitions) {\n this.#definitions = {\n resources: { },\n types: { },\n searchParametersByUrl: { },\n searchParametersByResourceType: { }\n }\n }\n\n (__resources.entry as any[]).forEach(entry => {\n const resource: any = entry.resource;\n if (resource?.snapshot?.element) {\n const rt = resource.type as string;\n this.#definitions!.resources[rt] = resource.snapshot.element;\n }\n });\n \n (__types.entry as any[]).forEach(entry => {\n const type = entry.resource;\n if (type?.snapshot?.element) {\n this.#definitions!.types[type.type] = type.snapshot.element;\n }\n });\n\n (__searchParams.entry as any[]).forEach(entry => {\n this.#definitions!.searchParametersByUrl[entry.fullUrl] = entry.resource;\n });\n\n await this._LoadSearchParameters();\n\n await this.PreLoadSearchParameterData();\n\n this.#loaded = true;\n this.#definitions = undefined;\n }\n\n PreLoadSearchParameterData = async () => {\n console.log(`PreLoadSearchParameterData(): Start ...`);\n this.searchParameterManager = new SearchParameterManager({\n name: 'stsfhirspdata',\n pollIntervalMs: 250,\n lockTtlMs: 30000,\n autoRenew: true,\n heartbeatMs: 10000\n });\n await this.searchParameterManager.EnsureSearchParameterDataLoaded(this.#definitions!);\n console.log(`PreLoadSearchParameterData(): End`);\n } \n\n private GetDefinitions = async (): Promise<void> => {\n if (!this.#loaded) {\n if (!this.#definitions) {\n await this.#LoadDefinitions();\n }\n }\n }\n\n private _GetResource = async (resourceType: string): Promise<any[]> => {\n await this.GetDefinitions();\n return this.#definitions!.resources[resourceType];\n }\n\n private _GetResourceField = async (resourceType: string, fieldPath: string): Promise<any> => {\n const resource: any[] = await this._GetResource(resourceType);\n if (resource) {\n const foundRecord = resource.filter(o => o.id === fieldPath);\n if (foundRecord.length > 0) {\n return foundRecord[0];\n }\n return undefined;\n }\n }\n\n private _GetSearchParam = async (url: string): Promise<any> => {\n await this.GetDefinitions();\n return this.#definitions!.searchParametersByUrl[url];\n }\n\n private _GetSearchParams = async (): Promise<any> => {\n await this.GetDefinitions();\n return this.#definitions!.searchParametersByUrl;\n }\n\n GetType = async (typeName: string): Promise<any[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetType(typeName);\n //return this.#definitions!.types[typeName];\n }\n\n GetResource = async (resourceType: string): Promise<any[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetResource(resourceType);\n }\n\n GetResourceField = async (resourceType: string, fieldPath: string): Promise<any> => {\n const resource: any[] = await this.GetResource(resourceType);\n if (resource) {\n const foundRecord = resource.filter(o => o.id === fieldPath);\n if (foundRecord.length > 0) {\n return foundRecord[0];\n }\n return undefined;\n }\n\n }\n\n GetSearchParam = async (url: string): Promise<any> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetSearchParam(url);\n }\n\n /*\n private GetSearchParams = async (): Promise<SearchParameter[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetSearchParams();\n }\n\n GetSearchParamsByResource = async (resource: string): Promise<SearchParameter[]> => {\n await this.GetDefinitions();\n const searchParams = await this.GetSearchParams();\n return searchParams\n .filter(sp => sp.base.includes(resource))\n .map(sp => sp)\n //return Object.values(this.#definitions!.searchParametersByUrl)\n //.filter(sp => sp.base.includes(resource))\n //.map(sp => sp)\n }\n */\n\n // ------------------------------------------------------------------------------------------------------------------\n\n // Remove ( ) when either are present\n #RemoveOuterParentheses = (input: string): string => {\n return input.replace(/^\\(|\\)$/g, '');\n }\n\n // Remove ( ) only when both are present\n #RemoveSurroundingParentheses = (input: string): string => {\n return input.replace(/^\\((.*)\\)$/, '$1').trim();\n }\n\n /*\n \nNamingSystem derived-from reference NamingSystem.relatedArtifact.where(type='derived-from').resource\n \nNamingSystem predecessor reference NamingSystem.relatedArtifact.where(type='predecessor').resource\n\nClinicalUseDefinition product reference ClinicalUseDefinition.subject.where(resolve() is MedicinalProductDefinition)\n\nOrganizationAffiliation email token OrganizationAffiliation.contact.telecom.where(system='email')\nOrganizationAffiliation phone token OrganizationAffiliation.contact.telecom.where(system='phone')\n\nPackagedProductDefinition biological reference PackagedProductDefinition.packaging.containedItem.item.reference\nPackagedProductDefinition contained-item reference PackagedProductDefinition.packaging.containedItem.item.reference\n\nPatient deceased token Patient.deceased.exists() and Patient.deceased != false\nPractitioner deceased token Practitioner.deceased.exists() and Practitioner.deceased != false\n\nLocation contains special Location.extension('http://hl7.org/fhir/StructureDefinition/location-boundary-geojson').value\n\nQuestionnaireResponse item-subject reference QuestionnaireResponse.item.where(extension('http://hl7.org/fhir/StructureDefinition/questionnaireresponse-isSubject').exists()).answer.valueReference\n */\n\n ProcessExpressions = (resourceName: string, SP_EXPRESSION: string): any => {\n let expressions: any[] = [];\n\n //SP_EXPRESSION = this.#RemoveSurroundingParentheses(val2.expression);\n expressions = SP_EXPRESSION.split('|').map(e => e.trim());\n\n expressions = expressions.map(e => this.#RemoveSurroundingParentheses(e).trim());\n\n if (resourceName !== '') {\n expressions = expressions.filter(e => e.split('.')[0].trim().localeCompare(resourceName) === 0);\n }\n\n let original_expressions = [ ...expressions ];\n\n // ofType processing\n expressions = expressions.map((e: string) => {\n let capturedTypeOf = undefined;\n return {\n path: e.replace(\n /\\.ofType\\(([^)]+)\\)/g,\n (_: string, typeName: string) => {\n capturedTypeOf = true;\n return typeName.charAt(0).toUpperCase() + typeName.slice(1)\n }),\n typeOf: capturedTypeOf\n }\n });\n\n //@@ exists processing here is more or less hard coded to the deceased attribute.\n //@@ in future, we need an actual fhir language parser.\n expressions.forEach(expression => {\n try {\n const sp = expression as ISearchParamExpressionRecord;\n if (sp.path.indexOf('exists()') >= 0) {\n // Person.deceased.exists() and Person.deceased != false\n const parts = sp.path.split(' ');\n const i = parts[0].indexOf('exists()');\n if (i >= 0) {\n let fieldExistsEx = parts[0].substring(0, i-1);\n let op = parts[1];\n let fieldTestEx = parts[2];\n let comparator = parts[3];\n let value = parts[4];\n\n const fieldExistsParts = fieldExistsEx.split('.');\n let fieldExists = fieldExistsParts.slice(1).join('.');\n\n const fieldTestParts = fieldTestEx.split('.');\n let fieldTest = fieldTestParts.slice(1).join('.');\n\n sp.exists = {\n fieldExists: [ `${fieldExists}Boolean`, `${fieldExists}DataTime` ], // [x]Boolean or [x]DateTime\n op,\n fieldTest: [ `${fieldTest}Boolean`, `${fieldTest}DataTime` ],\n comparator,\n value: [ value, undefined ]\n }\n }\n }\n } catch (error) {\n\n }\n });\n\n // where(resolve()) processing\n let capturedType: string | undefined;\n expressions = expressions.map((obj: any) => {\n capturedType = undefined;\n const { path, typeOf, exists } = obj;\n return {\n path: path.replace(\n /\\.where\\(resolve\\(\\)\\s+is\\s+([^)]+)\\)/,\n (_: string, typeName: string) => {\n capturedType = typeName;\n //return ` // reference = ${capturedType}`; // remove the .where(...) part (you can put ` // ${capturedType}` if you want to keep a comment)\n return '';\n }),\n typeOf,\n reference: capturedType,\n exists\n }\n });\n\n // .where processing\n // The element before the .where will be an array. So this test checks which element(s) from that array are satisifed.\n let capturedWhere: any = undefined;\n expressions = expressions.map((obj: any) => {\n capturedWhere = undefined;\n const { path, reference, typeOf, exists } = obj;\n const retVal: any = {\n path: path.replace(/([^.]+)\\.where\\(([^=]+)='([^']+)'\\)/g, (_: string, field: string, subfield: string, value: string) => {\n capturedWhere = { field, subfield, value } \n return field;\n }),\n typeOf,\n reference,\n exists\n }\n if (capturedWhere) {\n capturedWhere.full = `${capturedWhere.field}[*].${capturedWhere.subfield}=${capturedWhere.value}`;\n retVal.where = capturedWhere;\n }\n return retVal;\n });\n\n\n return {\n expressions,\n original_expressions\n };\n }\n\n private _LoadSearchParameters = async (): Promise<void> => {\n for (const [key, val] of Object.entries(await this._GetSearchParams()) as any) {\n const { id, url, code, base, type, expression, component, target } = val;\n\n for (let i=0; i < base.length; i++) {\n const resourceName = base[i];\n\n if (!this.#definitions?.searchParametersByResourceType[resourceName]) {\n this.#definitions!.searchParametersByResourceType[resourceName] = {\n resourceName,\n params: [ ]\n }\n }\n\n const SP_ID = id;\n const SP_NAME = code; // code is the true SP name (but in the spec, name is usually the same as code)\n const SP_TYPE = type;\n const SP_URL = url;\n const SP_TARGET = target;\n let SP_EXPRESSION: string = expression;\n let expressions: any[] = [];\n let original_expressions: any[] = [];\n if (SP_EXPRESSION) {\n const retVal = this.ProcessExpressions(resourceName, SP_EXPRESSION);\n expressions = retVal.expressions;\n original_expressions = retVal.original_expressions;\n }\n\n const record: ISearchParamRecord = {\n SP_ID,\n SP_NAME,\n SP_TYPE,\n SP_URL,\n SP_TARGET,\n expressions,\n original_expressions,\n SP_DEFINITION: await this._GetSearchParam(SP_URL)\n };\n\n for (let i=0; i < record.expressions.length; i++) {\n //console.log(record.expressions[i]);\n const rf = await this._GetResourceField(resourceName, record.expressions[i].path);\n if (rf) {\n expressions[i].RES_FIELD = rf;\n }\n }\n\n if (component) {\n record.component = [ ...component ];\n for (const c of record.component) {\n //c.SP_RAW_PATHS = (c.expression.split('|') as any[]).map(rp => rp.trim());\n //c.SP_PATHS = (c.SP_RAW_PATHS as any[]).map(rawPath => this.ResolveFhirChoiceType(rawPath));\n const retVal = this.ProcessExpressions('', (c as any).expression);\n c.expressions = retVal.expressions;\n c.original_expressions = retVal.original_expressions;\n const def = await this._GetSearchParam(c.definition);\n if (def && def.type) {\n (c as any).type = def.type\n }\n }\n }\n\n this.#definitions!.searchParametersByResourceType[resourceName].params.push(record);\n }\n }\n }\n\n GetSearchParamFromResourceTypeUrl = async (resourceType: string, url: string): Promise<ISearchParamRecord | undefined> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n const filterByNameAndUrl = rt!.params.filter(rt => rt.SP_URL.localeCompare(url) === 0);\n //const filterByNameAndUrl = this.#definitions!.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_URL.localeCompare(url) === 0);\n if (filterByNameAndUrl.length > 0) {\n return filterByNameAndUrl[0];\n }\n }\n\n GetSearchParamFromResourceType = async (resourceType: string, name: string): Promise<ISearchParamRecord | undefined> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n const filterByName = rt!.params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);\n //const filterByName = this.#definitions!.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);\n if (filterByName.length > 0) {\n return filterByName[0];\n }\n }\n\n GetSearchParamsFromResourceType = async (resourceType: string): Promise<ISearchParamRecord[]> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n return rt!.params;\n //return this.#definitions!.searchParametersByResourceType[resourceType].params;\n }\n}","import { randomUUID } from 'node:crypto';\nimport jmespath from 'jmespath';\nimport { defaultLogger } from '@nsshunt/stsutils';\n\nimport { ISearchParamRecord, ISearchParamExpressionRecord, IBaseIndexRecordEx } from '../fhir-utils/commonTypes.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\nimport { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\n\nexport abstract class DBSearchIndexBase {\n\n #ops: Record<string, (a: any, b: any) => boolean> = {\n \"==\": (a, b) => a == b,\n \"===\": (a, b) => a === b,\n \"!=\": (a, b) => a != b,\n \"!==\": (a, b) => a !== b,\n \">\": (a, b) => a > b,\n \">=\": (a, b) => a >= b,\n \"<\": (a, b) => a < b,\n \"<=\": (a, b) => a <= b\n }; \n\n FHIR_ROOT = 'http://stsfhir.io/r5';\n\n IsUndefined = (val: any): boolean => {\n if (val === undefined || val === null) {\n return true;\n } else {\n if (Array.isArray(val)) {\n return val.length === 0;\n } else {\n return false;\n }\n }\n }\n\n IsDefined = (val: any): boolean => {\n if (val !== undefined && val !== null) {\n if (Array.isArray(val)) {\n return val.length > 0;\n } else {\n return true;\n }\n } else {\n return false;\n }\n }\n\n GetNewBaseIndexRecord = (tir: IBaseIndexRecordEx): IBaseIndexRecordEx => {\n const copy: IBaseIndexRecordEx = {\n ...tir\n }\n copy.PID = randomUUID();\n return copy;\n }\n\n #GetValueFromResourceAtPath = (resource: Resource, path: string): any => {\n let retVal = jmespath.search(resource, path); \n if (retVal === null) {\n // Now try an array search\n if (path.split('.').length > 0) {\n const parts = path.split('.');\n const test = parts.map(p => `${p}[]`).join('.');\n retVal = jmespath.search(resource, test); \n }\n }\n if (retVal === null) {\n retVal = undefined;\n }\n return retVal;\n }\n\n ComputeCompositeHash = (path: string, index: number, tir: IBaseIndexRecordEx) => {\n const parts = path.split('.');\n let parent = '';\n if (parts.length > 1) {\n parent = parts[parts.length-2];\n }\n const pt = `${tir.RES_ID}|${tir.RES_TYPE}|${parent}_${index}`;\n tir.PATH_FOR_COMP = path;\n tir.COMPOSITE = pt;\n tir.COMPOSITE_HASH_EXACT = hashStringParam(`${pt}`, false);\n }\n\n //@@ This method requires re-word to correctly handle the FhirPath grammar. At the momenet, most cases are \n // looking for specific formats (like for example exists()).\n GetValueFromPath = (resource: Resource, path: string, searchParamRecord: ISearchParamRecord, searchParamExpressionRecord: ISearchParamExpressionRecord): any => {\n let retVal: any = undefined;\n try {\n // Check if the path is the root level of the resource\n if (resource && resource.resourceType && resource.resourceType === path) {\n return resource;\n }\n\n // Strip the resource type from the path\n if (path && path.split('.')[0].localeCompare(resource.resourceType) === 0) {\n path = path.split('.').slice(1).join('.');\n }\n\n if (!path) {\n return retVal;\n }\n\n if (searchParamExpressionRecord.exists) {\n const { fieldExists, op, fieldTest, comparator, value } = searchParamExpressionRecord.exists;\n for (let i=0; i < fieldExists.length; i++) {\n retVal = jmespath.search(resource, fieldExists[i]); \n // assume op is always and\n if (retVal) {\n if (value[i]) {\n retVal = jmespath.search(resource, fieldTest[i]); \n if (retVal) {\n retVal = this.#ops[comparator](retVal, value[i]);\n break;\n }\n } else {\n retVal = true; // If no value specified, we only need the exists rule to be true\n break;\n }\n }\n }\n } else if (searchParamExpressionRecord.typeOf) {\n //@@ The check should validate that only 1 value in the valueOf group for this attribute is used\n retVal = this.#GetValueFromResourceAtPath(resource, path);\n } else if (searchParamExpressionRecord.reference) {\n // Try the path \"as-is\"\n let searchField = this.#GetValueFromResourceAtPath(resource, path);\n if (searchField && Array.isArray(searchField)) {\n //console.log(searchField);\n const list = searchField.filter(sf => {\n if (sf.reference) {\n return (sf.reference as string).startsWith(`${searchParamExpressionRecord.reference}/`);\n } else if (sf.identifier) {\n //@@ could look this up ...\n return false;\n } else {\n return false;\n }\n });\n if (list.length > 0) {\n // Only get the first entry\n retVal = list[0];\n }\n } else {\n retVal = searchField;\n }\n } else if (searchParamExpressionRecord.where) {\n const { field, subfield, value } = searchParamExpressionRecord.where;\n\n const searchField = jmespath.search(resource, field); \n if (searchField && Array.isArray(searchField)) {\n const foundFields = searchField.filter(sf => sf[subfield] && sf[subfield].localeCompare(value) === 0);\n if (foundFields.length > 0) {\n // Only get the first entry\n retVal = foundFields[0];\n }\n }\n } else {\n retVal = this.#GetValueFromResourceAtPath(resource, path);\n }\n\n if (retVal === null) {\n retVal = undefined;\n }\n } catch (error) {\n defaultLogger.error(`\nDBSearchIndexBase:GetValueFromPath(): Error: [${error}]\n${JSON.stringify(searchParamRecord, null, 2)}\n${JSON.stringify(searchParamExpressionRecord, null, 2)}\n${JSON.stringify(resource, null, 2)}`);\n retVal = undefined;\n }\n return retVal;\n }\n\n abstract OutputIndexRecordFromFhirElement(path: string, inputNumberVal: any, tir: IBaseIndexRecordEx, \n searchParamExpressionRecord?: ISearchParamExpressionRecord, resource?: Resource): Promise<IBaseIndexRecordEx[]>;\n\n abstract OutputIndexRecord(resource: Resource, tir: IBaseIndexRecordEx, \n searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[]>;\n\n abstract OutputIndexRecordToConsole(tir: IBaseIndexRecordEx[]): string;\n}\n","import { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport validUrl from 'valid-url';\n\nimport { ISearchParamRecord, IBaseIndexRecordEx, ITokenIndexRecord } from './../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\n/*\nimport { Identifier } from '../fhir-ts';\nimport { Coding } from '../fhir-ts';\nimport { CodeableConcept } from '../fhir-ts';\nimport { ContactPoint } from '../fhir-ts';\n\n\nexport function isIdentifier(obj: any): obj is Identifier {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"value\" in obj;\n}\n\nexport function isCoding(obj: any): obj is Coding {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"code\" in obj;\n}\n\nexport function isCodeableConcept(obj: any): obj is CodeableConcept {\n return obj && typeof obj === \"object\" && Array.isArray(obj.coding);\n}\n\nexport function isContactPoint(obj: any): obj is ContactPoint {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"value\" in obj && !(\"code\" in obj);\n}\n\nexport function isPrimitiveToken(obj: any): obj is string | boolean {\n return typeof obj === \"string\" || typeof obj === \"boolean\";\n}\n\nexport type FhirToken =\n | Identifier\n | Coding\n | CodeableConcept\n | ContactPoint\n | string // primitive code/uri/canonical\n | boolean; // primitive boolean\n\nexport interface SearchParamMeta {\n name: string;\n type: string; // \"token\"\n expression?: string; // FHIRPath (e.g., \"Observation.status\")\n base?: string[]; // resource types\n}\n\nfunction inferPrimitiveTokenTypeFromExpression(expression?: string): string {\n if (!expression) return \"string\";\n\n if (expression.endsWith(\".status\")) return \"code\";\n if (expression.endsWith(\".url\")) return \"uri\";\n if (expression.endsWith(\".canonical\")) return \"canonical\";\n if (expression.endsWith(\".uuid\")) return \"uuid\";\n if (expression.endsWith(\".oid\")) return \"oid\";\n\n // Default\n return \"code\";\n}\n\n*/\n\n\n\n\n\n\nexport class DBSearchIndexToken extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n /*\n ExtractTokensWithMeta = (token: FhirToken, meta: SearchParamMeta, tir: IBaseIndexRecord): ITokenIndexRecord[] => {\n const results: ITokenIndexRecord[] = [];\n\n if (!token) return results;\n\n if (isIdentifier(token)) {\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = token.system || null,\n tokenIndexRecord.SP_VALUE = token.value || null,\n tokenIndexRecord.type = \"Identifier\"\n results.push(this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord);\n } \n else if (isContactPoint(token)) {\n results.push({\n system: token.system || null,\n code: token.value || null,\n type: \"ContactPoint\",\n ...base\n });\n }\n else if (isCoding(token)) {\n results.push({\n system: token.system || null,\n code: token.code || null,\n type: \"Coding\",\n ...base\n });\n } \n else if (isCodeableConcept(token)) {\n token.coding?.forEach(coding => {\n results.push({\n system: coding.system || null,\n code: coding.code || null,\n type: \"CodeableConcept\",\n ...base\n });\n });\n } \n else if (isPrimitiveToken(token)) {\n results.push({\n system: null,\n code: String(token),\n type: inferPrimitiveTokenTypeFromExpression(meta.expression),\n ...base\n });\n }\n\n return results;\n }\n */\n\n #GenerateHashValues = (tokenIndexRecord: Partial<ITokenIndexRecord>): Partial<ITokenIndexRecord> => {\n if (this.IsDefined(tokenIndexRecord.SP_SYSTEM)) {\n tokenIndexRecord.HASH_SYS = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_SYSTEM}`, true);\n } else {\n tokenIndexRecord.HASH_SYS = null;\n }\n if (this.IsDefined(tokenIndexRecord.SP_VALUE)) {\n tokenIndexRecord.HASH_VALUE = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_VALUE}`, true);\n } else {\n tokenIndexRecord.HASH_VALUE = null;\n }\n if (this.IsDefined(tokenIndexRecord.SP_SYSTEM) && this.IsDefined(tokenIndexRecord.SP_VALUE)) {\n tokenIndexRecord.HASH_SYS_AND_VALUE = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`, true);\n } else {\n tokenIndexRecord.HASH_SYS_AND_VALUE = null;\n }\n return tokenIndexRecord;\n }\n\n\n\n /* https://www.hl7.org/fhir/search.html#token\n\n| Datatype | URI | Code | Comments |\n|----------------|-----------------------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Coding | `Coding.system` | `Coding.code` | |\n| CodeableConcept| `CodeableConcept.coding.system` | `CodeableConcept.coding.code` | Matches against any coding in the CodeableConcept |\n| Identifier | `Identifier.system` | `Identifier.value` | Clients can search by type not system using the `:of-type` modifier. To search on a CDA II.root (which may appear in either `Identifier.system` or `Identifier.value`), use `identifier=|[root],[root]` |\n| ContactPoint | | `ContactPoint.value` | At the discretion of the server, token searches on ContactPoint may use special handling, such as ignoring punctuation or performing partial searches |\n| code | (implicit) | `code` | The system is defined in the value set (though it's not usually needed) |\n| boolean | | `boolean` | The implicit system for boolean values is `http://terminology.hl7.org/CodeSystem/special-values`, but this is never actually used |\n| id | | `id` | |\n| uri | | `uri` | |\n| string | n/a | `string` | Token is sometimes used for string to indicate that case-insensitive full-string matching is the correct default search strategy |\n*/\n \n #OutputToken = (tokens: any, tir: IBaseIndexRecordEx): ITokenIndexRecord[] => {\n if (this.IsDefined(tokens.system) && this.IsDefined(tokens.value)) {\n // Identifier\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.system;\n tokenIndexRecord.SP_VALUE= tokens.value;\n tokenIndexRecord.SP_TOKEN_TYPE = 'Identifier';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.system) && this.IsDefined(tokens.code)) {\n // Coding\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.system;\n tokenIndexRecord.SP_VALUE= tokens.code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'Coding';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.coding) && this.IsDefined(tokens.coding.system) && this.IsDefined(tokens.coding.code)) {\n // CodeableConcept (single)\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.coding.system;\n tokenIndexRecord.SP_VALUE= tokens.coding.code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'CodeableConcept';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.coding) && Array.isArray(tokens.coding)) {\n // CodeableConcept (array)\n const retVal: ITokenIndexRecord[] = [ ];\n for (let i=0 ; i < tokens.coding.length; i++) {\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.coding[i].system;\n tokenIndexRecord.SP_VALUE= tokens.coding[i].code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'CodeableConcept';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n retVal.push(this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord)\n }\n return retVal;\n } else if (this.IsDefined(tokens.value)) {\n // ContactPoint\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens.value;\n tokenIndexRecord.SP_TOKEN_TYPE = 'contactPoint';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else {\n if (typeof tokens === 'boolean') {\n // boolean\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens ? 'true' : 'false';\n tokenIndexRecord.SP_TOKEN_TYPE = 'boolean';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (validUrl.isUri(tokens)) {\n // uri\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens;\n tokenIndexRecord.SP_TOKEN_TYPE = 'uri';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else { //@@ how detect id over a string ?\n // id or string\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens;\n tokenIndexRecord.SP_TOKEN_TYPE = 'string';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n }\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputTokens: any, tir: IBaseIndexRecordEx): Promise<ITokenIndexRecord[]> => {\n const _OutputMissingParamater = () => {\n const tirc: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n //const tirc: ITokenIndexRecord = { ...tir } as ITokenIndexRecord;\n tirc.SP_MISSING = true;\n tirc.SP_SYSTEM = null;\n tirc.SP_VALUE = null;\n tirc.SP_TOKEN_TYPE = null;\n tirc.SP_STR = null;\n tirc.HASH_VALUE = null;\n tirc.HASH_SYS = null;\n tirc.HASH_SYS_AND_VALUE = null;\n this.ComputeCompositeHash(path, 0, tirc as ITokenIndexRecord);\n retVal.push(tirc as ITokenIndexRecord);\n }\n\n let retVal: ITokenIndexRecord[] = [ ];\n if (this.IsDefined(inputTokens)) {\n const _PushTokens = (tokens: any, index: number) => {\n if (Array.isArray(tokens) === true) {\n for (let i=0; i < tokens.length; i++) {\n _PushTokens(tokens[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(...this.#OutputToken(tokens, tir));\n }\n }\n _PushTokens(inputTokens, 0);\n } else {\n _OutputMissingParamater();\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<ITokenIndexRecord[]> => {\n let retVal: ITokenIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let tokens = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, tokens, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: ITokenIndexRecord[]): string => {\n return '';\n /*\n const tokenPromptColour = chalk.rgb(200,255,255);\n const tokenColour = chalk.rgb(200,200,10);\n\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = tokenPromptColour(`TOKEN INDEX: \\\n SP_ID: ${tokenColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${tokenColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${tokenColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${tokenColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_SYSTEM: ${tokenColour(tir[i].SP_SYSTEM ? tir[i].SP_SYSTEM.padEnd(45) : ''.padEnd(45))}\\\n SP_VALUE: ${tokenColour(tir[i].SP_VALUE!.padEnd(30))}\\\n UPDATED: ${tokenColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${tokenColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${tokenColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_SYS: ${tokenColour(tir[i].HASH_SYS ? tir[i].HASH_SYS.toString().padEnd(22): ''.padEnd(22))}\\\n HASH_SYS_AND_VALUE: ${tokenColour(tir[i].HASH_SYS_AND_VALUE ? tir[i].HASH_SYS_AND_VALUE.toString().padEnd(22) : ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** TOKEN: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import { Resource } from '@nsshunt/stsfhirclient';\nimport { randomUUID } from 'node:crypto';\nimport { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport { ISearchParamComponentRecord, ISearchParamRecord, IBaseIndexRecordEx, \n IComboNonUniqueRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { SearchRegistry } from './dbsearchregistry.js'\n\nimport { DBSearchIndex } from './dbsearchindex.js'\n\nexport class DBSearchIndexComposite extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #warn = (message: any) => {\n //defaultLogger.warn(message);\n }\n\n // This method is empty becuase the composite processor will not call itself recursively\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx): Promise<IBaseIndexRecordEx[]> => {\n this.#warn(`DBSearchIndexComposite:__OutputIndexRecordFromFhirElement(): composite (recursive) not supported within a composite expression. inputReferenceVal: [${inputReferenceVal}], tir: [${tir}]`);\n return [ ];\n }\n\n // Observation?code-value-quantity=code1234$le100,code5678$ge35 code: code value-quantity: value.ofType(Quantity)\n // Observation?combo-code-value-quantity=code1234$le100,code5678$ge35 combo-code: code combo-value-quantity: value.ofType(Quantity)\n\n // We need to ensure that each touple belongs to the same logical component, i.e.\n // when using combo-code-value-quantity, combo-code = Observation.code | Observation.component.code and Observation.component is an array\n // so there could be multiple index records create for code\n // we need to ensure the touple of code and quantity always belong to the same 'composite' touple pair so we need to use a\n // component_id concept to ensure they remain linked for composite searches.\n // One way to do this is the use the parent path as the composite_id, i.e.\n // / root level code and quantity, i.e. Observation.code + Observation.value[x]Quantity\n // /component_0 component level at index 0 Observation.component[0].code + Observation.component[0].value[x]Quantity\n // /component_1 component level at index 1 Observation.component[1].code + Observation.component[1].value[x]Quantity\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[]> => {\n let comboNonUniqueRecords: IComboNonUniqueRecord[] = [ ];\n //let extraIndexRecords: IBaseIndexRecord[] = [ ];\n\n //const resourceHelper: ResourceHelper = ResourceHelper.getInstance();\n const searchIndex: DBSearchIndex = DBSearchIndex.getInstance();\n\n let index = 0;\n let components: any[] = [ ];\n for (const searchParamComponentRecord of searchFieldRecord.component!) {\n components.push([ ]);\n const url = searchParamComponentRecord.definition;\n const sp = await searchIndex.resourceHelper.GetSearchParamFromResourceTypeUrl(resource.resourceType, url);\n if (this.IsDefined(sp)) {\n const tir = {\n PID: randomUUID(),\n RES_ID: resource.id!,\n SP_NAME: sp!.SP_NAME,\n RES_TYPE: resource.resourceType,\n UPDATED: BigInt(new Date().getTime()),\n SP_MISSING: false,\n HASH_IDENTITY: hashStringParam(`${sp!.SP_NAME}|${resource.resourceType}`, true),\n SP_PARAM_TYPE: sp!.SP_TYPE,\n SP_STR: null,\n PATH_FOR_COMP: null,\n COMPOSITE: null,\n COMPOSITE_HASH_EXACT: null\n };\n const retVal = await SearchRegistry.getInstance().searchIndexBaseRegistry[sp!.SP_TYPE].OutputIndexRecord(resource, tir, sp!);\n retVal.forEach(rv => {\n if (!((rv as any).SP_MISSING && (rv as any).SP_MISSING === true)) {\n if (rv.SP_STR && rv.SP_STR !== undefined) {\n components[index].push(rv);\n }\n }\n });\n index++;\n }\n\n };\n for (let i=0; i < components[0].length; i++) {\n for (let j=0; j < components[1].length; j++) {\n const idxString = `${components[0][i].SP_STR}|${components[1][j].SP_STR}`;\n const comboIndexRecord: Partial<IComboNonUniqueRecord> = this.GetNewBaseIndexRecord(tir);\n comboIndexRecord.IDX_STRING = idxString;\n comboIndexRecord.HASH_COMPLETE = hashStringParam(idxString, true);\n comboNonUniqueRecords.push(comboIndexRecord as IComboNonUniqueRecord);\n\n //@@ currently broken here as the quantity SP_STR field only has the value and ignores SP_SYSTEM and SP_UNITS\n if (comboIndexRecord.SP_NAME === 'combo-code-value-quantity') {\n //console.log(comboNonUniqueRecords);\n }\n }\n }\n\n return comboNonUniqueRecords;\n }\n \n OutputIndexRecordToConsole = (tir: IComboNonUniqueRecord[]): string => {\n let retVal = '';\n /*\n const compositePromptColour = chalk.rgb(100,200,255);\n const compositeColour = chalk.rgb(100,150,10);\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = compositePromptColour(`COMBO INDEX: \\\n SP_ID: ${compositeColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${compositeColour(tir[i].RES_ID.toString().padEnd(10))}\\\n IDX_STRING: ${compositeColour(tir[i].IDX_STRING.padEnd(15))}\\\n SP_VALUE_HIGH: ${compositeColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_HIGH_DATE_ORDINAL: ${compositeColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n SP_VALUE_LOW: ${compositeColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_LOW_DATE_ORDINAL: ${compositeColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n HASH_IDENTITY: ${compositeColour(tir[i].HASH_COMPLETE.toString().padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** COMPOSITE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n */\n \n return retVal;\n }\n\n}\n","import chalk from 'chalk';\nimport { DateTime } from 'luxon';\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nimport { FHIRDateUtils } from './../fhir-utils/fhirDateUtils.js'\nimport { ISearchParamRecord, IBaseIndexRecordEx, IDateIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexDates extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n // date search paramater type works with the following data types;\n /*\n| Type | Description |\n|-----------|-------------|\n| `date` | The range of the value is the day, month, or year as specified. |\n| `dateTime`| The range of the value as defined above; e.g., the date `2013-01-10` specifies all the time from 00:00 on 10-Jan-2013 to immediately before 00:00 on 11-Jan-2013. |\n| `instant` | An instant is considered a fixed point in time with an interval smaller than the precision of the system, i.e., an interval with an effective width of 0. |\n| `Period` | Explicit, though the upper or lower bound might not actually be specified in resources. |\n| `Timing` | The specified scheduling details are ignored and only the outer limits matter. For instance, a schedule that specifies every second day between 31-Jan-2013 and 24-Mar-2013 includes 1-Feb-2013, even though that is on an odd day that is not specified by the period. This is to keep the server load processing queries reasonable. |\n*/\n\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx): Promise<IDateIndexRecord[]> => {\n let retVal: IDateIndexRecord[] = [ ];\n\n const _OutputDate = (referenceVal: any, tir: IBaseIndexRecordEx, index: number): IDateIndexRecord => {\n let parsedDate: any;\n let parsedDatePeriodLow: any;\n let parsedDatePeriodHigh: any;\n\n if (this.IsDefined(referenceVal.start) || this.IsDefined(referenceVal.end)) {\n if (this.IsDefined(referenceVal.start)) {\n parsedDatePeriodLow = FHIRDateUtils.parseDateTime(referenceVal.start); \n }\n if (this.IsDefined(referenceVal.end)) {\n parsedDatePeriodHigh = FHIRDateUtils.parseDateTime(referenceVal.end); \n }\n } else {\n parsedDate = FHIRDateUtils.parseDateTime(referenceVal);\n }\n\n if (this.IsDefined(parsedDate)) {\n const dateIndexRecord: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n if (parsedDate.hour > 0 || parsedDate.minute > 0 || parsedDate.second > 0 || parsedDate.millisecond > 0) {\n dateIndexRecord.SP_VALUE_LOW = parsedDate;\n dateIndexRecord.SP_VALUE_HIGH = parsedDate;\n } else {\n dateIndexRecord.SP_VALUE_LOW = DateTime.local(parsedDate.year, parsedDate.month, parsedDate.day, 0, 0, 0, 0);\n dateIndexRecord.SP_VALUE_HIGH = DateTime.local(parsedDate.year, parsedDate.month, parsedDate.day, 23, 59, 59, 999);\n }\n dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_LOW!.toFormat('yyyyLLdd'), 10);\n dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_HIGH!.toFormat('yyyyLLdd'), 10);\n\n dateIndexRecord.SP_STR = `${dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL}|${dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL}`;\n \n this.ComputeCompositeHash(path, index, tir);\n\n return dateIndexRecord as IDateIndexRecord;\n } else if (this.IsDefined(parsedDatePeriodLow) || this.IsDefined(parsedDatePeriodHigh)) {\n const dateIndexRecord: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n if (this.IsDefined(parsedDatePeriodLow)) {\n dateIndexRecord.SP_VALUE_LOW = parsedDatePeriodLow;\n }\n if (this.IsDefined(parsedDatePeriodHigh)) {\n dateIndexRecord.SP_VALUE_HIGH = parsedDatePeriodHigh;\n }\n dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_LOW!.toFormat('yyyyLLdd'), 10);\n dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_HIGH!.toFormat('yyyyLLdd'), 10);\n\n dateIndexRecord.SP_STR = `${dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL}|${dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL}`;\n \n this.ComputeCompositeHash(path, index, tir);\n\n return dateIndexRecord as IDateIndexRecord;\n } else {\n const tirc: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_LOW = null;\n tirc.SP_VALUE_HIGH = null;\n tirc.SP_VALUE_LOW_DATE_ORDINAL = null;\n tirc.SP_VALUE_HIGH_DATE_ORDINAL = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IDateIndexRecord);\n return tirc as IDateIndexRecord;\n }\n }\n\n if (this.IsDefined(inputReferenceVal)) {\n const _PushDates = (dates: any, index: number) => {\n if (Array.isArray(dates) === true) {\n for (let i=0; i < dates.length; i++) {\n _PushDates(dates[i], i);\n }\n } else {\n retVal.push(_OutputDate(dates, tir, index));\n }\n }\n _PushDates(inputReferenceVal, 0);\n } else {\n const tirc: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n //const tirc: IDateIndexRecord = { ...tir } as IDateIndexRecord;\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_LOW = null;\n tirc.SP_VALUE_HIGH = null;\n tirc.SP_VALUE_LOW_DATE_ORDINAL = null;\n tirc.SP_VALUE_HIGH_DATE_ORDINAL = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IDateIndexRecord);\n retVal.push(tirc as IDateIndexRecord); \n }\n\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IDateIndexRecord[]> => {\n let retVal: IDateIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let referenceVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, referenceVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IDateIndexRecord[]): string => {\n const datesPromptColour = chalk.rgb(200,200,255);\n const datesColour = chalk.rgb(200,150,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = datesPromptColour(`DATE INDEX: \\\n SP_ID: ${datesColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${datesColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${datesColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${datesColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_VALUE_HIGH: ${datesColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_HIGH_DATE_ORDINAL: ${datesColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n SP_VALUE_LOW: ${datesColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_LOW_DATE_ORDINAL: ${datesColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n UPDATED: ${datesColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${datesColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${datesColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** DATE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n }\n\n}\n","import { hashStringParam } from '../fhir-utils/fhirHashUtils.js'\n\nimport { ISearchParamRecord, IBaseIndexRecordEx, IQuantityIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nexport class DBSearchIndexQuantity extends DBSearchIndexBase {\n constructor() {\n super();\n }\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputQuantity = (quantityInputVal: any, tir: IBaseIndexRecordEx): IQuantityIndexRecord => {\n const quantityIndexRecords: Partial<IQuantityIndexRecord> = this.GetNewBaseIndexRecord(tir);\n\n if (this.IsDefined(quantityInputVal.unit)) {\n quantityIndexRecords.SP_UNITS = quantityInputVal.unit;\n quantityIndexRecords.HASH_IDENTITY_AND_UNITS = hashStringParam(`${quantityIndexRecords.SP_NAME}|${quantityIndexRecords.RES_TYPE}|${quantityIndexRecords.SP_UNITS}`, true);\n } \n if (this.IsDefined(quantityInputVal.system)) {\n quantityIndexRecords.SP_SYSTEM = quantityInputVal.system;\n if (this.IsDefined(quantityInputVal.unit)) {\n quantityIndexRecords.HASH_IDENTITY_SYS_UNITS = hashStringParam(`${quantityIndexRecords.SP_NAME}|${quantityIndexRecords.RES_TYPE}|${quantityIndexRecords.SP_SYSTEM}|${quantityIndexRecords.SP_UNITS}`, true);\n }\n }\n if (this.IsDefined(quantityInputVal.value)) {\n quantityIndexRecords.SP_VALUE = Number.parseFloat(quantityInputVal.value);\n }\n\n if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_SYSTEM) && this.IsDefined(quantityIndexRecords.SP_UNITS)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_SYSTEM}|${quantityIndexRecords.SP_UNITS}`;\n } else if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_SYSTEM)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_SYSTEM}`;\n } else if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_UNITS)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_UNITS}`;\n } else {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}`;\n }\n return quantityIndexRecords as IQuantityIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputQuantityVal: any, tir: IBaseIndexRecordEx): Promise<IQuantityIndexRecord[]> => {\n const retVal: IQuantityIndexRecord[] = [ ];\n if (this.IsDefined(inputQuantityVal)) {\n const _PushQty = (qVal: any, index: number) => {\n if (Array.isArray(qVal)) {\n for (let i=0; i < qVal.length; i++) {\n _PushQty(qVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputQuantity(qVal, tir));\n }\n }\n _PushQty(inputQuantityVal, 0);\n } else {\n //const tirc: IQuantityIndexRecord = { ...tir } as IQuantityIndexRecord;\n const tirc: Partial<IQuantityIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_UNITS = null;\n tirc.SP_SYSTEM = null;\n tirc.SP_VALUE = null;\n tirc.SP_STR = null;\n tirc.HASH_IDENTITY_AND_UNITS = null;\n tirc.HASH_IDENTITY_SYS_UNITS = null;\n this.ComputeCompositeHash(path, 0, tirc as IQuantityIndexRecord);\n retVal.push(tirc as IQuantityIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IQuantityIndexRecord[]> => {\n const retVal: IQuantityIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let quantityVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, quantityVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IQuantityIndexRecord[]): string => {\n return '';\n /*\n const quantityPromptColour = chalk.rgb(0,100,255);\n const quantityColour = chalk.rgb(0,50,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = quantityPromptColour(`QUANTITY INDEX: \\\n SP_ID: ${quantityColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${quantityColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${quantityColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${quantityColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_UNITS: ${quantityColour(tir[i].SP_UNITS.toString().padEnd(15))}\\\n SP_SYSTEM: ${quantityColour(tir[i].SP_SYSTEM.toString().padEnd(25))}\\\n SP_VALUE: ${quantityColour(tir[i].SP_VALUE.toString().padEnd(15))}\\\n UPDATED: ${quantityColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${quantityColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${quantityColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_IDENTITY_AND_UNITS: ${quantityColour(tir[i].HASH_IDENTITY_AND_UNITS ? tir[i].HASH_IDENTITY_AND_UNITS.toString().padEnd(22): ''.padEnd(22))}\\\n HASH_IDENTITY_SYS_UNITS: ${quantityColour(tir[i].HASH_IDENTITY_SYS_UNITS ? tir[i].HASH_IDENTITY_SYS_UNITS.toString().padEnd(22): ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** QUANTITY: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n\n return retVal;\n */\n }\n\n}\n","//import { v4 as uuidv4 } from 'uuid';\nimport { randomUUID } from 'node:crypto';\nimport { ISearchParamRecord, IBaseIndexRecordEx, IResourceLinkIndexRecord, ISearchParamExpressionRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource, isAbsoluteUrl } from '@nsshunt/stsfhirclient';\n\nexport class DBSearchIndexReference extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #GetResourceID = (resourceName: string, resourceId: string): string => {\n return resourceId;\n }\n\n #OutputReference = (sourceResource: Resource, tir: IBaseIndexRecordEx, referenceVal: any, \n searchParamExpressionRecord: ISearchParamExpressionRecord): IResourceLinkIndexRecord => {\n try {\n const resourceIndexRecord: Partial<IResourceLinkIndexRecord> = { };\n resourceIndexRecord.PID = randomUUID();\n resourceIndexRecord.SP_NAME = tir.SP_NAME;\n resourceIndexRecord.SP_PARAM_TYPE = tir.SP_PARAM_TYPE;\n resourceIndexRecord.SRC_PATH = `${searchParamExpressionRecord.path}`; // `${resourceName}.${searchParamExpressionRecord.path}`;\n resourceIndexRecord.RES_ID = this.#GetResourceID(sourceResource.resourceType, sourceResource.id!); // need to lookup PK of the source resource\n resourceIndexRecord.RES_TYPE = sourceResource.resourceType;\n resourceIndexRecord.SP_MISSING = false;\n\n //@@ what about version using the | token\n if (isAbsoluteUrl(referenceVal)) {\n //@@ In future version, attempt to resolve this if the URL points back to this server.\n //@@ If so, update with the actual values from the lookup.\n resourceIndexRecord.TARGET_RESOURCE_ID = null;\n resourceIndexRecord.TARGET_RESOURCE_URL = referenceVal; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = null;\n resourceIndexRecord.SP_STR = resourceIndexRecord.TARGET_RESOURCE_URL;\n } else {\n const reference = referenceVal;\n const parts = reference.split('/');\n if (parts.length > 1) {\n const targetResType = parts[0];\n const targetResID = parts[1];\n\n resourceIndexRecord.TARGET_RESOURCE_ID = this.#GetResourceID(targetResType, targetResID); // need to lookup PK of referenced resource\n resourceIndexRecord.TARGET_RESOURCE_URL = null; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = targetResType;\n resourceIndexRecord.SP_STR = `${resourceIndexRecord.TARGET_RESOURCE_ID}|${resourceIndexRecord.TARGET_RESOURCE_TYPE}`\n } else {\n if ((referenceVal as string).substring(0, 1) === '#') {\n throw new Error(`#OutputReference(): Cannot index internal references, i.e. starts with #, referenceVal: [${referenceVal}]`);\n } else {\n resourceIndexRecord.TARGET_RESOURCE_ID = null;\n resourceIndexRecord.TARGET_RESOURCE_URL = referenceVal; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = null;\n resourceIndexRecord.SP_STR = resourceIndexRecord.TARGET_RESOURCE_URL;\n }\n }\n }\n resourceIndexRecord.UPDATED = BigInt(new Date().getTime());\n return resourceIndexRecord as IResourceLinkIndexRecord;\n } catch (error) {\n console.error(error);\n console.error(`referenceVal: [${JSON.stringify(referenceVal)}]`);\n throw error;\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx, \n searchParamExpressionRecord: ISearchParamExpressionRecord, resource: Resource, \n ): Promise<IResourceLinkIndexRecord[]> => {\n\n const _OutputReferencesFromFhirElement = (referenceVal: any, index: number) => {\n let resourceReference;\n if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.identifier) && this.IsDefined(referenceVal.identifier.value)) {\n resourceReference = referenceVal.identifier.value;\n } else if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.reference)) {\n resourceReference = referenceVal.reference;\n } else if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.type) && this.IsDefined(referenceVal.resource)) { // from a where(type=)\n resourceReference = referenceVal.resource;\n } else {\n resourceReference = referenceVal;\n }\n if (this.IsDefined(resourceReference) && resourceReference.substring(0,1) !== '#') {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputReference(resource, tir, resourceReference, searchParamExpressionRecord));\n }\n }\n\n let retVal: IResourceLinkIndexRecord[] = [ ];\n if (this.IsDefined(inputReferenceVal)) {\n const _PushReferences = (refVal: any, index: number) => {\n if (Array.isArray(refVal)) {\n for (let i=0; i < refVal.length; i++) {\n _PushReferences(refVal[i], i);\n }\n } else {\n _OutputReferencesFromFhirElement(refVal, index);\n }\n }\n _PushReferences(inputReferenceVal, 0);\n } else {\n const tirc: Partial<IResourceLinkIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SRC_PATH = `${searchParamExpressionRecord.path}`; // `${resourceName}.${searchParamExpressionRecord.path}`;\n tirc.SP_MISSING = true;\n tirc.TARGET_RESOURCE_ID = null;\n tirc.TARGET_RESOURCE_URL = null;\n tirc.TARGET_RESOURCE_TYPE = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IResourceLinkIndexRecord);\n retVal.push(tirc as IResourceLinkIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IResourceLinkIndexRecord[]> => {\n let retVal: IResourceLinkIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n const referenceVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, referenceVal, tir, expression, resource));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IResourceLinkIndexRecord[]): string => {\n return '';\n /*\n const resourceLinkedPromptColour = chalk.rgb(0,100,200);\n const resourceLinkedColour = chalk.rgb(0,100,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = resourceLinkedPromptColour(`RESOURCE LINKED INDEX: \\\n SP_ID: ${resourceLinkedColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${resourceLinkedColour(tir[i].RES_ID.toString().padEnd(10))}\\\n RES_TYPE: ${resourceLinkedColour(tir[i].RES_TYPE.padEnd(10))}\\\n SRC_PATH: ${resourceLinkedColour(tir[i].SRC_PATH.padEnd(30))}\\\n SP_MISSING: ${resourceLinkedColour(tir[i].SP_MISSING)}\\\n TARGET_RESOURCE_ID: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_ID?.toString().padEnd(30))}\\\n TARGET_RESOURCE_TYPE: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_TYPE.padEnd(30))}\\\n TARGET_RESOURCE_URL: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_URL ? tir[i].TARGET_RESOURCE_URL!.padEnd(40) : ''.padEnd(40))}\\\n UPDATED: ${resourceLinkedColour(tir[i].UPDATED!.toString().padEnd(15))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** REFERENCE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import chalk from 'chalk';\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nimport { hashStringParam, normalizeStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport { ResourceHelper } from './../fhir-utils/resourceHelper.js'\nimport { ISearchParamExpressionRecord, ISearchParamRecord, IBaseIndexRecordEx, IStringIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexString extends DBSearchIndexBase {\n #resourceHelper: ResourceHelper;\n\n constructor() {\n super();\n this.#resourceHelper = ResourceHelper.getInstance();\n }\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputString = async (stringInputVal: any, tir: IBaseIndexRecordEx, expression?: ISearchParamExpressionRecord): Promise<IStringIndexRecord[]> => {\n const stringIndexRecords: IStringIndexRecord[] = [ ];\n\n if (this.IsDefined(expression) && typeof stringInputVal === 'object') {\n let fields: string[] = [ ];\n // We have an object as the value, so we need to look up this Fhir type\n //console.log(stringInputVal);\n //console.log(expression);\n\n if (this.IsDefined(expression) && this.IsDefined(expression!.RES_FIELD) && this.IsDefined(expression!.RES_FIELD.type)) {\n let expressionType;\n if (Array.isArray(expression!.RES_FIELD.type)) {\n expressionType = expression!.RES_FIELD.type[0];\n } else {\n expressionType = expression!.RES_FIELD.type;\n }\n\n let res: any[];\n if (this.IsDefined(expressionType) && this.IsDefined(expressionType.code)) {\n res = await this.#resourceHelper.GetType(expressionType.code);\n } else {\n res = await this.#resourceHelper.GetType(expressionType);\n }\n \n if (this.IsDefined(res)) {\n for (let i=0; i < res.length; i++) {\n if (res[i].type && res[i].type[0].code && res[i].type[0].code === 'string') {\n //console.log(`${res[i].id} ${res[i].type[0].code}`);\n fields.push(res[i].id.split('.')[1]);\n }\n } \n }\n }\n\n // Flattern our to be indexed value\n const vals: any[] = [ ];\n const _getString = (key: string, val: any) => {\n if (Array.isArray(val)) {\n for (let i=0; i < val.length; i++) {\n _getString(key, val[i]);\n }\n }\n if (typeof val === 'string') {\n vals.push({key, val});\n }\n }\n for (const [k, v] of Object.entries(stringInputVal)) {\n _getString(k, v);\n }\n\n vals.forEach(v => {\n if (fields.includes(v.key)) {\n try {\n const stringIndexRecord: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n stringIndexRecord.SP_VALUE_EXACT = v.val;\n stringIndexRecord.SP_VALUE_NORMALIZED = normalizeStringParam(v.val);\n stringIndexRecord.HASH_EXACT = hashStringParam(`${stringIndexRecord.SP_NAME}|${stringIndexRecord.RES_TYPE}|${stringIndexRecord.SP_VALUE_EXACT}`, false);\n stringIndexRecord.SP_STR = stringIndexRecord.SP_VALUE_EXACT;\n stringIndexRecords.push(stringIndexRecord as IStringIndexRecord);\n } catch (error) {\n console.error(error);\n return stringIndexRecords;\n }\n }\n })\n return stringIndexRecords;\n } else {\n try {\n const stringIndexRecord: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n stringIndexRecord.SP_VALUE_EXACT = stringInputVal;\n stringIndexRecord.SP_VALUE_NORMALIZED = normalizeStringParam(stringInputVal);\n stringIndexRecord.HASH_EXACT = hashStringParam(`${stringIndexRecord.SP_NAME}|${stringIndexRecord.RES_TYPE}|${stringIndexRecord.SP_VALUE_EXACT}`, false);\n stringIndexRecord.SP_STR = stringIndexRecord.SP_VALUE_EXACT;\n stringIndexRecords.push(stringIndexRecord as IStringIndexRecord);\n return stringIndexRecords;\n } catch (error) {\n console.error(error);\n return stringIndexRecords;\n }\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputStringVal: any, tir: IBaseIndexRecordEx, expression?: ISearchParamExpressionRecord): Promise<IStringIndexRecord[]> => {\n const retVal: IStringIndexRecord[] = [ ];\n if (this.IsDefined(inputStringVal)) {\n const _PushStrings = async (stringVals: any, index: number) => {\n if (Array.isArray(stringVals)) {\n for (let i=0; i < stringVals.length; i++) {\n await _PushStrings(stringVals[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(...await this.#OutputString(stringVals, tir, expression));\n }\n }\n await _PushStrings(inputStringVal, 0);\n } else {\n //const tirc: IStringIndexRecord = { ...tir } as IStringIndexRecord;\n const tirc: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_EXACT = null;\n tirc.HASH_EXACT = null;\n tirc.SP_VALUE_NORMALIZED = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IStringIndexRecord);\n retVal.push(tirc as IStringIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchParamRecord: ISearchParamRecord): Promise<IStringIndexRecord[]> => {\n const retVal: IStringIndexRecord[] = [ ];\n for (const expression of searchParamRecord.expressions) {\n let stringVal = this.GetValueFromPath(resource, expression.path, searchParamRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, stringVal, tir, expression));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IStringIndexRecord[]): string => {\n return '';\n /*\n const stringPromptColour = chalk.rgb(0,255,255);\n const stringColour = chalk.rgb(0,200,10);\n \n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = stringPromptColour(`STRING INDEX: \\\n SP_ID: ${stringColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${stringColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${stringColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${stringColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_VALUE_EXACT: ${stringColour(tir[i].SP_VALUE_EXACT ? tir[i].SP_VALUE_EXACT.padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_NORMALIZED: ${stringColour(tir[i].SP_VALUE_NORMALIZED.padEnd(30))}\\\n UPDATED: ${stringColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${stringColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${stringColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_EXACT: ${stringColour(tir[i].HASH_EXACT ? tir[i].HASH_EXACT.toString().padEnd(22): ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** STRING: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import { ISearchParamRecord, IBaseIndexRecordEx, INumberIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\n// Note: The Number type in R5 has been deprecated.\nexport class DBSearchIndexNumber extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #OutputNumber = (numberInputVal: any, tir: IBaseIndexRecordEx): INumberIndexRecord => {\n const quantityIndexRecords: Partial<INumberIndexRecord> = this.GetNewBaseIndexRecord(tir);\n \n if (this.IsDefined(numberInputVal.value) && typeof numberInputVal.value === 'number' && Number.isFinite(numberInputVal.value)) {\n quantityIndexRecords.SP_VALUE = numberInputVal.value;\n } else if (this.IsDefined(numberInputVal) && typeof numberInputVal === 'number' && Number.isFinite(numberInputVal)) {\n quantityIndexRecords.SP_VALUE = numberInputVal;\n }\n if (this.IsDefined(quantityIndexRecords.SP_VALUE)) {\n quantityIndexRecords.SP_STR = quantityIndexRecords.SP_VALUE!.toString();\n } else {\n quantityIndexRecords.SP_STR = undefined;\n }\n return quantityIndexRecords as INumberIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputNumberVal: any, tir: IBaseIndexRecordEx): Promise<INumberIndexRecord[]> => {\n const retVal: INumberIndexRecord[] = [ ];\n if (this.IsDefined(inputNumberVal)) {\n const _PushNumberVal = (numberVal: any, index: number) => {\n if (Array.isArray(numberVal)) {\n for (let i=0; i < numberVal.length; i++) {\n _PushNumberVal(numberVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputNumber(numberVal, tir));\n }\n }\n _PushNumberVal(inputNumberVal, 0);\n } else {\n //const tirc: INumberIndexRecord = { ...tir } as INumberIndexRecord;\n const tirc: Partial<INumberIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE = undefined;\n tirc.SP_STR = undefined;\n this.ComputeCompositeHash(path, 0, tirc as INumberIndexRecord);\n retVal.push(tirc as INumberIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<INumberIndexRecord[]> => {\n const retVal: INumberIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let numberVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, numberVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IBaseIndexRecordEx[]): string => {\n //@@\n return '';\n }\n}\n","import { Resource } from '@nsshunt/stsfhirclient'\n\nimport { hashStringParam } from '../fhir-utils/fhirHashUtils.js'\nimport { ISearchParamRecord, IBaseIndexRecordEx, IUriIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexURI extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputURI = (uriInputVal: any, tir: IBaseIndexRecordEx): IUriIndexRecord => {\n const uriIndexRecords: Partial<IUriIndexRecord> = this.GetNewBaseIndexRecord(tir);\n\n if (this.IsDefined(uriInputVal.value)) {\n uriIndexRecords.SP_URI = uriInputVal.value;\n uriIndexRecords.HASH_URI = hashStringParam(`${uriIndexRecords.SP_NAME}|${uriIndexRecords.RES_TYPE}|${uriIndexRecords.SP_URI}`, true);\n uriIndexRecords.SP_STR = uriIndexRecords.SP_URI;\n } else if (this.IsDefined(uriInputVal)) {\n uriIndexRecords.SP_URI = uriInputVal;\n uriIndexRecords.HASH_URI = hashStringParam(`${uriIndexRecords.SP_NAME}|${uriIndexRecords.RES_TYPE}|${uriIndexRecords.SP_URI}`, true);\n uriIndexRecords.SP_STR = uriIndexRecords.SP_URI;\n } else {\n uriIndexRecords.SP_URI = null;\n uriIndexRecords.HASH_URI = null;\n uriIndexRecords.SP_STR = null;\n }\n return uriIndexRecords as IUriIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputUriVal: any, tir: IBaseIndexRecordEx): Promise<IUriIndexRecord[]> => {\n const retVal: IUriIndexRecord[] = [ ];\n const _processUriVal = (uriVal: any, index: number) => {\n if (Array.isArray(uriVal)) {\n for (let i=0; i < uriVal.length; i++) {\n _processUriVal(uriVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputURI(uriVal, tir));\n }\n }\n\n if (this.IsDefined(inputUriVal)) {\n _processUriVal(inputUriVal, 0);\n } else {\n //const tirc: IUriIndexRecord = { ...tir } as IUriIndexRecord;\n const tirc: Partial<IUriIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_URI = null;\n tirc.HASH_URI = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IUriIndexRecord);\n retVal.push(tirc as IUriIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IUriIndexRecord[]> => {\n const retVal: IUriIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let uriVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, uriVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IBaseIndexRecordEx[]): string => {\n return '';\n }\n}\n","import { DBSearchIndexToken } from './dbsearchindextoken.js'\nimport { DBSearchIndexComposite } from './dbsearchindexcomposite.js'\nimport { DBSearchIndexDates } from './dbsearchindexdates.js'\nimport { DBSearchIndexQuantity } from './dbsearchindexquantity.js'\nimport { DBSearchIndexReference } from './dbsearchindexreference.js'\nimport { DBSearchIndexString } from './dbsearchindexstring.js'\nimport { DBSearchIndexNumber } from './dbsearchindexnumber.js'\nimport { DBSearchIndexURI } from './dbsearchindexuri.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class SearchRegistry {\n private static instance: SearchRegistry;\n\n private constructor() {}\n\n static getInstance(): SearchRegistry {\n if (!SearchRegistry.instance) {\n SearchRegistry.instance = new SearchRegistry();\n }\n return SearchRegistry.instance;\n } \n\n #searchIndexBaseRegistry: Record<string, DBSearchIndexBase> = {\n ['token']: new DBSearchIndexToken(),\n ['composite']: new DBSearchIndexComposite(),\n ['date']: new DBSearchIndexDates(),\n ['quantity']: new DBSearchIndexQuantity(),\n ['reference']: new DBSearchIndexReference(),\n ['string']: new DBSearchIndexString(),\n ['number']: new DBSearchIndexNumber(),\n ['uri']: new DBSearchIndexURI()\n };\n\n get searchIndexBaseRegistry(): Record<string, DBSearchIndexBase> {\n return this.#searchIndexBaseRegistry;\n }\n}","import { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport chalk from 'chalk';\nimport { randomUUID } from 'node:crypto';\n\nimport { ISearchParamRecord, ISearchParams, ISearchFieldRecord, IBaseIndexRecordEx } from './../fhir-utils/commonTypes.js'\n\nimport { SearchRegistry } from './dbsearchregistry.js'\n\nimport { Resource } from '@nsshunt/stsfhirclient';\nimport { defaultLogger } from '@nsshunt/stsutils';\nimport { ResourceHelper } from './../fhir-utils/resourceHelper.js'\n\nexport class DBSearchIndex {\n #searchParams: ISearchParams | undefined = undefined;\n\n #OUTPUT_REPORT: boolean = false;\n\n private static instance: DBSearchIndex;\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n static getInstance(): DBSearchIndex {\n if (!DBSearchIndex.instance) {\n DBSearchIndex.instance = new DBSearchIndex();\n }\n return DBSearchIndex.instance;\n } \n\n get resourceHelper() {\n return ResourceHelper.getInstance();\n }\n\n get searchRegistry() {\n return SearchRegistry.getInstance();\n }\n\n Stop = async () => {\n await this.resourceHelper.Stop();\n }\n\n #OutputSearchDetails = (resourceName: string, resourceId: string, searchFieldRecord: ISearchFieldRecord) => {\n const hl = chalk.yellow.bold.italic;\n this.#debug('------------------')\n this.#debug(`resource: [${hl(resourceName)}] \\\n resourceId: [${hl(resourceId)}] \\\n SP_NAME: [${hl(searchFieldRecord.SP_NAME)}] \\\n SP_TYPE: [${hl(searchFieldRecord.SP_TYPE)}] \\\n SP_BASE: [${hl(searchFieldRecord.SP_BASE)}] \\\n path: [${hl(searchFieldRecord.path)}] \\\n RESOURCE_DATATYPE: [${hl(searchFieldRecord.RESOURCE_DATATYPE)}] \\\n subFieldDataType: [${hl(searchFieldRecord.subFieldDataType)}] \\\n stringIndexFields: [${hl(searchFieldRecord.stringIndexFields)}]`);\n }\n\n UpdateIndex = async (resource: Resource, searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[] | undefined> => {\n try {\n const tir: IBaseIndexRecordEx = {\n PID: randomUUID(),\n RES_ID: resource.id!,\n SP_NAME: searchFieldRecord.SP_NAME,\n RES_TYPE: resource.resourceType,\n UPDATED: BigInt(new Date().getTime()),\n SP_MISSING: false,\n HASH_IDENTITY: hashStringParam(`${searchFieldRecord.SP_NAME}|${resource.resourceType}`, true),\n SP_PARAM_TYPE: searchFieldRecord.SP_TYPE,\n SP_STR: '',\n PATH_FOR_COMP: null,\n COMPOSITE: null,\n COMPOSITE_HASH_EXACT: null\n }\n\n let saveRecord: IBaseIndexRecordEx[] | undefined;\n const searchIndexBaseProcessor = this.searchRegistry.searchIndexBaseRegistry[searchFieldRecord.SP_TYPE];\n if (searchIndexBaseProcessor) {\n saveRecord = await searchIndexBaseProcessor.OutputIndexRecord(resource, tir, searchFieldRecord);\n } else if (searchFieldRecord.SP_TYPE.localeCompare(\"special\") === 0) {\n // Don't do anything for this type\n } else {\n const message = `DBSearchIndex:UpdateIndex(): Error: Search field paramater type: [${searchFieldRecord.SP_TYPE}] unknown.`;\n defaultLogger.error(message);\n throw new Error(message);\n }\n return saveRecord;\n } catch (error) {\n console.error(error);\n return [ ];\n }\n }\n\n GetSearchIndexData = async (resource: Resource): Promise<IBaseIndexRecordEx[]> => {\n try {\n const searchParamRecords: ISearchParamRecord[] = await this.resourceHelper.GetSearchParamsFromResourceType(resource.resourceType);\n const searchIndexData: IBaseIndexRecordEx[] = [ ];\n for (let i=0; i < searchParamRecords.length; i++) {\n const searchRecord: ISearchParamRecord = searchParamRecords[i];\n try {\n const retVal = await this.UpdateIndex(resource, searchRecord);\n if (retVal && retVal.length > 0) {\n searchIndexData.push(...retVal);\n }\n } catch (error) {\n defaultLogger.error(`DBSearchIndex:GetSearchIndexData(): Error: [${error}] searchRecord: [${JSON.stringify(searchRecord)}]`)\n }\n }\n return searchIndexData;\n } catch (error) {\n defaultLogger.error(`DBSearchIndex:GetSearchIndexData(): Error: [${error}]`)\n return [ ];\n }\n }\n\n GetSearchParamFromResourceType = async (resourceType: string, name: string): Promise<ISearchParamRecord | undefined> => {\n return this.resourceHelper.GetSearchParamFromResourceType(resourceType, name);\n }\n\n GetSearchParamFromResourceTypeUrl = async (resourceType: string, url: string): Promise<ISearchParamRecord | undefined> => {\n return this.resourceHelper.GetSearchParamFromResourceTypeUrl(resourceType, url);\n }\n}\n","import { goptions } from '@nsshunt/stsconfig'\n\nimport chalk from 'chalk';\n\nimport cluster from 'cluster'\n\nimport crypto from 'crypto';\n\n//const pg = require('pg');\n//pg.types.setTypeParser(20, BigInt); // Type Id 20 = BIGINT | BIGSERIAL\n// https://stackoverflow.com/questions/39168501/pg-promise-returns-integers-as-strings\nimport { Pool, PoolConfig, PoolClient } from 'pg'\nimport { TinyEmitter } from 'tiny-emitter';\nimport { ISTSLogger } from '@nsshunt/stsutils';\n\nexport enum IDBAccessLayerEvents {\n UpdateInstruments = 'UpdateInstruments',\n}\n\nexport interface PGPoolManagerOptions {\n\tusedefaultdb: boolean\n logger: ISTSLogger\n}\n\nexport interface IPoolItem {\n pool: Pool\n connectionString: string\n safeConnectionString: string\n}\n\nexport class PGPoolManager extends TinyEmitter\n{\n #options: PGPoolManagerOptions;\n #observer: NodeJS.Timeout | null = null;\n #pools: Record<string, IPoolItem> = { };\n #keyPrefix: string = '__STS__';\n\n constructor(options: PGPoolManagerOptions) {\n super();\n this.#options = options;\n this.#CreatePools(this.#options);\n }\n\n \n #LogDebugMessage(message: any) {\n this.#options.logger.debug(message);\n }\n\n \n #LogErrorMessage(message: any) {\n this.#options.logger.error(message);\n }\n\n #CreatePools(options: PGPoolManagerOptions) {\n const { databaseUrl, connectionString, defaultDatabaseConnectionString, isProduction } = goptions;\n\n const poolConnectionString = isProduction ? databaseUrl as string : (options.usedefaultdb === true ? defaultDatabaseConnectionString : connectionString );\n\n const poolConnectionStrings = poolConnectionString.split(',');\n for (let i=0; i < poolConnectionStrings.length; i++) {\n this.#CreatePool(i, poolConnectionStrings[i]);\n }\n this.#AttachInstruments();\n }\n\n #CreatePool(poolIndex: number, poolConnectionString: string) {\n const { isProduction, poolSize } = goptions;\n\n // https://mylifedigital.co.uk/securing-node-postgres-with-ssl/\n const pool = new Pool({\n connectionString: poolConnectionString,\n ssl: isProduction,\n max: poolSize // Default is 10 - This will be the number in a pool per thread (worker)\n // Consideration needs to be given for the max number of connections at the database.\n // Max connections calculation = max pool size * max workers (threads) per instance/node * max instances in a cluster (k3s, k8s, swarm mode etc.)\n /*\n\t\t ssl: {\n\t\t\t// rejectUnauthorized: true, // Make this true for PROD\n\t\t\trejectUnauthorized: false,\n\t\t\t//ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(),\n\t\t\t//key: fs.readFileSync('/path/to/client-key/postgresql.key').toString(),\n\t\t\t//cert: fs.readFileSync('/path/to/client-certificates/postgresql.crt').toString(),\n\t\t }\n\t\t */\n } as PoolConfig);\n\n const re: RegExpExecArray | null = new RegExp('//(.*)@').exec(poolConnectionString);\n let usernamepassword = '';\n if (re) {\n usernamepassword = re[1];\n }\n const sep: string[] = usernamepassword.split(':');\n const usernamepasswordReplacement: string = usernamepassword.replace(sep[1], '*****************************');\n const safeConnectionString = poolConnectionString.replace(usernamepassword, usernamepasswordReplacement);\n\n this.#pools[this.#GetPoolKey(poolIndex)] = {\n connectionString: poolConnectionString,\n safeConnectionString,\n pool\n }\n\n if (cluster.isPrimary) {\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool with Master Thread, PID: [${process.pid}]`));\n } else {\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool with Worker Thread, PID: [${process.pid}]`));\n }\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool: Master Thread`));\n this.#LogDebugMessage(chalk.yellow(` Connection URI: [${safeConnectionString}]`));\n this.#LogDebugMessage(chalk.yellow(` Maximum Pool Size: [${poolSize}]`));\n this.#LogDebugMessage(chalk.yellow(` SSL Connection: [${isProduction}]`));\n\n // the pool will emit an error on behalf of any idle clients\n // it contains if a backend error or network partition happens\n pool.on('error', (error: Error) => {\n this.#LogDebugMessage(chalk.red(`[${safeConnectionString}]: pool error`));\n this.#LogErrorMessage(chalk.red(`Unexpected error on idle client: [${error}], connection: [${safeConnectionString}]`));\n });\n\n pool.on('connect', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool connect`));\n this.#UpdateInstruments();\n });\n\n pool.on('acquire', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool acquire`));\n this.#UpdateInstruments();\n });\n\n \n pool.on('release' as any, (error: Error) => {\n if (error) {\n this.#LogDebugMessage(chalk.red(`[${safeConnectionString}]: pool release`));\n this.#LogErrorMessage(chalk.red(`Unexpected error on client release from pool: [${error}], connection: [${safeConnectionString}]`));\n }\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool release`));\n this.#UpdateInstruments();\n });\n\n pool.on('remove', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool remove`));\n this.#UpdateInstruments();\n });\n }\n\n async EndPool(poolItem: IPoolItem) {\n this.#LogDebugMessage(chalk.cyan(`Ending database for process PID: ${process.pid}`));\n if (poolItem) {\n this.#LogDebugMessage(chalk.cyan(`ending pool with connection string: [${poolItem.safeConnectionString}]`));\n this.#LogDebugMessage(chalk.cyan(`pool details (before end), Total: [${poolItem.pool.totalCount}], Idle: [${poolItem.pool.idleCount}], Waiting: [${poolItem.pool.waitingCount}]`));\n await poolItem.pool.end();\n this.#LogDebugMessage(chalk.cyan(`pool details (after end), Total: [${poolItem.pool.totalCount}], Idle: [${poolItem.pool.idleCount}], Waiting: [${poolItem.pool.waitingCount}]`));\n this.#LogDebugMessage(chalk.green(`Database pool ended for PID: ${process.pid}`));\n poolItem.pool.removeAllListeners();\n this.#LogDebugMessage(chalk.green(`Removed all listeners: ${process.pid}`));\n } else {\n this.#LogDebugMessage(chalk.yellow(`Database pool was not defined - not ended for PID: ${process.pid}`));\n }\n }\n\n async End() {\n this.#LogDebugMessage(chalk.cyan(`Ending database for process PID: ${process.pid}`));\n for (const [, pool] of Object.entries(this.#pools)) {\n await this.EndPool(pool); //@@ should use promise.all\n }\n this.#DetachInstruments();\n }\n\n #GetPoolKey(index: number): string {\n return `${this.#keyPrefix}${index}`;\n }\n\n async connectReadWrite(): Promise<PoolClient> {\n return this.#pools[this.#GetPoolKey(0)].pool.connect()\n }\n\n async connectReadOnly(): Promise<PoolClient> {\n // Select a random pool member\n const poolIndex = crypto.randomInt(0, Object.keys(this.#pools).length);\n return this.#pools[this.#GetPoolKey(poolIndex)].pool.connect()\n }\n\n //@@ make event using TinyEmitter\n #UpdateInstruments()\n {\n const data = {\n totalCount: 0,\n idleCount: 0,\n waitingCount: 0,\n }\n for (const [, poolItem] of Object.entries(this.#pools)) {\n data.totalCount += poolItem.pool.totalCount;\n data.idleCount += poolItem.pool.idleCount;\n data.waitingCount += poolItem.pool.waitingCount;\n }\n this.emit(IDBAccessLayerEvents.UpdateInstruments, data);\n }\n\n #AttachInstruments(interval = 1000) {\n this.#observer = setInterval(() =>\n {\n this.#UpdateInstruments();\n }, interval).unref();\n }\n\n #DetachInstruments() {\n clearInterval(this.#observer as NodeJS.Timeout);\n this.#observer = null;\n }\n}\n","import { PGPoolManager } from './pgpoolmanager.js'\nimport { ISTSLogger } from '@nsshunt/stsutils';\nimport { PoolClient } from 'pg';\n\nexport interface IDBSTSFhirDBBaseOptions {\n logger: ISTSLogger\n poolManager: PGPoolManager\n}\n\nexport abstract class DBSTSFhirDBBase {\n protected _options: IDBSTSFhirDBBaseOptions;\n protected _poolManager: PGPoolManager;\n\n constructor(options: IDBSTSFhirDBBaseOptions) {\n this._options = options;\n this._poolManager = options.poolManager;\n }\n\n async withClient<T>(fname: string, fn: (client: PoolClient) => Promise<T>): Promise<T> {\n let client: PoolClient;\n\n // Connection phase\n try {\n client = await this._poolManager.connectReadWrite();\n } catch (error) {\n this._options.logger.error(`${fname}(): DB: Connection Error: [${error}]`);\n throw error;\n }\n\n // Execution phase\n try {\n return await fn(client);\n } catch (error) {\n this._options.logger.error(`${fname}(): DB: Query Error: [${error}]`);\n throw error;\n } finally {\n client.release();\n }\n }\n}","import { PoolClient } from 'pg';\nimport { IResource } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBBase, IDBSTSFhirDBBaseOptions } from './pgfhirdbbase.js'\n\nexport type NamedResourceInsert = {\n PID: string;\n PARTITION_ID: number;\n PARTITION_DATE: number;\n RES_ID: string;\n RES_VER: number;\n RES_VERSION: string;\n RES_TYPE: string;\n RES_PUBLISHED: number;\n RES_UPDATED: number;\n};\n\nexport type NamedResourceRead = {\n PID: string;\n};\n\nexport type NamedResourceDelete = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES_UPDATED: number;\n RES_DELETED_AT: number;\n};\n\nexport type NamedResourceUpdate = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES_UPDATED: number;\n};\n\nexport class DBSTSResource extends DBSTSFhirDBBase {\n constructor(options: IDBSTSFhirDBBaseOptions) {\n super(options);\n }\n\n async InsertResourceEx(client: PoolClient, data: NamedResourceInsert): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n INSERT INTO stsresfhir (\n PID, PARTITION_ID, PARTITION_DATE, RES_ID, RES_TYPE,\n RES_VER, RES_VERSION, RES_PUBLISHED, RES_UPDATED\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)\n RETURNING RES_VER\n `,\n [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER,\n data.RES_VERSION,\n BigInt(data.RES_PUBLISHED),\n BigInt(data.RES_UPDATED)\n ]\n );\n return res.rows[0]?.res_ver;\n } catch (error) {\n this._options.logger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async InsertResource(data: NamedResourceInsert): Promise<number | undefined> {\n return this.withClient('InsertResource', \n (client => this.InsertResourceEx(client, data)));\n }\n\n async UpdateResourceRecordEx(client: PoolClient, data: NamedResourceUpdate): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n UPDATE stsresfhir SET\n RES_VER = RES_VER + 1,\n RES_UPDATED = $1,\n RES_DELETED_AT = NULL\n WHERE RES_ID = $2 AND RES_TYPE = $3 AND RES_VER = $4\n RETURNING RES_VER\n `,\n [BigInt(data.RES_UPDATED), data.RES_ID, data.RES_TYPE, data.RES_VER]\n );\n return res.rows[0]?.res_ver;\n //return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n this._options.logger.error(`DBSTSResource:UpdateResourceRecordEx(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async UpdateResourceRecord(data: NamedResourceUpdate): Promise<number | undefined> {\n return this.withClient('UpdateResourceRecord', \n (client => this.UpdateResourceRecordEx(client, data)));\n }\n\n async DeleteResourceRecordEx(client: PoolClient, data: NamedResourceDelete): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n UPDATE stsresfhir SET\n RES_DELETED_AT = $1,\n RES_VER = RES_VER + 1,\n RES_UPDATED = $2\n WHERE RES_ID = $3 AND RES_TYPE = $4 AND RES_VER = $5\n RETURNING RES_VER\n `,\n [\n BigInt(data.RES_DELETED_AT),\n BigInt(data.RES_UPDATED),\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER\n ]\n );\n return res.rows[0]?.res_ver;\n //return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n this._options.logger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async DeleteResourceRecord(data: NamedResourceDelete): Promise<number | undefined> {\n return this.withClient('DeleteResourceRecord', \n (client => this.DeleteResourceRecordEx(client, data)));\n }\n\n async ReadResourceRecordEx(client: PoolClient, PID: string): Promise<IResource | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhir WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n this._options.logger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n throw (error);\n }\n }\n\n async ReadResourceRecord(PID: string): Promise<IResource | undefined> {\n return this.withClient('ReadResourceRecord', \n (client => this.ReadResourceRecordEx(client, PID)));\n }\n\n async ReadAllResourceRecordsEx(client: PoolClient): Promise<IResource[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhir`);\n return res.rows;\n } catch (error) {\n this._options.logger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n \n async ReadAllResourceRecords(): Promise<IResource[] | undefined> {\n return this.withClient('ReadAllResourceRecords', \n (client => this.ReadAllResourceRecordsEx(client)));\n }\n}\n","import { IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { PoolClient } from 'pg';\nimport { DBSTSFhirDBBase, IDBSTSFhirDBBaseOptions } from './pgfhirdbbase.js'\n\nexport type NamedResourceVersionInsert = {\n PID: string;\n PARTITION_ID: number;\n PARTITION_DATE: number;\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n OPERATION: 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n RES: string;\n};\n\nexport type NamedResourceVersionUpdate = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES: string;\n};\n\nexport class DBSTSResourceVersion extends DBSTSFhirDBBase {\n constructor(options: IDBSTSFhirDBBaseOptions) {\n super(options);\n }\n\n async InsertResourceVersionEx(client: PoolClient, data: NamedResourceVersionInsert): Promise<number | undefined> {\n const values = [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER,\n data.OPERATION,\n data.RES\n ];\n try {\n const res = await client.query(\n `\n INSERT INTO stsresfhirver (\n PID, PARTITION_ID, PARTITION_DATE,\n RES_ID, RES_TYPE, RES_VER, OPERATION, RES\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n RETURNING RES_VER\n `,values);\n return res.rows[0]?.res_ver;\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PID: [${values[0]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_ID: [${values[1]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_DATE: [${values[2]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_ID: [${values[3]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_TYPE: [${values[4]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_VER: [${values[5]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values OPERATION: [${values[6]}]`)\n throw error;\n }\n }\n\n async InsertResourceVersion(data: NamedResourceVersionInsert): Promise<number | undefined> {\n return this.withClient('InsertResourceVersion', \n (client => this.InsertResourceVersionEx(client, data)));\n }\n\n async ReadResourceVersionRecordEx(client: PoolClient, PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n try {\n const retVal = await client.query(`SELECT * FROM stsresfhirver WHERE PID = $1 AND RES_VER = $2`, [PID, RES_VER]);\n return retVal.rows[0];\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceVersionRecord(PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n return this.withClient('ReadResourceVersionRecord', \n (client => this.ReadResourceVersionRecordEx(client, PID, RES_VER)));\n }\n\n async ReadAllResourceVersionRecordsEx(client: PoolClient): Promise<IResourceVersion[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirver`);\n return res.rows;\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadAllResourceVersionRecords(): Promise<IResourceVersion[] | undefined> {\n return this.withClient('ReadAllResourceVersionRecords', \n (client => this.ReadAllResourceVersionRecordsEx(client)));\n }\n}\n","import { PoolClient } from 'pg';\nimport { IResourceLinkIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { defaultLogger } from '@nsshunt/stsutils';\n\nexport interface INamedResourceLinkInsert {\n PID: string\n PARTITION_ID?: number\n PARTITION_DATE?: number\n SP_NAME: string,\n SP_PARAM_TYPE: string,\n SRC_PATH: string\n RES_TYPE: string\n RES_ID: string\n TARGET_RESOURCE_TYPE: string | null\n TARGET_RESOURCE_ID: string | null\n TARGET_RESOURCE_URL: string | null\n SP_STR: string | null\n UPDATED: bigint\n SP_MISSING: boolean\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n}\n\nexport interface INamedResourceLinkReadByResourceId {\n RES_ID: string;\n}\n\nexport interface INamedResourceLinkReadByPID {\n PID: string;\n}\n\nexport interface INamedResourceLinkDelete {\n RES_ID: string;\n RES_TYPE: string;\n}\n\nexport class DBSTSResourceLink {\n async InsertResourceLink(client: PoolClient, data: INamedResourceLinkInsert): Promise<void> {\n try {\n await client.query(\n `\n INSERT INTO stsresfhirlink (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE,\n SRC_PATH, \n RES_TYPE, \n RES_ID,\n TARGET_RESOURCE_TYPE, \n TARGET_RESOURCE_ID, \n TARGET_RESOURCE_URL, \n SP_STR, \n UPDATED, \n SP_MISSING,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, \n $6, $7, $8,\n $9, $10, $11, $12, $13, $14,\n $15, $16, $17\n )\n `,\n [\n data.PID,\n data.PARTITION_ID ?? 0,\n data.PARTITION_DATE ?? 0,\n data.SP_NAME,\n data.SP_PARAM_TYPE,\n data.SRC_PATH,\n data.RES_TYPE,\n data.RES_ID,\n data.TARGET_RESOURCE_TYPE,\n data.TARGET_RESOURCE_ID ?? null,\n data.TARGET_RESOURCE_URL ?? null,\n data.SP_STR,\n BigInt(data.UPDATED),\n data.SP_MISSING,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ]\n );\n } catch (error) {\n defaultLogger.error(`DBSTSResourceLink:InsertResourceLink(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceLinkByResourceIdRecord(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IResourceLinkIndexRecord[] | undefined> {\n try {\n const res = await client.query(\n `SELECT * FROM stsresfhirlink WHERE RES_ID = $1 AND RES_TYPE = $2`,\n [RES_ID, RES_TYPE]\n );\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResourceLink:ReadResourceLinkByResourceIdRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceLinkByPIDRecord(client: PoolClient, PID: string): Promise<IResourceLinkIndexRecord | undefined> {\n try {\n const res = await client.query(\n `SELECT * FROM stsresfhirlink WHERE PID = $1 LIMIT 1`,\n [PID]\n );\n return res.rows[0];\n } catch (error) {\n defaultLogger.error(`DBSTSResourceLink:ReadResourceLinkByPIDRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadAllResourceLinkRecords(client: PoolClient): Promise<IResourceLinkIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirlink`);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResourceLink:ReadAllResourceLinkRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async DeleteResourceLinkRecord(client: PoolClient, data: INamedResourceLinkDelete): Promise<void> {\n try {\n await client.query(\n `DELETE FROM stsresfhirlink WHERE RES_ID = $1 AND RES_TYPE = $2`,\n [data.RES_ID, data.RES_TYPE]\n );\n } catch (error) {\n defaultLogger.error(`DBSTSResourceLink:DeleteResourceLinkRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirstring (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n HASH_EXACT BIGINT NOT NULL,\n SP_VALUE_NORMALIZED TEXT NOT NULL,\n SP_VALUE_EXACT TEXT NOT NULL,\n UPDATED BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsstring_hash_identity ON stsresfhirstring (HASH_IDENTITY);\nCREATE INDEX idx_stsstring_hash_exact ON stsresfhirstring (HASH_EXACT);\nCREATE INDEX idx_hash_value ON stsresfhirstring (HASH_IDENTITY, SP_VALUE_NORMALIZED);\n*/\nimport { PoolClient } from 'pg';\nimport { IStringIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { normalizeStringParam, hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\n\nexport type INamedInsert = {\n PID: string\n PARTITION_ID?: number\n PARTITION_DATE?: number\n SP_NAME?: string\n SP_PARAM_TYPE: string\n RES_ID: string\n RES_TYPE?: string\n UPDATED?: bigint\n SP_MISSING: boolean\n SP_STR: string | null\n HASH_IDENTITY: bigint\n HASH_EXACT: bigint | null\n SP_VALUE_NORMALIZED: string | null\n SP_VALUE_EXACT: string | null\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadByPID {\n PID: string;\n}\n\nexport interface INamedDelete {\n RES_ID: string;\n RES_TYPE: string;\n}\n\nexport interface INamedReadBase {\n SP_NAME?: string;\n RES_TYPE?: string;\n}\n\nexport interface INamedReadByExact extends INamedReadBase {\n HASH_EXACT: bigint;\n}\n\nexport interface INamedReadByValueNormalised extends INamedReadBase {\n HASH_IDENTITY: bigint;\n SP_VALUE_NORMALIZED: string;\n}\n\nexport interface INamedReadByResID {\n RES_ID: string;\n}\n\nexport class DBSTSString {\n async InsertRecord(client: PoolClient, data: INamedInsert): Promise<void> {\n await client.query(\n `\n INSERT INTO stsresfhirstring (\n PID, \n PARTITION_ID, \n PARTITION_DATE,\n SP_NAME, \n SP_PARAM_TYPE, \n RES_ID, \n RES_TYPE,\n SP_MISSING, \n SP_STR, \n HASH_IDENTITY, \n HASH_EXACT,\n SP_VALUE_NORMALIZED, \n SP_VALUE_EXACT, \n UPDATED,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3,\n $4, $5, $6, $7,\n $8, $9, $10,\n $11, $12, $13, $14,\n $15, $16, $17\n )\n `,\n [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.SP_NAME ?? null,\n data.SP_PARAM_TYPE,\n data.RES_ID,\n data.RES_TYPE ?? null,\n data.SP_MISSING,\n data.SP_STR,\n data.HASH_IDENTITY,\n data.HASH_EXACT,\n data.SP_VALUE_NORMALIZED,\n data.SP_VALUE_EXACT,\n data.UPDATED,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ]\n );\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IStringIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirstring WHERE PID = $1 LIMIT 1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IStringIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirstring`);\n return res.rows;\n }\n\n #FilterResults(data: INamedReadBase, results: IStringIndexRecord[]): IStringIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n\n async ReadByValueNormalized(client: PoolClient, \n searchString: string,\n parameterName: string,\n resourceName: string\n ): Promise<IStringIndexRecord[]> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const norm = normalizeStringParam(searchString);\n\n const res = await client.query(\n `SELECT * FROM stsresfhirstring WHERE HASH_IDENTITY = $1 AND SP_VALUE_NORMALIZED LIKE $2`,\n [hash, norm]\n );\n\n return this.#FilterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByValueExact(client: PoolClient, data: INamedReadByExact): Promise<IStringIndexRecord[]> {\n const res = await client.query(\n `SELECT * FROM stsresfhirstring WHERE HASH_EXACT = $1`,\n [BigInt(data.HASH_EXACT)]\n );\n\n return this.#FilterResults(data, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IStringIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirstring WHERE RES_ID = $1 AND RES_TYPE = $2`, [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhirstring WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n}\n","/*\nCREATE TABLE stsresfhirtoken (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE TEXT NOT NULL,\n HASH_VALUE BIGINT NOT NULL,\n HASH_SYS BIGINT NOT NULL,\n HASH_SYS_AND_VALUE BIGINT NOT NULL\n);\n\nCREATE INDEX idx_ststoken_hash_identity ON stsresfhirtoken (HASH_IDENTITY);\nCREATE INDEX idx_ststoken_hash_value ON stsresfhirtoken (HASH_VALUE);\nCREATE INDEX idx_ststoken_hash_sys ON stsresfhirtoken (HASH_SYS);\nCREATE INDEX idx_ststoken_hash_sys_and_value ON stsresfhirtoken (HASH_SYS_AND_VALUE);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { ITokenIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nexport type INamedInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_SYSTEM: string | null // The system of the code.\n SP_TOKEN_TYPE: string | null // The token type\n SP_VALUE: string | null // This is the bare code value.\n HASH_VALUE: bigint | null // A hash like HASH_IDENTITY (paramName|resType) that also includes the SP_VALUE column. (paramName|resType|value)\n HASH_SYS: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM column. (paramName|resType|system)\n HASH_SYS_AND_VALUE: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM and SP_VALUE columns. (paramName|resType|system|value)\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadByPID {\n PID: string\n};\n\nexport interface INamedDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\nexport interface INamedReadBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n\nexport class DBSTSToken {\n async InsertRecord(client: PoolClient, data: INamedInsert): Promise<void> {\n const text = `\n INSERT INTO stsresfhirtoken (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR, \n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_SYSTEM, \n SP_TOKEN_TYPE, \n SP_VALUE,\n HASH_VALUE, \n HASH_SYS, \n HASH_SYS_AND_VALUE,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15, $16, $17,\n $18, $19, $20\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_SYSTEM, \n data.SP_TOKEN_TYPE,\n data.SP_VALUE, \n data.HASH_VALUE,\n data.HASH_SYS, \n data.HASH_SYS_AND_VALUE,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhirtoken WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<ITokenIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE PID = $1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<ITokenIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirtoken`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_IDENTITY = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByValue(client: PoolClient, searchValue: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchValue}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_VALUE = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadBySystem(client: PoolClient, searchSystem: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_SYS = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadBySystemAndValue(client: PoolClient, searchSystem: string, searchValue: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}|${searchValue}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_SYS_AND_VALUE = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<ITokenIndexRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE RES_ID = $1 AND RES_TYPE = $2`, [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: ITokenIndexRecord[]): ITokenIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","/*\nCREATE TABLE stsresfhirquantity (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE DECIMAL NOT NULL,\n SP_UNITS TEXT NOT NULL,\n HASH_IDENTITY_AND_UNITS BIGINT NOT NULL,\n HASH_IDENTITY_SYS_UNITS BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsquantity_hash_identity ON stsresfhirquantity (HASH_IDENTITY);\nCREATE INDEX idx_stsquantity_hash_units ON stsresfhirquantity (HASH_IDENTITY_AND_UNITS);\nCREATE INDEX idx_stsquantity_hash_sys_units ON stsresfhirquantity (HASH_IDENTITY_SYS_UNITS);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IQuantityIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nexport type INamedQuantityInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_SYSTEM: string | null // The system of the quantity units. e.g. \"http://unitsofmeasure.org\".\n SP_VALUE: number | null // This is the value extracted by the SearchParameter expression. Note that this is a DECIMAL. String conversion used here to preserve precision.\n SP_UNITS: string | null // The units of the quantity. E.g. \"mg\".\n HASH_IDENTITY_AND_UNITS: bigint | null// A hash like HASH_IDENTITY that also includes the SP_UNITS column.\n HASH_IDENTITY_SYS_UNITS: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM and SP_UNITS columns.\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadQuantityByPID {\n PID: string\n};\n\nexport interface INamedQuantityDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSQuantity {\n async InsertRecord(client: PoolClient, data: INamedQuantityInsert): Promise<void> {\n const text = `\n INSERT INTO stsresfhirquantity (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_SYSTEM, \n SP_VALUE,\n SP_UNITS, \n HASH_IDENTITY_AND_UNITS, \n HASH_IDENTITY_SYS_UNITS,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15, $16,\n $17, $18, $19\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID, \n data.PARTITION_DATE, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_SYSTEM, \n data.SP_VALUE, \n data.SP_UNITS,\n data.HASH_IDENTITY_AND_UNITS,\n data.HASH_IDENTITY_SYS_UNITS,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n }\n\n async DeleteRecord(client: PoolClient, data: INamedQuantityDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhirquantity WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IQuantityIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE PID = $1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IQuantityIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirquantity`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByUnits(client: PoolClient, units: string, searchValue: string, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${units}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY_AND_UNITS = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadBySystemAndUnits(client: PoolClient, searchSystem: string, units: string, searchValue: string, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}|${units}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY_SYS_UNITS = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IQuantityIndexRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IQuantityIndexRecord[]): IQuantityIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","/*\nCREATE TABLE stsresfhirquantity (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE DECIMAL NOT NULL,\n SP_UNITS TEXT NOT NULL,\n HASH_IDENTITY_AND_UNITS BIGINT NOT NULL,\n HASH_IDENTITY_SYS_UNITS BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsquantity_hash_identity ON stsresfhirquantity (HASH_IDENTITY);\nCREATE INDEX idx_stsquantity_hash_units ON stsresfhirquantity (HASH_IDENTITY_AND_UNITS);\nCREATE INDEX idx_stsquantity_hash_sys_units ON stsresfhirquantity (HASH_IDENTITY_SYS_UNITS);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { INumberIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nexport type INamedNumberInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_VALUE: number\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedNumberDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSNumber {\n async InsertRecord(client: PoolClient, data: INamedNumberInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhirnumber (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_VALUE,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_VALUE ?? 0,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n \n await client.query(text, values);\n } catch (error) {\n console.error(error);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedNumberDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhirnumber WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<INumberIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE PID = $1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<INumberIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirnumber`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<INumberIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByValue(client: PoolClient, searchValue: string, parameterName: string, resourceName: string): Promise<INumberIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE HASH_IDENTITY = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<INumberIndexRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: INumberIndexRecord[]): INumberIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","/*\nCREATE TABLE stsresfhirdate (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_VALUE_LOW timestamp with time zone,\n SP_VALUE_HIGH timestamp with time zone,\n SP_VALUE_LOW_DATE_ORDINAL INTEGER,\n SP_VALUE_HIGH_DATE_ORDINAL INTEGER\n);\n\nCREATE INDEX idx_stsresfhirdate_hash_identity ON stsresfhirdate (HASH_IDENTITY);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IDateIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DateTime } from 'luxon';\n\nexport type INamedDateInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_VALUE_LOW: DateTime | null // This is the lower bound of the date in question.\n SP_VALUE_HIGH: DateTime | null // This is the upper bound of the date in question.\n SP_VALUE_LOW_DATE_ORDINAL: number | null // This column contains the same Timestamp as SP_VALUE_LOW, but truncated to Date precision and formatted as an integer in the format \"YYYYMMDD\".\n SP_VALUE_HIGH_DATE_ORDINAL: number | null // This column contains the same Timestamp as SP_VALUE_HIGH, but truncated to Date precision and formatted as an integer in the format \"YYYYMMDD\".\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadDateByPID {\n PID: string\n};\n\nexport interface INamedDateDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSDate {\n async InsertRecord(client: PoolClient, data: INamedDateInsert): Promise<void> {\n const text = `\n INSERT INTO stsresfhirdate (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_VALUE_LOW,\n SP_VALUE_HIGH,\n SP_VALUE_LOW_DATE_ORDINAL,\n SP_VALUE_HIGH_DATE_ORDINAL,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15,\n $16, $17, $18\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n (data.SP_VALUE_LOW ? data.SP_VALUE_LOW.toJSDate() : null),\n (data.SP_VALUE_HIGH ? data.SP_VALUE_HIGH.toJSDate() : null),\n data.SP_VALUE_LOW_DATE_ORDINAL,\n data.SP_VALUE_HIGH_DATE_ORDINAL,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDateDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhirdate WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IDateIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE PID = $1`, [PID]);\n\n if (res.rows && res.rows.length === 1) {\n if (res.rows[0].sp_value_high !== null) {\n res.rows[0].sp_value_high = DateTime.fromJSDate(res.rows[0].sp_value_high);\n }\n if (res.rows[0].sp_value_low !== null) {\n res.rows[0].sp_value_low = DateTime.fromJSDate(res.rows[0].sp_value_low);\n }\n }\n\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IDateIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhirdate`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByDateTime(client: PoolClient, SP_VALUE_LOW: DateTime, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW >= $2 AND SP_VALUE_HIGH <= $3`, \n [hash, SP_VALUE_LOW, SP_VALUE_HIGH]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByDateTimeLow(client: PoolClient, SP_VALUE_LOW: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW >= $2`, \n [hash, SP_VALUE_LOW]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByDateTimeHigh(client: PoolClient, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_HIGH <= $2`, \n [hash, SP_VALUE_HIGH]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByDateOrdinal(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW_DATE_ORDINAL >= $2 AND SP_VALUE_HIGH_DATE_ORDINAL <= $3`, \n [hash, SP_VALUE_LOW_DATE_ORDINAL, SP_VALUE_HIGH_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByDateOrdinalLow(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW_DATE_ORDINAL >= $2`, \n [hash, SP_VALUE_LOW_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByDateOrdinalHigh(client: PoolClient, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_HIGH_DATE_ORDINAL <= $2`, \n [hash, SP_VALUE_HIGH_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IDateIndexRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IDateIndexRecord[]): IDateIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","/*\nCREATE TABLE stsresfhiruri (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_URI TEXT NOT NULL,\n\tHASH_URI BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsresfhiruri_hash_identity ON stsresfhiruri (HASH_IDENTITY);\nCREATE INDEX idx_stsresfhiruri_hash_uri ON stsresfhiruri (HASH_URI);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IUriIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nexport type INamedUriInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_URI: string | null // \n HASH_URI: bigint | null // \n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadUriByPID {\n PID: string\n};\n\nexport interface INamedUriDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSUri {\n async InsertRecord(client: PoolClient, data: INamedUriInsert): Promise<void> {\n const text = `\n INSERT INTO stsresfhiruri (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_URI, \n HASH_URI,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12, $13,\n $14, $15, $16\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_URI, \n data.HASH_URI,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n }\n\n async DeleteRecord(client: PoolClient, data: INamedUriDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhiruri WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IUriIndexRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE PID = $1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IUriIndexRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhiruri`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IUriIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByURI(client: PoolClient, uri: string, parameterName: string, resourceName: string): Promise<IUriIndexRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${uri}`, true);\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE HASH_URI = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IUriIndexRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IUriIndexRecord[]): IUriIndexRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","/*\nCREATE TABLE stsresfhircombo (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n\tIDX_STRING TEXT,\n\tHASH_COMPLETE BIGINT\n);\n\nCREATE INDEX idx_stsresfhircombo_hash_identity ON stsresfhircombo (HASH_IDENTITY);\nCREATE INDEX idx_stsresfhircombo_hash_complete ON stsresfhircombo (HASH_COMPLETE);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IComboNonUniqueRecord } from '../../fhir-utils/commonTypes.js'\nimport { DateTime } from 'luxon';\nimport { defaultLogger } from '@nsshunt/stsutils';\n\nexport type INamedComboInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n IDX_STRING: string | null, //\n HASH_COMPLETE: bigint | null// A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadComboByPID {\n PID: string\n};\n\nexport interface INamedComboDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\nexport class DBSTSCombo {\n #replacer = (_: any, v: any) => typeof v === 'bigint' ? { __bigint__: v.toString() } : v;\n #reviver = (_: any, v: any) => v && v.__bigint__ !== undefined ? BigInt(v.__bigint__) : v;\n\n async InsertRecord(client: PoolClient, data: INamedComboInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhircombo (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n IDX_STRING,\n HASH_COMPLETE\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12, $13\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID, \n data.PARTITION_DATE, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.IDX_STRING,\n data.HASH_COMPLETE\n ];\n\n await client.query(text, values);\n } catch (error) {\n defaultLogger.error(`DBSTSCombo:InsertRecord(): Error: [${error}]`);\n defaultLogger.error(data);\n defaultLogger.error(JSON.stringify(data, this.#replacer, 2));\n throw error;\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedComboDelete): Promise<void> {\n await client.query(`DELETE FROM stsresfhircombo WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IComboNonUniqueRecord | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE PID = $1`, [PID]);\n return res.rows[0];\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IComboNonUniqueRecord[]> {\n const res = await client.query(`SELECT * FROM stsresfhircombo`);\n return res.rows;\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n }\n\n async ReadByString(client: PoolClient, stringVal: string, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByDateTime(client: PoolClient, SP_VALUE_LOW: DateTime, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateTimeLow(client: PoolClient, SP_VALUE_LOW: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateTimeHigh(client: PoolClient, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinal(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinalLow(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinalHigh(client: PoolClient, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IComboNonUniqueRecord[] | undefined> {\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IComboNonUniqueRecord[]): IComboNonUniqueRecord[] {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n }\n}\n","//import { v4 as uuidv4 } from 'uuid'\nimport { randomUUID } from 'node:crypto';\nimport { PGPoolManager } from './pgpoolmanager.js'\nimport { defaultLogger, ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n \nimport { TinyEmitter } from 'tiny-emitter';\n\nimport { DBSTSResource } from './pgfhirresource.js'\nimport { DBSTSResourceVersion } from './pgfhirresourceversion.js'\n\nimport { IResource, IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { DBSearchIndex } from '../dbsearchindex.js'\n\nimport { IComboNonUniqueRecord, INumberIndexRecord, IQuantityIndexRecord, IResourceLinkIndexRecord, \n IStringIndexRecord, ITokenIndexRecord, IDateIndexRecord, IUriIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nimport { DBSTSResourceLink } from './pgfhirresourcelink.js'\n\nimport { Resource, OperationOutcome } from '@nsshunt/stsfhirclient';\n\nimport { PoolClient } from 'pg';\nimport { DBSTSString } from './pgfhirstring.js'\nimport { DBSTSToken } from './pgfhirtoken.js'\nimport { DBSTSQuantity } from './pgfhirquantity.js'\nimport { DBSTSNumber } from './pgfhirnumber.js'\nimport { DBSTSDate } from './pgfhirdate.js'\nimport { DBSTSUri } from './pgfhiruri.js'\nimport { DBSTSCombo } from './pgfhircombo.js'\nimport { DateTime } from 'luxon';\n\nimport chalk from 'chalk';\nchalk.level = 3;\n\nexport interface IPGAccessLayerOptions {\n usedefaultdb: boolean\n logger: ISTSLogger\n}\n\ninterface ITransactionRecord {\n client: PoolClient,\n timeout: NodeJS.Timeout\n}\n\nexport class PGFhirAccessLayer extends TinyEmitter {\n #options: IPGAccessLayerOptions;\n #poolManager: PGPoolManager | null = null;\n #dbSTSResource: DBSTSResource;\n #dbSTSResourceVersion: DBSTSResourceVersion;\n #dbSearchIndex: DBSearchIndex;\n #dbSTSResourceLink: DBSTSResourceLink;\n #dbSTSString: DBSTSString;\n #dbSTSToken: DBSTSToken;\n #dbSTSQuantity: DBSTSQuantity;\n #dbSTSNumber: DBSTSNumber;\n #dbSTSDate: DBSTSDate;\n #dbSTSUri: DBSTSUri;\n #dbSTSCombo: DBSTSCombo;\n #transactions: Record<string, ITransactionRecord> = { };\n #maxTransactionTime: number = 60000; //@@ 1 minute for transactions max\n\n #replacer = (_: any, v: any) => typeof v === 'bigint' ? { __bigint__: v.toString() } : v;\n #reviver = (_: any, v: any) => v && v.__bigint__ !== undefined ? BigInt(v.__bigint__) : v;\n\n constructor(options: IPGAccessLayerOptions) {\n super();\n\n this.#options = options;\n\n this.#poolManager = new PGPoolManager({\n logger: this.#options.logger,\n usedefaultdb: this.#options.usedefaultdb\n });\n\n this.#dbSTSResource = new DBSTSResource({\n logger: this.#options.logger,\n poolManager: this.#poolManager\n } );\n this.#dbSTSResourceVersion = new DBSTSResourceVersion({\n logger: this.#options.logger,\n poolManager: this.#poolManager\n });\n\n this.#dbSearchIndex = DBSearchIndex.getInstance();\n\n this.#dbSTSResourceLink = new DBSTSResourceLink();\n this.#dbSTSString = new DBSTSString();\n this.#dbSTSToken = new DBSTSToken();\n this.#dbSTSQuantity = new DBSTSQuantity();\n this.#dbSTSNumber = new DBSTSNumber();\n this.#dbSTSDate = new DBSTSDate();\n this.#dbSTSUri = new DBSTSUri();\n this.#dbSTSCombo = new DBSTSCombo();\n\n //this.#poolManager.on(IDBAccessLayerEvents.UpdateInstruments, this.#UpdateInstruments);\n }\n\n GetOperationOutcome = (code: string, diagnostics: string): OperationOutcome => {\n return {\n resourceType: \"OperationOutcome\",\n issue: [\n {\n severity: \"error\",\n code, // \"invalid\",\n diagnostics\n }\n ]\n }\n }\n\n /*\n #UpdateInstruments = (data: any) => {\n this.emit(IDBAccessLayerEvents.UpdateInstruments, data);\n }\n */\n\n // Method only used for testing. Ensure that if redis is being used that the cache is always flushed.\n async StartDatabase(): Promise<boolean> {\n return true;\n }\n\n async EndDatabase(): Promise<boolean> {\n if (this.#poolManager) {\n //this.#poolManager.off(IDBAccessLayerEvents.UpdateInstruments, this.#UpdateInstruments);\n await this.#poolManager.End();\n }\n this.#poolManager = null;\n return true;\n }\n\n GetFhirResourceController = (): DBSTSResource => {\n return this.#dbSTSResource;\n }\n\n GetFhirResourceVersionController = (): DBSTSResourceVersion => {\n return this.#dbSTSResourceVersion;\n }\n\n UpdateIndexes = async (client: PoolClient, resource: Resource) => {\n let start = performance.now();\n const oa = start;\n const searchIndexData = await this.#dbSearchIndex.GetSearchIndexData(resource);\n\n const lap1 = performance.now() - start;\n start = performance.now();\n\n const InsertResourceLinkRecord = async (client: PoolClient, resourceLinkIndexRecord: IResourceLinkIndexRecord) => {\n const retVal = await this.#dbSTSResourceLink.InsertResourceLink(client, resourceLinkIndexRecord);\n }\n\n const InsertResourceStringRecord = async (client: PoolClient, stringRecord: IStringIndexRecord) => {\n const retVal = await this.#dbSTSString.InsertRecord(client, stringRecord);\n }\n\n const InsertResourceTokenRecord = async (client: PoolClient, tokenRecord: ITokenIndexRecord) => {\n const retVal = await this.#dbSTSToken.InsertRecord(client, tokenRecord);\n }\n\n const InsertResourceQuantityRecord = async (client: PoolClient, quantityRecord: IQuantityIndexRecord) => {\n const retVal = await this.#dbSTSQuantity.InsertRecord(client, quantityRecord);\n }\n\n const InsertResourceNumberRecord = async (client: PoolClient, numberRecord: INumberIndexRecord) => {\n const retVal = await this.#dbSTSNumber.InsertRecord(client, numberRecord);\n }\n\n const InsertResourceDateRecord = async (client: PoolClient, dateRecord: IDateIndexRecord) => {\n const retVal = await this.#dbSTSDate.InsertRecord(client, dateRecord);\n }\n\n const InsertResourceUriRecord = async (client: PoolClient, uriRecord: IUriIndexRecord) => {\n const retVal = await this.#dbSTSUri.InsertRecord(client, uriRecord);\n }\n\n const InsertResourceComboRecord = async (client: PoolClient, comboRecord: IComboNonUniqueRecord) => {\n const retVal = await this.#dbSTSCombo.InsertRecord(client, comboRecord);\n }\n\n // Delete previous index records for this resource\n await this.#dbSTSResourceLink.DeleteResourceLinkRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSString.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSToken.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSQuantity.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSNumber.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSDate.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSUri.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSCombo.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n\n const lap2 = performance.now() - start;\n start = performance.now();\n \n try {\n for (let i=0; i < searchIndexData.length; i++) {\n const si = searchIndexData[i];\n const st = performance.now();\n\n if (si && (si as any).SP_MISSING) {\n //console.log(chalk.magenta.italic(`-->> MISSING ${si.SP_NAME} ${si.SP_PARAM_TYPE} ${si.PID} ${si.SP_STR}`));\n //console.log(JSON.stringify(si, this.#replacer, 2));\n } else {\n //console.log(chalk.green(`-->> ${si.SP_NAME} ${si.SP_PARAM_TYPE} ${si.PID} ${si.SP_STR}`));\n }\n\n switch (si.SP_PARAM_TYPE) {\n case 'reference' :\n await InsertResourceLinkRecord(client, si as IResourceLinkIndexRecord);\n break;\n case 'string' :\n await InsertResourceStringRecord(client, si as IStringIndexRecord);\n break;\n case 'token' :\n await InsertResourceTokenRecord(client, si as ITokenIndexRecord);\n break;\n case 'quantity' :\n await InsertResourceQuantityRecord(client, si as IQuantityIndexRecord);\n break;\n case 'number' :\n await InsertResourceNumberRecord(client, si as INumberIndexRecord);\n break;\n case 'date' :\n await InsertResourceDateRecord(client, si as IDateIndexRecord);\n break;\n case 'uri' :\n await InsertResourceUriRecord(client, si as IUriIndexRecord);\n break;\n case 'composite' :\n await InsertResourceComboRecord(client, si as IComboNonUniqueRecord);\n break;\n default :\n //console.log(`-->> ${si.SP_PARAM_TYPE} *** UNKNOWN ***`);\n }\n //console.log(` -->> individual index [${si.SP_PARAM_TYPE}] update time: [${(performance.now() - st)}]`)\n };\n\n //console.log(` -->> index update time: [${(performance.now() - st1)}]`)\n } catch (error) {\n console.error(error);\n }\n const lap3 = performance.now() - start;\n const total = performance.now() - oa;\n\n if (total > 100.0) {\n console.log(chalk.hex('#E33A36')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n } else if (total > 75.0) {\n console.log(chalk.hex('#e27270')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n } else if (total > 50.0) {\n console.log(chalk.hex('#e2c3c2')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n }\n }\n\n #isInTransaction = async (client: PoolClient): Promise<boolean> => {\n const res = await client.query(`\n SELECT txid_current_if_assigned() AS txid\n `);\n return res.rows[0].txid !== null;\n }\n\n\n BeginTransaction = async (): Promise<string | undefined> => {\n if (this.#poolManager) {\n try {\n const transactionHandle = randomUUID();\n const client = await this.#poolManager.connectReadWrite();\n try {\n await client.query('BEGIN');\n this.#transactions[transactionHandle] = {\n client,\n timeout: setTimeout(async () => {\n await this.#transactions[transactionHandle].client.query('ROLLBACK');\n client.release();\n delete this.#transactions[transactionHandle];\n }, this.#maxTransactionTime)\n }\n return transactionHandle;\n } catch (error) {\n console.error(error);\n client.release();\n }\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n CommitTransaction = async (transactionHandle: string): Promise<boolean> => {\n if (this.#transactions[transactionHandle]) {\n clearInterval(this.#transactions[transactionHandle].timeout);\n const client = this.#transactions[transactionHandle].client;\n try {\n await client.query('COMMIT');\n client.release();\n delete this.#transactions[transactionHandle];\n return true;\n } catch (error) {\n console.error(error);\n client.release();\n delete this.#transactions[transactionHandle];\n return false;\n }\n }\n return false;\n }\n\n RollbackTransaction = async (transactionHandle: string): Promise<boolean> => {\n if (this.#transactions[transactionHandle]) {\n clearInterval(this.#transactions[transactionHandle].timeout);\n const client = this.#transactions[transactionHandle].client;\n try {\n await client.query('ROLLBACK');\n client.release();\n delete this.#transactions[transactionHandle];\n return true;\n } catch (error) {\n console.error(error);\n client.release();\n delete this.#transactions[transactionHandle];\n return false;\n }\n }\n return false;\n }\n\n //begin X - returns a handle in a recordset\n CreateResource = async (resource: Resource, transactionHandle?: string): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `CreateResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `CreateResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.InsertResourceEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: 1,\n RES_VERSION: 'r5', //@@ needs to be from FHIR\n RES_PUBLISHED: now,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `CreateResource(): Version Conflict. newVersion is undefined.`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const RES = JSON.stringify(resource);\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: 'POST',\n RES\n })\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `CreateResource(): Version Conflict. resourceVersionRunResult is undefined.`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n const st = performance.now();\n await this.UpdateIndexes(client, resource);\n //console.log(` -->> Update Index Time: ${(performance.now() - st) / 1000.0}`);\n\n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `CreateResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n UpdateResource = async (resource: Resource, RES_VER: number, operation: 'PUT' | 'PATCH', transactionHandle: string | undefined): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `UpdateResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `UpdateResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.UpdateResourceRecordEx(client, {\n RES_TYPE,\n RES_ID,\n RES_VER,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `UpdateResource(): Version Conflict. newVersion is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const RES = JSON.stringify(resource);\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: operation,\n RES\n });\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `UpdateResource(): Version Conflict. resourceVersionRunResult is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n await this.UpdateIndexes(client, resource);\n\n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `UpdateResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n DeleteResource = async (resource: Resource, RES_VER: number, transactionHandle?: string): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `DeleteResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `DeleteResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n //const now = new Date(DateTime.fromISO(resource.meta!.lastUpdated as string).toJSDate()).getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.DeleteResourceRecordEx(client, {\n RES_ID,\n RES_TYPE,\n RES_VER,\n RES_DELETED_AT: now,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `DeleteResource(): Version Conflict. newVersion is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: 'DELETE',\n RES: ''\n });\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `DeleteResource(): Version Conflict. resourceVersionRunResult is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n await this.UpdateIndexes(client, resource);\n \n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `DeleteResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n //@@ needs to return a 410 (GONE) if record exists but deleted ...\n /* \n| Request type | Response |\n| ----------------------------- | -------------------------------------------------- |\n| `GET /Patient/123` | 🔴 `410 Gone` |\n| `GET /Patient/123/_history/1` | ✅ Returns version 1 if it exists |\n| `GET /Patient/123/_history` | ✅ Shows all historical versions including deletion |\n| `POST /Patient` (same ID) | 🔄 Creates a new version |\n| `PUT /Patient/123` | 🔄 Reactivates (undeletes) with new version |\n*/\n\n ReadResourceRecord = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceRecord(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.* FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE AND\n r.RES_VER = v.RES_VER\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2 AND\n r.RES_DELETED_AT IS NULL\n `, [RES_ID, RES_TYPE]);\n return res.rows[0];\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourceRecordWithVersion = async (RES_TYPE: string, RES_ID: string, RES_VER: number, transactionHandle?: string): Promise<IResource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceRecordWithVersion(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2 AND\n v.RES_VER = $3\n `, [RES_ID, RES_TYPE, RES_VER]);\n return res.rows[0];\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourceInstanceWithAllVersions = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceInstanceWithAllVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `, [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourcesWithAllVersions = async (RES_TYPE: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourcesWithAllVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_TYPE = $1\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `, [RES_TYPE]);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadAllResourcesWithVersions = async (transactionHandle?: string) => {\n if (!this.#poolManager) {\n const errorMessage = `ReadAllResourcesWithVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.* FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE AND\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadAllResourceVersionRecord = (): Promise<IResourceVersion[] | undefined> => {\n return this.#dbSTSResourceVersion.ReadAllResourceVersionRecords();\n }\n\n ReadResourceIndexes = async (resource: Resource, transactionHandle?: string): Promise<JSONObject | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceIndexes(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n const resultSet: Record<string, any[] | undefined> = {\n \"stsresfhirlink\": [ ],\n \"stsresfhirstring\": [ ],\n \"stsresfhirtoken\": [ ],\n \"stsresfhirquantity\": [ ],\n \"stsresfhirnumber\": [ ],\n \"stsresfhirdate\": [ ],\n \"stsresfhiruri\": [ ],\n \"stsresfhircombo\": [ ]\n };\n\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n\n try {\n\n const retValLinks = await this.#dbSTSResourceLink.ReadResourceLinkByResourceIdRecord(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirlink\"] = retValLinks;\n\n const retValStrings = await this.#dbSTSString.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirstring\"] = retValStrings;\n\n const retValTokens = await this.#dbSTSToken.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirtoken\"] = retValTokens;\n\n const retValQuantity = await this.#dbSTSQuantity.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirquantity\"] = retValQuantity;\n\n const retValNumber = await this.#dbSTSNumber.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirnumber\"] = retValNumber;\n\n const retValDate = await this.#dbSTSDate.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirdate\"] = retValDate;\n\n const retValUri = await this.#dbSTSUri.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhiruri\"] = retValUri;\n\n const retValCombo = await this.#dbSTSCombo.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhircombo\"] = retValCombo;\n\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceIndexes(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n return resultSet;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceIndexes(): Connection Error: [${error}]`)\n }\n }\n\n ExecuteReadQuery = async (queryData: any, transactionHandle?: string): Promise<any> => {\n if (!this.#poolManager) {\n const errorMessage = `ExecuteReadQuery(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const { queryText, vals } = queryData;\n const res = await client.query(queryText, vals);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ExecuteReadQuery(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ExecuteReadQuery(): Connection Error: [${error}]`)\n }\n }\n\n TruncateAll = async () => {\n if (!this.#poolManager) {\n const errorMessage = `TruncateAll(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n client = await this.#poolManager.connectReadWrite();\n try {\n client.query('TRUNCATE TABLE stsresfhir, stsresfhirver, stsresfhirlink, stsresfhirstring, stsresfhirtoken, stsresfhirquantity, stsresfhirnumber, stsresfhiruri, stsresfhirdate, stsresfhircoords, stsresfhircombo');\n } catch (error) {\n defaultLogger.error(`DBSTSResource:TruncateAll(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:TruncateAll(): Connection Error: [${error}]`)\n }\n }\n}\n"],"x_google_ignoreList":[1],"mappings":"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;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["#LoadDefinitions","#searchParametersByResourceTypeKey","#searchParametersByUrlKey","#resourcesKey","#typesKey","#definitions","#loaded","#LoadDefinitions","#RemoveSurroundingParentheses","#ops","#GetValueFromResourceAtPath","#GenerateHashValues","#OutputToken","#warn","#debug","#OutputQuantity","#GetResourceID","#OutputReference","#resourceHelper","#OutputString","#OutputNumber","#OutputURI","#searchIndexBaseRegistry","#debug","#options","#CreatePools","#CreatePool","#AttachInstruments","#pools","#GetPoolKey","#LogDebugMessage","#LogErrorMessage","#UpdateInstruments","#DetachInstruments","#keyPrefix","#observer","#FilterResults","#filterResults","#filterResults","#filterResults","#filterResults","#filterResults","#filterResults","#options","#poolManager","#dbSTSResource","#dbSTSResourceVersion","#dbSearchIndex","#dbSTSResourceLink","#dbSTSString","#dbSTSToken","#dbSTSQuantity","#dbSTSNumber","#dbSTSDate","#dbSTSUri","#dbSTSCombo","#transactions","#maxTransactionTime"],"sources":["../src/fhir-utils/fhirDateUtils.ts","../node_modules/xxhash-wasm/esm/xxhash-wasm.js","../__vite-browser-external","../src/fhir-utils/hashUtils.ts","../src/fhir-utils/fhirHashUtils.ts","../src/redisDistributedLock.ts","../src/searchParameterManager.ts","../src/fhir-utils/resourceHelper.ts","../src/fhir-database/dbsearchindexbase.ts","../src/fhir-database/dbsearchindextoken.ts","../src/fhir-database/dbsearchindexcomposite.ts","../src/fhir-database/dbsearchindexdates.ts","../src/fhir-database/dbsearchindexquantity.ts","../src/fhir-database/dbsearchindexreference.ts","../src/fhir-database/dbsearchindexstring.ts","../src/fhir-database/dbsearchindexnumber.ts","../src/fhir-database/dbsearchindexuri.ts","../src/fhir-database/dbsearchregistry.ts","../src/fhir-database/dbsearchindex.ts","../src/fhir-database/pg/pgpoolmanager.ts","../src/fhir-database/pg/pgfhirdbbase.ts","../src/fhir-database/pg/pgfhirresource.ts","../src/fhir-database/pg/pgfhirresourceversion.ts","../src/fhir-database/pg/pgfhirdbparamtypebase.ts","../src/fhir-database/pg/pgfhirresourcelink.ts","../src/fhir-database/pg/pgfhirstring.ts","../src/fhir-database/pg/pgfhirtoken.ts","../src/fhir-database/pg/pgfhirquantity.ts","../src/fhir-database/pg/pgfhirnumber.ts","../src/fhir-database/pg/pgfhirdate.ts","../src/fhir-database/pg/pgfhiruri.ts","../src/fhir-database/pg/pgfhircombo.ts","../src/fhir-database/pg/pgfhiraccesslayer.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF\n/* eslint @typescript-eslint/no-unused-vars: 0 */ // --> OFF\nimport { DateTime } from 'luxon';\n\nexport class FHIRDateUtils {\n static fullDateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n static yearMonthRegex = /^\\d{4}-\\d{2}$/;\n static yearRegex = /^\\d{4}$/;\n\n // Parse FHIR date: YYYY | YYYY-MM | YYYY-MM-DD\n static parseDate(value: string): DateTime | null {\n if (this.yearRegex.test(value)) {\n return DateTime.fromFormat(value, 'yyyy', { zone: 'utc' });\n } else if (this.yearMonthRegex.test(value)) {\n return DateTime.fromFormat(value, 'yyyy-MM', { zone: 'utc' });\n } else if (this.fullDateRegex.test(value)) {\n return DateTime.fromISO(value, { zone: 'utc' });\n } else {\n return null;\n }\n }\n\n // Parse FHIR dateTime\n static parseDateTime(value: string): DateTime | null {\n const dt = DateTime.fromISO(value);\n return dt.isValid ? dt : null;\n }\n\n // Parse FHIR instant (must include timezone per spec)\n static parseInstant(value: string): DateTime | null {\n const dt = DateTime.fromISO(value, { setZone: true });\n return dt.isValid && dt.offset !== null ? dt : null;\n }\n\n // Format DateTime to FHIR date\n static formatDate(dt: DateTime, precision: 'year' | 'month' | 'day' = 'day'): string {\n switch (precision) {\n case 'year': return dt.toFormat('yyyy');\n case 'month': return dt.toFormat('yyyy-MM');\n case 'day':\n default: return dt.toFormat('yyyy-MM-dd');\n }\n }\n\n // Format DateTime to FHIR dateTime\n static formatDateTime(dt: DateTime, includeTimeZone = true): string {\n return includeTimeZone\n ? dt.toISO()!\n : dt.toISO({ includeOffset: false, suppressMilliseconds: true })!;\n }\n\n // Format FHIR instant (must include time + timezone)\n static formatInstant(dt: DateTime): string {\n return dt.toUTC().toISO()!; // Always UTC/Z\n }\n\n // Parse FHIR Period\n static parsePeriod(period: { start?: string; end?: string }): { start: DateTime | null; end: DateTime | null } {\n return {\n start: period.start ? this.parseDateTime(period.start) : null,\n end: period.end ? this.parseDateTime(period.end) : null\n };\n }\n\n // Format Period\n static formatPeriod(start?: DateTime, end?: DateTime): { start?: string; end?: string } {\n const out: any = {};\n if (start) {\n out.start = this.formatDateTime(start);\n }\n if (end) {\n out.end = this.formatDateTime(end);\n }\n return out;\n }\n\n // Very basic Timing parser (expands repeat boundsPeriod only)\n static parseTiming(timing: any): { boundsStart?: DateTime; boundsEnd?: DateTime } {\n if (!timing || !timing.repeat || !timing.repeat.boundsPeriod) {\n return {};\n }\n const { start, end } = timing.repeat.boundsPeriod;\n return {\n boundsStart: start ? this.parseDateTime(start)! : undefined,\n boundsEnd: end ? this.parseDateTime(end)! : undefined\n };\n }\n}\n","const t=new Uint8Array([0,97,115,109,1,0,0,0,1,48,8,96,3,127,127,127,1,127,96,3,127,127,127,0,96,2,127,127,0,96,1,127,1,127,96,3,127,127,126,1,126,96,3,126,127,127,1,126,96,2,127,126,0,96,1,127,1,126,3,11,10,0,0,2,1,3,4,5,6,1,7,5,3,1,0,1,7,85,9,3,109,101,109,2,0,5,120,120,104,51,50,0,0,6,105,110,105,116,51,50,0,2,8,117,112,100,97,116,101,51,50,0,3,8,100,105,103,101,115,116,51,50,0,4,5,120,120,104,54,52,0,5,6,105,110,105,116,54,52,0,7,8,117,112,100,97,116,101,54,52,0,8,8,100,105,103,101,115,116,54,52,0,9,10,251,22,10,242,1,1,4,127,32,0,32,1,106,33,3,32,1,65,16,79,4,127,32,3,65,16,107,33,6,32,2,65,168,136,141,161,2,106,33,3,32,2,65,137,235,208,208,7,107,33,4,32,2,65,207,140,162,142,6,106,33,5,3,64,32,3,32,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,4,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,4,32,2,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,5,32,0,65,4,106,34,0,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,6,32,0,65,4,106,34,0,79,13,0,11,32,2,65,12,119,32,5,65,18,119,106,32,4,65,7,119,106,32,3,65,1,119,106,5,32,2,65,177,207,217,178,1,106,11,32,1,106,32,0,32,1,65,15,113,16,1,11,146,1,0,32,1,32,2,106,33,2,3,64,32,1,65,4,106,32,2,75,69,4,64,32,0,32,1,40,2,0,65,189,220,202,149,124,108,106,65,17,119,65,175,214,211,190,2,108,33,0,32,1,65,4,106,33,1,12,1,11,11,3,64,32,1,32,2,79,69,4,64,32,0,32,1,45,0,0,65,177,207,217,178,1,108,106,65,11,119,65,177,243,221,241,121,108,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,65,15,118,115,65,247,148,175,175,120,108,34,0,65,13,118,32,0,115,65,189,220,202,149,124,108,34,0,65,16,118,32,0,115,11,63,0,32,0,65,8,106,32,1,65,168,136,141,161,2,106,54,2,0,32,0,65,12,106,32,1,65,137,235,208,208,7,107,54,2,0,32,0,65,16,106,32,1,54,2,0,32,0,65,20,106,32,1,65,207,140,162,142,6,106,54,2,0,11,195,4,1,6,127,32,1,32,2,106,33,6,32,0,65,24,106,33,4,32,0,65,40,106,40,2,0,33,3,32,0,32,0,40,2,0,32,2,106,54,2,0,32,0,65,4,106,34,5,32,5,40,2,0,32,2,65,16,79,32,0,40,2,0,65,16,79,114,114,54,2,0,32,2,32,3,106,65,16,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,40,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,16,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,40,2,0,32,4,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,12,106,34,3,32,3,40,2,0,32,4,65,4,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,16,106,34,3,32,3,40,2,0,32,4,65,8,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,20,106,34,3,32,3,40,2,0,32,4,65,12,106,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,54,2,0,32,0,65,40,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,32,6,65,16,107,77,4,64,32,6,65,16,107,33,8,32,0,65,8,106,40,2,0,33,2,32,0,65,12,106,40,2,0,33,3,32,0,65,16,106,40,2,0,33,5,32,0,65,20,106,40,2,0,33,7,3,64,32,2,32,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,2,32,3,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,3,32,5,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,5,32,7,32,1,65,4,106,34,1,40,2,0,65,247,148,175,175,120,108,106,65,13,119,65,177,243,221,241,121,108,33,7,32,8,32,1,65,4,106,34,1,79,13,0,11,32,0,65,8,106,32,2,54,2,0,32,0,65,12,106,32,3,54,2,0,32,0,65,16,106,32,5,54,2,0,32,0,65,20,106,32,7,54,2,0,11,32,1,32,6,73,4,64,32,4,32,1,32,6,32,1,107,34,1,252,10,0,0,32,0,65,40,106,32,1,54,2,0,11,11,97,1,1,127,32,0,65,16,106,40,2,0,33,1,32,0,65,4,106,40,2,0,4,127,32,1,65,12,119,32,0,65,20,106,40,2,0,65,18,119,106,32,0,65,12,106,40,2,0,65,7,119,106,32,0,65,8,106,40,2,0,65,1,119,106,5,32,1,65,177,207,217,178,1,106,11,32,0,40,2,0,106,32,0,65,24,106,32,0,65,40,106,40,2,0,16,1,11,255,3,2,3,126,1,127,32,0,32,1,106,33,6,32,1,65,32,79,4,126,32,6,65,32,107,33,6,32,2,66,214,235,130,238,234,253,137,245,224,0,124,33,3,32,2,66,177,169,172,193,173,184,212,166,61,125,33,4,32,2,66,249,234,208,208,231,201,161,228,225,0,124,33,5,3,64,32,3,32,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,3,32,4,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,4,32,2,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,2,32,5,32,0,65,8,106,34,0,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,5,32,6,32,0,65,8,106,34,0,79,13,0,11,32,2,66,12,137,32,5,66,18,137,124,32,4,66,7,137,124,32,3,66,1,137,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,2,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,2,66,197,207,217,178,241,229,186,234,39,124,11,32,1,173,124,32,0,32,1,65,31,113,16,6,11,134,2,0,32,1,32,2,106,33,2,3,64,32,2,32,1,65,8,106,79,4,64,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,32,0,133,66,27,137,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,33,0,32,1,65,8,106,33,1,12,1,11,11,32,1,65,4,106,32,2,77,4,64,32,0,32,1,53,2,0,66,135,149,175,175,152,182,222,155,158,127,126,133,66,23,137,66,207,214,211,190,210,199,171,217,66,126,66,249,243,221,241,153,246,153,171,22,124,33,0,32,1,65,4,106,33,1,11,3,64,32,1,32,2,73,4,64,32,0,32,1,49,0,0,66,197,207,217,178,241,229,186,234,39,126,133,66,11,137,66,135,149,175,175,152,182,222,155,158,127,126,33,0,32,1,65,1,106,33,1,12,1,11,11,32,0,32,0,66,33,136,133,66,207,214,211,190,210,199,171,217,66,126,34,0,32,0,66,29,136,133,66,249,243,221,241,153,246,153,171,22,126,34,0,32,0,66,32,136,133,11,77,0,32,0,65,8,106,32,1,66,214,235,130,238,234,253,137,245,224,0,124,55,3,0,32,0,65,16,106,32,1,66,177,169,172,193,173,184,212,166,61,125,55,3,0,32,0,65,24,106,32,1,55,3,0,32,0,65,32,106,32,1,66,249,234,208,208,231,201,161,228,225,0,124,55,3,0,11,244,4,2,3,127,4,126,32,1,32,2,106,33,5,32,0,65,40,106,33,4,32,0,65,200,0,106,40,2,0,33,3,32,0,32,0,41,3,0,32,2,173,124,55,3,0,32,2,32,3,106,65,32,73,4,64,32,3,32,4,106,32,1,32,2,252,10,0,0,32,0,65,200,0,106,32,2,32,3,106,54,2,0,15,11,32,3,4,64,32,3,32,4,106,32,1,65,32,32,3,107,34,2,252,10,0,0,32,0,65,8,106,34,3,32,3,41,3,0,32,4,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,16,106,34,3,32,3,41,3,0,32,4,65,8,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,24,106,34,3,32,3,41,3,0,32,4,65,16,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,32,106,34,3,32,3,41,3,0,32,4,65,24,106,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,55,3,0,32,0,65,200,0,106,65,0,54,2,0,32,1,32,2,106,33,1,11,32,1,65,32,106,32,5,77,4,64,32,5,65,32,107,33,2,32,0,65,8,106,41,3,0,33,6,32,0,65,16,106,41,3,0,33,7,32,0,65,24,106,41,3,0,33,8,32,0,65,32,106,41,3,0,33,9,3,64,32,6,32,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,6,32,7,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,7,32,8,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,8,32,9,32,1,65,8,106,34,1,41,3,0,66,207,214,211,190,210,199,171,217,66,126,124,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,33,9,32,2,32,1,65,8,106,34,1,79,13,0,11,32,0,65,8,106,32,6,55,3,0,32,0,65,16,106,32,7,55,3,0,32,0,65,24,106,32,8,55,3,0,32,0,65,32,106,32,9,55,3,0,11,32,1,32,5,73,4,64,32,4,32,1,32,5,32,1,107,34,1,252,10,0,0,32,0,65,200,0,106,32,1,54,2,0,11,11,188,2,1,5,126,32,0,65,24,106,41,3,0,33,1,32,0,41,3,0,34,2,66,32,90,4,126,32,0,65,8,106,41,3,0,34,3,66,1,137,32,0,65,16,106,41,3,0,34,4,66,7,137,124,32,1,66,12,137,32,0,65,32,106,41,3,0,34,5,66,18,137,124,124,32,3,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,4,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,1,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,32,5,66,207,214,211,190,210,199,171,217,66,126,66,31,137,66,135,149,175,175,152,182,222,155,158,127,126,133,66,135,149,175,175,152,182,222,155,158,127,126,66,157,163,181,234,131,177,141,138,250,0,125,5,32,1,66,197,207,217,178,241,229,186,234,39,124,11,32,2,124,32,0,65,40,106,32,2,66,31,131,167,16,6,11]);async function e(){return function(t){const{exports:{mem:e,xxh32:n,xxh64:r,init32:i,update32:a,digest32:o,init64:s,update64:u,digest64:c}}=t;let h=new Uint8Array(e.buffer);function g(t,n){if(e.buffer.byteLength<t+n){const r=Math.ceil((t+n-e.buffer.byteLength)/65536);e.grow(r),h=new Uint8Array(e.buffer)}}function f(t,e,n,r,i,a){g(t);const o=new Uint8Array(t);return h.set(o),n(0,e),o.set(h.subarray(0,t)),{update(e){let n;return h.set(o),\"string\"==typeof e?(g(3*e.length,t),n=w.encodeInto(e,h.subarray(t)).written):(g(e.byteLength,t),h.set(e,t),n=e.byteLength),r(0,t,n),o.set(h.subarray(0,t)),this},digest:()=>(h.set(o),a(i(0)))}}function y(t){return t>>>0}const b=2n**64n-1n;function d(t){return t&b}const w=new TextEncoder,l=0,p=0n;function x(t,e=l){return g(3*t.length,0),y(n(0,w.encodeInto(t,h).written,e))}function L(t,e=p){return g(3*t.length,0),d(r(0,w.encodeInto(t,h).written,e))}return{h32:x,h32ToString:(t,e=l)=>x(t,e).toString(16).padStart(8,\"0\"),h32Raw:(t,e=l)=>(g(t.byteLength,0),h.set(t),y(n(0,t.byteLength,e))),create32:(t=l)=>f(48,t,i,a,o,y),h64:L,h64ToString:(t,e=p)=>L(t,e).toString(16).padStart(16,\"0\"),h64Raw:(t,e=p)=>(g(t.byteLength,0),h.set(t),d(r(0,t.byteLength,e))),create64:(t=p)=>f(88,t,s,u,c,d)}}((await WebAssembly.instantiate(t)).instance)}export{e as default};\n//# sourceMappingURL=xxhash-wasm.js.map\n","module.exports = {}","import { error } from 'node:console';\nimport xxhash from 'xxhash-wasm';\n\nexport type TokenParam = {\n system?: string | null;\n code: string;\n};\n\nexport class HashUtils {\n private static instance: HashUtils;\n\n private HASH_SEED = 0xABCDn;\n private h64?: (input: string, seed?: bigint) => bigint;\n\n static getInstance(): HashUtils {\n if (!HashUtils.instance) {\n HashUtils.instance = new HashUtils();\n }\n return HashUtils.instance;\n }\n\n private constructor() {\n\n }\n\n normalizeStringParam = (input: string): string => {\n return input.trim().replace(/\\s+/g, ' ').toLowerCase();\n }\n\n InitHash = async (): Promise<void> => {\n const api = await xxhash();\n this.h64 = api.h64;\n }\n\n xxhash64Signed(input: string): bigint {\n if (this.h64) {\n return BigInt.asIntN(64, this.h64(input, this.HASH_SEED));\n }\n throw error(`h64 not initialized`);\n }\n\n hashStringParam(input: string, normalize: boolean): bigint {\n if (normalize === true) {\n const normalized = this.normalizeStringParam(input);\n return this.xxhash64Signed(normalized);\n } else {\n return this.xxhash64Signed(input);\n }\n }\n\n hashTokenParam({ system, code }: TokenParam): bigint {\n const combined = (system ?? '') + '|' + code;\n return this.xxhash64Signed(combined);\n }\n\n hashReferenceParam(reference: string): bigint {\n return this.xxhash64Signed(reference);\n }\n\n hashUriParam(uri: string, lowercase = false): bigint {\n return this.xxhash64Signed(lowercase ? uri.toLowerCase() : uri);\n }\n\n}","//import { x64 } from 'murmurhash3js';\nimport xxhash from 'xxhash-wasm';\n\nimport { HashUtils } from './hashUtils.js'\n\nHashUtils.getInstance().InitHash();\n\nconst HASH_SEED = 0xABCDn;\n\nexport type TokenParam = {\n system?: string | null;\n code: string;\n};\n\n//\n// NORMALIZATION HELPERS\n//\n\n/**\n * Normalize string values similar to HAPI FHIR (trim, collapse whitespace, lowercase)\n */\nexport function normalizeStringParam(input: string): string {\n return input.trim().replace(/\\s+/g, ' ').toLowerCase();\n}\n\n//\n// HASHING HELPERS\n//\n\nlet h64: (input: string, seed?: bigint) => bigint;\n\nexport async function initHash(): Promise<void> {\n const api = await xxhash();\n h64 = api.h64;\n}\n\nexport function xxhash64Signed(input: string): bigint {\n return BigInt.asIntN(64, h64(input, HASH_SEED));\n}\n\n\n/*\nexport function xxhash64Signed(input: string): bigint {\n const hashHex = xxhash.h64(input, 0xABCD).toString(16).padStart(16, '0');\n const buf = Buffer.from(hashHex, 'hex');\n return buf.readBigInt64BE(0);\n}\n*/\n\n/**\n * Converts first 64 bits of MurmurHash3_x64_128 result into signed BigInt\n */\n\n/*\nexport function murmur64Signed(input: string): bigint {\n //const hex128 = x64.hash128(input);\n const hex128 = xxhash.h64(input, 0xABCD).toString(16);\n const buf = Buffer.from(hex128.slice(0, 16), 'hex');\n return buf.readBigInt64LE(0);\n}\n*/\n\n/**\n * Compute hash for a normalized string search parameter\n */\nexport function hashStringParam(input: string, normalize: boolean): bigint {\n\n return HashUtils.getInstance().hashStringParam(input, normalize);\n\n if (normalize === true) {\n const normalized = normalizeStringParam(input);\n return xxhash64Signed(normalized);\n } else {\n return xxhash64Signed(input);\n }\n}\n\n/**\n * Compute hash for a token search parameter (system|code)\n */\nexport function hashTokenParam({ system, code }: TokenParam): bigint {\n const combined = (system ?? '') + '|' + code;\n return xxhash64Signed(combined);\n}\n\n/**\n * Compute hash for a reference search parameter\n * Case-sensitive and used as-is\n */\nexport function hashReferenceParam(reference: string): bigint {\n return xxhash64Signed(reference);\n}\n\n/**\n * Compute hash for a URI parameter (optionally lowercased)\n */\nexport function hashUriParam(uri: string, lowercase = false): bigint {\n return xxhash64Signed(lowercase ? uri.toLowerCase() : uri);\n}\n","import { createClient, RedisClientType } from 'redis';\nimport { randomUUID } from 'crypto';\n\nexport type AppRedisClient = ReturnType<typeof createClient>;\n\nconst RELEASE_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"del\", KEYS[1])\nelse\n return 0\nend\n`;\n\nconst RENEW_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"pexpire\", KEYS[1], ARGV[2])\nelse\n return 0\nend\n`;\n\nexport interface RedisDistributedLockOptions {\n ttlMs?: number;\n heartbeatMs?: number;\n keyPrefix?: string;\n}\n\nexport interface LockHandle {\n key: string;\n token: string;\n ttlMs: number;\n}\n\nexport class RedisDistributedLock {\n private readonly client: AppRedisClient;\n private readonly ttlMs: number;\n private readonly heartbeatMs: number;\n private readonly keyPrefix: string;\n\n public constructor(\n client: AppRedisClient,\n options?: RedisDistributedLockOptions\n ) {\n this.client = client;\n this.ttlMs = options?.ttlMs ?? 30000;\n this.heartbeatMs = options?.heartbeatMs ?? Math.floor(this.ttlMs / 3);\n this.keyPrefix = options?.keyPrefix ?? 'lock:';\n\n if (this.ttlMs <= 0) {\n throw new Error('ttlMs must be > 0');\n }\n\n if (this.heartbeatMs <= 0) {\n throw new Error('heartbeatMs must be > 0');\n }\n\n if (this.heartbeatMs >= this.ttlMs) {\n throw new Error('heartbeatMs should be less than ttlMs');\n }\n }\n\n private buildKey(name: string): string {\n return `${this.keyPrefix}${name}`;\n }\n\n public async acquire(\n name: string,\n ttlMs?: number\n ): Promise<LockHandle | null> {\n const key = this.buildKey(name);\n const token = randomUUID();\n const effectiveTtlMs = ttlMs ?? this.ttlMs;\n\n const result = await this.client.set(key, token, {\n NX: true,\n PX: effectiveTtlMs\n });\n\n if (result !== 'OK') {\n return null;\n }\n\n return {\n key,\n token,\n ttlMs: effectiveTtlMs\n };\n }\n\n public async release(lock: LockHandle): Promise<boolean> {\n const result = await this.client.eval(RELEASE_SCRIPT, {\n keys: [lock.key],\n arguments: [lock.token]\n });\n\n return Number(result) === 1;\n }\n\n public async renew(lock: LockHandle, ttlMs?: number): Promise<boolean> {\n const effectiveTtlMs = ttlMs ?? lock.ttlMs;\n\n const result = await this.client.eval(RENEW_SCRIPT, {\n keys: [lock.key],\n arguments: [lock.token, String(effectiveTtlMs)]\n });\n\n return Number(result) === 1;\n }\n\n public async isOwner(lock: LockHandle): Promise<boolean> {\n const currentValue = await this.client.get(lock.key);\n return currentValue === lock.token;\n }\n\n public async runExclusive<T>(\n name: string,\n task: () => Promise<T>,\n options?: {\n ttlMs?: number;\n autoRenew?: boolean;\n heartbeatMs?: number;\n onLockNotAcquired?: () => void | Promise<void>;\n }\n ): Promise<{ acquired: true; result: T } | { acquired: false }> {\n const lock = await this.acquire(name, options?.ttlMs);\n\n if (!lock) {\n if (options?.onLockNotAcquired) {\n await options.onLockNotAcquired();\n }\n return { acquired: false };\n }\n\n let timer: NodeJS.Timeout | null = null;\n let stopped = false;\n let renewalError: Error | null = null;\n\n const autoRenew = options?.autoRenew ?? false;\n const heartbeatMs = options?.heartbeatMs ?? this.heartbeatMs;\n\n const stopHeartbeat = (): void => {\n stopped = true;\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n\n if (autoRenew) {\n timer = setInterval(async () => {\n if (stopped) {\n return\n }\n\n try {\n const ok = await this.renew(lock, lock.ttlMs);\n if (!ok) {\n renewalError = new Error(\n `Lost lock ownership while renewing \"${lock.key}\"`\n );\n stopHeartbeat();\n }\n } catch (err) {\n renewalError =\n err instanceof Error ? err : new Error(String(err));\n stopHeartbeat();\n }\n }, heartbeatMs).unref();\n }\n\n try {\n const result = await task();\n\n if (renewalError) {\n throw renewalError;\n }\n\n return { acquired: true, result };\n } finally {\n stopHeartbeat();\n\n try {\n await this.release(lock);\n } catch {\n // Intentionally swallow release errors here.\n // If needed, log them through your own logger.\n }\n }\n }\n}","import { RedisDistributedLock, AppRedisClient } from './redisDistributedLock.js'\nimport { Sleep } from '@nsshunt/stsutils';\nimport { goptions } from '@nsshunt/stsconfig';\nimport { createClient } from 'redis';\n\nimport fs from 'node:fs';\n\nimport { SearchParameter } from '@nsshunt/stsfhirclient'\nimport { IResources } from './fhir-utils/resourceHelper.js'\n\nimport { ISearchParam} from './fhir-utils/commonTypes.js'\n\nconst specPath1: string = './dist/';\nconst specPath2: string = './node_modules/@nsshunt/stsfhirpg/dist/';\n\nconst resourcesPath = 'fhir-spec/profiles-resources.json';\nconst typesPath = 'fhir-spec/profiles-types.json';\nconst searchParamsPath = 'fhir-spec/search-parameters.json';\n\nexport interface ISearchParameterManagerOptions {\n name: string\n pollIntervalMs?: number;\n lockTtlMs?: number;\n autoRenew?: boolean;\n heartbeatMs?: number;\n completeTtlSeconds?: number;\n timeoutMs?: number;\n}\n\nexport class SearchParameterManager {\n private redis?: AppRedisClient;\n private alreadyComplete: string | null = null;\n private options: ISearchParameterManagerOptions;\n private cache: Record<string, any> = { };\n\n constructor(options: ISearchParameterManagerOptions) {\n this.options = options;\n }\n\n EnsureSearchParameterDataLoaded = async (resources: IResources): Promise<string> => {\n if (this.alreadyComplete) {\n return this.alreadyComplete;\n }\n if (!this.redis) {\n const redisUrl = goptions.imRedisMessageProcessorUrl;\n console.log(`SearchParameterManager(): redis trying to connect ...`);\n this.redis = createClient({\n url: redisUrl\n });\n await this.redis.connect();\n console.log(`SearchParameterManager(): redis connected`);\n }\n\n try {\n const pollIntervalMs = this.options?.pollIntervalMs ?? 250;\n const lockTtlMs = this.options?.lockTtlMs ?? 30000;\n const autoRenew = this.options?.autoRenew ?? true;\n const heartbeatMs = this.options?.heartbeatMs ?? 10000;\n const completeTtlSeconds = this.options?.completeTtlSeconds;\n const timeoutMs = this.options?.timeoutMs;\n\n const completeKey = `fhir:searchparam:${this.options.name}:complete`;\n const startedAt = Date.now();\n\n const lockManager = new RedisDistributedLock(this.redis, {\n ttlMs: 30000,\n heartbeatMs: 10000,\n keyPrefix: 'lock:'\n });\n\n while (true) {\n if (typeof timeoutMs === 'number' && timeoutMs > 0) {\n const elapsedMs = Date.now() - startedAt;\n if (elapsedMs >= timeoutMs) {\n throw new Error(\n `Timed out waiting for search param \"${this.options.name}\" to be loaded`\n );\n }\n }\n\n try {\n this.alreadyComplete = await this.redis.get(completeKey);\n if (this.alreadyComplete) {\n console.log(`ensureSearchParamLoaded():alreadyComplete: PID: [${process.pid}] data loaded: [${this.alreadyComplete}]`);\n return this.alreadyComplete;\n }\n } catch (error) {\n console.error(error);\n throw error;\n }\n\n const runResult = await lockManager.runExclusive(\n `fhir:searchparam:${this.options.name}`,\n async () => {\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] lock acquired`);\n this.alreadyComplete = await this.redis!.get(completeKey);\n if (this.alreadyComplete) {\n console.log(`ensureSearchParamLoaded():completeAfterLock: PID: [${process.pid}] data loaded: [${this.alreadyComplete}]`);\n return;\n }\n\n try {\n await this.#LoadDefinitions(resources);\n } catch (error) {\n console.error(error);\n throw error;\n }\n\n const completeValue = JSON.stringify({\n loaded: true,\n loadedAt: new Date().toLocaleString(),\n name: this.options.name,\n workerPid: process.pid\n });\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] data loaded: [${completeValue}]`);\n\n if (typeof completeTtlSeconds === 'number' && completeTtlSeconds > 0) {\n await this.redis!.set(completeKey, completeValue, {\n EX: completeTtlSeconds\n });\n } else {\n await this.redis!.set(completeKey, completeValue);\n }\n this.alreadyComplete = completeValue;\n },\n {\n ttlMs: lockTtlMs,\n autoRenew,\n heartbeatMs\n }\n );\n\n if (runResult.acquired) {\n if (this.alreadyComplete) {\n return this.alreadyComplete;\n } else {\n throw new Error(`EnsureSearchParameterDataLoaded(): runResult.acquired is true but this.alreadyComplete not set`);\n }\n }\n console.log(`ensureSearchParamLoaded(): PID: [${process.pid}] Did not get lock`);\n\n await Sleep(pollIntervalMs);\n }\n } catch (error) {\n console.error(`SearchParameterManager:EnsureSearchParameterDataLoaded(): Error: [${error}]`);\n throw error;\n }\n }\n\n Stop = async () => {\n if (this.redis) {\n await this.redis.close();\n console.log(`SearchParameterManager(): redis closed`);\n }\n }\n\n #searchParametersByResourceTypeKey = `__stsfhir__searchParametersByResourceType`;\n #searchParametersByUrlKey = `__stsfhir__searchParametersByUrl`;\n #resourcesKey = `__stsfhir__resources`;\n #typesKey = `__stsfhir__types`;\n\n #LoadDefinitions = async (resources: IResources) => {\n console.log('Data Load Starting ...');\n\n for (const [key, value] of Object.entries(resources.searchParametersByResourceType)) {\n await this.redis!.hSet(this.#searchParametersByResourceTypeKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.searchParametersByUrl)) {\n await this.redis!.hSet(this.#searchParametersByUrlKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.resources)) {\n await this.redis!.hSet(this.#resourcesKey, key, JSON.stringify(value));\n }\n\n for (const [key, value] of Object.entries(resources.types)) {\n await this.redis!.hSet(this.#typesKey, key, JSON.stringify(value));\n }\n\n console.log('All Done ***********************************************************************************');\n }\n\n GetSearchParamFromResourceType = async (resourceType: string): Promise<ISearchParam> => {\n const key = `${this.#searchParametersByResourceTypeKey}_${resourceType}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#searchParametersByResourceTypeKey, resourceType);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetType = async (typeName: string): Promise<any[]> => {\n const key = `${this.#typesKey}_${typeName}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#typesKey, typeName);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetResource = async (resourceType: string): Promise<any[]> => {\n const key = `${this.#resourcesKey}_${resourceType}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#resourcesKey, resourceType);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n\n GetSearchParam = async (url: string): Promise<SearchParameter> => {\n const key = `${this.#searchParametersByUrlKey}_${url}`;\n if (this.cache[key]) {\n return this.cache[key];\n }\n const retVal = await this.redis!.hGet(this.#searchParametersByUrlKey, url);\n this.cache[key] = JSON.parse(retVal!);\n return this.cache[key];\n }\n}\n","import fs from 'node:fs';\n\nimport { SearchParameter } from '@nsshunt/stsfhirclient'\n\nimport { ISearchParamRecord, ISearchParams, ISearchParamExpressionRecord,\n ISearchFieldRecord, ISearchParam } from './commonTypes.js'\n\n//import __resources from './../fhir-spec/profiles-resources.json'\n//import __types from './../fhir-spec/profiles-types.json'\n//import __searchParams from './../fhir-spec/search-parameters.json'\n\nimport { SearchParameterManager } from './../searchParameterManager.js'\n\nconst specPath1: string = './dist/';\nconst specPath2: string = './node_modules/@nsshunt/stsfhirpg/dist/';\n\nconst resourcesPath = 'fhir-spec/profiles-resources.json';\nconst typesPath = 'fhir-spec/profiles-types.json';\nconst searchParamsPath = 'fhir-spec/search-parameters.json';\n\n// './node_modules/@nsshunt/stsdatamanagement/dist'\n\nexport interface IResources {\n resources: Record<string, any>\n types: Record<string, any>\n searchParametersByUrl: Record<string, SearchParameter>\n searchParametersByResourceType: Record<string, ISearchParam>\n}\n\nexport class ResourceHelper {\n #definitions: IResources | undefined;\n #loaded: boolean = false;\n private searchParameterManager?: SearchParameterManager;\n\n private static instance: ResourceHelper;\n\n private constructor() {}\n\n static getInstance(): ResourceHelper {\n if (!ResourceHelper.instance) {\n ResourceHelper.instance = new ResourceHelper();\n }\n return ResourceHelper.instance;\n }\n\n Stop = async () => {\n if (this.searchParameterManager) {\n await this.searchParameterManager.Stop();\n }\n this.searchParameterManager = undefined;\n }\n\n #LoadDefinitions = async (): Promise<void> => {\n let usePath = '';\n if (fs.existsSync(`${specPath1}${resourcesPath}`)) {\n usePath = specPath1;\n } else {\n usePath = specPath2;\n }\n const __resources: any = JSON.parse(fs.readFileSync(`${usePath}${resourcesPath}`, 'utf-8'));\n const __types: any = JSON.parse(fs.readFileSync(`${usePath}${typesPath}`, 'utf-8'));\n const __searchParams: any = JSON.parse(fs.readFileSync(`${usePath}${searchParamsPath}`, 'utf-8'));\n\n if (!this.#definitions) {\n this.#definitions = {\n resources: { },\n types: { },\n searchParametersByUrl: { },\n searchParametersByResourceType: { }\n }\n }\n\n (__resources.entry as any[]).forEach(entry => {\n const resource: any = entry.resource;\n if (resource?.snapshot?.element) {\n const rt = resource.type as string;\n this.#definitions!.resources[rt] = resource.snapshot.element;\n }\n });\n \n (__types.entry as any[]).forEach(entry => {\n const type = entry.resource;\n if (type?.snapshot?.element) {\n this.#definitions!.types[type.type] = type.snapshot.element;\n }\n });\n\n (__searchParams.entry as any[]).forEach(entry => {\n this.#definitions!.searchParametersByUrl[entry.fullUrl] = entry.resource;\n });\n\n await this._LoadSearchParameters();\n\n await this.PreLoadSearchParameterData();\n\n this.#loaded = true;\n this.#definitions = undefined;\n }\n\n PreLoadSearchParameterData = async () => {\n console.log(`PreLoadSearchParameterData(): Start ...`);\n this.searchParameterManager = new SearchParameterManager({\n name: 'stsfhirspdata',\n pollIntervalMs: 250,\n lockTtlMs: 30000,\n autoRenew: true,\n heartbeatMs: 10000\n });\n await this.searchParameterManager.EnsureSearchParameterDataLoaded(this.#definitions!);\n console.log(`PreLoadSearchParameterData(): End`);\n } \n\n private GetDefinitions = async (): Promise<void> => {\n if (!this.#loaded) {\n if (!this.#definitions) {\n await this.#LoadDefinitions();\n }\n }\n }\n\n private _GetResource = async (resourceType: string): Promise<any[]> => {\n await this.GetDefinitions();\n return this.#definitions!.resources[resourceType];\n }\n\n private _GetResourceField = async (resourceType: string, fieldPath: string): Promise<any> => {\n const resource: any[] = await this._GetResource(resourceType);\n if (resource) {\n const foundRecord = resource.filter(o => o.id === fieldPath);\n if (foundRecord.length > 0) {\n return foundRecord[0];\n }\n return undefined;\n }\n }\n\n private _GetSearchParam = async (url: string): Promise<any> => {\n await this.GetDefinitions();\n return this.#definitions!.searchParametersByUrl[url];\n }\n\n private _GetSearchParams = async (): Promise<any> => {\n await this.GetDefinitions();\n return this.#definitions!.searchParametersByUrl;\n }\n\n GetType = async (typeName: string): Promise<any[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetType(typeName);\n //return this.#definitions!.types[typeName];\n }\n\n GetResource = async (resourceType: string): Promise<any[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetResource(resourceType);\n }\n\n GetResourceField = async (resourceType: string, fieldPath: string): Promise<any> => {\n const resource: any[] = await this.GetResource(resourceType);\n if (resource) {\n const foundRecord = resource.filter(o => o.id === fieldPath);\n if (foundRecord.length > 0) {\n return foundRecord[0];\n }\n return undefined;\n }\n\n }\n\n GetSearchParam = async (url: string): Promise<any> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetSearchParam(url);\n }\n\n /*\n private GetSearchParams = async (): Promise<SearchParameter[]> => {\n await this.GetDefinitions();\n return await this.searchParameterManager!.GetSearchParams();\n }\n\n GetSearchParamsByResource = async (resource: string): Promise<SearchParameter[]> => {\n await this.GetDefinitions();\n const searchParams = await this.GetSearchParams();\n return searchParams\n .filter(sp => sp.base.includes(resource))\n .map(sp => sp)\n //return Object.values(this.#definitions!.searchParametersByUrl)\n //.filter(sp => sp.base.includes(resource))\n //.map(sp => sp)\n }\n */\n\n // ------------------------------------------------------------------------------------------------------------------\n\n // Remove ( ) when either are present\n #RemoveOuterParentheses = (input: string): string => {\n return input.replace(/^\\(|\\)$/g, '');\n }\n\n // Remove ( ) only when both are present\n #RemoveSurroundingParentheses = (input: string): string => {\n return input.replace(/^\\((.*)\\)$/, '$1').trim();\n }\n\n /*\n \nNamingSystem derived-from reference NamingSystem.relatedArtifact.where(type='derived-from').resource\n \nNamingSystem predecessor reference NamingSystem.relatedArtifact.where(type='predecessor').resource\n\nClinicalUseDefinition product reference ClinicalUseDefinition.subject.where(resolve() is MedicinalProductDefinition)\n\nOrganizationAffiliation email token OrganizationAffiliation.contact.telecom.where(system='email')\nOrganizationAffiliation phone token OrganizationAffiliation.contact.telecom.where(system='phone')\n\nPackagedProductDefinition biological reference PackagedProductDefinition.packaging.containedItem.item.reference\nPackagedProductDefinition contained-item reference PackagedProductDefinition.packaging.containedItem.item.reference\n\nPatient deceased token Patient.deceased.exists() and Patient.deceased != false\nPractitioner deceased token Practitioner.deceased.exists() and Practitioner.deceased != false\n\nLocation contains special Location.extension('http://hl7.org/fhir/StructureDefinition/location-boundary-geojson').value\n\nQuestionnaireResponse item-subject reference QuestionnaireResponse.item.where(extension('http://hl7.org/fhir/StructureDefinition/questionnaireresponse-isSubject').exists()).answer.valueReference\n */\n\n ProcessExpressions = (resourceName: string, SP_EXPRESSION: string): any => {\n let expressions: any[] = [];\n\n //SP_EXPRESSION = this.#RemoveSurroundingParentheses(val2.expression);\n expressions = SP_EXPRESSION.split('|').map(e => e.trim());\n\n expressions = expressions.map(e => this.#RemoveSurroundingParentheses(e).trim());\n\n if (resourceName !== '') {\n expressions = expressions.filter(e => e.split('.')[0].trim().localeCompare(resourceName) === 0);\n }\n\n let original_expressions = [ ...expressions ];\n\n // ofType processing\n expressions = expressions.map((e: string) => {\n let capturedTypeOf = undefined;\n return {\n path: e.replace(\n /\\.ofType\\(([^)]+)\\)/g,\n (_: string, typeName: string) => {\n capturedTypeOf = true;\n return typeName.charAt(0).toUpperCase() + typeName.slice(1)\n }),\n typeOf: capturedTypeOf\n }\n });\n\n //@@ exists processing here is more or less hard coded to the deceased attribute.\n //@@ in future, we need an actual fhir language parser.\n expressions.forEach(expression => {\n try {\n const sp = expression as ISearchParamExpressionRecord;\n if (sp.path.indexOf('exists()') >= 0) {\n // Person.deceased.exists() and Person.deceased != false\n const parts = sp.path.split(' ');\n const i = parts[0].indexOf('exists()');\n if (i >= 0) {\n let fieldExistsEx = parts[0].substring(0, i-1);\n let op = parts[1];\n let fieldTestEx = parts[2];\n let comparator = parts[3];\n let value = parts[4];\n\n const fieldExistsParts = fieldExistsEx.split('.');\n let fieldExists = fieldExistsParts.slice(1).join('.');\n\n const fieldTestParts = fieldTestEx.split('.');\n let fieldTest = fieldTestParts.slice(1).join('.');\n\n sp.exists = {\n fieldExists: [ `${fieldExists}Boolean`, `${fieldExists}DataTime` ], // [x]Boolean or [x]DateTime\n op,\n fieldTest: [ `${fieldTest}Boolean`, `${fieldTest}DataTime` ],\n comparator,\n value: [ value, undefined ]\n }\n }\n }\n } catch (error) {\n\n }\n });\n\n // where(resolve()) processing\n let capturedType: string | undefined;\n expressions = expressions.map((obj: any) => {\n capturedType = undefined;\n const { path, typeOf, exists } = obj;\n return {\n path: path.replace(\n /\\.where\\(resolve\\(\\)\\s+is\\s+([^)]+)\\)/,\n (_: string, typeName: string) => {\n capturedType = typeName;\n //return ` // reference = ${capturedType}`; // remove the .where(...) part (you can put ` // ${capturedType}` if you want to keep a comment)\n return '';\n }),\n typeOf,\n reference: capturedType,\n exists\n }\n });\n\n // .where processing\n // The element before the .where will be an array. So this test checks which element(s) from that array are satisifed.\n let capturedWhere: any = undefined;\n expressions = expressions.map((obj: any) => {\n capturedWhere = undefined;\n const { path, reference, typeOf, exists } = obj;\n const retVal: any = {\n path: path.replace(/([^.]+)\\.where\\(([^=]+)='([^']+)'\\)/g, (_: string, field: string, subfield: string, value: string) => {\n capturedWhere = { field, subfield, value } \n return field;\n }),\n typeOf,\n reference,\n exists\n }\n if (capturedWhere) {\n capturedWhere.full = `${capturedWhere.field}[*].${capturedWhere.subfield}=${capturedWhere.value}`;\n retVal.where = capturedWhere;\n }\n return retVal;\n });\n\n\n return {\n expressions,\n original_expressions\n };\n }\n\n private _LoadSearchParameters = async (): Promise<void> => {\n for (const [key, val] of Object.entries(await this._GetSearchParams()) as any) {\n const { id, url, code, base, type, expression, component, target } = val;\n\n for (let i=0; i < base.length; i++) {\n const resourceName = base[i];\n\n if (!this.#definitions?.searchParametersByResourceType[resourceName]) {\n this.#definitions!.searchParametersByResourceType[resourceName] = {\n resourceName,\n params: [ ]\n }\n }\n\n const SP_ID = id;\n const SP_NAME = code; // code is the true SP name (but in the spec, name is usually the same as code)\n const SP_TYPE = type;\n const SP_URL = url;\n const SP_TARGET = target;\n let SP_EXPRESSION: string = expression;\n let expressions: any[] = [];\n let original_expressions: any[] = [];\n if (SP_EXPRESSION) {\n const retVal = this.ProcessExpressions(resourceName, SP_EXPRESSION);\n expressions = retVal.expressions;\n original_expressions = retVal.original_expressions;\n }\n\n const record: ISearchParamRecord = {\n SP_ID,\n SP_NAME,\n SP_TYPE,\n SP_URL,\n SP_TARGET,\n expressions,\n original_expressions,\n SP_DEFINITION: await this._GetSearchParam(SP_URL)\n };\n\n for (let i=0; i < record.expressions.length; i++) {\n //console.log(record.expressions[i]);\n const rf = await this._GetResourceField(resourceName, record.expressions[i].path);\n if (rf) {\n expressions[i].RES_FIELD = rf;\n }\n }\n\n if (component) {\n record.component = [ ...component ];\n for (const c of record.component) {\n //c.SP_RAW_PATHS = (c.expression.split('|') as any[]).map(rp => rp.trim());\n //c.SP_PATHS = (c.SP_RAW_PATHS as any[]).map(rawPath => this.ResolveFhirChoiceType(rawPath));\n const retVal = this.ProcessExpressions('', (c as any).expression);\n c.expressions = retVal.expressions;\n c.original_expressions = retVal.original_expressions;\n const def = await this._GetSearchParam(c.definition);\n if (def && def.type) {\n (c as any).type = def.type\n }\n }\n }\n\n this.#definitions!.searchParametersByResourceType[resourceName].params.push(record);\n }\n }\n }\n\n GetSearchParamFromResourceTypeUrl = async (resourceType: string, url: string): Promise<ISearchParamRecord | undefined> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n const filterByNameAndUrl = rt!.params.filter(rt => rt.SP_URL.localeCompare(url) === 0);\n //const filterByNameAndUrl = this.#definitions!.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_URL.localeCompare(url) === 0);\n if (filterByNameAndUrl.length > 0) {\n return filterByNameAndUrl[0];\n }\n }\n\n GetSearchParamFromResourceType = async (resourceType: string, name: string): Promise<ISearchParamRecord | undefined> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n const filterByName = rt!.params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);\n //const filterByName = this.#definitions!.searchParametersByResourceType[resourceType].params.filter(rt => rt.SP_NAME.localeCompare(name) === 0);\n if (filterByName.length > 0) {\n return filterByName[0];\n }\n }\n\n GetSearchParamsFromResourceType = async (resourceType: string): Promise<ISearchParamRecord[]> => {\n await this.GetDefinitions();\n const rt = await this.searchParameterManager?.GetSearchParamFromResourceType(resourceType);\n return rt!.params;\n //return this.#definitions!.searchParametersByResourceType[resourceType].params;\n }\n}","import { randomUUID } from 'node:crypto';\nimport jmespath from 'jmespath';\nimport { defaultLogger } from '@nsshunt/stsutils';\n\nimport { ISearchParamRecord, ISearchParamExpressionRecord, IBaseIndexRecordEx } from '../fhir-utils/commonTypes.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\nimport { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\n\nexport abstract class DBSearchIndexBase {\n\n #ops: Record<string, (a: any, b: any) => boolean> = {\n \"==\": (a, b) => a == b,\n \"===\": (a, b) => a === b,\n \"!=\": (a, b) => a != b,\n \"!==\": (a, b) => a !== b,\n \">\": (a, b) => a > b,\n \">=\": (a, b) => a >= b,\n \"<\": (a, b) => a < b,\n \"<=\": (a, b) => a <= b\n }; \n\n FHIR_ROOT = 'http://stsfhir.io/r5';\n\n IsUndefined = (val: any): boolean => {\n if (val === undefined || val === null) {\n return true;\n } else {\n if (Array.isArray(val)) {\n return val.length === 0;\n } else {\n return false;\n }\n }\n }\n\n IsDefined = (val: any): boolean => {\n if (val !== undefined && val !== null) {\n if (Array.isArray(val)) {\n return val.length > 0;\n } else {\n return true;\n }\n } else {\n return false;\n }\n }\n\n GetNewBaseIndexRecord = (tir: IBaseIndexRecordEx): IBaseIndexRecordEx => {\n const copy: IBaseIndexRecordEx = {\n ...tir\n }\n copy.PID = randomUUID();\n return copy;\n }\n\n #GetValueFromResourceAtPath = (resource: Resource, path: string): any => {\n let retVal = jmespath.search(resource, path); \n if (retVal === null) {\n // Now try an array search\n if (path.split('.').length > 0) {\n const parts = path.split('.');\n const test = parts.map(p => `${p}[]`).join('.');\n retVal = jmespath.search(resource, test); \n }\n }\n if (retVal === null) {\n retVal = undefined;\n }\n return retVal;\n }\n\n ComputeCompositeHash = (path: string, index: number, tir: IBaseIndexRecordEx) => {\n const parts = path.split('.');\n let parent = '';\n if (parts.length > 1) {\n parent = parts[parts.length-2];\n }\n const pt = `${tir.RES_ID}|${tir.RES_TYPE}|${parent}_${index}`;\n tir.PATH_FOR_COMP = path;\n tir.COMPOSITE = pt;\n tir.COMPOSITE_HASH_EXACT = hashStringParam(`${pt}`, false);\n }\n\n //@@ This method requires re-word to correctly handle the FhirPath grammar. At the momenet, most cases are \n // looking for specific formats (like for example exists()).\n GetValueFromPath = (resource: Resource, path: string, searchParamRecord: ISearchParamRecord, searchParamExpressionRecord: ISearchParamExpressionRecord): any => {\n let retVal: any = undefined;\n try {\n // Check if the path is the root level of the resource\n if (resource && resource.resourceType && resource.resourceType === path) {\n return resource;\n }\n\n // Strip the resource type from the path\n if (path && path.split('.')[0].localeCompare(resource.resourceType) === 0) {\n path = path.split('.').slice(1).join('.');\n }\n\n if (!path) {\n return retVal;\n }\n\n if (searchParamExpressionRecord.exists) {\n const { fieldExists, op, fieldTest, comparator, value } = searchParamExpressionRecord.exists;\n for (let i=0; i < fieldExists.length; i++) {\n retVal = jmespath.search(resource, fieldExists[i]); \n // assume op is always and\n if (retVal) {\n if (value[i]) {\n retVal = jmespath.search(resource, fieldTest[i]); \n if (retVal) {\n retVal = this.#ops[comparator](retVal, value[i]);\n break;\n }\n } else {\n retVal = true; // If no value specified, we only need the exists rule to be true\n break;\n }\n }\n }\n } else if (searchParamExpressionRecord.typeOf) {\n //@@ The check should validate that only 1 value in the valueOf group for this attribute is used\n retVal = this.#GetValueFromResourceAtPath(resource, path);\n } else if (searchParamExpressionRecord.reference) {\n // Try the path \"as-is\"\n let searchField = this.#GetValueFromResourceAtPath(resource, path);\n if (searchField && Array.isArray(searchField)) {\n //console.log(searchField);\n const list = searchField.filter(sf => {\n if (sf.reference) {\n return (sf.reference as string).startsWith(`${searchParamExpressionRecord.reference}/`);\n } else if (sf.identifier) {\n //@@ could look this up ...\n return false;\n } else {\n return false;\n }\n });\n if (list.length > 0) {\n // Only get the first entry\n retVal = list[0];\n }\n } else {\n retVal = searchField;\n }\n } else if (searchParamExpressionRecord.where) {\n const { field, subfield, value } = searchParamExpressionRecord.where;\n\n const searchField = jmespath.search(resource, field); \n if (searchField && Array.isArray(searchField)) {\n const foundFields = searchField.filter(sf => sf[subfield] && sf[subfield].localeCompare(value) === 0);\n if (foundFields.length > 0) {\n // Only get the first entry\n retVal = foundFields[0];\n }\n }\n } else {\n retVal = this.#GetValueFromResourceAtPath(resource, path);\n }\n\n if (retVal === null) {\n retVal = undefined;\n }\n } catch (error) {\n defaultLogger.error(`\nDBSearchIndexBase:GetValueFromPath(): Error: [${error}]\n${JSON.stringify(searchParamRecord, null, 2)}\n${JSON.stringify(searchParamExpressionRecord, null, 2)}\n${JSON.stringify(resource, null, 2)}`);\n retVal = undefined;\n }\n return retVal;\n }\n\n abstract OutputIndexRecordFromFhirElement(path: string, inputNumberVal: any, tir: IBaseIndexRecordEx, \n searchParamExpressionRecord?: ISearchParamExpressionRecord, resource?: Resource): Promise<IBaseIndexRecordEx[]>;\n\n abstract OutputIndexRecord(resource: Resource, tir: IBaseIndexRecordEx, \n searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[]>;\n\n abstract OutputIndexRecordToConsole(tir: IBaseIndexRecordEx[]): string;\n}\n","import { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport validUrl from 'valid-url';\n\nimport { ISearchParamRecord, IBaseIndexRecordEx, ITokenIndexRecord } from './../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\n/*\nimport { Identifier } from '../fhir-ts';\nimport { Coding } from '../fhir-ts';\nimport { CodeableConcept } from '../fhir-ts';\nimport { ContactPoint } from '../fhir-ts';\n\n\nexport function isIdentifier(obj: any): obj is Identifier {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"value\" in obj;\n}\n\nexport function isCoding(obj: any): obj is Coding {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"code\" in obj;\n}\n\nexport function isCodeableConcept(obj: any): obj is CodeableConcept {\n return obj && typeof obj === \"object\" && Array.isArray(obj.coding);\n}\n\nexport function isContactPoint(obj: any): obj is ContactPoint {\n return obj && typeof obj === \"object\" && \"system\" in obj && \"value\" in obj && !(\"code\" in obj);\n}\n\nexport function isPrimitiveToken(obj: any): obj is string | boolean {\n return typeof obj === \"string\" || typeof obj === \"boolean\";\n}\n\nexport type FhirToken =\n | Identifier\n | Coding\n | CodeableConcept\n | ContactPoint\n | string // primitive code/uri/canonical\n | boolean; // primitive boolean\n\nexport interface SearchParamMeta {\n name: string;\n type: string; // \"token\"\n expression?: string; // FHIRPath (e.g., \"Observation.status\")\n base?: string[]; // resource types\n}\n\nfunction inferPrimitiveTokenTypeFromExpression(expression?: string): string {\n if (!expression) return \"string\";\n\n if (expression.endsWith(\".status\")) return \"code\";\n if (expression.endsWith(\".url\")) return \"uri\";\n if (expression.endsWith(\".canonical\")) return \"canonical\";\n if (expression.endsWith(\".uuid\")) return \"uuid\";\n if (expression.endsWith(\".oid\")) return \"oid\";\n\n // Default\n return \"code\";\n}\n\n*/\n\n\n\n\n\n\nexport class DBSearchIndexToken extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n /*\n ExtractTokensWithMeta = (token: FhirToken, meta: SearchParamMeta, tir: IBaseIndexRecord): ITokenIndexRecord[] => {\n const results: ITokenIndexRecord[] = [];\n\n if (!token) return results;\n\n if (isIdentifier(token)) {\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = token.system || null,\n tokenIndexRecord.SP_VALUE = token.value || null,\n tokenIndexRecord.type = \"Identifier\"\n results.push(this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord);\n } \n else if (isContactPoint(token)) {\n results.push({\n system: token.system || null,\n code: token.value || null,\n type: \"ContactPoint\",\n ...base\n });\n }\n else if (isCoding(token)) {\n results.push({\n system: token.system || null,\n code: token.code || null,\n type: \"Coding\",\n ...base\n });\n } \n else if (isCodeableConcept(token)) {\n token.coding?.forEach(coding => {\n results.push({\n system: coding.system || null,\n code: coding.code || null,\n type: \"CodeableConcept\",\n ...base\n });\n });\n } \n else if (isPrimitiveToken(token)) {\n results.push({\n system: null,\n code: String(token),\n type: inferPrimitiveTokenTypeFromExpression(meta.expression),\n ...base\n });\n }\n\n return results;\n }\n */\n\n #GenerateHashValues = (tokenIndexRecord: Partial<ITokenIndexRecord>): Partial<ITokenIndexRecord> => {\n if (this.IsDefined(tokenIndexRecord.SP_SYSTEM)) {\n tokenIndexRecord.HASH_SYS = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_SYSTEM}`, true);\n } else {\n tokenIndexRecord.HASH_SYS = null;\n }\n if (this.IsDefined(tokenIndexRecord.SP_VALUE)) {\n tokenIndexRecord.HASH_VALUE = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_VALUE}`, true);\n } else {\n tokenIndexRecord.HASH_VALUE = null;\n }\n if (this.IsDefined(tokenIndexRecord.SP_SYSTEM) && this.IsDefined(tokenIndexRecord.SP_VALUE)) {\n tokenIndexRecord.HASH_SYS_AND_VALUE = hashStringParam(`${tokenIndexRecord.SP_NAME}|${tokenIndexRecord.RES_TYPE}|${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`, true);\n } else {\n tokenIndexRecord.HASH_SYS_AND_VALUE = null;\n }\n return tokenIndexRecord;\n }\n\n\n\n /* https://www.hl7.org/fhir/search.html#token\n\n| Datatype | URI | Code | Comments |\n|----------------|-----------------------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Coding | `Coding.system` | `Coding.code` | |\n| CodeableConcept| `CodeableConcept.coding.system` | `CodeableConcept.coding.code` | Matches against any coding in the CodeableConcept |\n| Identifier | `Identifier.system` | `Identifier.value` | Clients can search by type not system using the `:of-type` modifier. To search on a CDA II.root (which may appear in either `Identifier.system` or `Identifier.value`), use `identifier=|[root],[root]` |\n| ContactPoint | | `ContactPoint.value` | At the discretion of the server, token searches on ContactPoint may use special handling, such as ignoring punctuation or performing partial searches |\n| code | (implicit) | `code` | The system is defined in the value set (though it's not usually needed) |\n| boolean | | `boolean` | The implicit system for boolean values is `http://terminology.hl7.org/CodeSystem/special-values`, but this is never actually used |\n| id | | `id` | |\n| uri | | `uri` | |\n| string | n/a | `string` | Token is sometimes used for string to indicate that case-insensitive full-string matching is the correct default search strategy |\n*/\n \n #OutputToken = (tokens: any, tir: IBaseIndexRecordEx): ITokenIndexRecord[] => {\n if (this.IsDefined(tokens.system) && this.IsDefined(tokens.value)) {\n // Identifier\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.system;\n tokenIndexRecord.SP_VALUE= tokens.value;\n tokenIndexRecord.SP_TOKEN_TYPE = 'Identifier';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.system) && this.IsDefined(tokens.code)) {\n // Coding\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.system;\n tokenIndexRecord.SP_VALUE= tokens.code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'Coding';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.coding) && this.IsDefined(tokens.coding.system) && this.IsDefined(tokens.coding.code)) {\n // CodeableConcept (single)\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.coding.system;\n tokenIndexRecord.SP_VALUE= tokens.coding.code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'CodeableConcept';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (this.IsDefined(tokens.coding) && Array.isArray(tokens.coding)) {\n // CodeableConcept (array)\n const retVal: ITokenIndexRecord[] = [ ];\n for (let i=0 ; i < tokens.coding.length; i++) {\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_SYSTEM = tokens.coding[i].system;\n tokenIndexRecord.SP_VALUE= tokens.coding[i].code;\n tokenIndexRecord.SP_TOKEN_TYPE = 'CodeableConcept';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_SYSTEM}|${tokenIndexRecord.SP_VALUE}`;\n retVal.push(this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord)\n }\n return retVal;\n } else if (this.IsDefined(tokens.value)) {\n // ContactPoint\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens.value;\n tokenIndexRecord.SP_TOKEN_TYPE = 'contactPoint';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else {\n if (typeof tokens === 'boolean') {\n // boolean\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens ? 'true' : 'false';\n tokenIndexRecord.SP_TOKEN_TYPE = 'boolean';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else if (validUrl.isUri(tokens)) {\n // uri\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens;\n tokenIndexRecord.SP_TOKEN_TYPE = 'uri';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n } else { //@@ how detect id over a string ?\n // id or string\n const tokenIndexRecord: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tokenIndexRecord.SP_VALUE= tokens;\n tokenIndexRecord.SP_TOKEN_TYPE = 'string';\n tokenIndexRecord.SP_STR = `${tokenIndexRecord.SP_VALUE}`;\n return [ this.#GenerateHashValues(tokenIndexRecord) as ITokenIndexRecord ];\n }\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputTokens: any, tir: IBaseIndexRecordEx): Promise<ITokenIndexRecord[]> => {\n const _OutputMissingParamater = () => {\n const tirc: Partial<ITokenIndexRecord> = this.GetNewBaseIndexRecord(tir);\n //const tirc: ITokenIndexRecord = { ...tir } as ITokenIndexRecord;\n tirc.SP_MISSING = true;\n tirc.SP_SYSTEM = null;\n tirc.SP_VALUE = null;\n tirc.SP_TOKEN_TYPE = null;\n tirc.SP_STR = null;\n tirc.HASH_VALUE = null;\n tirc.HASH_SYS = null;\n tirc.HASH_SYS_AND_VALUE = null;\n this.ComputeCompositeHash(path, 0, tirc as ITokenIndexRecord);\n retVal.push(tirc as ITokenIndexRecord);\n }\n\n let retVal: ITokenIndexRecord[] = [ ];\n if (this.IsDefined(inputTokens)) {\n const _PushTokens = (tokens: any, index: number) => {\n if (Array.isArray(tokens) === true) {\n for (let i=0; i < tokens.length; i++) {\n _PushTokens(tokens[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(...this.#OutputToken(tokens, tir));\n }\n }\n _PushTokens(inputTokens, 0);\n } else {\n _OutputMissingParamater();\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<ITokenIndexRecord[]> => {\n let retVal: ITokenIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let tokens = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, tokens, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: ITokenIndexRecord[]): string => {\n return '';\n /*\n const tokenPromptColour = chalk.rgb(200,255,255);\n const tokenColour = chalk.rgb(200,200,10);\n\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = tokenPromptColour(`TOKEN INDEX: \\\n SP_ID: ${tokenColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${tokenColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${tokenColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${tokenColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_SYSTEM: ${tokenColour(tir[i].SP_SYSTEM ? tir[i].SP_SYSTEM.padEnd(45) : ''.padEnd(45))}\\\n SP_VALUE: ${tokenColour(tir[i].SP_VALUE!.padEnd(30))}\\\n UPDATED: ${tokenColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${tokenColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${tokenColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_SYS: ${tokenColour(tir[i].HASH_SYS ? tir[i].HASH_SYS.toString().padEnd(22): ''.padEnd(22))}\\\n HASH_SYS_AND_VALUE: ${tokenColour(tir[i].HASH_SYS_AND_VALUE ? tir[i].HASH_SYS_AND_VALUE.toString().padEnd(22) : ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** TOKEN: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import { Resource } from '@nsshunt/stsfhirclient';\nimport { randomUUID } from 'node:crypto';\nimport { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport { ISearchParamComponentRecord, ISearchParamRecord, IBaseIndexRecordEx, \n IComboNonUniqueRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { SearchRegistry } from './dbsearchregistry.js'\n\nimport { DBSearchIndex } from './dbsearchindex.js'\n\nexport class DBSearchIndexComposite extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #warn = (message: any) => {\n //defaultLogger.warn(message);\n }\n\n // This method is empty becuase the composite processor will not call itself recursively\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx): Promise<IBaseIndexRecordEx[]> => {\n this.#warn(`DBSearchIndexComposite:__OutputIndexRecordFromFhirElement(): composite (recursive) not supported within a composite expression. inputReferenceVal: [${inputReferenceVal}], tir: [${tir}]`);\n return [ ];\n }\n\n // Observation?code-value-quantity=code1234$le100,code5678$ge35 code: code value-quantity: value.ofType(Quantity)\n // Observation?combo-code-value-quantity=code1234$le100,code5678$ge35 combo-code: code combo-value-quantity: value.ofType(Quantity)\n\n // We need to ensure that each touple belongs to the same logical component, i.e.\n // when using combo-code-value-quantity, combo-code = Observation.code | Observation.component.code and Observation.component is an array\n // so there could be multiple index records create for code\n // we need to ensure the touple of code and quantity always belong to the same 'composite' touple pair so we need to use a\n // component_id concept to ensure they remain linked for composite searches.\n // One way to do this is the use the parent path as the composite_id, i.e.\n // / root level code and quantity, i.e. Observation.code + Observation.value[x]Quantity\n // /component_0 component level at index 0 Observation.component[0].code + Observation.component[0].value[x]Quantity\n // /component_1 component level at index 1 Observation.component[1].code + Observation.component[1].value[x]Quantity\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[]> => {\n let comboNonUniqueRecords: IComboNonUniqueRecord[] = [ ];\n //let extraIndexRecords: IBaseIndexRecord[] = [ ];\n\n //const resourceHelper: ResourceHelper = ResourceHelper.getInstance();\n const searchIndex: DBSearchIndex = DBSearchIndex.getInstance();\n\n let index = 0;\n let components: any[] = [ ];\n for (const searchParamComponentRecord of searchFieldRecord.component!) {\n components.push([ ]);\n const url = searchParamComponentRecord.definition;\n const sp = await searchIndex.resourceHelper.GetSearchParamFromResourceTypeUrl(resource.resourceType, url);\n if (this.IsDefined(sp)) {\n const tir = {\n PID: randomUUID(),\n RES_ID: resource.id!,\n SP_NAME: sp!.SP_NAME,\n RES_TYPE: resource.resourceType,\n UPDATED: BigInt(new Date().getTime()),\n SP_MISSING: false,\n HASH_IDENTITY: hashStringParam(`${sp!.SP_NAME}|${resource.resourceType}`, true),\n SP_PARAM_TYPE: sp!.SP_TYPE,\n SP_STR: null,\n PATH_FOR_COMP: null,\n COMPOSITE: null,\n COMPOSITE_HASH_EXACT: null\n };\n const retVal = await SearchRegistry.getInstance().searchIndexBaseRegistry[sp!.SP_TYPE].OutputIndexRecord(resource, tir, sp!);\n retVal.forEach(rv => {\n if (!((rv as any).SP_MISSING && (rv as any).SP_MISSING === true)) {\n if (rv.SP_STR && rv.SP_STR !== undefined) {\n components[index].push(rv);\n }\n }\n });\n index++;\n }\n\n };\n for (let i=0; i < components[0].length; i++) {\n for (let j=0; j < components[1].length; j++) {\n const idxString = `${components[0][i].SP_STR}|${components[1][j].SP_STR}`;\n const comboIndexRecord: Partial<IComboNonUniqueRecord> = this.GetNewBaseIndexRecord(tir);\n comboIndexRecord.IDX_STRING = idxString;\n comboIndexRecord.HASH_COMPLETE = hashStringParam(idxString, true);\n comboNonUniqueRecords.push(comboIndexRecord as IComboNonUniqueRecord);\n\n //@@ currently broken here as the quantity SP_STR field only has the value and ignores SP_SYSTEM and SP_UNITS\n if (comboIndexRecord.SP_NAME === 'combo-code-value-quantity') {\n //console.log(comboNonUniqueRecords);\n }\n }\n }\n\n return comboNonUniqueRecords;\n }\n \n OutputIndexRecordToConsole = (tir: IComboNonUniqueRecord[]): string => {\n let retVal = '';\n /*\n const compositePromptColour = chalk.rgb(100,200,255);\n const compositeColour = chalk.rgb(100,150,10);\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = compositePromptColour(`COMBO INDEX: \\\n SP_ID: ${compositeColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${compositeColour(tir[i].RES_ID.toString().padEnd(10))}\\\n IDX_STRING: ${compositeColour(tir[i].IDX_STRING.padEnd(15))}\\\n SP_VALUE_HIGH: ${compositeColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_HIGH_DATE_ORDINAL: ${compositeColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n SP_VALUE_LOW: ${compositeColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_LOW_DATE_ORDINAL: ${compositeColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n HASH_IDENTITY: ${compositeColour(tir[i].HASH_COMPLETE.toString().padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** COMPOSITE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n */\n \n return retVal;\n }\n\n}\n","import chalk from 'chalk';\nimport { DateTime } from 'luxon';\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nimport { FHIRDateUtils } from './../fhir-utils/fhirDateUtils.js'\nimport { ISearchParamRecord, IBaseIndexRecordEx, IDateIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexDates extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n // date search paramater type works with the following data types;\n /*\n| Type | Description |\n|-----------|-------------|\n| `date` | The range of the value is the day, month, or year as specified. |\n| `dateTime`| The range of the value as defined above; e.g., the date `2013-01-10` specifies all the time from 00:00 on 10-Jan-2013 to immediately before 00:00 on 11-Jan-2013. |\n| `instant` | An instant is considered a fixed point in time with an interval smaller than the precision of the system, i.e., an interval with an effective width of 0. |\n| `Period` | Explicit, though the upper or lower bound might not actually be specified in resources. |\n| `Timing` | The specified scheduling details are ignored and only the outer limits matter. For instance, a schedule that specifies every second day between 31-Jan-2013 and 24-Mar-2013 includes 1-Feb-2013, even though that is on an odd day that is not specified by the period. This is to keep the server load processing queries reasonable. |\n*/\n\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx): Promise<IDateIndexRecord[]> => {\n let retVal: IDateIndexRecord[] = [ ];\n\n const _OutputDate = (referenceVal: any, tir: IBaseIndexRecordEx, index: number): IDateIndexRecord => {\n let parsedDate: any;\n let parsedDatePeriodLow: any;\n let parsedDatePeriodHigh: any;\n\n if (this.IsDefined(referenceVal.start) || this.IsDefined(referenceVal.end)) {\n if (this.IsDefined(referenceVal.start)) {\n parsedDatePeriodLow = FHIRDateUtils.parseDateTime(referenceVal.start); \n }\n if (this.IsDefined(referenceVal.end)) {\n parsedDatePeriodHigh = FHIRDateUtils.parseDateTime(referenceVal.end); \n }\n } else {\n parsedDate = FHIRDateUtils.parseDateTime(referenceVal);\n }\n\n if (this.IsDefined(parsedDate)) {\n const dateIndexRecord: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n if (parsedDate.hour > 0 || parsedDate.minute > 0 || parsedDate.second > 0 || parsedDate.millisecond > 0) {\n dateIndexRecord.SP_VALUE_LOW = parsedDate;\n dateIndexRecord.SP_VALUE_HIGH = parsedDate;\n } else {\n dateIndexRecord.SP_VALUE_LOW = DateTime.local(parsedDate.year, parsedDate.month, parsedDate.day, 0, 0, 0, 0);\n dateIndexRecord.SP_VALUE_HIGH = DateTime.local(parsedDate.year, parsedDate.month, parsedDate.day, 23, 59, 59, 999);\n }\n dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_LOW!.toFormat('yyyyLLdd'), 10);\n dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_HIGH!.toFormat('yyyyLLdd'), 10);\n\n dateIndexRecord.SP_STR = `${dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL}|${dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL}`;\n \n this.ComputeCompositeHash(path, index, tir);\n\n return dateIndexRecord as IDateIndexRecord;\n } else if (this.IsDefined(parsedDatePeriodLow) || this.IsDefined(parsedDatePeriodHigh)) {\n const dateIndexRecord: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n if (this.IsDefined(parsedDatePeriodLow)) {\n dateIndexRecord.SP_VALUE_LOW = parsedDatePeriodLow;\n }\n if (this.IsDefined(parsedDatePeriodHigh)) {\n dateIndexRecord.SP_VALUE_HIGH = parsedDatePeriodHigh;\n }\n dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_LOW!.toFormat('yyyyLLdd'), 10);\n dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL = parseInt(dateIndexRecord.SP_VALUE_HIGH!.toFormat('yyyyLLdd'), 10);\n\n dateIndexRecord.SP_STR = `${dateIndexRecord.SP_VALUE_LOW_DATE_ORDINAL}|${dateIndexRecord.SP_VALUE_HIGH_DATE_ORDINAL}`;\n \n this.ComputeCompositeHash(path, index, tir);\n\n return dateIndexRecord as IDateIndexRecord;\n } else {\n const tirc: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_LOW = null;\n tirc.SP_VALUE_HIGH = null;\n tirc.SP_VALUE_LOW_DATE_ORDINAL = null;\n tirc.SP_VALUE_HIGH_DATE_ORDINAL = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IDateIndexRecord);\n return tirc as IDateIndexRecord;\n }\n }\n\n if (this.IsDefined(inputReferenceVal)) {\n const _PushDates = (dates: any, index: number) => {\n if (Array.isArray(dates) === true) {\n for (let i=0; i < dates.length; i++) {\n _PushDates(dates[i], i);\n }\n } else {\n retVal.push(_OutputDate(dates, tir, index));\n }\n }\n _PushDates(inputReferenceVal, 0);\n } else {\n const tirc: Partial<IDateIndexRecord> = this.GetNewBaseIndexRecord(tir);\n //const tirc: IDateIndexRecord = { ...tir } as IDateIndexRecord;\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_LOW = null;\n tirc.SP_VALUE_HIGH = null;\n tirc.SP_VALUE_LOW_DATE_ORDINAL = null;\n tirc.SP_VALUE_HIGH_DATE_ORDINAL = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IDateIndexRecord);\n retVal.push(tirc as IDateIndexRecord); \n }\n\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IDateIndexRecord[]> => {\n let retVal: IDateIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let referenceVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, referenceVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IDateIndexRecord[]): string => {\n const datesPromptColour = chalk.rgb(200,200,255);\n const datesColour = chalk.rgb(200,150,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = datesPromptColour(`DATE INDEX: \\\n SP_ID: ${datesColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${datesColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${datesColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${datesColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_VALUE_HIGH: ${datesColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_HIGH_DATE_ORDINAL: ${datesColour(tir[i].SP_VALUE_HIGH ? tir[i].SP_VALUE_HIGH_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n SP_VALUE_LOW: ${datesColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW!.toString().padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_LOW_DATE_ORDINAL: ${datesColour(tir[i].SP_VALUE_LOW ? tir[i].SP_VALUE_LOW_DATE_ORDINAL!.toString().padEnd(12) : ''.padEnd(12))}\\\n UPDATED: ${datesColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${datesColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${datesColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** DATE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n }\n\n}\n","import { hashStringParam } from '../fhir-utils/fhirHashUtils.js'\n\nimport { ISearchParamRecord, IBaseIndexRecordEx, IQuantityIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nexport class DBSearchIndexQuantity extends DBSearchIndexBase {\n constructor() {\n super();\n }\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputQuantity = (quantityInputVal: any, tir: IBaseIndexRecordEx): IQuantityIndexRecord => {\n const quantityIndexRecords: Partial<IQuantityIndexRecord> = this.GetNewBaseIndexRecord(tir);\n\n if (this.IsDefined(quantityInputVal.unit)) {\n quantityIndexRecords.SP_UNITS = quantityInputVal.unit;\n quantityIndexRecords.HASH_IDENTITY_AND_UNITS = hashStringParam(`${quantityIndexRecords.SP_NAME}|${quantityIndexRecords.RES_TYPE}|${quantityIndexRecords.SP_UNITS}`, true);\n } \n if (this.IsDefined(quantityInputVal.system)) {\n quantityIndexRecords.SP_SYSTEM = quantityInputVal.system;\n if (this.IsDefined(quantityInputVal.unit)) {\n quantityIndexRecords.HASH_IDENTITY_SYS_UNITS = hashStringParam(`${quantityIndexRecords.SP_NAME}|${quantityIndexRecords.RES_TYPE}|${quantityIndexRecords.SP_SYSTEM}|${quantityIndexRecords.SP_UNITS}`, true);\n }\n }\n if (this.IsDefined(quantityInputVal.value)) {\n quantityIndexRecords.SP_VALUE = Number.parseFloat(quantityInputVal.value);\n }\n\n if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_SYSTEM) && this.IsDefined(quantityIndexRecords.SP_UNITS)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_SYSTEM}|${quantityIndexRecords.SP_UNITS}`;\n } else if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_SYSTEM)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_SYSTEM}`;\n } else if (this.IsDefined(quantityIndexRecords.SP_VALUE) && this.IsDefined(quantityIndexRecords.SP_UNITS)) {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}|${quantityIndexRecords.SP_UNITS}`;\n } else {\n quantityIndexRecords.SP_STR = `${quantityIndexRecords.SP_VALUE}`;\n }\n return quantityIndexRecords as IQuantityIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputQuantityVal: any, tir: IBaseIndexRecordEx): Promise<IQuantityIndexRecord[]> => {\n const retVal: IQuantityIndexRecord[] = [ ];\n if (this.IsDefined(inputQuantityVal)) {\n const _PushQty = (qVal: any, index: number) => {\n if (Array.isArray(qVal)) {\n for (let i=0; i < qVal.length; i++) {\n _PushQty(qVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputQuantity(qVal, tir));\n }\n }\n _PushQty(inputQuantityVal, 0);\n } else {\n //const tirc: IQuantityIndexRecord = { ...tir } as IQuantityIndexRecord;\n const tirc: Partial<IQuantityIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_UNITS = null;\n tirc.SP_SYSTEM = null;\n tirc.SP_VALUE = null;\n tirc.SP_STR = null;\n tirc.HASH_IDENTITY_AND_UNITS = null;\n tirc.HASH_IDENTITY_SYS_UNITS = null;\n this.ComputeCompositeHash(path, 0, tirc as IQuantityIndexRecord);\n retVal.push(tirc as IQuantityIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IQuantityIndexRecord[]> => {\n const retVal: IQuantityIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let quantityVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, quantityVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IQuantityIndexRecord[]): string => {\n return '';\n /*\n const quantityPromptColour = chalk.rgb(0,100,255);\n const quantityColour = chalk.rgb(0,50,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = quantityPromptColour(`QUANTITY INDEX: \\\n SP_ID: ${quantityColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${quantityColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${quantityColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${quantityColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_UNITS: ${quantityColour(tir[i].SP_UNITS.toString().padEnd(15))}\\\n SP_SYSTEM: ${quantityColour(tir[i].SP_SYSTEM.toString().padEnd(25))}\\\n SP_VALUE: ${quantityColour(tir[i].SP_VALUE.toString().padEnd(15))}\\\n UPDATED: ${quantityColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${quantityColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${quantityColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_IDENTITY_AND_UNITS: ${quantityColour(tir[i].HASH_IDENTITY_AND_UNITS ? tir[i].HASH_IDENTITY_AND_UNITS.toString().padEnd(22): ''.padEnd(22))}\\\n HASH_IDENTITY_SYS_UNITS: ${quantityColour(tir[i].HASH_IDENTITY_SYS_UNITS ? tir[i].HASH_IDENTITY_SYS_UNITS.toString().padEnd(22): ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** QUANTITY: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n\n return retVal;\n */\n }\n\n}\n","import { randomUUID } from 'node:crypto';\nimport { ISearchParamRecord, IBaseIndexRecordEx, IResourceLinkIndexRecord, ISearchParamExpressionRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource, isAbsoluteUrl } from '@nsshunt/stsfhirclient';\n\nexport class DBSearchIndexReference extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #GetResourceID = (resourceName: string, resourceId: string): string => {\n return resourceId;\n }\n\n #OutputReference = (sourceResource: Resource, tir: IBaseIndexRecordEx, referenceVal: any, \n searchParamExpressionRecord: ISearchParamExpressionRecord): IResourceLinkIndexRecord => {\n try {\n const resourceIndexRecord: Partial<IResourceLinkIndexRecord> = { };\n resourceIndexRecord.PID = randomUUID();\n resourceIndexRecord.SP_NAME = tir.SP_NAME;\n resourceIndexRecord.SP_PARAM_TYPE = tir.SP_PARAM_TYPE;\n resourceIndexRecord.SRC_PATH = `${searchParamExpressionRecord.path}`; // `${resourceName}.${searchParamExpressionRecord.path}`;\n resourceIndexRecord.RES_ID = this.#GetResourceID(sourceResource.resourceType, sourceResource.id!); // need to lookup PK of the source resource\n resourceIndexRecord.RES_TYPE = sourceResource.resourceType;\n resourceIndexRecord.SP_MISSING = false;\n\n //@@ what about version using the | token\n if (isAbsoluteUrl(referenceVal)) {\n //@@ In future version, attempt to resolve this if the URL points back to this server.\n //@@ If so, update with the actual values from the lookup.\n resourceIndexRecord.TARGET_RESOURCE_ID = null;\n resourceIndexRecord.TARGET_RESOURCE_URL = referenceVal; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = null;\n resourceIndexRecord.SP_STR = resourceIndexRecord.TARGET_RESOURCE_URL;\n } else {\n const reference = referenceVal;\n const parts = reference.split('/');\n if (parts.length > 1) {\n const targetResType = parts[0];\n const targetResID = parts[1];\n\n resourceIndexRecord.TARGET_RESOURCE_ID = this.#GetResourceID(targetResType, targetResID); // need to lookup PK of referenced resource\n resourceIndexRecord.TARGET_RESOURCE_URL = null; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = targetResType;\n resourceIndexRecord.SP_STR = `${resourceIndexRecord.TARGET_RESOURCE_ID}|${resourceIndexRecord.TARGET_RESOURCE_TYPE}`\n } else {\n if ((referenceVal as string).substring(0, 1) === '#') {\n throw new Error(`#OutputReference(): Cannot index internal references, i.e. starts with #, referenceVal: [${referenceVal}]`);\n } else {\n resourceIndexRecord.TARGET_RESOURCE_ID = null;\n resourceIndexRecord.TARGET_RESOURCE_URL = referenceVal; // This used for absolute (usually external) canonical references\n resourceIndexRecord.TARGET_RESOURCE_TYPE = null;\n resourceIndexRecord.SP_STR = resourceIndexRecord.TARGET_RESOURCE_URL;\n }\n }\n }\n resourceIndexRecord.UPDATED = BigInt(new Date().getTime());\n return resourceIndexRecord as IResourceLinkIndexRecord;\n } catch (error) {\n console.error(error);\n console.error(`referenceVal: [${JSON.stringify(referenceVal)}]`);\n throw error;\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputReferenceVal: any, tir: IBaseIndexRecordEx, \n searchParamExpressionRecord: ISearchParamExpressionRecord, resource: Resource, \n ): Promise<IResourceLinkIndexRecord[]> => {\n\n const _OutputReferencesFromFhirElement = (referenceVal: any, index: number) => {\n let resourceReference;\n if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.identifier) && this.IsDefined(referenceVal.identifier.value)) {\n resourceReference = referenceVal.identifier.value;\n } else if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.reference)) {\n resourceReference = referenceVal.reference;\n } else if (this.IsDefined(referenceVal) && this.IsDefined(referenceVal.type) && this.IsDefined(referenceVal.resource)) { // from a where(type=)\n resourceReference = referenceVal.resource;\n } else {\n resourceReference = referenceVal;\n }\n if (this.IsDefined(resourceReference) && resourceReference.substring(0,1) !== '#') {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputReference(resource, tir, resourceReference, searchParamExpressionRecord));\n }\n }\n\n let retVal: IResourceLinkIndexRecord[] = [ ];\n if (this.IsDefined(inputReferenceVal)) {\n const _PushReferences = (refVal: any, index: number) => {\n if (Array.isArray(refVal)) {\n for (let i=0; i < refVal.length; i++) {\n _PushReferences(refVal[i], i);\n }\n } else {\n _OutputReferencesFromFhirElement(refVal, index);\n }\n }\n _PushReferences(inputReferenceVal, 0);\n } else {\n const tirc: Partial<IResourceLinkIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SRC_PATH = `${searchParamExpressionRecord.path}`; // `${resourceName}.${searchParamExpressionRecord.path}`;\n tirc.SP_MISSING = true;\n tirc.TARGET_RESOURCE_ID = null;\n tirc.TARGET_RESOURCE_URL = null;\n tirc.TARGET_RESOURCE_TYPE = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IResourceLinkIndexRecord);\n retVal.push(tirc as IResourceLinkIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IResourceLinkIndexRecord[]> => {\n let retVal: IResourceLinkIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n const referenceVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, referenceVal, tir, expression, resource));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IResourceLinkIndexRecord[]): string => {\n return '';\n /*\n const resourceLinkedPromptColour = chalk.rgb(0,100,200);\n const resourceLinkedColour = chalk.rgb(0,100,10);\n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = resourceLinkedPromptColour(`RESOURCE LINKED INDEX: \\\n SP_ID: ${resourceLinkedColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${resourceLinkedColour(tir[i].RES_ID.toString().padEnd(10))}\\\n RES_TYPE: ${resourceLinkedColour(tir[i].RES_TYPE.padEnd(10))}\\\n SRC_PATH: ${resourceLinkedColour(tir[i].SRC_PATH.padEnd(30))}\\\n SP_MISSING: ${resourceLinkedColour(tir[i].SP_MISSING)}\\\n TARGET_RESOURCE_ID: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_ID?.toString().padEnd(30))}\\\n TARGET_RESOURCE_TYPE: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_TYPE.padEnd(30))}\\\n TARGET_RESOURCE_URL: ${resourceLinkedColour(tir[i].TARGET_RESOURCE_URL ? tir[i].TARGET_RESOURCE_URL!.padEnd(40) : ''.padEnd(40))}\\\n UPDATED: ${resourceLinkedColour(tir[i].UPDATED!.toString().padEnd(15))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** REFERENCE: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import chalk from 'chalk';\nimport { Resource } from '@nsshunt/stsfhirclient'\n\nimport { hashStringParam, normalizeStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport { ResourceHelper } from './../fhir-utils/resourceHelper.js'\nimport { ISearchParamExpressionRecord, ISearchParamRecord, IBaseIndexRecordEx, IStringIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexString extends DBSearchIndexBase {\n #resourceHelper: ResourceHelper;\n\n constructor() {\n super();\n this.#resourceHelper = ResourceHelper.getInstance();\n }\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputString = async (stringInputVal: any, tir: IBaseIndexRecordEx, expression?: ISearchParamExpressionRecord): Promise<IStringIndexRecord[]> => {\n const stringIndexRecords: IStringIndexRecord[] = [ ];\n\n if (this.IsDefined(expression) && typeof stringInputVal === 'object') {\n let fields: string[] = [ ];\n // We have an object as the value, so we need to look up this Fhir type\n //console.log(stringInputVal);\n //console.log(expression);\n\n if (this.IsDefined(expression) && this.IsDefined(expression!.RES_FIELD) && this.IsDefined(expression!.RES_FIELD.type)) {\n let expressionType;\n if (Array.isArray(expression!.RES_FIELD.type)) {\n expressionType = expression!.RES_FIELD.type[0];\n } else {\n expressionType = expression!.RES_FIELD.type;\n }\n\n let res: any[];\n if (this.IsDefined(expressionType) && this.IsDefined(expressionType.code)) {\n res = await this.#resourceHelper.GetType(expressionType.code);\n } else {\n res = await this.#resourceHelper.GetType(expressionType);\n }\n \n if (this.IsDefined(res)) {\n for (let i=0; i < res.length; i++) {\n if (res[i].type && res[i].type[0].code && res[i].type[0].code === 'string') {\n //console.log(`${res[i].id} ${res[i].type[0].code}`);\n fields.push(res[i].id.split('.')[1]);\n }\n } \n }\n }\n\n // Flattern our to be indexed value\n const vals: any[] = [ ];\n const _getString = (key: string, val: any) => {\n if (Array.isArray(val)) {\n for (let i=0; i < val.length; i++) {\n _getString(key, val[i]);\n }\n }\n if (typeof val === 'string') {\n vals.push({key, val});\n }\n }\n for (const [k, v] of Object.entries(stringInputVal)) {\n _getString(k, v);\n }\n\n vals.forEach(v => {\n if (fields.includes(v.key)) {\n try {\n const stringIndexRecord: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n stringIndexRecord.SP_VALUE_EXACT = v.val;\n stringIndexRecord.SP_VALUE_NORMALIZED = normalizeStringParam(v.val);\n stringIndexRecord.HASH_EXACT = hashStringParam(`${stringIndexRecord.SP_NAME}|${stringIndexRecord.RES_TYPE}|${stringIndexRecord.SP_VALUE_EXACT}`, false);\n stringIndexRecord.SP_STR = stringIndexRecord.SP_VALUE_EXACT;\n stringIndexRecords.push(stringIndexRecord as IStringIndexRecord);\n } catch (error) {\n console.error(error);\n return stringIndexRecords;\n }\n }\n })\n return stringIndexRecords;\n } else {\n try {\n const stringIndexRecord: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n stringIndexRecord.SP_VALUE_EXACT = stringInputVal;\n stringIndexRecord.SP_VALUE_NORMALIZED = normalizeStringParam(stringInputVal);\n stringIndexRecord.HASH_EXACT = hashStringParam(`${stringIndexRecord.SP_NAME}|${stringIndexRecord.RES_TYPE}|${stringIndexRecord.SP_VALUE_EXACT}`, false);\n stringIndexRecord.SP_STR = stringIndexRecord.SP_VALUE_EXACT;\n stringIndexRecords.push(stringIndexRecord as IStringIndexRecord);\n return stringIndexRecords;\n } catch (error) {\n console.error(error);\n return stringIndexRecords;\n }\n }\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputStringVal: any, tir: IBaseIndexRecordEx, expression?: ISearchParamExpressionRecord): Promise<IStringIndexRecord[]> => {\n const retVal: IStringIndexRecord[] = [ ];\n if (this.IsDefined(inputStringVal)) {\n const _PushStrings = async (stringVals: any, index: number) => {\n if (Array.isArray(stringVals)) {\n for (let i=0; i < stringVals.length; i++) {\n await _PushStrings(stringVals[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(...await this.#OutputString(stringVals, tir, expression));\n }\n }\n await _PushStrings(inputStringVal, 0);\n } else {\n //const tirc: IStringIndexRecord = { ...tir } as IStringIndexRecord;\n const tirc: Partial<IStringIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE_EXACT = null;\n tirc.HASH_EXACT = null;\n tirc.SP_VALUE_NORMALIZED = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IStringIndexRecord);\n retVal.push(tirc as IStringIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchParamRecord: ISearchParamRecord): Promise<IStringIndexRecord[]> => {\n const retVal: IStringIndexRecord[] = [ ];\n for (const expression of searchParamRecord.expressions) {\n let stringVal = this.GetValueFromPath(resource, expression.path, searchParamRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, stringVal, tir, expression));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IStringIndexRecord[]): string => {\n return '';\n /*\n const stringPromptColour = chalk.rgb(0,255,255);\n const stringColour = chalk.rgb(0,200,10);\n \n let retVal = '';\n let sep = '';\n if (tir) {\n for (let i=0; i < tir.length; i++) {\n const outputText = stringPromptColour(`STRING INDEX: \\\n SP_ID: ${stringColour(tir[i].PID.padEnd(40))}\\\n RES_ID: ${stringColour(tir[i].RES_ID.toString().padEnd(10))}\\\n SP_NAME: ${stringColour(tir[i].SP_NAME!.padEnd(15))}\\\n RES_TYPE: ${stringColour(tir[i].RES_TYPE!.padEnd(10))}\\\n SP_VALUE_EXACT: ${stringColour(tir[i].SP_VALUE_EXACT ? tir[i].SP_VALUE_EXACT.padEnd(30) : ''.padEnd(30))}\\\n SP_VALUE_NORMALIZED: ${stringColour(tir[i].SP_VALUE_NORMALIZED.padEnd(30))}\\\n UPDATED: ${stringColour(tir[i].UPDATED!.toString().padEnd(15))}\\\n SP_MISSING: ${stringColour(tir[i].SP_MISSING!.toString().padEnd(8))}\\\n HASH_IDENTITY: ${stringColour(tir[i].HASH_IDENTITY!.toString().padEnd(22))}\\\n HASH_EXACT: ${stringColour(tir[i].HASH_EXACT ? tir[i].HASH_EXACT.toString().padEnd(22): ''.padEnd(22))}`);\n retVal = `${retVal}${sep}${outputText}`;\n sep = '\\n';\n }\n }\n if (retVal === '') {\n this.#debug(chalk.rgb(250,50,100)` --> *** STRING: Search Param Not Found *** <--`);\n } else {\n this.#debug(retVal);\n }\n return retVal;\n */\n }\n}\n","import { ISearchParamRecord, IBaseIndexRecordEx, INumberIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\nimport { Resource } from '@nsshunt/stsfhirclient'\n\n// Note: The Number type in R5 has been deprecated.\nexport class DBSearchIndexNumber extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #OutputNumber = (numberInputVal: any, tir: IBaseIndexRecordEx): INumberIndexRecord => {\n const quantityIndexRecords: Partial<INumberIndexRecord> = this.GetNewBaseIndexRecord(tir);\n \n if (this.IsDefined(numberInputVal.value) && typeof numberInputVal.value === 'number' && Number.isFinite(numberInputVal.value)) {\n quantityIndexRecords.SP_VALUE = numberInputVal.value;\n } else if (this.IsDefined(numberInputVal) && typeof numberInputVal === 'number' && Number.isFinite(numberInputVal)) {\n quantityIndexRecords.SP_VALUE = numberInputVal;\n }\n if (this.IsDefined(quantityIndexRecords.SP_VALUE)) {\n quantityIndexRecords.SP_STR = quantityIndexRecords.SP_VALUE!.toString();\n } else {\n quantityIndexRecords.SP_STR = undefined;\n }\n return quantityIndexRecords as INumberIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputNumberVal: any, tir: IBaseIndexRecordEx): Promise<INumberIndexRecord[]> => {\n const retVal: INumberIndexRecord[] = [ ];\n if (this.IsDefined(inputNumberVal)) {\n const _PushNumberVal = (numberVal: any, index: number) => {\n if (Array.isArray(numberVal)) {\n for (let i=0; i < numberVal.length; i++) {\n _PushNumberVal(numberVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputNumber(numberVal, tir));\n }\n }\n _PushNumberVal(inputNumberVal, 0);\n } else {\n //const tirc: INumberIndexRecord = { ...tir } as INumberIndexRecord;\n const tirc: Partial<INumberIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_VALUE = undefined;\n tirc.SP_STR = undefined;\n this.ComputeCompositeHash(path, 0, tirc as INumberIndexRecord);\n retVal.push(tirc as INumberIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<INumberIndexRecord[]> => {\n const retVal: INumberIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let numberVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, numberVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IBaseIndexRecordEx[]): string => {\n //@@\n return '';\n }\n}\n","import { Resource } from '@nsshunt/stsfhirclient'\n\nimport { hashStringParam } from '../fhir-utils/fhirHashUtils.js'\nimport { ISearchParamRecord, IBaseIndexRecordEx, IUriIndexRecord } from '../fhir-utils/commonTypes.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class DBSearchIndexURI extends DBSearchIndexBase {\n constructor() {\n super();\n }\n\n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n #OutputURI = (uriInputVal: any, tir: IBaseIndexRecordEx): IUriIndexRecord => {\n const uriIndexRecords: Partial<IUriIndexRecord> = this.GetNewBaseIndexRecord(tir);\n\n if (this.IsDefined(uriInputVal.value)) {\n uriIndexRecords.SP_URI = uriInputVal.value;\n uriIndexRecords.HASH_URI = hashStringParam(`${uriIndexRecords.SP_NAME}|${uriIndexRecords.RES_TYPE}|${uriIndexRecords.SP_URI}`, true);\n uriIndexRecords.SP_STR = uriIndexRecords.SP_URI;\n } else if (this.IsDefined(uriInputVal)) {\n uriIndexRecords.SP_URI = uriInputVal;\n uriIndexRecords.HASH_URI = hashStringParam(`${uriIndexRecords.SP_NAME}|${uriIndexRecords.RES_TYPE}|${uriIndexRecords.SP_URI}`, true);\n uriIndexRecords.SP_STR = uriIndexRecords.SP_URI;\n } else {\n uriIndexRecords.SP_URI = null;\n uriIndexRecords.HASH_URI = null;\n uriIndexRecords.SP_STR = null;\n }\n return uriIndexRecords as IUriIndexRecord;\n }\n\n OutputIndexRecordFromFhirElement = async (path: string, inputUriVal: any, tir: IBaseIndexRecordEx): Promise<IUriIndexRecord[]> => {\n const retVal: IUriIndexRecord[] = [ ];\n const _processUriVal = (uriVal: any, index: number) => {\n if (Array.isArray(uriVal)) {\n for (let i=0; i < uriVal.length; i++) {\n _processUriVal(uriVal[i], i);\n }\n } else {\n this.ComputeCompositeHash(path, index, tir);\n retVal.push(this.#OutputURI(uriVal, tir));\n }\n }\n\n if (this.IsDefined(inputUriVal)) {\n _processUriVal(inputUriVal, 0);\n } else {\n //const tirc: IUriIndexRecord = { ...tir } as IUriIndexRecord;\n const tirc: Partial<IUriIndexRecord> = this.GetNewBaseIndexRecord(tir);\n tirc.SP_MISSING = true;\n tirc.SP_URI = null;\n tirc.HASH_URI = null;\n tirc.SP_STR = null;\n this.ComputeCompositeHash(path, 0, tirc as IUriIndexRecord);\n retVal.push(tirc as IUriIndexRecord);\n }\n return retVal;\n }\n\n OutputIndexRecord = async (resource: Resource, tir: IBaseIndexRecordEx, searchFieldRecord: ISearchParamRecord): Promise<IUriIndexRecord[]> => {\n const retVal: IUriIndexRecord[] = [ ];\n for (const expression of searchFieldRecord.expressions) {\n let uriVal = this.GetValueFromPath(resource, expression.path, searchFieldRecord, expression);\n retVal.push(...await this.OutputIndexRecordFromFhirElement(expression.path, uriVal, tir));\n }\n return retVal;\n }\n\n OutputIndexRecordToConsole = (tir: IBaseIndexRecordEx[]): string => {\n return '';\n }\n}\n","import { DBSearchIndexToken } from './dbsearchindextoken.js'\nimport { DBSearchIndexComposite } from './dbsearchindexcomposite.js'\nimport { DBSearchIndexDates } from './dbsearchindexdates.js'\nimport { DBSearchIndexQuantity } from './dbsearchindexquantity.js'\nimport { DBSearchIndexReference } from './dbsearchindexreference.js'\nimport { DBSearchIndexString } from './dbsearchindexstring.js'\nimport { DBSearchIndexNumber } from './dbsearchindexnumber.js'\nimport { DBSearchIndexURI } from './dbsearchindexuri.js'\nimport { DBSearchIndexBase } from './dbsearchindexbase.js'\n\nexport class SearchRegistry {\n private static instance: SearchRegistry;\n\n private constructor() {}\n\n static getInstance(): SearchRegistry {\n if (!SearchRegistry.instance) {\n SearchRegistry.instance = new SearchRegistry();\n }\n return SearchRegistry.instance;\n } \n\n #searchIndexBaseRegistry: Record<string, DBSearchIndexBase> = {\n ['token']: new DBSearchIndexToken(),\n ['composite']: new DBSearchIndexComposite(),\n ['date']: new DBSearchIndexDates(),\n ['quantity']: new DBSearchIndexQuantity(),\n ['reference']: new DBSearchIndexReference(),\n ['string']: new DBSearchIndexString(),\n ['number']: new DBSearchIndexNumber(),\n ['uri']: new DBSearchIndexURI()\n };\n\n get searchIndexBaseRegistry(): Record<string, DBSearchIndexBase> {\n return this.#searchIndexBaseRegistry;\n }\n}","import { hashStringParam } from './../fhir-utils/fhirHashUtils.js'\nimport chalk from 'chalk';\nimport { randomUUID } from 'node:crypto';\n\nimport { ISearchParamRecord, ISearchParams, ISearchFieldRecord, IBaseIndexRecordEx } from './../fhir-utils/commonTypes.js'\n\nimport { SearchRegistry } from './dbsearchregistry.js'\n\nimport { Resource } from '@nsshunt/stsfhirclient';\nimport { defaultLogger } from '@nsshunt/stsutils';\nimport { ResourceHelper } from './../fhir-utils/resourceHelper.js'\n\nexport class DBSearchIndex {\n #searchParams: ISearchParams | undefined = undefined;\n\n #OUTPUT_REPORT: boolean = false;\n\n private static instance: DBSearchIndex;\n \n #debug = (message: any) => {\n //defaultLogger.debug(message);\n }\n\n static getInstance(): DBSearchIndex {\n if (!DBSearchIndex.instance) {\n DBSearchIndex.instance = new DBSearchIndex();\n }\n return DBSearchIndex.instance;\n } \n\n get resourceHelper() {\n return ResourceHelper.getInstance();\n }\n\n get searchRegistry() {\n return SearchRegistry.getInstance();\n }\n\n Stop = async () => {\n await this.resourceHelper.Stop();\n }\n\n #OutputSearchDetails = (resourceName: string, resourceId: string, searchFieldRecord: ISearchFieldRecord) => {\n const hl = chalk.yellow.bold.italic;\n this.#debug('------------------')\n this.#debug(`resource: [${hl(resourceName)}] \\\n resourceId: [${hl(resourceId)}] \\\n SP_NAME: [${hl(searchFieldRecord.SP_NAME)}] \\\n SP_TYPE: [${hl(searchFieldRecord.SP_TYPE)}] \\\n SP_BASE: [${hl(searchFieldRecord.SP_BASE)}] \\\n path: [${hl(searchFieldRecord.path)}] \\\n RESOURCE_DATATYPE: [${hl(searchFieldRecord.RESOURCE_DATATYPE)}] \\\n subFieldDataType: [${hl(searchFieldRecord.subFieldDataType)}] \\\n stringIndexFields: [${hl(searchFieldRecord.stringIndexFields)}]`);\n }\n\n UpdateIndex = async (resource: Resource, searchFieldRecord: ISearchParamRecord): Promise<IBaseIndexRecordEx[] | undefined> => {\n try {\n const tir: IBaseIndexRecordEx = {\n PID: randomUUID(),\n RES_ID: resource.id!,\n SP_NAME: searchFieldRecord.SP_NAME,\n RES_TYPE: resource.resourceType,\n UPDATED: BigInt(new Date().getTime()),\n SP_MISSING: false,\n HASH_IDENTITY: hashStringParam(`${searchFieldRecord.SP_NAME}|${resource.resourceType}`, true),\n SP_PARAM_TYPE: searchFieldRecord.SP_TYPE,\n SP_STR: '',\n PATH_FOR_COMP: null,\n COMPOSITE: null,\n COMPOSITE_HASH_EXACT: null\n }\n\n let saveRecord: IBaseIndexRecordEx[] | undefined;\n const searchIndexBaseProcessor = this.searchRegistry.searchIndexBaseRegistry[searchFieldRecord.SP_TYPE];\n if (searchIndexBaseProcessor) {\n saveRecord = await searchIndexBaseProcessor.OutputIndexRecord(resource, tir, searchFieldRecord);\n } else if (searchFieldRecord.SP_TYPE.localeCompare(\"special\") === 0) {\n // Don't do anything for this type\n } else {\n const message = `DBSearchIndex:UpdateIndex(): Error: Search field paramater type: [${searchFieldRecord.SP_TYPE}] unknown.`;\n defaultLogger.error(message);\n throw new Error(message);\n }\n return saveRecord;\n } catch (error) {\n console.error(error);\n return [ ];\n }\n }\n\n GetSearchIndexData = async (resource: Resource): Promise<IBaseIndexRecordEx[]> => {\n try {\n const searchParamRecords: ISearchParamRecord[] = await this.resourceHelper.GetSearchParamsFromResourceType(resource.resourceType);\n const searchIndexData: IBaseIndexRecordEx[] = [ ];\n for (let i=0; i < searchParamRecords.length; i++) {\n const searchRecord: ISearchParamRecord = searchParamRecords[i];\n try {\n const retVal = await this.UpdateIndex(resource, searchRecord);\n if (retVal && retVal.length > 0) {\n searchIndexData.push(...retVal);\n }\n } catch (error) {\n defaultLogger.error(`DBSearchIndex:GetSearchIndexData(): Error: [${error}] searchRecord: [${JSON.stringify(searchRecord)}]`)\n }\n }\n return searchIndexData;\n } catch (error) {\n defaultLogger.error(`DBSearchIndex:GetSearchIndexData(): Error: [${error}]`)\n return [ ];\n }\n }\n\n GetSearchParamFromResourceType = async (resourceType: string, name: string): Promise<ISearchParamRecord | undefined> => {\n return this.resourceHelper.GetSearchParamFromResourceType(resourceType, name);\n }\n\n GetSearchParamFromResourceTypeUrl = async (resourceType: string, url: string): Promise<ISearchParamRecord | undefined> => {\n return this.resourceHelper.GetSearchParamFromResourceTypeUrl(resourceType, url);\n }\n}\n","import { goptions } from '@nsshunt/stsconfig'\n\nimport chalk from 'chalk';\n\nimport cluster from 'cluster'\n\nimport crypto from 'crypto';\n\n//const pg = require('pg');\n//pg.types.setTypeParser(20, BigInt); // Type Id 20 = BIGINT | BIGSERIAL\n// https://stackoverflow.com/questions/39168501/pg-promise-returns-integers-as-strings\nimport { Pool, PoolConfig, PoolClient } from 'pg'\nimport { TinyEmitter } from 'tiny-emitter';\nimport { ISTSLogger } from '@nsshunt/stsutils';\n\nexport enum IDBAccessLayerEvents {\n UpdateInstruments = 'UpdateInstruments',\n}\n\nexport interface PGPoolManagerOptions {\n\tusedefaultdb: boolean\n logger: ISTSLogger\n}\n\nexport interface IPoolItem {\n pool: Pool\n connectionString: string\n safeConnectionString: string\n}\n\nexport class PGPoolManager extends TinyEmitter\n{\n #options: PGPoolManagerOptions;\n #observer: NodeJS.Timeout | null = null;\n #pools: Record<string, IPoolItem> = { };\n #keyPrefix: string = '__STS__';\n\n constructor(options: PGPoolManagerOptions) {\n super();\n this.#options = options;\n this.#CreatePools(this.#options);\n }\n\n \n #LogDebugMessage(message: any) {\n this.#options.logger.debug(message);\n }\n\n \n #LogErrorMessage(message: any) {\n this.#options.logger.error(message);\n }\n\n #CreatePools(options: PGPoolManagerOptions) {\n const { databaseUrl, connectionString, defaultDatabaseConnectionString, isProduction } = goptions;\n\n const poolConnectionString = isProduction ? databaseUrl as string : (options.usedefaultdb === true ? defaultDatabaseConnectionString : connectionString );\n\n const poolConnectionStrings = poolConnectionString.split(',');\n for (let i=0; i < poolConnectionStrings.length; i++) {\n this.#CreatePool(i, poolConnectionStrings[i]);\n }\n this.#AttachInstruments();\n }\n\n #CreatePool(poolIndex: number, poolConnectionString: string) {\n const { isProduction, poolSize } = goptions;\n\n // https://mylifedigital.co.uk/securing-node-postgres-with-ssl/\n const pool = new Pool({\n connectionString: poolConnectionString,\n ssl: isProduction,\n max: poolSize // Default is 10 - This will be the number in a pool per thread (worker)\n // Consideration needs to be given for the max number of connections at the database.\n // Max connections calculation = max pool size * max workers (threads) per instance/node * max instances in a cluster (k3s, k8s, swarm mode etc.)\n /*\n\t\t ssl: {\n\t\t\t// rejectUnauthorized: true, // Make this true for PROD\n\t\t\trejectUnauthorized: false,\n\t\t\t//ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(),\n\t\t\t//key: fs.readFileSync('/path/to/client-key/postgresql.key').toString(),\n\t\t\t//cert: fs.readFileSync('/path/to/client-certificates/postgresql.crt').toString(),\n\t\t }\n\t\t */\n } as PoolConfig);\n\n const re: RegExpExecArray | null = new RegExp('//(.*)@').exec(poolConnectionString);\n let usernamepassword = '';\n if (re) {\n usernamepassword = re[1];\n }\n const sep: string[] = usernamepassword.split(':');\n const usernamepasswordReplacement: string = usernamepassword.replace(sep[1], '*****************************');\n const safeConnectionString = poolConnectionString.replace(usernamepassword, usernamepasswordReplacement);\n\n this.#pools[this.#GetPoolKey(poolIndex)] = {\n connectionString: poolConnectionString,\n safeConnectionString,\n pool\n }\n\n if (cluster.isPrimary) {\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool with Master Thread, PID: [${process.pid}]`));\n } else {\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool with Worker Thread, PID: [${process.pid}]`));\n }\n this.#LogDebugMessage(chalk.yellow(`Created Database Pool: Master Thread`));\n this.#LogDebugMessage(chalk.yellow(` Connection URI: [${safeConnectionString}]`));\n this.#LogDebugMessage(chalk.yellow(` Maximum Pool Size: [${poolSize}]`));\n this.#LogDebugMessage(chalk.yellow(` SSL Connection: [${isProduction}]`));\n\n // the pool will emit an error on behalf of any idle clients\n // it contains if a backend error or network partition happens\n pool.on('error', (error: Error) => {\n this.#LogDebugMessage(chalk.red(`[${safeConnectionString}]: pool error`));\n this.#LogErrorMessage(chalk.red(`Unexpected error on idle client: [${error}], connection: [${safeConnectionString}]`));\n });\n\n pool.on('connect', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool connect`));\n this.#UpdateInstruments();\n });\n\n pool.on('acquire', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool acquire`));\n this.#UpdateInstruments();\n });\n\n \n pool.on('release' as any, (error: Error) => {\n if (error) {\n this.#LogDebugMessage(chalk.red(`[${safeConnectionString}]: pool release`));\n this.#LogErrorMessage(chalk.red(`Unexpected error on client release from pool: [${error}], connection: [${safeConnectionString}]`));\n }\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool release`));\n this.#UpdateInstruments();\n });\n\n pool.on('remove', () => {\n //this.#LogDebugMessage(chalk.green(`[${safeConnectionString}]: pool remove`));\n this.#UpdateInstruments();\n });\n }\n\n async EndPool(poolItem: IPoolItem) {\n this.#LogDebugMessage(chalk.cyan(`Ending database for process PID: ${process.pid}`));\n if (poolItem) {\n this.#LogDebugMessage(chalk.cyan(`ending pool with connection string: [${poolItem.safeConnectionString}]`));\n this.#LogDebugMessage(chalk.cyan(`pool details (before end), Total: [${poolItem.pool.totalCount}], Idle: [${poolItem.pool.idleCount}], Waiting: [${poolItem.pool.waitingCount}]`));\n await poolItem.pool.end();\n this.#LogDebugMessage(chalk.cyan(`pool details (after end), Total: [${poolItem.pool.totalCount}], Idle: [${poolItem.pool.idleCount}], Waiting: [${poolItem.pool.waitingCount}]`));\n this.#LogDebugMessage(chalk.green(`Database pool ended for PID: ${process.pid}`));\n poolItem.pool.removeAllListeners();\n this.#LogDebugMessage(chalk.green(`Removed all listeners: ${process.pid}`));\n } else {\n this.#LogDebugMessage(chalk.yellow(`Database pool was not defined - not ended for PID: ${process.pid}`));\n }\n }\n\n async End() {\n this.#LogDebugMessage(chalk.cyan(`Ending database for process PID: ${process.pid}`));\n for (const [, pool] of Object.entries(this.#pools)) {\n await this.EndPool(pool); //@@ should use promise.all\n }\n this.#DetachInstruments();\n }\n\n #GetPoolKey(index: number): string {\n return `${this.#keyPrefix}${index}`;\n }\n\n async connectReadWrite(): Promise<PoolClient> {\n return this.#pools[this.#GetPoolKey(0)].pool.connect()\n }\n\n async connectReadOnly(): Promise<PoolClient> {\n // Select a random pool member\n const poolIndex = crypto.randomInt(0, Object.keys(this.#pools).length);\n return this.#pools[this.#GetPoolKey(poolIndex)].pool.connect()\n }\n\n //@@ make event using TinyEmitter\n #UpdateInstruments()\n {\n const data = {\n totalCount: 0,\n idleCount: 0,\n waitingCount: 0,\n }\n for (const [, poolItem] of Object.entries(this.#pools)) {\n data.totalCount += poolItem.pool.totalCount;\n data.idleCount += poolItem.pool.idleCount;\n data.waitingCount += poolItem.pool.waitingCount;\n }\n this.emit(IDBAccessLayerEvents.UpdateInstruments, data);\n }\n\n #AttachInstruments(interval = 1000) {\n this.#observer = setInterval(() =>\n {\n this.#UpdateInstruments();\n }, interval).unref();\n }\n\n #DetachInstruments() {\n clearInterval(this.#observer as NodeJS.Timeout);\n this.#observer = null;\n }\n}\n","import { PGPoolManager } from './pgpoolmanager.js'\nimport { ISTSLogger } from '@nsshunt/stsutils';\nimport { PoolClient } from 'pg';\n\nexport interface IDBSTSFhirDBBaseOptions {\n logger: ISTSLogger\n poolManager: PGPoolManager\n}\n\nexport abstract class DBSTSFhirDBBase {\n protected _options: IDBSTSFhirDBBaseOptions;\n protected _poolManager: PGPoolManager;\n\n constructor(options: IDBSTSFhirDBBaseOptions) {\n this._options = options;\n this._poolManager = options.poolManager;\n }\n\n async withClient<T>(fname: string, fn: (client: PoolClient) => Promise<T>): Promise<T> {\n let client: PoolClient;\n\n // Connection phase\n try {\n client = await this._poolManager.connectReadWrite();\n } catch (error) {\n this._options.logger.error(`${fname}(): DB: Connection Error: [${error}]`);\n throw error;\n }\n\n // Execution phase\n try {\n return await fn(client);\n } catch (error) {\n this._options.logger.error(`${fname}(): DB: Query Error: [${error}]`);\n throw error;\n } finally {\n client.release();\n }\n }\n}","import { PoolClient } from 'pg';\nimport { IResource } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBBase, IDBSTSFhirDBBaseOptions } from './pgfhirdbbase.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type NamedResourceInsert = {\n PID: string;\n PARTITION_ID: number;\n PARTITION_DATE: number;\n RES_ID: string;\n RES_VER: number;\n RES_VERSION: string;\n RES_TYPE: string;\n RES_PUBLISHED: number;\n RES_UPDATED: number;\n};\n\nexport type NamedResourceRead = {\n PID: string;\n};\n\nexport type NamedResourceDelete = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES_UPDATED: number;\n RES_DELETED_AT: number;\n};\n\nexport type NamedResourceUpdate = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES_UPDATED: number;\n};\n\nexport class DBSTSResource extends DBSTSFhirDBBase {\n constructor(options: IDBSTSFhirDBBaseOptions) {\n super(options);\n }\n\n async InsertResourceEx(client: PoolClient, data: NamedResourceInsert): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n INSERT INTO stsresfhir (\n PID, PARTITION_ID, PARTITION_DATE, RES_ID, RES_TYPE,\n RES_VER, RES_VERSION, RES_PUBLISHED, RES_UPDATED\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)\n RETURNING RES_VER\n `,\n [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER,\n data.RES_VERSION,\n BigInt(data.RES_PUBLISHED),\n BigInt(data.RES_UPDATED)\n ]\n );\n return res.rows[0]?.res_ver;\n } catch (error) {\n this._options.logger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async InsertResource(data: NamedResourceInsert): Promise<number | undefined> {\n return this.withClient('InsertResource', \n (client => this.InsertResourceEx(client, data)));\n }\n\n async UpdateResourceRecordEx(client: PoolClient, data: NamedResourceUpdate): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n UPDATE stsresfhir SET\n RES_VER = RES_VER + 1,\n RES_UPDATED = $1,\n RES_DELETED_AT = NULL\n WHERE RES_ID = $2 AND RES_TYPE = $3 AND RES_VER = $4\n RETURNING RES_VER\n `,\n [BigInt(data.RES_UPDATED), data.RES_ID, data.RES_TYPE, data.RES_VER]\n );\n return res.rows[0]?.res_ver;\n //return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n this._options.logger.error(`DBSTSResource:UpdateResourceRecordEx(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async UpdateResourceRecord(data: NamedResourceUpdate): Promise<number | undefined> {\n return this.withClient('UpdateResourceRecord', \n (client => this.UpdateResourceRecordEx(client, data)));\n }\n\n async DeleteResourceRecordEx(client: PoolClient, data: NamedResourceDelete): Promise<number | undefined> {\n try {\n const res = await client.query(\n `\n UPDATE stsresfhir SET\n RES_DELETED_AT = $1,\n RES_VER = RES_VER + 1,\n RES_UPDATED = $2\n WHERE RES_ID = $3 AND RES_TYPE = $4 AND RES_VER = $5\n RETURNING RES_VER\n `,\n [\n BigInt(data.RES_DELETED_AT),\n BigInt(data.RES_UPDATED),\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER\n ]\n );\n return res.rows[0]?.res_ver;\n //return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n this._options.logger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async DeleteResourceRecord(data: NamedResourceDelete): Promise<number | undefined> {\n return this.withClient('DeleteResourceRecord', \n (client => this.DeleteResourceRecordEx(client, data)));\n }\n\n async ReadResourceRecordEx(client: PoolClient, PID: string): Promise<IResource | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhir WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n this._options.logger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n throw (error);\n }\n }\n\n async ReadResourceRecord(PID: string): Promise<IResource | undefined> {\n return this.withClient('ReadResourceRecord', \n (client => this.ReadResourceRecordEx(client, PID)));\n }\n\n async ReadAllResourceRecordsEx(client: PoolClient): Promise<IResource[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhir`);\n return res.rows;\n } catch (error) {\n this._options.logger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n \n async ReadAllResourceRecords(): Promise<IResource[] | undefined> {\n return this.withClient('ReadAllResourceRecords', \n (client => this.ReadAllResourceRecordsEx(client)));\n }\n}\n","import { IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { PoolClient } from 'pg';\nimport { DBSTSFhirDBBase, IDBSTSFhirDBBaseOptions } from './pgfhirdbbase.js'\n\nexport type NamedResourceVersionInsert = {\n PID: string;\n PARTITION_ID: number;\n PARTITION_DATE: number;\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n OPERATION: 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n RES: string;\n};\n\nexport type NamedResourceVersionUpdate = {\n RES_ID: string;\n RES_TYPE: string;\n RES_VER: number;\n RES: string;\n};\n\nexport class DBSTSResourceVersion extends DBSTSFhirDBBase {\n constructor(options: IDBSTSFhirDBBaseOptions) {\n super(options);\n }\n\n async InsertResourceVersionEx(client: PoolClient, data: NamedResourceVersionInsert): Promise<number | undefined> {\n const values = [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.RES_ID,\n data.RES_TYPE,\n data.RES_VER,\n data.OPERATION,\n data.RES\n ];\n try {\n const res = await client.query(\n `\n INSERT INTO stsresfhirver (\n PID, PARTITION_ID, PARTITION_DATE,\n RES_ID, RES_TYPE, RES_VER, OPERATION, RES\n ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n RETURNING RES_VER\n `,values);\n return res.rows[0]?.res_ver;\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PID: [${values[0]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_ID: [${values[1]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_DATE: [${values[2]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_ID: [${values[3]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_TYPE: [${values[4]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_VER: [${values[5]}]`)\n this._options.logger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values OPERATION: [${values[6]}]`)\n throw error;\n }\n }\n\n async InsertResourceVersion(data: NamedResourceVersionInsert): Promise<number | undefined> {\n return this.withClient('InsertResourceVersion', \n (client => this.InsertResourceVersionEx(client, data)));\n }\n\n async ReadResourceVersionRecordEx(client: PoolClient, PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n try {\n const retVal = await client.query(`SELECT * FROM stsresfhirver WHERE PID = $1 AND RES_VER = $2`, [PID, RES_VER]);\n return retVal.rows[0];\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceVersionRecord(PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n return this.withClient('ReadResourceVersionRecord', \n (client => this.ReadResourceVersionRecordEx(client, PID, RES_VER)));\n }\n\n async ReadAllResourceVersionRecordsEx(client: PoolClient): Promise<IResourceVersion[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirver`);\n return res.rows;\n } catch (error) {\n this._options.logger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadAllResourceVersionRecords(): Promise<IResourceVersion[] | undefined> {\n return this.withClient('ReadAllResourceVersionRecords', \n (client => this.ReadAllResourceVersionRecordsEx(client)));\n }\n}\n","import { ISTSLogger } from '@nsshunt/stsutils';\n\nexport interface IDBSTSFhirDBParamTypeBaseOptions {\n logger: ISTSLogger\n}\n\nexport abstract class DBSTSFhirDBParamTypeBase {\n protected _options: IDBSTSFhirDBParamTypeBaseOptions;\n\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n this._options = options;\n }\n\n protected replacer = (_: any, v: any) => typeof v === 'bigint' ? { __bigint__: v.toString() } : v;\n protected reviver = (_: any, v: any) => v && v.__bigint__ !== undefined ? BigInt(v.__bigint__) : v;\n}\n","import { PoolClient } from 'pg';\nimport { IResourceLinkIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport interface INamedResourceLinkInsert {\n PID: string\n PARTITION_ID?: number\n PARTITION_DATE?: number\n SP_NAME: string,\n SP_PARAM_TYPE: string,\n SRC_PATH: string\n RES_TYPE: string\n RES_ID: string\n TARGET_RESOURCE_TYPE: string | null\n TARGET_RESOURCE_ID: string | null\n TARGET_RESOURCE_URL: string | null\n SP_STR: string | null\n UPDATED: bigint\n SP_MISSING: boolean\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n}\n\nexport interface INamedResourceLinkReadByResourceId {\n RES_ID: string;\n}\n\nexport interface INamedResourceLinkReadByPID {\n PID: string;\n}\n\nexport interface INamedResourceLinkDelete {\n RES_ID: string;\n RES_TYPE: string;\n}\n\nexport class DBSTSResourceLink extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertResourceLink(client: PoolClient, data: INamedResourceLinkInsert): Promise<void> {\n try {\n await client.query(\n `\n INSERT INTO stsresfhirlink (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE,\n SRC_PATH, \n RES_TYPE, \n RES_ID,\n TARGET_RESOURCE_TYPE, \n TARGET_RESOURCE_ID, \n TARGET_RESOURCE_URL, \n SP_STR, \n UPDATED, \n SP_MISSING,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, \n $6, $7, $8,\n $9, $10, $11, $12, $13, $14,\n $15, $16, $17\n )\n `,\n [\n data.PID,\n data.PARTITION_ID ?? 0,\n data.PARTITION_DATE ?? 0,\n data.SP_NAME,\n data.SP_PARAM_TYPE,\n data.SRC_PATH,\n data.RES_TYPE,\n data.RES_ID,\n data.TARGET_RESOURCE_TYPE,\n data.TARGET_RESOURCE_ID ?? null,\n data.TARGET_RESOURCE_URL ?? null,\n data.SP_STR,\n BigInt(data.UPDATED),\n data.SP_MISSING,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ]\n );\n } catch (error) {\n const message = `DBSTSResourceLink:InsertResourceLink(): Query Error: [${error}]`\n this._options.logger.error(message)\n throw new Error(message);\n }\n }\n\n async ReadResourceLinkByResourceIdRecord(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IResourceLinkIndexRecord[] | undefined> {\n try {\n const res = await client.query(\n `SELECT * FROM stsresfhirlink WHERE RES_ID = $1 AND RES_TYPE = $2`,\n [RES_ID, RES_TYPE]\n );\n return res.rows;\n } catch (error) {\n const message = `DBSTSResourceLink:ReadResourceLinkByResourceIdRecord(): Query Error: [${error}]`\n this._options.logger.error(message)\n throw new Error(message);\n }\n }\n\n async ReadResourceLinkByPIDRecord(client: PoolClient, PID: string): Promise<IResourceLinkIndexRecord | undefined> {\n try {\n const res = await client.query(\n `SELECT * FROM stsresfhirlink WHERE PID = $1 LIMIT 1`,\n [PID]\n );\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSResourceLink:ReadResourceLinkByPIDRecord(): Query Error: [${error}]`\n this._options.logger.error(message)\n throw new Error(message);\n }\n }\n\n async ReadAllResourceLinkRecords(client: PoolClient): Promise<IResourceLinkIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirlink`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSResourceLink:ReadAllResourceLinkRecords(): Query Error: [${error}]`;\n this._options.logger.error(message)\n throw new Error(message);\n }\n }\n\n async DeleteResourceLinkRecord(client: PoolClient, data: INamedResourceLinkDelete): Promise<void> {\n try {\n await client.query(\n `DELETE FROM stsresfhirlink WHERE RES_ID = $1 AND RES_TYPE = $2`,\n [data.RES_ID, data.RES_TYPE]\n );\n } catch (error) {\n const message = `DBSTSResourceLink:DeleteResourceLinkRecord(): Query Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirstring (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n HASH_EXACT BIGINT NOT NULL,\n SP_VALUE_NORMALIZED TEXT NOT NULL,\n SP_VALUE_EXACT TEXT NOT NULL,\n UPDATED BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsstring_hash_identity ON stsresfhirstring (HASH_IDENTITY);\nCREATE INDEX idx_stsstring_hash_exact ON stsresfhirstring (HASH_EXACT);\nCREATE INDEX idx_hash_value ON stsresfhirstring (HASH_IDENTITY, SP_VALUE_NORMALIZED);\n*/\nimport { PoolClient } from 'pg';\nimport { IStringIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { normalizeStringParam, hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedInsert = {\n PID: string\n PARTITION_ID?: number\n PARTITION_DATE?: number\n SP_NAME?: string\n SP_PARAM_TYPE: string\n RES_ID: string\n RES_TYPE?: string\n UPDATED?: bigint\n SP_MISSING: boolean\n SP_STR: string | null\n HASH_IDENTITY: bigint\n HASH_EXACT: bigint | null\n SP_VALUE_NORMALIZED: string | null\n SP_VALUE_EXACT: string | null\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadByPID {\n PID: string;\n}\n\nexport interface INamedDelete {\n RES_ID: string;\n RES_TYPE: string;\n}\n\nexport interface INamedReadBase {\n SP_NAME?: string;\n RES_TYPE?: string;\n}\n\nexport interface INamedReadByExact extends INamedReadBase {\n HASH_EXACT: bigint;\n}\n\nexport interface INamedReadByValueNormalised extends INamedReadBase {\n HASH_IDENTITY: bigint;\n SP_VALUE_NORMALIZED: string;\n}\n\nexport interface INamedReadByResID {\n RES_ID: string;\n}\n\nexport class DBSTSString extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedInsert): Promise<void> {\n try {\n await client.query(\n `\n INSERT INTO stsresfhirstring (\n PID, \n PARTITION_ID, \n PARTITION_DATE,\n SP_NAME, \n SP_PARAM_TYPE, \n RES_ID, \n RES_TYPE,\n SP_MISSING, \n SP_STR, \n HASH_IDENTITY, \n HASH_EXACT,\n SP_VALUE_NORMALIZED, \n SP_VALUE_EXACT, \n UPDATED,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3,\n $4, $5, $6, $7,\n $8, $9, $10,\n $11, $12, $13, $14,\n $15, $16, $17\n )\n `,\n [\n data.PID,\n data.PARTITION_ID,\n data.PARTITION_DATE,\n data.SP_NAME ?? null,\n data.SP_PARAM_TYPE,\n data.RES_ID,\n data.RES_TYPE ?? null,\n data.SP_MISSING,\n data.SP_STR,\n data.HASH_IDENTITY,\n data.HASH_EXACT,\n data.SP_VALUE_NORMALIZED,\n data.SP_VALUE_EXACT,\n data.UPDATED,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ]\n );\n } catch (error) {\n const message = `DBSTSString:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IStringIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirstring WHERE PID = $1 LIMIT 1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSString:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IStringIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirstring`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSString:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #FilterResults(data: INamedReadBase, results: IStringIndexRecord[]): IStringIndexRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSString:#FilterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByValueNormalized(client: PoolClient, searchString: string, parameterName: string, resourceName: string): Promise<IStringIndexRecord[]> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const norm = normalizeStringParam(searchString);\n\n const res = await client.query(\n `SELECT * FROM stsresfhirstring WHERE HASH_IDENTITY = $1 AND SP_VALUE_NORMALIZED LIKE $2`,\n [hash, norm]\n );\n\n return this.#FilterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSString:ReadByValueNormalized(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByValueExact(client: PoolClient, data: INamedReadByExact): Promise<IStringIndexRecord[]> {\n try {\n const res = await client.query(\n `SELECT * FROM stsresfhirstring WHERE HASH_EXACT = $1`,\n [BigInt(data.HASH_EXACT)]\n );\n\n return this.#FilterResults(data, res.rows);\n } catch (error) {\n const message = `DBSTSString:ReadByValueExact(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IStringIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirstring WHERE RES_ID = $1 AND RES_TYPE = $2`, [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSString:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhirstring WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSString:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirtoken (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE TEXT NOT NULL,\n HASH_VALUE BIGINT NOT NULL,\n HASH_SYS BIGINT NOT NULL,\n HASH_SYS_AND_VALUE BIGINT NOT NULL\n);\n\nCREATE INDEX idx_ststoken_hash_identity ON stsresfhirtoken (HASH_IDENTITY);\nCREATE INDEX idx_ststoken_hash_value ON stsresfhirtoken (HASH_VALUE);\nCREATE INDEX idx_ststoken_hash_sys ON stsresfhirtoken (HASH_SYS);\nCREATE INDEX idx_ststoken_hash_sys_and_value ON stsresfhirtoken (HASH_SYS_AND_VALUE);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { ITokenIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_SYSTEM: string | null // The system of the code.\n SP_TOKEN_TYPE: string | null // The token type\n SP_VALUE: string | null // This is the bare code value.\n HASH_VALUE: bigint | null // A hash like HASH_IDENTITY (paramName|resType) that also includes the SP_VALUE column. (paramName|resType|value)\n HASH_SYS: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM column. (paramName|resType|system)\n HASH_SYS_AND_VALUE: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM and SP_VALUE columns. (paramName|resType|system|value)\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadByPID {\n PID: string\n};\n\nexport interface INamedDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\nexport interface INamedReadBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n\nexport class DBSTSToken extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhirtoken (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR, \n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_SYSTEM, \n SP_TOKEN_TYPE, \n SP_VALUE,\n HASH_VALUE, \n HASH_SYS, \n HASH_SYS_AND_VALUE,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15, $16, $17,\n $18, $19, $20\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_SYSTEM, \n data.SP_TOKEN_TYPE,\n data.SP_VALUE, \n data.HASH_VALUE,\n data.HASH_SYS, \n data.HASH_SYS_AND_VALUE,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSToken:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhirtoken WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSToken:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<ITokenIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSToken:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<ITokenIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirtoken`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSToken:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_IDENTITY = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSToken:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByValue(client: PoolClient, searchValue: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchValue}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_VALUE = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSToken:ReadByValue(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadBySystem(client: PoolClient, searchSystem: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_SYS = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSToken:ReadBySystem(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadBySystemAndValue(client: PoolClient, searchSystem: string, searchValue: string, parameterName: string, resourceName: string): Promise<ITokenIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}|${searchValue}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE HASH_SYS_AND_VALUE = $1`, [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSToken:ReadBySystemAndValue(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<ITokenIndexRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirtoken WHERE RES_ID = $1 AND RES_TYPE = $2`, [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSToken:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: ITokenIndexRecord[]): ITokenIndexRecord[] {\n try{\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSToken:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirquantity (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE DECIMAL NOT NULL,\n SP_UNITS TEXT NOT NULL,\n HASH_IDENTITY_AND_UNITS BIGINT NOT NULL,\n HASH_IDENTITY_SYS_UNITS BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsquantity_hash_identity ON stsresfhirquantity (HASH_IDENTITY);\nCREATE INDEX idx_stsquantity_hash_units ON stsresfhirquantity (HASH_IDENTITY_AND_UNITS);\nCREATE INDEX idx_stsquantity_hash_sys_units ON stsresfhirquantity (HASH_IDENTITY_SYS_UNITS);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IQuantityIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedQuantityInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_SYSTEM: string | null // The system of the quantity units. e.g. \"http://unitsofmeasure.org\".\n SP_VALUE: number | null // This is the value extracted by the SearchParameter expression. Note that this is a DECIMAL. String conversion used here to preserve precision.\n SP_UNITS: string | null // The units of the quantity. E.g. \"mg\".\n HASH_IDENTITY_AND_UNITS: bigint | null// A hash like HASH_IDENTITY that also includes the SP_UNITS column.\n HASH_IDENTITY_SYS_UNITS: bigint | null // A hash like HASH_IDENTITY that also includes the SP_SYSTEM and SP_UNITS columns.\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadQuantityByPID {\n PID: string\n};\n\nexport interface INamedQuantityDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSQuantity extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedQuantityInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhirquantity (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_SYSTEM, \n SP_VALUE,\n SP_UNITS, \n HASH_IDENTITY_AND_UNITS, \n HASH_IDENTITY_SYS_UNITS,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15, $16,\n $17, $18, $19\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID, \n data.PARTITION_DATE, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_SYSTEM, \n data.SP_VALUE, \n data.SP_UNITS,\n data.HASH_IDENTITY_AND_UNITS,\n data.HASH_IDENTITY_SYS_UNITS,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSQuantity:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedQuantityDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhirquantity WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSQuantity:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IQuantityIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSQuantity:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IQuantityIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirquantity`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSQuantity:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSQuantity:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByUnits(client: PoolClient, units: string, searchValue: string, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${units}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY_AND_UNITS = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSQuantity:ReadByUnits(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadBySystemAndUnits(client: PoolClient, searchSystem: string, units: string, searchValue: string, parameterName: string, resourceName: string): Promise<IQuantityIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${searchSystem}|${units}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE HASH_IDENTITY_SYS_UNITS = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSQuantity:ReadBySystemAndUnits(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IQuantityIndexRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirquantity WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSQuantity:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IQuantityIndexRecord[]): IQuantityIndexRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSQuantity:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirquantity (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_SYSTEM TEXT NOT NULL,\n SP_VALUE DECIMAL NOT NULL,\n SP_UNITS TEXT NOT NULL,\n HASH_IDENTITY_AND_UNITS BIGINT NOT NULL,\n HASH_IDENTITY_SYS_UNITS BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsquantity_hash_identity ON stsresfhirquantity (HASH_IDENTITY);\nCREATE INDEX idx_stsquantity_hash_units ON stsresfhirquantity (HASH_IDENTITY_AND_UNITS);\nCREATE INDEX idx_stsquantity_hash_sys_units ON stsresfhirquantity (HASH_IDENTITY_SYS_UNITS);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { INumberIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedNumberInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_VALUE: number\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedNumberDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSNumber extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedNumberInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhirnumber (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_VALUE,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_VALUE ?? 0,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n \n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSNumber:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedNumberDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhirnumber WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSNumber:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<INumberIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSNumber:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<INumberIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirnumber`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSNumber:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<INumberIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSNumber:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByValue(client: PoolClient, searchValue: string, parameterName: string, resourceName: string): Promise<INumberIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE HASH_IDENTITY = $1 AND SP_VALUE = $2`, \n [hash, searchValue]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSNumber:ReadByValue(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<INumberIndexRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirnumber WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSNumber:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: INumberIndexRecord[]): INumberIndexRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSNumber:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhirdate (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_VALUE_LOW timestamp with time zone,\n SP_VALUE_HIGH timestamp with time zone,\n SP_VALUE_LOW_DATE_ORDINAL INTEGER,\n SP_VALUE_HIGH_DATE_ORDINAL INTEGER\n);\n\nCREATE INDEX idx_stsresfhirdate_hash_identity ON stsresfhirdate (HASH_IDENTITY);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IDateIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DateTime } from 'luxon';\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedDateInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_VALUE_LOW: DateTime | null // This is the lower bound of the date in question.\n SP_VALUE_HIGH: DateTime | null // This is the upper bound of the date in question.\n SP_VALUE_LOW_DATE_ORDINAL: number | null // This column contains the same Timestamp as SP_VALUE_LOW, but truncated to Date precision and formatted as an integer in the format \"YYYYMMDD\".\n SP_VALUE_HIGH_DATE_ORDINAL: number | null // This column contains the same Timestamp as SP_VALUE_HIGH, but truncated to Date precision and formatted as an integer in the format \"YYYYMMDD\".\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadDateByPID {\n PID: string\n};\n\nexport interface INamedDateDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSDate extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedDateInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhirdate (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_VALUE_LOW,\n SP_VALUE_HIGH,\n SP_VALUE_LOW_DATE_ORDINAL,\n SP_VALUE_HIGH_DATE_ORDINAL,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12,\n $13, $14, $15,\n $16, $17, $18\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n (data.SP_VALUE_LOW ? data.SP_VALUE_LOW.toJSDate() : null),\n (data.SP_VALUE_HIGH ? data.SP_VALUE_HIGH.toJSDate() : null),\n data.SP_VALUE_LOW_DATE_ORDINAL,\n data.SP_VALUE_HIGH_DATE_ORDINAL,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSDate:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedDateDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhirdate WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSDate:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IDateIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE PID = $1`, [PID]);\n\n if (res.rows && res.rows.length === 1) {\n if (res.rows[0].sp_value_high !== null) {\n res.rows[0].sp_value_high = DateTime.fromJSDate(res.rows[0].sp_value_high);\n }\n if (res.rows[0].sp_value_low !== null) {\n res.rows[0].sp_value_low = DateTime.fromJSDate(res.rows[0].sp_value_low);\n }\n }\n\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSDate:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IDateIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirdate`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSDate:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByDateTime(client: PoolClient, SP_VALUE_LOW: DateTime, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW >= $2 AND SP_VALUE_HIGH <= $3`, \n [hash, SP_VALUE_LOW, SP_VALUE_HIGH]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateTime(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByDateTimeLow(client: PoolClient, SP_VALUE_LOW: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW >= $2`, \n [hash, SP_VALUE_LOW]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateTimeLow(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByDateTimeHigh(client: PoolClient, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_HIGH <= $2`, \n [hash, SP_VALUE_HIGH]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateTimeHigh(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByDateOrdinal(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW_DATE_ORDINAL >= $2 AND SP_VALUE_HIGH_DATE_ORDINAL <= $3`, \n [hash, SP_VALUE_LOW_DATE_ORDINAL, SP_VALUE_HIGH_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateOrdinal(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByDateOrdinalLow(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_LOW_DATE_ORDINAL >= $2`, \n [hash, SP_VALUE_LOW_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateOrdinalLow(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByDateOrdinalHigh(client: PoolClient, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE HASH_IDENTITY = $1 AND SP_VALUE_HIGH_DATE_ORDINAL <= $2`, \n [hash, SP_VALUE_HIGH_DATE_ORDINAL]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSDate:ReadByDateOrdinalHigh(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IDateIndexRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhirdate WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSDate:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IDateIndexRecord[]): IDateIndexRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSDate:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhiruri (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n SP_URI TEXT NOT NULL,\n\tHASH_URI BIGINT NOT NULL\n);\n\nCREATE INDEX idx_stsresfhiruri_hash_identity ON stsresfhiruri (HASH_IDENTITY);\nCREATE INDEX idx_stsresfhiruri_hash_uri ON stsresfhiruri (HASH_URI);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IUriIndexRecord } from '../../fhir-utils/commonTypes.js'\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedUriInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null,\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n SP_URI: string | null // \n HASH_URI: bigint | null // \n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadUriByPID {\n PID: string\n};\n\nexport interface INamedUriDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\n/*\nexport interface INamedReadQuantityBase {\n SP_NAME?: string // This is the name of the search parameter being indexed.\n RES_TYPE?: string // This is the name of the resource being indexed.\n}\n\nexport interface INamedReadByIdentity extends INamedReadBase {\n HASH_IDENTITY: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadBySystem extends INamedReadBase {\n HASH_SYS: bigint // A hash like HASH_IDENTITY that also includes the SP_VALUE_EXACT column.\n};\n\nexport interface INamedReadByValue extends INamedReadBase {\n HASH_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadBySystemAndValue extends INamedReadBase {\n HASH_SYS_AND_VALUE: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n};\n\nexport interface INamedReadByResID {\n RES_ID: string\n}\n*/\n\nexport class DBSTSUri extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedUriInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhiruri (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n SP_URI, \n HASH_URI,\n PATH_FOR_COMP,\n COMPOSITE,\n COMPOSITE_HASH_EXACT\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12, $13,\n $14, $15, $16\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID ?? 0, \n data.PARTITION_DATE ?? 0, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.SP_URI, \n data.HASH_URI,\n data.PATH_FOR_COMP,\n data.COMPOSITE,\n (data.COMPOSITE_HASH_EXACT ? BigInt(data.COMPOSITE_HASH_EXACT) : null)\n ];\n\n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSUri:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedUriDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhiruri WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSUri:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IUriIndexRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSUri:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IUriIndexRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhiruri`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSUri:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IUriIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSUri:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByURI(client: PoolClient, uri: string, parameterName: string, resourceName: string): Promise<IUriIndexRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}|${uri}`, true);\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE HASH_URI = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSUri:ReadByURI(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IUriIndexRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhiruri WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSUri:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IUriIndexRecord[]): IUriIndexRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSUri:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","/*\nCREATE TABLE stsresfhircombo (\n PID UUID PRIMARY KEY,\n PARTITION_ID INTEGER,\n PARTITION_DATE INTEGER,\n SP_NAME TEXT NOT NULL,\n SP_PARAM_TYPE TEXT NOT NULL,\n RES_ID TEXT NOT NULL,\n RES_TYPE TEXT NOT NULL,\n UPDATED BIGINT NOT NULL,\n SP_MISSING BOOLEAN NOT NULL,\n HASH_IDENTITY BIGINT NOT NULL,\n\tIDX_STRING TEXT,\n\tHASH_COMPLETE BIGINT\n);\n\nCREATE INDEX idx_stsresfhircombo_hash_identity ON stsresfhircombo (HASH_IDENTITY);\nCREATE INDEX idx_stsresfhircombo_hash_complete ON stsresfhircombo (HASH_COMPLETE);\n*/\n\nimport { PoolClient } from 'pg';\nimport { hashStringParam } from '../../fhir-utils/fhirHashUtils.js'\nimport { IComboNonUniqueRecord } from '../../fhir-utils/commonTypes.js'\nimport { DateTime } from 'luxon';\nimport { DBSTSFhirDBParamTypeBase, IDBSTSFhirDBParamTypeBaseOptions } from './pgfhirdbparamtypebase.js'\n\nexport type INamedComboInsert = {\n PID: string // Holds the persistent ID - uuidv4\n PARTITION_ID?: number // This is the optional partition ID, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n PARTITION_DATE?: number // This is the optional partition date, if the resource is in a partition. See Partitioning. Note that the partition indicated by the PARTITION_ID and PARTITION_DATE columns refers to the partition of the SOURCE resource, and not necessarily the TARGET.\n SP_NAME: string // This is the name of the search parameter being indexed.\n SP_PARAM_TYPE: string // The paramater data type\n SP_STR: string | null\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string // This is the name of the resource being indexed.\n UPDATED: bigint // This is the time that this row was last updated.\n SP_MISSING: boolean // If this row represents a search parameter that is **not** populated at all in the resource being indexed, this will be populated with the value `true`. Otherwise it will be populated with `false`.\n HASH_IDENTITY: bigint // A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n IDX_STRING: string | null, //\n HASH_COMPLETE: bigint | null// A hash of paramName and resType. Used to narrow the table to a specific SearchParameter during sorting, and some queries.\n PATH_FOR_COMP: string | null\n COMPOSITE: string | null\n COMPOSITE_HASH_EXACT: bigint | null\n};\n\nexport interface INamedReadComboByPID {\n PID: string\n};\n\nexport interface INamedComboDelete {\n RES_ID: string // Contains the PID of the resource being indexed. FK to resource table.\n RES_TYPE: string\n};\n\nexport class DBSTSCombo extends DBSTSFhirDBParamTypeBase {\n constructor(options: IDBSTSFhirDBParamTypeBaseOptions) {\n super(options);\n }\n\n async InsertRecord(client: PoolClient, data: INamedComboInsert): Promise<void> {\n try {\n const text = `\n INSERT INTO stsresfhircombo (\n PID, \n PARTITION_ID, \n PARTITION_DATE, \n SP_NAME, \n SP_PARAM_TYPE, \n SP_STR,\n RES_ID,\n RES_TYPE, \n UPDATED, \n SP_MISSING, \n HASH_IDENTITY, \n IDX_STRING,\n HASH_COMPLETE\n ) VALUES (\n $1, $2, $3, $4, $5, $6,\n $7, $8, $9, $10, $11, $12, $13\n )`;\n\n const values = [\n data.PID, \n data.PARTITION_ID, \n data.PARTITION_DATE, \n data.SP_NAME, \n data.SP_PARAM_TYPE, \n data.SP_STR,\n data.RES_ID,\n data.RES_TYPE, \n BigInt(data.UPDATED), \n data.SP_MISSING, \n BigInt(data.HASH_IDENTITY),\n data.IDX_STRING,\n data.HASH_COMPLETE\n ];\n\n await client.query(text, values);\n } catch (error) {\n const message = `DBSTSCombo:InsertRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async DeleteRecord(client: PoolClient, data: INamedComboDelete): Promise<void> {\n try {\n await client.query(`DELETE FROM stsresfhircombo WHERE RES_ID = $1 AND RES_TYPE = $2`, [data.RES_ID, data.RES_TYPE]);\n } catch (error) {\n const message = `DBSTSCombo:DeleteRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByPIDRecord(client: PoolClient, PID: string): Promise<IComboNonUniqueRecord | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE PID = $1`, [PID]);\n return res.rows[0];\n } catch (error) {\n const message = `DBSTSCombo:ReadByPIDRecord(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadAllRecords(client: PoolClient): Promise<IComboNonUniqueRecord[]> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhircombo`);\n return res.rows;\n } catch (error) {\n const message = `DBSTSCombo:ReadAllRecords(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByIdentity(client: PoolClient, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n try {\n const hash = hashStringParam(`${parameterName}|${resourceName}`, true);\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE HASH_IDENTITY = $1`, \n [hash]);\n return this.#filterResults({ SP_NAME: parameterName, RES_TYPE: resourceName }, res.rows);\n } catch (error) {\n const message = `DBSTSCombo:ReadByIdentity(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n async ReadByString(client: PoolClient, stringVal: string, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n // All these need to handle\n // https://www.hl7.org/fhir/search.html#prefix\n async ReadByDateTime(client: PoolClient, SP_VALUE_LOW: DateTime, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateTimeLow(client: PoolClient, SP_VALUE_LOW: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateTimeHigh(client: PoolClient, SP_VALUE_HIGH: DateTime, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinal(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinalLow(client: PoolClient, SP_VALUE_LOW_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByDateOrdinalHigh(client: PoolClient, SP_VALUE_HIGH_DATE_ORDINAL: number, parameterName: string, resourceName: string): Promise<IComboNonUniqueRecord[] | undefined> {\n return [ ];\n }\n\n async ReadByResID(client: PoolClient, RES_ID: string, RES_TYPE: string): Promise<IComboNonUniqueRecord[] | undefined> {\n try {\n const res = await client.query(`SELECT * FROM stsresfhircombo WHERE RES_ID = $1 AND RES_TYPE = $2`, \n [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n const message = `DBSTSCombo:ReadByResID(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n\n #filterResults(data: { SP_NAME?: string; RES_TYPE?: string }, results: IComboNonUniqueRecord[]): IComboNonUniqueRecord[] {\n try {\n return results.filter(r =>\n r.SP_NAME === data.SP_NAME && r.RES_TYPE === data.RES_TYPE\n );\n } catch (error) {\n const message = `DBSTSCombo:#filterResults(): Error: [${error}]`;\n this._options.logger.error(message);\n throw new Error(message);\n }\n }\n}\n","\nimport { randomUUID } from 'node:crypto';\nimport { PGPoolManager } from './pgpoolmanager.js'\nimport { defaultLogger, ISTSLogger, JSONObject } from '@nsshunt/stsutils'\n \nimport { TinyEmitter } from 'tiny-emitter';\n\nimport { DBSTSResource } from './pgfhirresource.js'\nimport { DBSTSResourceVersion } from './pgfhirresourceversion.js'\n\nimport { IResource, IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { DBSearchIndex } from '../dbsearchindex.js'\n\nimport { IComboNonUniqueRecord, INumberIndexRecord, IQuantityIndexRecord, IResourceLinkIndexRecord, \n IStringIndexRecord, ITokenIndexRecord, IDateIndexRecord, IUriIndexRecord } from '../../fhir-utils/commonTypes.js'\n\nimport { DBSTSResourceLink } from './pgfhirresourcelink.js'\n\nimport { Resource, OperationOutcome } from '@nsshunt/stsfhirclient';\n\nimport { PoolClient } from 'pg';\nimport { DBSTSString } from './pgfhirstring.js'\nimport { DBSTSToken } from './pgfhirtoken.js'\nimport { DBSTSQuantity } from './pgfhirquantity.js'\nimport { DBSTSNumber } from './pgfhirnumber.js'\nimport { DBSTSDate } from './pgfhirdate.js'\nimport { DBSTSUri } from './pgfhiruri.js'\nimport { DBSTSCombo } from './pgfhircombo.js'\nimport { DateTime } from 'luxon';\n\nimport chalk from 'chalk';\nchalk.level = 3;\n\nexport interface IPGAccessLayerOptions {\n usedefaultdb: boolean\n logger: ISTSLogger\n}\n\ninterface ITransactionRecord {\n client: PoolClient,\n timeout: NodeJS.Timeout\n}\n\nexport class PGFhirAccessLayer extends TinyEmitter {\n #options: IPGAccessLayerOptions;\n #poolManager: PGPoolManager | null = null;\n #dbSTSResource: DBSTSResource;\n #dbSTSResourceVersion: DBSTSResourceVersion;\n #dbSearchIndex: DBSearchIndex;\n #dbSTSResourceLink: DBSTSResourceLink;\n #dbSTSString: DBSTSString;\n #dbSTSToken: DBSTSToken;\n #dbSTSQuantity: DBSTSQuantity;\n #dbSTSNumber: DBSTSNumber;\n #dbSTSDate: DBSTSDate;\n #dbSTSUri: DBSTSUri;\n #dbSTSCombo: DBSTSCombo;\n #transactions: Record<string, ITransactionRecord> = { };\n #maxTransactionTime: number = 60000; //@@ 1 minute for transactions max\n\n constructor(options: IPGAccessLayerOptions) {\n super();\n\n this.#options = options;\n\n this.#poolManager = new PGPoolManager({\n logger: this.#options.logger,\n usedefaultdb: this.#options.usedefaultdb\n });\n\n this.#dbSTSResource = new DBSTSResource({\n logger: this.#options.logger,\n poolManager: this.#poolManager\n } );\n this.#dbSTSResourceVersion = new DBSTSResourceVersion({\n logger: this.#options.logger,\n poolManager: this.#poolManager\n });\n\n this.#dbSearchIndex = DBSearchIndex.getInstance();\n\n this.#dbSTSResourceLink = new DBSTSResourceLink({ logger: this.#options.logger });\n this.#dbSTSString = new DBSTSString({ logger: this.#options.logger });\n this.#dbSTSToken = new DBSTSToken({ logger: this.#options.logger });\n this.#dbSTSQuantity = new DBSTSQuantity({ logger: this.#options.logger });\n this.#dbSTSNumber = new DBSTSNumber({ logger: this.#options.logger });\n this.#dbSTSDate = new DBSTSDate({ logger: this.#options.logger });\n this.#dbSTSUri = new DBSTSUri({ logger: this.#options.logger });\n this.#dbSTSCombo = new DBSTSCombo({ logger: this.#options.logger });\n\n //this.#poolManager.on(IDBAccessLayerEvents.UpdateInstruments, this.#UpdateInstruments);\n }\n\n GetOperationOutcome = (code: string, diagnostics: string): OperationOutcome => {\n return {\n resourceType: \"OperationOutcome\",\n issue: [\n {\n severity: \"error\",\n code, // \"invalid\",\n diagnostics\n }\n ]\n }\n }\n\n /*\n #UpdateInstruments = (data: any) => {\n this.emit(IDBAccessLayerEvents.UpdateInstruments, data);\n }\n */\n\n // Method only used for testing. Ensure that if redis is being used that the cache is always flushed.\n async StartDatabase(): Promise<boolean> {\n return true;\n }\n\n async EndDatabase(): Promise<boolean> {\n if (this.#poolManager) {\n //this.#poolManager.off(IDBAccessLayerEvents.UpdateInstruments, this.#UpdateInstruments);\n await this.#poolManager.End();\n }\n this.#poolManager = null;\n return true;\n }\n\n GetFhirResourceController = (): DBSTSResource => {\n return this.#dbSTSResource;\n }\n\n GetFhirResourceVersionController = (): DBSTSResourceVersion => {\n return this.#dbSTSResourceVersion;\n }\n\n UpdateIndexes = async (client: PoolClient, resource: Resource) => {\n let start = performance.now();\n const oa = start;\n const searchIndexData = await this.#dbSearchIndex.GetSearchIndexData(resource);\n\n const lap1 = performance.now() - start;\n start = performance.now();\n\n const InsertResourceLinkRecord = async (client: PoolClient, resourceLinkIndexRecord: IResourceLinkIndexRecord) => {\n const retVal = await this.#dbSTSResourceLink.InsertResourceLink(client, resourceLinkIndexRecord);\n }\n\n const InsertResourceStringRecord = async (client: PoolClient, stringRecord: IStringIndexRecord) => {\n const retVal = await this.#dbSTSString.InsertRecord(client, stringRecord);\n }\n\n const InsertResourceTokenRecord = async (client: PoolClient, tokenRecord: ITokenIndexRecord) => {\n const retVal = await this.#dbSTSToken.InsertRecord(client, tokenRecord);\n }\n\n const InsertResourceQuantityRecord = async (client: PoolClient, quantityRecord: IQuantityIndexRecord) => {\n const retVal = await this.#dbSTSQuantity.InsertRecord(client, quantityRecord);\n }\n\n const InsertResourceNumberRecord = async (client: PoolClient, numberRecord: INumberIndexRecord) => {\n const retVal = await this.#dbSTSNumber.InsertRecord(client, numberRecord);\n }\n\n const InsertResourceDateRecord = async (client: PoolClient, dateRecord: IDateIndexRecord) => {\n const retVal = await this.#dbSTSDate.InsertRecord(client, dateRecord);\n }\n\n const InsertResourceUriRecord = async (client: PoolClient, uriRecord: IUriIndexRecord) => {\n const retVal = await this.#dbSTSUri.InsertRecord(client, uriRecord);\n }\n\n const InsertResourceComboRecord = async (client: PoolClient, comboRecord: IComboNonUniqueRecord) => {\n const retVal = await this.#dbSTSCombo.InsertRecord(client, comboRecord);\n }\n\n // Delete previous index records for this resource\n await this.#dbSTSResourceLink.DeleteResourceLinkRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSString.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSToken.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSQuantity.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSNumber.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSDate.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSUri.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n await this.#dbSTSCombo.DeleteRecord(client, { RES_ID: resource.id!, RES_TYPE: resource.resourceType });\n\n const lap2 = performance.now() - start;\n start = performance.now();\n \n try {\n for (let i=0; i < searchIndexData.length; i++) {\n const si = searchIndexData[i];\n const st = performance.now();\n\n if (si && (si as any).SP_MISSING) {\n //console.log(chalk.magenta.italic(`-->> MISSING ${si.SP_NAME} ${si.SP_PARAM_TYPE} ${si.PID} ${si.SP_STR}`));\n //console.log(JSON.stringify(si, this.#replacer, 2));\n } else {\n //console.log(chalk.green(`-->> ${si.SP_NAME} ${si.SP_PARAM_TYPE} ${si.PID} ${si.SP_STR}`));\n }\n\n switch (si.SP_PARAM_TYPE) {\n case 'reference' :\n await InsertResourceLinkRecord(client, si as IResourceLinkIndexRecord);\n break;\n case 'string' :\n await InsertResourceStringRecord(client, si as IStringIndexRecord);\n break;\n case 'token' :\n await InsertResourceTokenRecord(client, si as ITokenIndexRecord);\n break;\n case 'quantity' :\n await InsertResourceQuantityRecord(client, si as IQuantityIndexRecord);\n break;\n case 'number' :\n await InsertResourceNumberRecord(client, si as INumberIndexRecord);\n break;\n case 'date' :\n await InsertResourceDateRecord(client, si as IDateIndexRecord);\n break;\n case 'uri' :\n await InsertResourceUriRecord(client, si as IUriIndexRecord);\n break;\n case 'composite' :\n await InsertResourceComboRecord(client, si as IComboNonUniqueRecord);\n break;\n default :\n //console.log(`-->> ${si.SP_PARAM_TYPE} *** UNKNOWN ***`);\n }\n //console.log(` -->> individual index [${si.SP_PARAM_TYPE}] update time: [${(performance.now() - st)}]`)\n };\n\n //console.log(` -->> index update time: [${(performance.now() - st1)}]`)\n } catch (error) {\n console.error(error);\n }\n const lap3 = performance.now() - start;\n const total = performance.now() - oa;\n\n if (total > 100.0) {\n console.log(chalk.hex('#E33A36')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n } else if (total > 75.0) {\n console.log(chalk.hex('#e27270')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n } else if (total > 50.0) {\n console.log(chalk.hex('#e2c3c2')(`--> Slow: O/A:[${total.toFixed(2)}] Index Calc:[${lap1.toFixed(2)}] Delete:[${lap2.toFixed(2)}] Insert:[${lap3.toFixed(2)}]`));\n }\n }\n\n #isInTransaction = async (client: PoolClient): Promise<boolean> => {\n const res = await client.query(`\n SELECT txid_current_if_assigned() AS txid\n `);\n return res.rows[0].txid !== null;\n }\n\n\n BeginTransaction = async (): Promise<string | undefined> => {\n if (this.#poolManager) {\n try {\n const transactionHandle = randomUUID();\n const client = await this.#poolManager.connectReadWrite();\n try {\n await client.query('BEGIN');\n this.#transactions[transactionHandle] = {\n client,\n timeout: setTimeout(async () => {\n await this.#transactions[transactionHandle].client.query('ROLLBACK');\n client.release();\n delete this.#transactions[transactionHandle];\n }, this.#maxTransactionTime)\n }\n return transactionHandle;\n } catch (error) {\n console.error(error);\n client.release();\n }\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n CommitTransaction = async (transactionHandle: string): Promise<boolean> => {\n if (this.#transactions[transactionHandle]) {\n clearInterval(this.#transactions[transactionHandle].timeout);\n const client = this.#transactions[transactionHandle].client;\n try {\n await client.query('COMMIT');\n client.release();\n delete this.#transactions[transactionHandle];\n return true;\n } catch (error) {\n console.error(error);\n client.release();\n delete this.#transactions[transactionHandle];\n return false;\n }\n }\n return false;\n }\n\n RollbackTransaction = async (transactionHandle: string): Promise<boolean> => {\n if (this.#transactions[transactionHandle]) {\n clearInterval(this.#transactions[transactionHandle].timeout);\n const client = this.#transactions[transactionHandle].client;\n try {\n await client.query('ROLLBACK');\n client.release();\n delete this.#transactions[transactionHandle];\n return true;\n } catch (error) {\n console.error(error);\n client.release();\n delete this.#transactions[transactionHandle];\n return false;\n }\n }\n return false;\n }\n\n //begin X - returns a handle in a recordset\n CreateResource = async (resource: Resource, transactionHandle?: string): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `CreateResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `CreateResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.InsertResourceEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: 1,\n RES_VERSION: 'r5', //@@ needs to be from FHIR\n RES_PUBLISHED: now,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `CreateResource(): Version Conflict. newVersion is undefined.`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const RES = JSON.stringify(resource);\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: 'POST',\n RES\n })\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `CreateResource(): Version Conflict. resourceVersionRunResult is undefined.`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n const st = performance.now();\n await this.UpdateIndexes(client, resource);\n //console.log(` -->> Update Index Time: ${(performance.now() - st) / 1000.0}`);\n\n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `CreateResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n UpdateResource = async (resource: Resource, RES_VER: number, operation: 'PUT' | 'PATCH', transactionHandle: string | undefined): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `UpdateResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `UpdateResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.UpdateResourceRecordEx(client, {\n RES_TYPE,\n RES_ID,\n RES_VER,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `UpdateResource(): Version Conflict. newVersion is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const RES = JSON.stringify(resource);\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: operation,\n RES\n });\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `UpdateResource(): Version Conflict. resourceVersionRunResult is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n await this.UpdateIndexes(client, resource);\n\n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `UpdateResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n DeleteResource = async (resource: Resource, RES_VER: number, transactionHandle?: string): Promise<Resource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `DeleteResource(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n let client: PoolClient;\n let useTransaction: boolean;\n\n try {\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadWrite();\n useTransaction = true;\n }\n } catch (error) {\n const errorMessage = `DeleteResource(): Could not get connection: Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const now = new Date().getTime();\n //const now = new Date(DateTime.fromISO(resource.meta!.lastUpdated as string).toJSDate()).getTime();\n\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const newVersion = await this.#dbSTSResource.DeleteResourceRecordEx(client, {\n RES_ID,\n RES_TYPE,\n RES_VER,\n RES_DELETED_AT: now,\n RES_UPDATED: now\n });\n if (newVersion === undefined) {\n const errorMessage = `DeleteResource(): Version Conflict. newVersion is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n resource.meta ??= {};\n resource.meta.versionId = String(newVersion);\n resource.meta.lastUpdated = new Date(now).toISOString();\n\n const resourceVersionRunResult = await this.#dbSTSResourceVersion.InsertResourceVersionEx(client, {\n PID: randomUUID(),\n PARTITION_ID: 0,\n PARTITION_DATE: 0,\n RES_ID,\n RES_TYPE,\n RES_VER: newVersion,\n OPERATION: 'DELETE',\n RES: ''\n });\n\n if (resourceVersionRunResult === undefined) {\n const errorMessage = `DeleteResource(): Version Conflict. resourceVersionRunResult is undefined. RES_VER: [${RES_VER}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n\n await this.UpdateIndexes(client, resource);\n \n if (useTransaction) {\n await client.query('COMMIT');\n }\n return resource;\n } catch (error) {\n if (useTransaction) {\n await client.query('ROLLBACK');\n }\n const errorMessage = `DeleteResource(): Error: [${error}]`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n }\n\n //@@ needs to return a 410 (GONE) if record exists but deleted ...\n /* \n| Request type | Response |\n| ----------------------------- | -------------------------------------------------- |\n| `GET /Patient/123` | 🔴 `410 Gone` |\n| `GET /Patient/123/_history/1` | ✅ Returns version 1 if it exists |\n| `GET /Patient/123/_history` | ✅ Shows all historical versions including deletion |\n| `POST /Patient` (same ID) | 🔄 Creates a new version |\n| `PUT /Patient/123` | 🔄 Reactivates (undeletes) with new version |\n*/\n\n ReadResourceRecord = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceRecord(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.* FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE AND\n r.RES_VER = v.RES_VER\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2 AND\n r.RES_DELETED_AT IS NULL\n `, [RES_ID, RES_TYPE]);\n return res.rows[0];\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourceRecordWithVersion = async (RES_TYPE: string, RES_ID: string, RES_VER: number, transactionHandle?: string): Promise<IResource | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceRecordWithVersion(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2 AND\n v.RES_VER = $3\n `, [RES_ID, RES_TYPE, RES_VER]);\n return res.rows[0];\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourceInstanceWithAllVersions = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceInstanceWithAllVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_ID = $1 AND\n r.RES_TYPE = $2\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `, [RES_ID, RES_TYPE]);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadResourcesWithAllVersions = async (RES_TYPE: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourcesWithAllVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.*, r.res_ver as R_res_ver, v.res_ver as V_res_ver FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE\n WHERE\n r.RES_TYPE = $1\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `, [RES_TYPE]);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadAllResourcesWithVersions = async (transactionHandle?: string) => {\n if (!this.#poolManager) {\n const errorMessage = `ReadAllResourcesWithVersions(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const res = await client.query(`\n SELECT\n r.*, v.* FROM stsresfhir r\n JOIN \n stsresfhirver v\n ON \n r.RES_ID = v.RES_ID AND \n r.RES_TYPE = v.RES_TYPE AND\n ORDER BY\n v.RES_TYPE ASC, v.RES_ID ASC, v.RES_VER DESC\n `);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\n }\n\n ReadAllResourceVersionRecord = (): Promise<IResourceVersion[] | undefined> => {\n return this.#dbSTSResourceVersion.ReadAllResourceVersionRecords();\n }\n\n ReadResourceIndexes = async (resource: Resource, transactionHandle?: string): Promise<JSONObject | undefined> => {\n if (!this.#poolManager) {\n const errorMessage = `ReadResourceIndexes(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n const resultSet: Record<string, any[] | undefined> = {\n \"stsresfhirlink\": [ ],\n \"stsresfhirstring\": [ ],\n \"stsresfhirtoken\": [ ],\n \"stsresfhirquantity\": [ ],\n \"stsresfhirnumber\": [ ],\n \"stsresfhirdate\": [ ],\n \"stsresfhiruri\": [ ],\n \"stsresfhircombo\": [ ]\n };\n\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n\n try {\n\n const retValLinks = await this.#dbSTSResourceLink.ReadResourceLinkByResourceIdRecord(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirlink\"] = retValLinks;\n\n const retValStrings = await this.#dbSTSString.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirstring\"] = retValStrings;\n\n const retValTokens = await this.#dbSTSToken.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirtoken\"] = retValTokens;\n\n const retValQuantity = await this.#dbSTSQuantity.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirquantity\"] = retValQuantity;\n\n const retValNumber = await this.#dbSTSNumber.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirnumber\"] = retValNumber;\n\n const retValDate = await this.#dbSTSDate.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhirdate\"] = retValDate;\n\n const retValUri = await this.#dbSTSUri.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhiruri\"] = retValUri;\n\n const retValCombo = await this.#dbSTSCombo.ReadByResID(client, resource.id!, resource.resourceType);\n resultSet[\"stsresfhircombo\"] = retValCombo;\n\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceIndexes(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n return resultSet;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceIndexes(): Connection Error: [${error}]`)\n }\n }\n\n ExecuteReadQuery = async (queryData: any, transactionHandle?: string): Promise<any> => {\n if (!this.#poolManager) {\n const errorMessage = `ExecuteReadQuery(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n let useTransaction: boolean;\n if (transactionHandle && this.#transactions[transactionHandle]) {\n client = this.#transactions[transactionHandle].client;\n useTransaction = false;\n } else {\n client = await this.#poolManager.connectReadOnly();\n useTransaction = true;\n }\n try {\n const { queryText, vals } = queryData;\n const res = await client.query(queryText, vals);\n return res.rows;\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ExecuteReadQuery(): Query Error: [${error}]`)\n } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ExecuteReadQuery(): Connection Error: [${error}]`)\n }\n }\n\n TruncateAll = async () => {\n if (!this.#poolManager) {\n const errorMessage = `TruncateAll(): poolManager not set`;\n this.#options.logger.error(errorMessage);\n throw new Error(errorMessage);\n }\n try {\n let client: PoolClient;\n client = await this.#poolManager.connectReadWrite();\n try {\n client.query('TRUNCATE TABLE stsresfhir, stsresfhirver, stsresfhirlink, stsresfhirstring, stsresfhirtoken, stsresfhirquantity, stsresfhirnumber, stsresfhiruri, stsresfhirdate, stsresfhircoords, stsresfhircombo');\n } catch (error) {\n defaultLogger.error(`DBSTSResource:TruncateAll(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:TruncateAll(): Connection Error: [${error}]`)\n }\n }\n}\n"],"x_google_ignoreList":[1],"mappings":"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;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAE;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAG;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAG;CAAI;CAAE;CAAE;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAE;CAAI;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAG;CAAG;CAAI;CAAG;CAAE;CAAE;CAAG;CAAE;CAAG;CAAG;CAAI;CAAI;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAE;CAAI;CAAG;CAAE;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAG;CAAG;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI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"}
|